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

📄 qtransportauth_qws.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    : moreData( false )    , dataSize( 0 ){}RequestAnalyzer::~RequestAnalyzer(){}/*!  Analzye the data in the\a msgQueue according to some protocol  and produce a request string for policy analysis.  If enough data is in the queue for analysis of a complete message,  return a non-null string, and set a flag so requireMoreData() will  return false; otherwise return a null string and requireMoreData()  return true.  The amount of bytes analyzed is then available via bytesAnalyzed().  A null string is also returned in the case where the message was  corrupt and could not be analyzed.  In this case requireMoreData()  returns false.Note: this method will modify the msgQueue and pull off the data  deemed to be corrupt, in the case of corrupt data.  In all other cases the msgQueue is left alone.  The calling code  should then pull off the analyzed data.  Use bytesAnalzyed() to  find how much data to pull off the queue.*/QString RequestAnalyzer::analyze( QByteArray *msgQueue ){#ifdef Q_WS_QWS    dataSize = 0;    moreData = false;    QBuffer cmdBuf( msgQueue );    cmdBuf.open( QIODevice::ReadOnly | QIODevice::Unbuffered );    QWSCommand::Type command_type = (QWSCommand::Type)(qws_read_uint( &cmdBuf ));    QWSCommand *command = QWSCommand::factory(command_type);    // if NULL, factory will have already printed warning for bogus    // command_type just purge the bad stuff and attempt to recover    if ( command == NULL )    {        *msgQueue = msgQueue->mid( sizeof(int) );        return QString();    }    QString request( qws_getCommandTypeString( command_type ));#ifndef QT_NO_COP    if ( !command->read( &cmdBuf ))    {        // not all command arrived yet - come back later        delete command;        moreData = true;        return QString();    }    if ( command_type == QWSCommand::QCopSend )    {        QWSQCopSendCommand *sendCommand = static_cast<QWSQCopSendCommand*>(command);        request += QString( "/QCop/%1/%2" ).arg( sendCommand->channel ).arg( sendCommand->message );    }    if ( command_type == QWSCommand::QCopRegisterChannel )    {        QWSQCopRegisterChannelCommand *registerCommand = static_cast<QWSQCopRegisterChannelCommand*>(command);        request += QString( "/QCop/RegisterChannel/%1" ).arg( registerCommand->channel );    }#endif    dataSize = QWS_PROTOCOL_ITEM_SIZE( *command );    delete command;    return request;#else    Q_UNUSED(msgQueue);    return QString();#endif}////////////////////////////////////////////////////////////////////////////////  AuthDevice definition/////*!  Constructs a new auth device for the transport \a data and I/O device \a parent.  Incoming or outgoing data will be authenticated according to the auth direction \a dir.  The auth device will take ownership of the transport \a data and delete it when the device  is destroyed.*/QAuthDevice::QAuthDevice( QIODevice *parent, QTransportAuth::Data *data, AuthDirection dir )    : QIODevice( parent )    , d( data )    , way( dir )    , m_target( parent )    , m_client( 0 )    , m_bytesAvailable( 0 )    , m_skipWritten( 0 )    , analyzer( 0 ){    if ( dir == Receive ) // server side    {        connect( m_target, SIGNAL(readyRead()),                this, SLOT(recvReadyRead()));    } else {        connect( m_target, SIGNAL(readyRead()),                this, SIGNAL(readyRead()));    }    connect( m_target, SIGNAL(bytesWritten(qint64)),            this, SLOT(targetBytesWritten(qint64)) );    open( QIODevice::ReadWrite | QIODevice::Unbuffered );}QAuthDevice::~QAuthDevice(){    if ( analyzer )        delete analyzer;    delete d;}/*!  \internal  Store a pointer to the related device or instance which this  authorizer is proxying for*/void QAuthDevice::setClient( QObject *cli ){    m_client = cli;    QTransportAuth::getInstance()->d_func()->buffersByClient[cli] = this;    QObject::connect( cli, SIGNAL(destroyed(QObject*)),            QTransportAuth::getInstance(), SLOT(bufferDestroyed(QObject*)) );    // qDebug( "@@@@@@@@@@@@ client set %p @@@@@@@@@", cli );    // qDebug( "           client count %d", QTransportAuth::getInstance()->d_func()->buffersByClient.count() );}QObject *QAuthDevice::client() const{    return m_client;}/*  \fn void QAuthDevice::authViolation(QTransportAuth::Data &)  This signal is emitted if an authorization failure is generated, as  described in checkAuth();  \sa checkAuth()*//*  \fn void QAuthDevice::policyCheck(QTransportAuth::Data &transport, const QString &request )  This signal is emitted when a transport successfully delivers a request  and gives the opportunity to either deny or accept the request.  This signal must be connected in the same thread, ie it cannot be queued.  As soon as all handlers connected to this signal are processed the Allow or  Deny state on the \a transport is checked, and the request is allowed or denied  accordingly.  \sa checkAuth()*//*!  \internal  Reimplement QIODevice writeData method.  For client end, when the device is written to the incoming data is  processed and an authentication header calculated.  This is pushed  into the target device, followed by the actual incoming data (the  payload).  For server end, it is a fatal error to write to the device.*/qint64 QAuthDevice::writeData(const char *data, qint64 len){    if ( way == Receive )  // server        return m_target->write( data, len );    // client#ifdef QTRANSPORTAUTH_DEBUG    char displaybuf[1024];#endif    char header[QSXE_HEADER_LEN];    ::memset( header, 0, QSXE_HEADER_LEN );    qint64 bytes = 0;    if ( QTransportAuth::getInstance()->authToMessage( *d, header, data, len ))    {        m_target->write( header, QSXE_HEADER_LEN );#ifdef QTRANSPORTAUTH_DEBUG        hexstring( displaybuf, (const unsigned char *)header, QSXE_HEADER_LEN );        qDebug( "%d QAuthDevice::writeData - CLIENT: Header written: %s", getpid(), displaybuf );#endif        m_skipWritten += QSXE_HEADER_LEN;    }    m_target->write( data, len );    bytes += len;#ifdef QTRANSPORTAUTH_DEBUG    int bytesToDisplay = bytes;    const unsigned char *dataptr = (const unsigned char *)data;    while ( bytesToDisplay > 0 )    {        int amt = bytes < 500 ? bytes : 500;        hexstring( displaybuf, dataptr, amt );        qDebug( "%d QAuthDevice::writeData - CLIENT: %s", getpid(), bytes > 0 ? displaybuf : "(null)" );        dataptr += 500;        bytesToDisplay -= 500;    }#endif    if ( m_target->inherits( "QAbstractSocket" ))        static_cast<QAbstractSocket*>(m_target)->flush();    return bytes;}/*!  Reimplement from QIODevice  Read data out of the internal message queue, reduce the queue by the amount  read.  Note that the amount available is only ever the size of a command  (although a command can be very big) since we need to check at command  boundaries for new authentication headers.*/qint64 QAuthDevice::readData( char *data, qint64 maxSize ){    if ( way == Send )  // client        return m_target->read( data, maxSize );    if ( msgQueue.size() == 0 )        return 0;#ifdef QTRANSPORTAUTH_DEBUG    char displaybuf[1024];    hexstring( displaybuf, reinterpret_cast<const unsigned char *>(msgQueue.constData()),            msgQueue.size() > 500 ? 500 : msgQueue.size() );    qDebug() << getpid() << "QAuthDevice::readData() buffered/requested/avail"            << msgQueue.size() << maxSize << m_bytesAvailable << displaybuf;#endif    Q_ASSERT( m_bytesAvailable <= msgQueue.size() );    qint64 bytes = ( maxSize > m_bytesAvailable ) ? m_bytesAvailable : maxSize;    ::memcpy( data, msgQueue.constData(), bytes );    msgQueue = msgQueue.mid( bytes );    m_bytesAvailable -= bytes;    return bytes;}/*!  \internal  Receive readyRead signal from the target recv device.  In response  authorize the data, and write results out to the recvBuf() device  for processing by the application.  Trigger the readyRead signal.  Authorizing involves first checking the transport is valid, ie the  handshake has either already been done and is cached on a trusted  transport, or was valid with this message; then second passing the  string representation of the service request up to any policyReceivers  If either of these fail, the message is denied.  In discovery mode  denied messages are allowed, but the message is logged.*/void QAuthDevice::recvReadyRead(){    qint64 bytes = m_target->bytesAvailable();    if ( bytes <= 0 ) return;    open( QIODevice::ReadWrite | QIODevice::Unbuffered );    QUnixSocket *usock = static_cast<QUnixSocket*>(m_target);    QUnixSocketMessage msg = usock->read();    msgQueue.append( msg.bytes() );    d->processId = msg.processId();    // if "fragmented" packet 1/2 way through start of a command, ie    // in the QWS msg type, cant do anything, come back later when    // there's more of the packet    if ( msgQueue.size() < (int)sizeof(int) )    {        // qDebug() << "returning: msg size too small" << msgQueue.size();        return;    }#ifdef QTRANSPORTAUTH_DEBUG    char displaybuf[1024];    hexstring( displaybuf, reinterpret_cast<const unsigned char *>(msgQueue.constData()),            msgQueue.size() > 500 ? 500 : msgQueue.size() );    qDebug( "%d ***** SERVER read %lli bytes - msg %s", getpid(), bytes, displaybuf );#endif    bool bufHasMessages = msgQueue.size() >= (int)sizeof(int);    while ( bufHasMessages )    {        unsigned char saveStatus = d->status;        if (( d->status & QTransportAuth::ErrMask ) == QTransportAuth::NoSuchKey )        {            QTransportAuth::getInstance()->authorizeRequest( *d, "NoSuchKey" );            break;        }        if ( !QTransportAuth::getInstance()->authFromMessage( *d, msgQueue, msgQueue.size() ))        {            // not all arrived yet?  come back later            if (( d->status & QTransportAuth::ErrMask ) == QTransportAuth::TooSmall )            {                d->status = saveStatus;                return;            }        }        if (( d->status & QTransportAuth::ErrMask ) == QTransportAuth::NoMagic )        {            // no msg auth header, don't change the success status for connections            if ( d->connection() )                d->status = saveStatus;        }        else        {            // msg auth header detected and auth determined, remove hdr            msgQueue = msgQueue.mid( QSXE_HEADER_LEN );        }        if ( !authorizeMessage() )            break;        bufHasMessages = msgQueue.size() >= (int)sizeof(int);    }}/**  \internal  Handle bytesWritten signals from the underlying target device.  We adjust the target's value for bytes that are part of auth packets.*/void QAuthDevice::targetBytesWritten( qint64 bytes ){    if ( m_skipWritten >= bytes ) {        m_skipWritten -= bytes;        bytes = 0;    } else if ( m_skipWritten > 0 ) {        bytes -= m_skipWritten;        m_skipWritten = 0;    }    if ( bytes > 0 ) {        emit bytesWritten( bytes );    }}/**  \internal  Pre-process the message to determine what QWS command it is.  This  information is used as the "request" for the purposes of authorization.  The request and other data on the connection (id, PID, etc.) are forwarded  to all policy listeners by emitting a signal.  The signal must be processed synchronously because on return the allow/deny  status is used immediately to either drop or continue processing the message.*/bool QAuthDevice::authorizeMessage(){    if ( analyzer == NULL )        analyzer = new RequestAnalyzer();    QString request = (*analyzer)( &msgQueue );    if ( analyzer->requireMoreData() )        return false;    bool isAuthorized = true;    if ( !request.isEmpty() && request != "Unknown" )    {        isAuthorized = QTransportAuth::getInstance()->authorizeRequest( *d, request );    }    bool moreToProcess = ( msgQueue.size() - analyzer->bytesAnalyzed() ) > (int)sizeof(int);    if ( isAuthorized )    {#ifdef QTRANSPORTAUTH_DEBUG        qDebug() << getpid() << "SERVER authorized: releasing" << analyzer->bytesAnalyzed() << "byte command" << request;#endif        m_bytesAvailable = analyzer->bytesAnalyzed();        emit QIODevice::readyRead();        return moreToProcess;    }    else    {        msgQueue = msgQueue.mid( analyzer->bytesAnalyzed() );    }    return true;}void QAuthDevice::setRequestAnalyzer( RequestAnalyzer *ra ){    Q_ASSERT( ra );    if ( analyzer )        delete analyzer;    analyzer = ra;}/*!  \internal   Add authentication header to the beginning of a message   Note that the per-process auth cookie is used.  This key should be rewritten in   the binary image of the executable at install time to make it unique.   For this to be secure some mechanism (eg MAC kernel or other   permissions) must prevent other processes from reading the key.

⌨️ 快捷键说明

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