47 #include "../../3rdparty/md5/md5.h" 48 #include "../../3rdparty/md5/md5.cpp" 59 #include <private/qcore_unix_p.h> 65 #include <sys/types.h> 66 #include <sys/socket.h> 73 #include <QtCore/qcache.h> 86 volatile char *p = (
char *)v;
while (n--) *p++=
c;
return v;
138 const unsigned char*
key,
140 unsigned char * digest
145 #define KEY_CACHE_SIZE 30 148 "pending identity verification",
149 "message too small to carry auth data",
150 "cache miss on connection oriented transport",
151 "no magic bytes on message",
152 "key not found for prog id",
153 "authorization key match failed",
185 : keyInitialised(false)
186 , m_packageRegistry( 0 )
221 ::memcpy(&
d->authKey, authdata,
sizeof(
struct AuthCookie));
227 #ifdef QTRANSPORTAUTH_DEBUG 228 qDebug(
"Using %li bytes of /proc/%i/lids_key\n", (
long int)kb, getpid() );
233 d->keyInitialised =
true;
248 #ifdef QTRANSPORTAUTH_DEBUG 250 hexstring( displaybuf, (
const unsigned char *)key,
QSXE_KEY_LEN );
251 qDebug() <<
"key" << displaybuf <<
"set";
378 d->m_keyFilePath = path;
384 return d->m_keyFilePath;
390 d->m_logFilePath = path;
396 return d->m_logFilePath;
402 d->m_packageRegistry = registry;
407 #if defined(SXE_DISCOVERY) 408 static bool checked =
false;
409 static bool yesItIs =
false;
411 if ( checked )
return yesItIs;
413 yesItIs = ( getenv(
"SXE_DISCOVERY_MODE" ) != 0 );
416 qWarning(
"SXE Discovery mode on, ALLOWING ALL requests and logging to %s",
439 if ( client == 0 )
return 0;
440 if (
d->buffersByClient.contains( client ))
442 return d->buffersByClient[client];
501 return d->getClientKey( progId );
507 d->invalidateClientKeyCache();
513 return &
d->keyfileMutex;
524 if ( cli == NULL )
return;
526 if (
d->buffersByClient.contains( cli ))
528 d->buffersByClient.remove( cli );
536 bool isAuthorized =
true;
544 #if defined(SXE_DISCOVERY) 546 #ifndef QT_NO_TEXTSTREAM 550 qWarning(
"Could not write to log in discovery mode: %s",
554 ts << d.
progId <<
'\t' << ( isAuthorized ?
"Allow" :
"Deny" ) <<
'\t' << request <<
endl;
563 qWarning(
"%s - denied: for Program Id %u [PID %d]" 573 if ( -1 == ::readlink( exeLink, linkTarget,
BUF_SIZE - 1 ) )
575 qWarning(
"SXE:- Error encountered in retrieving executable link target from /proc/%u/exe : %s",
577 snprintf( linkTarget,
BUF_SIZE,
"%s", linkTarget );
583 if ( cmdlineFd == -1 )
585 qWarning(
"SXE:- Error encountered in opening /proc/%u/cmdline: %s",
587 snprintf( cmdline,
BUF_SIZE,
"%s",
"Unknown" );
593 qWarning(
"SXE:- Error encountered in reading /proc/%u/cmdline : %s",
595 snprintf( cmdline,
BUF_SIZE,
"%s",
"Unknown" );
600 syslog( LOG_ERR | LOG_LOCAL6,
"%s // PID:%u // ProgId:%u // Exe:%s // Request:%s // Cmdline:%s",
609 #ifdef QTRANSPORTAUTH_DEBUG 660 int manifestMatchCount = 0;
670 if ( keyCache.contains( progId ))
671 return (
const unsigned char *)keyCache[progId];
678 bool noFailOnKeyMissing =
true;
682 QFile kf( actualKeyPath );
683 QFile mn( manifestPath );
687 while ( mn.
read( (
char*)&mr,
sizeof(
struct IdBlock)) > 0 )
688 if ( mr.progId == progId )
689 manifestMatchCount++;
690 if ( manifestMatchCount == 0 )
694 noFailOnKeyMissing =
false;
698 result = (
char*)malloc( total_size );
704 while (( keysRead = kf.
read( (
char*)keys_list,
sizeof(
struct usr_key_entry)*128 )) > 0 )
709 while ( mn.
read( (
char*)&mr,
sizeof(
struct IdBlock)) > 0 )
711 if ( mr.progId == progId )
714 for (
int i = 0; i < keysRead; ++i )
719 if ( keys_list[i].
ino == (ino_t)mr.inode && keys_list[i].dev == (dev_t)mr.device )
721 memcpy( result_ptr, keys_list[i].
key, QSXE_KEY_LEN );
730 if ( keysFound == manifestMatchCount )
736 if ( result_ptr == result )
739 for (
int i = 0; i < 2; ++i )
741 *result_ptr++ =
magic[j];
742 keyCache.insert( progId, result, total_size / 10 );
747 if ( noFailOnKeyMissing )
751 result = (
char*)malloc( 2 * QSXE_MAGIC_BYTES );
755 for (
int i = 0; i < 2; ++i )
757 *result_ptr++ =
magic[j];
758 return (
unsigned char *)result;
760 qWarning(
"PID %d : Not found client key for prog %u", getpid(), progId );
771 return (
unsigned char *)result;
778 keyfileMutex.unlock();
830 if ( command == NULL )
832 *msgQueue = msgQueue->
mid(
sizeof(
int) );
837 if ( !command->
read( &cmdBuf ))
883 , m_bytesAvailable( 0 )
971 #ifdef QTRANSPORTAUTH_DEBUG 972 char displaybuf[1024];
980 #ifdef QTRANSPORTAUTH_DEBUG 981 hexstring( displaybuf, (
const unsigned char *)header,
QSXE_HEADER_LEN );
982 qDebug(
"%d QAuthDevice::writeData - CLIENT: Header written: %s", getpid(), displaybuf );
988 #ifdef QTRANSPORTAUTH_DEBUG 989 int bytesToDisplay = bytes;
990 const unsigned char *dataptr = (
const unsigned char *)data;
991 while ( bytesToDisplay > 0 )
993 int amt = bytes < 500 ? bytes : 500;
994 hexstring( displaybuf, dataptr, amt );
995 qDebug(
"%d QAuthDevice::writeData - CLIENT: %s", getpid(), bytes > 0 ? displaybuf :
"(null)" );
997 bytesToDisplay -= 500;
1001 static_cast<QAbstractSocket*>(
m_target)->flush();
1019 #ifdef QTRANSPORTAUTH_DEBUG 1020 char displaybuf[1024];
1021 hexstring( displaybuf, reinterpret_cast<const unsigned char *>(
msgQueue.
constData()),
1023 qDebug() << getpid() <<
"QAuthDevice::readData() buffered/requested/avail" 1054 if ( bytes <= 0 )
return;
1068 #ifdef QTRANSPORTAUTH_DEBUG 1069 char displaybuf[1024];
1070 hexstring( displaybuf, reinterpret_cast<const unsigned char *>(
msgQueue.
constData()),
1072 qDebug(
"%d ***** SERVER read %lli bytes - msg %s", getpid(), bytes, displaybuf );
1075 bool bufHasMessages =
msgQueue.
size() >= (int)
sizeof(
int);
1076 while ( bufHasMessages )
1078 unsigned char saveStatus =
d->
status;
1147 bool isAuthorized =
true;
1157 #ifdef QTRANSPORTAUTH_DEBUG 1162 return moreToProcess;
1204 d_func()->authKey.progId == d.
progId )
1206 d.
progId = d_func()->authKey.progId;
1208 if ( !d_func()->keyInitialised )
1214 *msgPtr++ =
magic[m];
1219 int rc =
hmac_md5( (
unsigned char *)msg, msgLen, d_func()->authKey.key,
QSXE_KEY_LEN, digest );
1231 #ifdef QTRANSPORTAUTH_DEBUG 1233 hexstring( keydisplay, d_func()->authKey.key,
QSXE_KEY_LEN );
1235 qDebug(
"%d CLIENT Auth to message %s against prog id %u and key %s\n",
1236 getpid(), msg, d_func()->authKey.progId, keydisplay );
1303 const unsigned char *mptr =
reinterpret_cast<const unsigned char *
>(msg);
1306 if ( *mptr++ !=
magic[m] )
1326 #ifdef QTRANSPORTAUTH_DEBUG 1328 hexstring( authhdr, reinterpret_cast<const unsigned char *>(msg),
QSXE_HEADER_LEN );
1329 qDebug(
"%d SERVER authFromMessage(): message header is %s",
1330 getpid(), authhdr );
1333 unsigned char authLen = (
unsigned char)(msg[
QSXE_LEN_IDX ]);
1341 bool isCached = d_func()->keyCache.contains( d.
progId );
1342 const unsigned char *clientKey = d_func()->getClientKey( d.
progId );
1343 if ( clientKey == NULL )
1349 #ifdef QTRANSPORTAUTH_DEBUG 1352 qDebug(
"\t\tauthFromMessage(): message %s against prog id %u and key %s\n",
1356 const unsigned char *auth_tok;
1358 bool multi_tok =
false;
1360 bool need_to_recheck=
false;
1370 auth_tok = clientKey;
1375 if ( memcmp( auth_tok,
magic, QSXE_MAGIC_BYTES ) == 0
1376 && memcmp( auth_tok + QSXE_MAGIC_BYTES,
magic, QSXE_MAGIC_BYTES ) == 0 )
1391 d_func()->keyCache.remove(d.
progId);
1394 #ifdef QTRANSPORTAUTH_DEBUG 1395 qDebug() <<
"QTransportAuth::authFromMessage(): key not found in set of keys cached" 1396 <<
"against prog Id =" << d.
progId <<
". Re-obtaining client key. ";
1398 clientKey = d_func()->getClientKey( d.
progId );
1399 if ( clientKey == NULL )
1404 need_to_recheck =
true;
1408 need_to_recheck =
false;
1410 }
while( need_to_recheck );
1413 qWarning() <<
"QTransportAuth::authFromMessage():failed authentication";
1415 emit authViolation( d );
1420 #ifdef QTRANSPORTAUTH_DEBUG 1426 void hexstring(
char *buf,
const unsigned char*
key,
size_t key_len )
1429 for ( i = 0, p = 0; i < key_len; i++, p+=2 )
1431 unsigned char lo_nibble =
key[i] & 0x0f;
1432 unsigned char hi_nibble =
key[i] >> 4;
1433 buf[p] = (int)hi_nibble > 9 ? hi_nibble-10 +
'A' : hi_nibble +
'0';
1434 buf[p+1] = (int)lo_nibble > 9 ? lo_nibble-10 +
'A' : lo_nibble +
'0';
1467 unsigned char*
text,
1469 const unsigned char*
key,
1471 unsigned char * digest
1475 unsigned char k_ipad[65];
1476 unsigned char k_opad[65];
1480 if ( key_length != 16 )
1482 fprintf( stderr,
"Key length was %d - must be 16 bytes", key_length );
1487 memset( k_ipad, 0,
sizeof k_ipad );
1488 memset( k_opad, 0,
sizeof k_opad );
1489 memcpy( k_ipad, key, key_length );
1490 memcpy( k_opad, key, key_length );
1493 for (i=0; i<64; i++) {
1500 MD5Update(&context, k_ipad, 64);
1501 MD5Update(&context, text, text_length);
1502 MD5Final(&context, digest);
1506 MD5Update(&context, k_opad, 64);
1507 MD5Update(&context, digest, 16);
1508 MD5Final(&context, digest);
1529 return &theInstance;
1539 #if defined(SXE_DISCOVERY) 1543 #ifndef QT_NO_TEXTSTREAM 1545 if ( !logFilePath.
isEmpty() ) {
1546 QFile log( logFilePath );
1548 qWarning(
"Could not write to log in discovery mode: %s",
1552 ts <<
"\t\tWarning: False Authentication Rate of " <<
minutelyRate <<
"\n" 1553 <<
"\t\tserver connections/authentications per minute has been exceeded,\n" 1554 <<
"\t\tno further warnings will be issued\n";
1563 syslog( LOG_ERR | LOG_LOCAL6,
"%s %s",
1579 #include "moc_qtransportauth_qws_p.cpp" bool authFromMessage(QTransportAuth::Data &d, const char *msg, int msgLen)
Check authorization on the msg, which must be of size msgLen, for the transport d.
QString fileName() const
Returns the name set by setFileName() or to the QFile constructors.
const unsigned char magic[QSXE_MAGIC_BYTES]
void setTrusted(bool)
Assert that the transport is trusted.
void setRequestAnalyzer(RequestAnalyzer *)
qint64 bytesAnalyzed() const
qint64 writeData(const char *, qint64)
Reimplement QIODevice writeData method.
#define QT_END_NAMESPACE
This macro expands to.
bool __fileOpen(QFile *f)
bool authorizeRequest(QTransportAuth::Data &d, const QString &request)
The QUnixSocket class provides a Unix domain socket.
The QMutex class provides access serialization between threads.
QAuthDevice * authBuf(QTransportAuth::Data *, QIODevice *)
Return a QIODevice pointer (to an internal QBuffer) which can be used to write data onto...
qint64 read(char *data, qint64 maxSize)
static QWSCommand * factory(int type)
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
QByteArray & append(char c)
Appends the character ch to this byte array.
void policyCheck(QTransportAuth::Data &, const QString &)
virtual QString analyze(QByteArray *)
Analzye the data in themsgQueue according to some protocol and produce a request string for policy an...
const char *const errorStrings[]
bool open(OpenMode openMode)
Reimplemented Function
QTransportAuth::Data * connectTransport(unsigned char, int)
Record a new transport connection with properties and descriptor.
The QByteArray class provides an array of bytes.
void setPackageRegistry(QObject *registry)
static const char * errorString(const QTransportAuth::Data &)
Pass-through QIODevice sub-class for authentication.
Data record for the manifest file.
static const QString SxeTag
int qws_read_uint(QIODevice *socket)
Q_GUI_EXPORT void * guaranteed_memset(void *v, int c, size_t n)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
void invalidateClientKeyCache()
void bytesWritten(qint64 bytes)
This signal is emitted every time a payload of data has been written to the device.
The QBuffer class provides a QIODevice interface for a QByteArray.
The QString class provides a Unicode character string.
const unsigned char * getClientKey(unsigned char progId)
Find client keys for the progId.
The QObject class is the base class of all Qt objects.
#define Q_BASIC_ATOMIC_INITIALIZER(a)
void targetBytesWritten(qint64)
void registerPolicyReceiver(QObject *)
Register pr as a policy handler object.
virtual ~RequestAnalyzer()
QList< QDateTime > authAttempts
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
bool exists() const
Returns true if the file specified by fileName() exists; otherwise returns false. ...
Q_CORE_EXPORT void qDebug(const char *,...)
void append(const T &t)
Inserts value at the end of the list.
bool trusted() const
Is the transport trusted.
bool testAndSetRelaxed(int expectedValue, int newValue)
#define QT_BEGIN_NAMESPACE
This macro expands to.
bool isOpen() const
Returns true if the device is open; otherwise returns false.
void destroyed(QObject *=0)
This signal is emitted immediately before the object obj is destroyed, and can not be blocked...
static FAREnforcer * getInstance()
RequestAnalyzer * analyzer
SxeRegistryLocker(QObject *)
T takeFirst()
Removes the first item in the list and returns it.
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
static const int minutelyRate
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
This comes from the SXE kernel patch file include/linux/lidsif.
int secsTo(const QDateTime &) const
Returns the number of seconds from this datetime to the other datetime.
Q_CORE_EXPORT void qWarning(const char *,...)
static const QString FARMessage
static const char * data(const QByteArray &arr)
#define Q_RETURN_ARG(type, data)
void logAuthAttempt(QDateTime time=QDateTime::currentDateTime())
QAuthDevice * recvBuf(QTransportAuth::Data *, QIODevice *)
Return a QIODevice pointer (to an internal QBuffer) which can be used to receive data after authoriza...
QByteArray mid(int index, int len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos...
bool inherits(const char *classname) const
Returns true if this object is an instance of a class that inherits className or a QObject subclass t...
const char * constData() const
Returns a pointer to the data stored in the byte array.
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Enforces the False Authentication Rate.
void setProcessKey(const char *)
Set the process key for this currently running Qt Extended process to the authdata.
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
bool authToMessage(QTransportAuth::Data &d, char *hdr, const char *msg, int msgLen)
Add authentication header to the beginning of a message.
The QDateTime class provides date and time functions.
The QFile class provides an interface for reading from and writing to files.
void recvReadyRead()
Receive readyRead signal from the target recv device.
#define QWS_PROTOCOL_ITEM_SIZE(item)
The QTextStream class provides a convenient interface for reading and writing text.
pid_t processId() const
Returns the process id credential associated with this message.
QAuthDevice(QIODevice *, QTransportAuth::Data *, AuthDirection)
Constructs a new auth device for the transport data and I/O device parent.
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
QString logFilePath() const
void setConnection(bool)
Assert that the transport is connection oriented.
void setKeyFilePath(const QString &)
Set the full path to the key file.
void unregisterPolicyReceiver(QObject *)
Unregister the pr from being a policy handler.
T & last()
Returns a reference to the last item in the list.
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
static QDateTime currentDateTime()
Returns the current datetime, as reported by the system clock, in the local time zone.
void invalidateClientKeyCache()
void setClient(QObject *)
int size() const
Returns the number of bytes in this byte array.
static const QCssKnownValue properties[NumProperties - 1]
QString keyFilePath() const
void bufferDestroyed(QObject *)
virtual bool open(OpenMode mode)
Opens the device and sets its OpenMode to mode.
const char * qws_getCommandTypeString(QWSCommand::Type tp)
bool remove()
Removes the file specified by fileName().
bool connection() const
Is the transport connection oriented.
const QByteArray & bytes() const
Return the data portion of the message.
Authenticate a message transport.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
void readyRead()
This signal is emitted once every time new data is available for reading from the device...
The QIODevice class is the base interface class of all I/O devices in Qt.
QIODevice * passThroughByClient(QWSClient *) const
virtual void close()
Calls QFile::flush() and closes the file.
const unsigned char * getClientKey(unsigned char progId)
#define qPrintable(string)
bool seek(qint64 offset)
For random-access devices, this function sets the current position to pos, returning true on success...
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
The QWSClient class encapsulates a client process in Qt for Embedded Linux.
QMutex * getKeyFileMutex()
void setLogFilePath(const QString &)
static int hmac_md5(unsigned char *text, int text_length, const unsigned char *key, int key_length, unsigned char *digest)
The QUnixSocketMessage class encapsulates a message sent or received through the QUnixSocket class...
qint64 readData(char *, qint64)
Reimplement from QIODevice.
static QTransportAuth * getInstance()
Return a pointer to the instance of this process's QTransportAuth object.
bool isDiscoveryMode() const
Q_CORE_EXPORT QTextStream & endl(QTextStream &s)
bool requireMoreData() const