⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qtransportauth_qws.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
   The buffer must have AUTH_SPACE(0) bytes spare at the beginning for the   authentication header to be added.   Returns true if header successfully added.  Will fail if the   per-process key has not yet been set with setProcessKey()*/bool QTransportAuth::authToMessage( QTransportAuth::Data &d, char *hdr, const char *msg, int msgLen ){    // qDebug( "authToMessage(): prog id %u", d.progId );    // only authorize connection oriented transports once, unless key has changed    if ( d.connection() && ((d.status & QTransportAuth::ErrMask) != QTransportAuth::Pending) &&        d_func()->authKey.progId == d.progId )        return false;    d.progId = d_func()->authKey.progId;    // If Unix socket credentials are being used the key wont be set    if ( !d_func()->keyInitialised )        return false;    unsigned char digest[QSXE_KEY_LEN];    char *msgPtr = hdr;    // magic always goes on the beginning    for ( int m = 0; m < QSXE_MAGIC_BYTES; ++m )        *msgPtr++ = magic[m];    hdr[ QSXE_LEN_IDX ] = (unsigned char)msgLen;    if ( !d.trusted())    {        // Use HMAC        int rc = hmac_md5( (unsigned char *)msg, msgLen, d_func()->authKey.key, QSXE_KEY_LEN, digest );        if ( rc == -1 )            return false;        memcpy( hdr + QSXE_KEY_IDX, digest, QSXE_KEY_LEN );    }    else    {        memcpy( hdr + QSXE_KEY_IDX, d_func()->authKey.key, QSXE_KEY_LEN );    }    hdr[ QSXE_PROG_IDX ] = d_func()->authKey.progId;#ifdef QTRANSPORTAUTH_DEBUG    char keydisplay[QSXE_KEY_LEN*2+1];    hexstring( keydisplay, d_func()->authKey.key, QSXE_KEY_LEN );    qDebug( "%d CLIENT Auth to message %s against prog id %u and key %s\n",            getpid(), msg, d_func()->authKey.progId, keydisplay );#endif    // TODO implement sequence to prevent replay attack, not required    // for trusted transports    hdr[ QSXE_SEQ_IDX ] = 1;  // dummy sequence    d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::Success;    return true;}/*!  Check authorization on the \a msg, which must be of size \a msgLen,  for the transport \a d.  If able to determine authorization, return the program identity of  the message source in the reference \a progId, and return true.  Otherwise return false.  If data is being received on a socket, it may be that more data is yet  needed before authentication can proceed.  Also the message may not be an authenticated at all.  In these cases the method returns false to indicate authorization could  not be determined:  \list    \i The message is too small to carry the authentication data       (status TooSmall is set on the \a d transport )    \i The 4 magic bytes are missing from the message start       (status NoMagic is set on the \a d transport )    \i The message is too small to carry the auth + claimed payload       (status TooSmall is set on the \a d transport )  \endlist  If however the authentication header (preceded by the magic bytes) and  any authenticated payload is received the method will determine the  authentication status, and return true.  In the following cases as well as returning true it will also emit  an authViolation():  \list    \i If the program id claimed by the message is not found in the key file       (status NoSuchKey is set on the \a d transport )    \i The authentication token failed against the claimed program id:        \list            \i in the case of trusted transports, the secret did not match            \i in the case of untrusted transports the HMAC code did not match        \endlist       (status FailMatch is set on the \a d transport )    \endlist  In these cases the authViolation( QTransportAuth::Data d ) signal is emitted  and the error string can be obtained from the status like this:  \code      QTransportAuth::Result r = d.status & QTransportAuth::ErrMask;      qWarning( "error: %s", QTransportAuth::errorStrings[r] );  \endcode*/bool QTransportAuth::authFromMessage( QTransportAuth::Data &d, const char *msg, int msgLen ){    if ( msgLen < QSXE_MAGIC_BYTES )    {        d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::TooSmall;        return false;    }    // if no magic bytes, exit straight away    int m;    const unsigned char *mptr = reinterpret_cast<const unsigned char *>(msg);    for ( m = 0; m < QSXE_MAGIC_BYTES; ++m )    {        if ( *mptr++ != magic[m] )        {            d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::NoMagic;            return false;        }    }    if ( msgLen < AUTH_SPACE(1) )    {        d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::TooSmall;        return false;    }    // At this point we know the header is at least long enough to contain valid auth    // data, however the data may be spoofed.  If it is not verified then the status will    // be set to uncertified so the spoofed data will not be relied on.  However we want to    // know the program id which is being reported (even if it might be spoofed) for    // policy debugging purposes.  So set it here, rather than after verification.    d.progId = msg[QSXE_PROG_IDX];#ifdef QTRANSPORTAUTH_DEBUG    char authhdr[QSXE_HEADER_LEN*2+1];    hexstring( authhdr, reinterpret_cast<const unsigned char *>(msg), QSXE_HEADER_LEN );    qDebug( "%d SERVER authFromMessage(): message header is %s",            getpid(), authhdr );#endif    unsigned char authLen = (unsigned char)(msg[ QSXE_LEN_IDX ]);    if ( msgLen < AUTH_SPACE(authLen) )    {        d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::TooSmall;        return false;    }    bool isCached = d_func()->keyCache.contains( d.progId );    const unsigned char *clientKey = d_func()->getClientKey( d.progId );    if ( clientKey == NULL )    {        d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::NoSuchKey;        return false;    }#ifdef QTRANSPORTAUTH_DEBUG    char keydisplay[QSXE_KEY_LEN*2+1];    hexstring( keydisplay, clientKey, QSXE_KEY_LEN );    qDebug( "\t\tauthFromMessage(): message %s against prog id %u and key %s\n",            AUTH_DATA(msg), ((unsigned int)d.progId), keydisplay );#endif    const unsigned char *auth_tok;    unsigned char digest[QSXE_KEY_LEN];    bool multi_tok = false;    bool need_to_recheck=false;    do    {        if ( !d.trusted())        {            hmac_md5( AUTH_DATA(msg), authLen, clientKey, QSXE_KEY_LEN, digest );            auth_tok = digest;        }        else        {            auth_tok = clientKey;            multi_tok = true;  // 1 or more keys are in the clientKey        }        while( true )        {            if ( memcmp( auth_tok, magic, QSXE_MAGIC_BYTES ) == 0                    && memcmp( auth_tok + QSXE_MAGIC_BYTES, magic, QSXE_MAGIC_BYTES ) == 0 )                break;            if ( memcmp( msg + QSXE_KEY_IDX, auth_tok, QSXE_KEY_LEN ) == 0 )            {                d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::Success;                return true;            }            if ( !multi_tok )                break;            auth_tok += QSXE_KEY_LEN;        }        //the keys cached on d.progId may not contain the binary key because the cache entry was made        //before the binary had first started, must search for client key again.        if ( isCached )        {            d_func()->keyCache.remove(d.progId);            isCached = false;#ifdef QTRANSPORTAUTH_DEBUG            qDebug() << "QTransportAuth::authFromMessage(): key not found in set of keys cached"                     << "against prog Id =" << d.progId << ". Re-obtaining client key. ";#endif            clientKey = d_func()->getClientKey( d.progId );            if ( clientKey == NULL )            {                d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::NoSuchKey;                return false;            }            need_to_recheck = true;        }        else        {            need_to_recheck = false;        }    } while( need_to_recheck );    d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::FailMatch;    qWarning() << "QTransportAuth::authFromMessage():failed authentication";    FAREnforcer::getInstance()->logAuthAttempt( QDateTime::currentDateTime() );    emit authViolation( d );    return false;}#ifdef QTRANSPORTAUTH_DEBUG/*!  sprintf into hex - dest \a buf, src \a key, \a key_len is length of key.  The target buf should be [ key_len * 2 + 1 ] in size*/void hexstring( char *buf, const unsigned char* key, size_t key_len ){    unsigned int i, p;    for ( i = 0, p = 0; i < key_len; i++, p+=2 )    {        unsigned char lo_nibble = key[i] & 0x0f;        unsigned char hi_nibble = key[i] >> 4;        buf[p] = (int)hi_nibble > 9 ? hi_nibble-10 + 'A' : hi_nibble + '0';        buf[p+1] = (int)lo_nibble > 9 ? lo_nibble-10 + 'A' : lo_nibble + '0';    }    buf[p] = '\0';}#endif/*  HMAC MD5 as listed in RFC 2104  This code is taken from:      http://www.faqs.org/rfcs/rfc2104.html  with the allowance for keys other than length 16 removed, but otherwise  a straight cut-and-paste.  The HMAC_MD5 transform looks like:  \code      MD5(K XOR opad, MD5(K XOR ipad, text))  \endcode  \list    \i where K is an n byte key    \i ipad is the byte 0x36 repeated 64 times    \i opad is the byte 0x5c repeated 64 times    \i and text is the data being protected  \endlist  Hardware is available with accelerated implementations of HMAC-MD5 and  HMAC-SHA1.  Where this hardware is available, this routine should be  replaced with a call into the accelerated version.*/static int hmac_md5(        unsigned char*  text,         /* pointer to data stream */        int             text_length,  /* length of data stream */        const unsigned char*  key,    /* pointer to authentication key */        int             key_length,   /* length of authentication key */        unsigned char * digest        /* caller digest to be filled in */        ){        MD5Context context;        unsigned char k_ipad[65];    /* inner padding - * key XORd with ipad */        unsigned char k_opad[65];    /* outer padding - * key XORd with opad */        int i;        /* in this implementation key_length == 16 */        if ( key_length != 16 )        {            fprintf( stderr, "Key length was %d - must be 16 bytes", key_length );            return 0;        }        /* start out by storing key in pads */        memset( k_ipad, 0, sizeof k_ipad );        memset( k_opad, 0, sizeof k_opad );        memcpy( k_ipad, key, key_length );        memcpy( k_opad, key, key_length );        /* XOR key with ipad and opad values */        for (i=0; i<64; i++) {                k_ipad[i] ^= 0x36;                k_opad[i] ^= 0x5c;        }        /* perform inner MD5 */        MD5Init(&context);                   /* init context for 1st pass */        MD5Update(&context, k_ipad, 64);     /* start with inner pad */        MD5Update(&context, text, text_length); /* then text of datagram */        MD5Final(&context, digest);          /* finish up 1st pass */        /* perform outer MD5 */        MD5Init(&context);                   /* init context for 2nd pass */        MD5Update(&context, k_opad, 64);     /* start with outer pad */        MD5Update(&context, digest, 16);     /* then results of 1st * hash */        MD5Final(&context, digest);          /* finish up 2nd pass */        return 1;}const int FAREnforcer::minutelyRate = 4; //allowed number of false authentication attempts per minuteconst QString FAREnforcer::FARMessage = "FAR_Exceeded";const QString FAREnforcer::SxeTag = "<SXE Breach>";const int FAREnforcer::minute = 60;FAREnforcer::FAREnforcer():authAttempts(){    QDateTime nullDateTime = QDateTime();    for (int i = 0; i < minutelyRate; i++ )        authAttempts << nullDateTime;}FAREnforcer *FAREnforcer::getInstance(){    static FAREnforcer theInstance;    return &theInstance;}void FAREnforcer::logAuthAttempt( QDateTime time ){    QDateTime dt =  authAttempts.takeFirst();    authAttempts.append( time );    if ( dt.secsTo( authAttempts.last() ) <= minute )    {#if defined(SXE_DISCOVERY)        if ( QTransportAuth::getInstance()->isDiscoveryMode() ) {            static QBasicAtomic reported = {0};            if ( reported.testAndSet(0,1) ) {#ifndef QT_NO_TEXTSTREAM                QString logFilePath = QTransportAuth::getInstance()->logFilePath();                if ( !logFilePath.isEmpty() ) {                      QFile log( logFilePath );                    if ( !log.open(QIODevice::WriteOnly | QIODevice::Append) ) {                        qWarning("Could not write to log in discovery mode: %s",                                 qPrintable(logFilePath) );                    } else {                        QTextStream ts( &log );                        ts << "\t\tWarning: False Authentication Rate of " <<  minutelyRate << "\n"                           << "\t\tserver connections/authentications per minute has been exceeded,\n"                           << "\t\tno further warnings will be issued\n";                    }                }            }#endif            reset();            return;        }#endif        syslog( LOG_ERR | LOG_LOCAL6, "%s %s",                qPrintable( FAREnforcer::SxeTag ),                 qPrintable( FAREnforcer::FARMessage ) );        reset();    }}void FAREnforcer::reset(){    QDateTime nullDateTime = QDateTime();    for (int i = 0; i < minutelyRate; i++ )        authAttempts[i] = nullDateTime; }#include "moc_qtransportauth_qws_p.cpp"#endif // QT_NO_SXE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -