Ignore:
Timestamp:
08/10/10 17:24:19 (18 months ago)
Author:
shiretu
Message:

-- common library refactoring

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/thelib/src/protocols/rtmp/inboundrtmpprotocol.cpp

    r2 r56  
    11/*  
    2 *  Copyright (c) 2010, 
    3 *  Gavriloaie Eugen-Andrei (shiretu@gmail.com) 
    4  
    5 *  This file is part of crtmpserver. 
    6 *  crtmpserver is free software: you can redistribute it and/or modify 
    7 *  it under the terms of the GNU General Public License as published by 
    8 *  the Free Software Foundation, either version 3 of the License, or 
    9 *  (at your option) any later version. 
    10  
    11 *  crtmpserver is distributed in the hope that it will be useful, 
    12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    14 *  GNU General Public License for more details. 
    15  
    16 *  You should have received a copy of the GNU General Public License 
    17 *  along with crtmpserver.  If not, see <http://www.gnu.org/licenses/>. 
    18 */ 
     2 *  Copyright (c) 2010, 
     3 *  Gavriloaie Eugen-Andrei (shiretu@gmail.com) 
     4 * 
     5 *  This file is part of crtmpserver. 
     6 *  crtmpserver is free software: you can redistribute it and/or modify 
     7 *  it under the terms of the GNU General Public License as published by 
     8 *  the Free Software Foundation, either version 3 of the License, or 
     9 *  (at your option) any later version. 
     10 * 
     11 *  crtmpserver is distributed in the hope that it will be useful, 
     12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
     13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     14 *  GNU General Public License for more details. 
     15 * 
     16 *  You should have received a copy of the GNU General Public License 
     17 *  along with crtmpserver.  If not, see <http://www.gnu.org/licenses/>. 
     18 */ 
    1919 
    2020#ifdef HAS_PROTOCOL_RTMP 
    2121#include "protocols/rtmp/inboundrtmpprotocol.h" 
    22 #include "buffering/iobuffer.h" 
    2322#include "protocols/rtmp/rtmpeprotocol.h" 
    2423#include "protocols/rtmp/basertmpappprotocolhandler.h" 
    25 #include "utils/crypto.h" 
    2624 
    2725InboundRTMPProtocol::InboundRTMPProtocol() 
    2826: BaseRTMPProtocol(PT_INBOUND_RTMP) { 
    29     _pKeyIn = NULL; 
    30     _pKeyOut = NULL; 
    31     _pOutputBuffer = NULL; 
    32     _currentFPVersion = 0; 
    33     _validationScheme = 0; 
     27        _pKeyIn = NULL; 
     28        _pKeyOut = NULL; 
     29        _pOutputBuffer = NULL; 
     30        _currentFPVersion = 0; 
     31        _validationScheme = 0; 
    3432} 
    3533 
    3634InboundRTMPProtocol::~InboundRTMPProtocol() { 
    37     if (_pKeyIn != NULL) { 
    38         delete _pKeyIn; 
    39         _pKeyIn = NULL; 
    40     } 
    41  
    42     if (_pKeyOut != NULL) { 
    43         delete _pKeyOut; 
    44         _pKeyOut = NULL; 
    45     } 
    46  
    47     if (_pOutputBuffer != NULL) { 
    48         delete[] _pOutputBuffer; 
    49         _pOutputBuffer = NULL; 
    50     } 
     35        if (_pKeyIn != NULL) { 
     36                delete _pKeyIn; 
     37                _pKeyIn = NULL; 
     38        } 
     39 
     40        if (_pKeyOut != NULL) { 
     41                delete _pKeyOut; 
     42                _pKeyOut = NULL; 
     43        } 
     44 
     45        if (_pOutputBuffer != NULL) { 
     46                delete[] _pOutputBuffer; 
     47                _pOutputBuffer = NULL; 
     48        } 
    5149} 
    5250 
    5351bool InboundRTMPProtocol::PerformHandshake(IOBuffer &buffer) { 
    54     switch (_rtmpState) { 
    55         case RTMP_STATE_NOT_INITIALIZED: 
    56         { 
    57             if (GETAVAILABLEBYTESCOUNT(buffer) < 1537) { 
    58                 //FINEST("Not enough data"); 
    59                 return true; 
    60             } 
    61             uint8_t handshakeType = GETIBPOINTER(buffer)[0]; 
    62             if (!buffer.Ignore(1)) { 
    63                 FATAL("Unable to ignore one byte"); 
    64                 return false; 
    65             } 
    66  
    67             _currentFPVersion = ntohl(*((uint32_t *) (GETIBPOINTER(buffer) + 4))); //----MARKED-LONG--- 
    68             //FINEST("Flash player: %s", STR(_currentFlashPlayerVersion)); 
    69  
    70             switch (handshakeType) { 
    71                 case 3: //plain 
    72                 { 
    73                     return PerformHandshake(buffer, false); 
    74                 } 
    75                 case 6: //encrypted 
    76                 { 
    77                     return PerformHandshake(buffer, true); 
    78                 } 
    79                 default: 
    80                 { 
    81                     FATAL("Handshake type not implemented: %d", handshakeType); 
    82                     return false; 
    83                 } 
    84             } 
    85         } 
    86         case RTMP_STATE_SERVER_RESPONSE_SENT: 
    87         { 
    88             //FINEST("I: Player request 2:\n%s", STR(*pInputBuffer)); 
    89             if (GETAVAILABLEBYTESCOUNT(buffer) < 1536) { 
    90                 return true; 
    91             } else { 
    92                 //ignore the client's last handshake part 
    93                 if (!buffer.Ignore(1536)) { 
    94                     FATAL("Unable to ignore inbound data"); 
    95                     return false; 
    96                 } 
    97                 _handshakeCompleted = true; 
    98                 _rtmpState = RTMP_STATE_DONE; 
    99  
    100                 if (_pKeyIn != NULL && _pKeyOut != NULL) { 
    101                     //insert the RTMPE protocol in the current protocol stack 
    102                     BaseProtocol *pFarProtocol = GetFarProtocol(); 
    103                     RTMPEProtocol *pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut); 
    104                     ResetFarProtocol(); 
    105                     pFarProtocol->SetNearProtocol(pRTMPE); 
    106                     pRTMPE->SetNearProtocol(this); 
    107                     FINEST("New protocol chain: %s", STR(*pFarProtocol)); 
    108  
    109                     //decrypt the leftovers 
    110                     RC4(_pKeyIn, GETAVAILABLEBYTESCOUNT(buffer), 
    111                             GETIBPOINTER(buffer), 
    112                             GETIBPOINTER(buffer)); 
    113                 } 
    114  
    115                 return true; 
    116             } 
    117         } 
    118         default: 
    119         { 
    120             FATAL("Invalid RTMP state: %d", _rtmpState); 
    121             return false; 
    122         } 
    123     } 
     52        switch (_rtmpState) { 
     53                case RTMP_STATE_NOT_INITIALIZED: 
     54                { 
     55                        if (GETAVAILABLEBYTESCOUNT(buffer) < 1537) { 
     56                                //FINEST("Not enough data"); 
     57                                return true; 
     58                        } 
     59                        uint8_t handshakeType = GETIBPOINTER(buffer)[0]; 
     60                        if (!buffer.Ignore(1)) { 
     61                                FATAL("Unable to ignore one byte"); 
     62                                return false; 
     63                        } 
     64 
     65                        _currentFPVersion = ntohl(*((uint32_t *) (GETIBPOINTER(buffer) + 4))); //----MARKED-LONG--- 
     66                        //FINEST("Flash player: %s", STR(_currentFlashPlayerVersion)); 
     67 
     68                        switch (handshakeType) { 
     69                                case 3: //plain 
     70                                { 
     71                                        return PerformHandshake(buffer, false); 
     72                                } 
     73                                case 6: //encrypted 
     74                                { 
     75                                        return PerformHandshake(buffer, true); 
     76                                } 
     77                                default: 
     78                                { 
     79                                        FATAL("Handshake type not implemented: %d", handshakeType); 
     80                                        return false; 
     81                                } 
     82                        } 
     83                } 
     84                case RTMP_STATE_SERVER_RESPONSE_SENT: 
     85                { 
     86                        //FINEST("I: Player request 2:\n%s", STR(*pInputBuffer)); 
     87                        if (GETAVAILABLEBYTESCOUNT(buffer) < 1536) { 
     88                                return true; 
     89                        } else { 
     90                                //ignore the client's last handshake part 
     91                                if (!buffer.Ignore(1536)) { 
     92                                        FATAL("Unable to ignore inbound data"); 
     93                                        return false; 
     94                                } 
     95                                _handshakeCompleted = true; 
     96                                _rtmpState = RTMP_STATE_DONE; 
     97 
     98                                if (_pKeyIn != NULL && _pKeyOut != NULL) { 
     99                                        //insert the RTMPE protocol in the current protocol stack 
     100                                        BaseProtocol *pFarProtocol = GetFarProtocol(); 
     101                                        RTMPEProtocol *pRTMPE = new RTMPEProtocol(_pKeyIn, _pKeyOut); 
     102                                        ResetFarProtocol(); 
     103                                        pFarProtocol->SetNearProtocol(pRTMPE); 
     104                                        pRTMPE->SetNearProtocol(this); 
     105                                        FINEST("New protocol chain: %s", STR(*pFarProtocol)); 
     106 
     107                                        //decrypt the leftovers 
     108                                        RC4(_pKeyIn, GETAVAILABLEBYTESCOUNT(buffer), 
     109                                                        GETIBPOINTER(buffer), 
     110                                                        GETIBPOINTER(buffer)); 
     111                                } 
     112 
     113                                return true; 
     114                        } 
     115                } 
     116                default: 
     117                { 
     118                        FATAL("Invalid RTMP state: %d", _rtmpState); 
     119                        return false; 
     120                } 
     121        } 
    124122} 
    125123 
    126124bool InboundRTMPProtocol::ValidateClient(IOBuffer &inputBuffer) { 
    127     if (_currentFPVersion == 0) { 
    128         WARN("This version of player doesn't support validation"); 
    129         return true; 
    130     } 
    131     if (ValidateClientScheme(inputBuffer, 0)) { 
    132         _validationScheme = 0; 
    133         return true; 
    134     } 
    135     if (ValidateClientScheme(inputBuffer, 1)) { 
    136         _validationScheme = 1; 
    137         return true; 
    138     } 
    139     FATAL("Unable to validate client"); 
    140     return false; 
     125        if (_currentFPVersion == 0) { 
     126                WARN("This version of player doesn't support validation"); 
     127                return true; 
     128        } 
     129        if (ValidateClientScheme(inputBuffer, 0)) { 
     130                _validationScheme = 0; 
     131                return true; 
     132        } 
     133        if (ValidateClientScheme(inputBuffer, 1)) { 
     134                _validationScheme = 1; 
     135                return true; 
     136        } 
     137        FATAL("Unable to validate client"); 
     138        return false; 
    141139} 
    142140 
    143141bool InboundRTMPProtocol::ValidateClientScheme(IOBuffer &inputBuffer, uint8_t scheme) { 
    144     uint8_t *pBuffer = GETIBPOINTER(inputBuffer); 
    145  
    146     uint32_t clientDigestOffset = GetDigestOffset(pBuffer, scheme); 
    147  
    148     uint8_t *pTempBuffer = new uint8_t[1536 - 32]; 
    149     memcpy(pTempBuffer, pBuffer, clientDigestOffset); 
    150     memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32, 
    151             1536 - clientDigestOffset - 32); 
    152  
    153     //uint8_t *pTempHash = new uint8_t[mhash_get_hash_pblock(MHASH_SHA256)]; 
    154     uint8_t *pTempHash = new uint8_t[512]; 
    155     HMACsha256(pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash); 
    156  
    157     bool result = true; 
    158     for (uint32_t i = 0; i < 32; i++) { 
    159         if (pBuffer[clientDigestOffset + i] != pTempHash[i]) { 
    160             result = false; 
    161             break; 
    162         } 
    163     } 
    164  
    165     delete[] pTempBuffer; 
    166     delete[] pTempHash; 
    167  
    168     return result; 
     142        uint8_t *pBuffer = GETIBPOINTER(inputBuffer); 
     143 
     144        uint32_t clientDigestOffset = GetDigestOffset(pBuffer, scheme); 
     145 
     146        uint8_t *pTempBuffer = new uint8_t[1536 - 32]; 
     147        memcpy(pTempBuffer, pBuffer, clientDigestOffset); 
     148        memcpy(pTempBuffer + clientDigestOffset, pBuffer + clientDigestOffset + 32, 
     149                        1536 - clientDigestOffset - 32); 
     150 
     151        //uint8_t *pTempHash = new uint8_t[mhash_get_hash_pblock(MHASH_SHA256)]; 
     152        uint8_t *pTempHash = new uint8_t[512]; 
     153        HMACsha256(pTempBuffer, 1536 - 32, genuineFPKey, 30, pTempHash); 
     154 
     155        bool result = true; 
     156        for (uint32_t i = 0; i < 32; i++) { 
     157                if (pBuffer[clientDigestOffset + i] != pTempHash[i]) { 
     158                        result = false; 
     159                        break; 
     160                } 
     161        } 
     162 
     163        delete[] pTempBuffer; 
     164        delete[] pTempHash; 
     165 
     166        return result; 
    169167} 
    170168 
    171169bool InboundRTMPProtocol::PerformHandshake(IOBuffer &buffer, bool encrypted) { 
    172     if (encrypted || _pProtocolHandler->ValidateHandshake()) { 
    173         if (!ValidateClient(buffer)) { 
    174             FATAL("Unable to validate client"); 
    175             return false; 
    176         } 
    177     } 
    178  
    179     //get the buffers 
    180     uint8_t *pInputBuffer = GETIBPOINTER(buffer); 
    181     if (_pOutputBuffer == NULL) { 
    182         _pOutputBuffer = new uint8_t[3072]; 
    183     } else { 
    184         delete[] _pOutputBuffer; 
    185         _pOutputBuffer = new uint8_t[3072]; 
    186     } 
    187  
    188     //timestamp 
    189     *(uint32_t *) _pOutputBuffer = 0; 
    190  
    191     //version 
    192     *(uint32_t *) (_pOutputBuffer + 4) = htonl(0x01020304); //----MARKED-LONG--- 
    193  
    194     //generate random data 
    195     srand((uint32_t) time(NULL)); 
    196     for (uint32_t i = 8; i < 3072; i++) { 
    197         _pOutputBuffer[i] = rand() % 256; 
    198     } 
    199     for (uint32_t i = 0; i < 10; i++) { 
    200         uint32_t index = rand() % (3072 - HTTP_HEADERS_SERVER_US_LEN); 
    201         memcpy(_pOutputBuffer + index, HTTP_HEADERS_SERVER_US, HTTP_HEADERS_SERVER_US_LEN); 
    202     } 
    203  
    204     //**** FIRST 1536 bytes from server response ****// 
    205     //compute DH key position 
    206     uint32_t serverDHOffset = GetDHOffset(_pOutputBuffer, _validationScheme); 
    207     uint32_t clientDHOffset = GetDHOffset(pInputBuffer, _validationScheme); 
    208     //FINEST("serverDHOffset: %u", serverDHOffset); 
    209  
    210     //generate DH key 
    211     DHWrapper dhWrapper(1024); 
    212  
    213     if (!dhWrapper.Initialize()) { 
    214         FATAL("Unable to initialize DH wrapper"); 
    215         return false; 
    216     } 
    217  
    218     if (!dhWrapper.CreateSharedKey(pInputBuffer + clientDHOffset, 128)) { 
    219         FATAL("Unable to create shared key"); 
    220         return false; 
    221     } 
    222  
    223     if (!dhWrapper.CopyPublicKey(_pOutputBuffer + serverDHOffset, 128)) { 
    224         FATAL("Couldn't write public key!"); 
    225         return false; 
    226     } 
    227  
    228     if (encrypted) { 
    229         uint8_t secretKey[128]; 
    230         if (!dhWrapper.CopySharedKey(secretKey, sizeof (secretKey))) { 
    231             FATAL("Unable to copy shared key"); 
    232             return false; 
    233         } 
    234  
    235         _pKeyIn = new RC4_KEY; 
    236         _pKeyOut = new RC4_KEY; 
    237         InitRC4Encryption( 
    238                 secretKey, 
    239                 (uint8_t*) & pInputBuffer[clientDHOffset], 
    240                 (uint8_t*) & _pOutputBuffer[serverDHOffset], 
    241                 _pKeyIn, 
    242                 _pKeyOut); 
    243  
    244         //bring the keys to correct cursor 
    245         uint8_t data[1536]; 
    246         RC4(_pKeyIn, 1536, data, data); 
    247         RC4(_pKeyOut, 1536, data, data); 
    248     } 
    249  
    250     //generate the digest 
    251     uint32_t serverDigestOffset = GetDigestOffset(_pOutputBuffer, _validationScheme); 
    252     //FINEST("serverDigestOffset: %u", serverDigestOffset); 
    253  
    254     uint8_t *pTempBuffer = new uint8_t[1536 - 32]; 
    255     memcpy(pTempBuffer, _pOutputBuffer, serverDigestOffset); 
    256     memcpy(pTempBuffer + serverDigestOffset, _pOutputBuffer + serverDigestOffset + 32, 
    257             1536 - serverDigestOffset - 32); 
    258  
    259     uint8_t *pTempHash = new uint8_t[512]; 
    260     HMACsha256(pTempBuffer, 1536 - 32, genuineFMSKey, 36, pTempHash); 
    261  
    262     //put the digest in place 
    263     memcpy(_pOutputBuffer + serverDigestOffset, pTempHash, 32); 
    264  
    265     //cleanup 
    266     delete[] pTempBuffer; 
    267     delete[] pTempHash; 
    268  
    269  
    270     //**** SECOND 1536 bytes from server response ****// 
    271     //Compute the chalange index from the initial client request 
    272     uint32_t keyChallengeIndex = GetDigestOffset(pInputBuffer, _validationScheme); 
    273     //FINEST("keyChallengeIndex: %u", keyChallengeIndex); 
    274  
    275     //compute the key 
    276     pTempHash = new uint8_t[512]; 
    277     HMACsha256(pInputBuffer + keyChallengeIndex, //pData 
    278             32, //dataLength 
    279             BaseRTMPProtocol::genuineFMSKey, //key 
    280             68, //keyLength 
    281             pTempHash //pResult 
    282             ); 
    283  
    284     //generate the hash 
    285     uint8_t *pLastHash = new uint8_t[512]; 
    286     HMACsha256(_pOutputBuffer + 1536, //pData 
    287             1536 - 32, //dataLength 
    288             pTempHash, //key 
    289             32, //keyLength 
    290             pLastHash //pResult 
    291             ); 
    292  
    293     //put the hash where it belongs 
    294     memcpy(_pOutputBuffer + 1536 * 2 - 32, pLastHash, 32); 
    295  
    296  
    297     //cleanup 
    298     delete[] pTempHash; 
    299     delete[] pLastHash; 
    300     //***** DONE BUILDING THE RESPONSE ***// 
    301  
    302  
    303     //wire the response 
    304     if (encrypted) 
    305         _outputBuffer.ReadFromByte(6); 
    306     else 
    307         _outputBuffer.ReadFromByte(3); 
    308     _outputBuffer.ReadFromBuffer(_pOutputBuffer, 3072); 
    309  
    310     //final cleanup 
    311     delete[] _pOutputBuffer; 
    312     _pOutputBuffer = NULL; 
    313     if (!buffer.IgnoreAll()) { 
    314         FATAL("Unable to ignore input buffer"); 
    315         return false; 
    316     } 
    317  
    318     //signal outbound data 
    319     if (!EnqueueForOutbound()) { 
    320         FATAL("Unable to signal outbound data"); 
    321         return false; 
    322     } 
    323  
    324     //move to the next stage in the handshake 
    325     _rtmpState = RTMP_STATE_SERVER_RESPONSE_SENT; 
    326  
    327     return true; 
     170        if (encrypted || _pProtocolHandler->ValidateHandshake()) { 
     171                if (!ValidateClient(buffer)) { 
     172                        FATAL("Unable to validate client"); 
     173                        return false; 
     174                } 
     175        } 
     176 
     177        //get the buffers 
     178        uint8_t *pInputBuffer = GETIBPOINTER(buffer); 
     179        if (_pOutputBuffer == NULL) { 
     180                _pOutputBuffer = new uint8_t[3072]; 
     181        } else { 
     182                delete[] _pOutputBuffer; 
     183                _pOutputBuffer = new uint8_t[3072]; 
     184        } 
     185 
     186        //timestamp 
     187        *(uint32_t *) _pOutputBuffer = 0; 
     188 
     189        //version 
     190        *(uint32_t *) (_pOutputBuffer + 4) = htonl(0x01020304); //----MARKED-LONG--- 
     191 
     192        //generate random data 
     193        srand((uint32_t) time(NULL)); 
     194        for (uint32_t i = 8; i < 3072; i++) { 
     195                _pOutputBuffer[i] = rand() % 256; 
     196        } 
     197        for (uint32_t i = 0; i < 10; i++) { 
     198                uint32_t index = rand() % (3072 - HTTP_HEADERS_SERVER_US_LEN); 
     199                memcpy(_pOutputBuffer + index, HTTP_HEADERS_SERVER_US, HTTP_HEADERS_SERVER_US_LEN); 
     200        } 
     201 
     202        //**** FIRST 1536 bytes from server response ****// 
     203        //compute DH key position 
     204        uint32_t serverDHOffset = GetDHOffset(_pOutputBuffer, _validationScheme); 
     205        uint32_t clientDHOffset = GetDHOffset(pInputBuffer, _validationScheme); 
     206        //FINEST("serverDHOffset: %u", serverDHOffset); 
     207 
     208        //generate DH key 
     209        DHWrapper dhWrapper(1024); 
     210 
     211        if (!dhWrapper.Initialize()) { 
     212                FATAL("Unable to initialize DH wrapper"); 
     213                return false; 
     214        } 
     215 
     216        if (!dhWrapper.CreateSharedKey(pInputBuffer + clientDHOffset, 128)) { 
     217                FATAL("Unable to create shared key"); 
     218                return false; 
     219        } 
     220 
     221        if (!dhWrapper.CopyPublicKey(_pOutputBuffer + serverDHOffset, 128)) { 
     222                FATAL("Couldn't write public key!"); 
     223                return false; 
     224        } 
     225 
     226        if (encrypted) { 
     227                uint8_t secretKey[128]; 
     228                if (!dhWrapper.CopySharedKey(secretKey, sizeof (secretKey))) { 
     229                        FATAL("Unable to copy shared key"); 
     230                        return false; 
     231                } 
     232 
     233                _pKeyIn = new RC4_KEY; 
     234                _pKeyOut = new RC4_KEY; 
     235                InitRC4Encryption( 
     236                                secretKey, 
     237                                (uint8_t*) & pInputBuffer[clientDHOffset], 
     238                                (uint8_t*) & _pOutputBuffer[serverDHOffset], 
     239                                _pKeyIn, 
     240                                _pKeyOut); 
     241 
     242                //bring the keys to correct cursor 
     243                uint8_t data[1536]; 
     244                RC4(_pKeyIn, 1536, data, data); 
     245                RC4(_pKeyOut, 1536, data, data); 
     246        } 
     247 
     248        //generate the digest 
     249        uint32_t serverDigestOffset = GetDigestOffset(_pOutputBuffer, _validationScheme); 
     250        //FINEST("serverDigestOffset: %u", serverDigestOffset); 
     251 
     252        uint8_t *pTempBuffer = new uint8_t[1536 - 32]; 
     253        memcpy(pTempBuffer, _pOutputBuffer, serverDigestOffset); 
     254        memcpy(pTempBuffer + serverDigestOffset, _pOutputBuffer + serverDigestOffset + 32, 
     255                        1536 - serverDigestOffset - 32); 
     256 
     257        uint8_t *pTempHash = new uint8_t[512]; 
     258        HMACsha256(pTempBuffer, 1536 - 32, genuineFMSKey, 36, pTempHash); 
     259 
     260        //put the digest in place 
     261        memcpy(_pOutputBuffer + serverDigestOffset, pTempHash, 32); 
     262 
     263        //cleanup 
     264        delete[] pTempBuffer; 
     265        delete[] pTempHash; 
     266 
     267 
     268        //**** SECOND 1536 bytes from server response ****// 
     269        //Compute the chalange index from the initial client request 
     270        uint32_t keyChallengeIndex = GetDigestOffset(pInputBuffer, _validationScheme); 
     271        //FINEST("keyChallengeIndex: %u", keyChallengeIndex); 
     272 
     273        //compute the key 
     274        pTempHash = new uint8_t[512]; 
     275        HMACsha256(pInputBuffer + keyChallengeIndex, //pData 
     276                        32, //dataLength 
     277                        BaseRTMPProtocol::genuineFMSKey, //key 
     278                        68, //keyLength 
     279                        pTempHash //pResult 
     280                        ); 
     281 
     282        //generate the hash 
     283        uint8_t *pLastHash = new uint8_t[512]; 
     284        HMACsha256(_pOutputBuffer + 1536, //pData 
     285                        1536 - 32, //dataLength 
     286                        pTempHash, //key 
     287                        32, //keyLength 
     288                        pLastHash //pResult 
     289                        ); 
     290 
     291        //put the hash where it belongs 
     292        memcpy(_pOutputBuffer + 1536 * 2 - 32, pLastHash, 32); 
     293 
     294 
     295        //cleanup 
     296        delete[] pTempHash; 
     297        delete[] pLastHash; 
     298        //***** DONE BUILDING THE RESPONSE ***// 
     299 
     300 
     301        //wire the response 
     302        if (encrypted) 
     303                _outputBuffer.ReadFromByte(6); 
     304        else 
     305                _outputBuffer.ReadFromByte(3); 
     306        _outputBuffer.ReadFromBuffer(_pOutputBuffer, 3072); 
     307 
     308        //final cleanup 
     309        delete[] _pOutputBuffer; 
     310        _pOutputBuffer = NULL; 
     311        if (!buffer.IgnoreAll()) { 
     312                FATAL("Unable to ignore input buffer"); 
     313                return false; 
     314        } 
     315 
     316        //signal outbound data 
     317        if (!EnqueueForOutbound()) { 
     318                FATAL("Unable to signal outbound data"); 
     319                return false; 
     320        } 
     321 
     322        //move to the next stage in the handshake 
     323        _rtmpState = RTMP_STATE_SERVER_RESPONSE_SENT; 
     324 
     325        return true; 
    328326} 
    329327 
Note: See TracChangeset for help on using the changeset viewer.