00001
00002
00003 #include "SSLv2.h"
00004 #include "SSLv3.h"
00005
00006
00007
00008 uint SSLv2_Interpreter::totalConnections = 0;
00009 uint SSLv2_Interpreter::analyzedConnections = 0;
00010 uint SSLv2_Interpreter::openedConnections = 0;
00011 uint SSLv2_Interpreter::failedConnections = 0;
00012 uint SSLv2_Interpreter::weirdConnections = 0;
00013 uint SSLv2_Interpreter::totalRecords = 0;
00014 uint SSLv2_Interpreter::clientHelloRecords = 0;
00015 uint SSLv2_Interpreter::serverHelloRecords = 0;
00016 uint SSLv2_Interpreter::clientMasterKeyRecords = 0;
00017 uint SSLv2_Interpreter::errorRecords = 0;
00018
00019
00020
00021
00027 SSLv2_Interpreter::SSLv2_Interpreter(SSL_ConnectionProxy* proxy)
00028 : SSL_Interpreter(proxy)
00029 {
00030 ++totalConnections;
00031 records = 0;
00032 bAnalyzedCounted = false;
00033 connState = START;
00034
00035 pServerCipherSpecs = 0;
00036 pClientCipherSpecs = 0;
00037 bClientWantsCachedSession = false;
00038 usedCipherSpec = (SSLv2_CipherSpec) 0;
00039
00040 pConnectionId = 0;
00041 pChallenge = 0;
00042 pSessionId = 0;
00043 pMasterClearKey = 0;
00044 pMasterEncryptedKey = 0;
00045 pClientReadKey = 0;
00046 pServerReadKey = 0;
00047 }
00048
00052 SSLv2_Interpreter::~SSLv2_Interpreter()
00053 {
00054 if ( connState != CLIENT_MASTERKEY_SEEN &&
00055 connState != CACHED_SESSION &&
00056 connState != START &&
00057 connState != ERROR_SEEN )
00058 ++failedConnections;
00059
00060 if ( connState != CLIENT_MASTERKEY_SEEN && connState != CACHED_SESSION )
00061 ++weirdConnections;
00062
00063 delete pServerCipherSpecs;
00064 delete pClientCipherSpecs;
00065 delete pConnectionId;
00066 delete pChallenge;
00067 delete pSessionId;
00068 delete pMasterClearKey;
00069 delete pMasterEncryptedKey;
00070 delete pClientReadKey;
00071 delete pServerReadKey;
00072 }
00073
00077 void SSLv2_Interpreter::BuildInterpreterEndpoints()
00078 {
00079 orig = new SSLv2_Endpoint(this, 1);
00080 resp = new SSLv2_Endpoint(this, 0);
00081 }
00082
00086 void SSLv2_Interpreter::printStats()
00087 {
00088 printf("SSLv2:\n");
00089 printf("totalConnections = %u\n", totalConnections);
00090 printf("analyzedConnections = %u\n", analyzedConnections);
00091 printf("openedConnections = %u\n", openedConnections);
00092 printf("failedConnections = %u\n", failedConnections);
00093 printf("weirdConnections = %u\n", weirdConnections);
00094
00095 printf("totalRecords = %u\n", totalRecords);
00096 printf("clientHelloRecords = %u\n", clientHelloRecords);
00097 printf("serverHelloRecords = %u\n", serverHelloRecords);
00098 printf("clientMasterKeyRecords = %u\n", clientMasterKeyRecords);
00099 printf("errorRecords = %u\n", errorRecords);
00100
00101 printf("SSL_RecordBuilder::maxAllocCount = %u\n", SSL_RecordBuilder::maxAllocCount);
00102 printf("SSL_RecordBuilder::maxFragmentCount = %u\n", SSL_RecordBuilder::maxFragmentCount);
00103 printf("SSL_RecordBuilder::fragmentedHeaders = %u\n", SSL_RecordBuilder::fragmentedHeaders);
00104 }
00105
00109 SSLv2_States SSLv2_Interpreter::ConnState()
00110 {
00111 return connState;
00112 }
00113
00124 void SSLv2_Interpreter::NewSSLRecord(SSL_InterpreterEndpoint* s,
00125 int length, u_char* data)
00126 {
00127 ++records;
00128 ++totalRecords;
00129
00130 if ( ! bAnalyzedCounted )
00131 {
00132 ++analyzedConnections;
00133 bAnalyzedCounted = true;
00134 }
00135
00136
00137 if ( records == 5 )
00138 {
00139 Weird("SSLv2: Saw more than 4 records, skipping connection...");
00140 proxy->SetSkip(1);
00141 return;
00142 }
00143
00144
00145 uint32 recordLength = 0;
00146 bool isEscape = false;
00147 uint8 padding = 0;
00148 u_char* contents;
00149
00150 if ( (data[0] & 0x80) > 0 )
00151 {
00152 recordLength = ((data[0] & 0x7f) << 8) | data[1];
00153 contents = data + 2;
00154 if ( recordLength + 2 != uint32(length) )
00155 {
00156
00157
00158 Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
00159 connState = ERROR_REQUIRED;
00160 proxy->SetSkip(1);
00161 return;
00162 }
00163 }
00164 else
00165 {
00166 recordLength = ((data[0] & 0x3f) << 8) | data[1];
00167 isEscape = (data[0] & 0x40) != 0;
00168 padding = data[2];
00169 contents = data + 3;
00170 if ( recordLength + 3 != uint32(length) )
00171 {
00172
00173
00174 Weird("SSLv2: FATAL: recordLength doesn't match data block length!");
00175 connState = ERROR_REQUIRED;
00176 proxy->SetSkip(1);
00177 return;
00178 }
00179
00180 if ( padding == 0 && ! isEscape )
00181 Weird("SSLv2: 3 Byte record header, but no escape, no padding!");
00182 }
00183
00184 if ( recordLength == 0 )
00185 {
00186 Weird("SSLv2: Record length is zero (no record data)!");
00187 return;
00188 }
00189
00190 if ( isEscape )
00191 Weird("SSLv2: Record has escape bit set (security escape)!");
00192
00193 if ( padding > 0 && connState != CACHED_SESSION &&
00194 connState != CLIENT_MASTERKEY_SEEN )
00195 Weird("SSLv2 record with padding > 0 in cleartext!");
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 switch ( connState ) {
00207 case START:
00208
00209 if ( contents[0] != SSLv2_MT_CLIENT_HELLO )
00210 {
00211 Weird("SSLv2: First packet is not a CLIENT-HELLO!");
00212 analyzeRecord(s, recordLength, contents);
00213 connState = ERROR_REQUIRED;
00214 }
00215 else
00216 connState = ClientHelloRecord(s, recordLength, contents);
00217 break;
00218
00219 case CLIENT_HELLO_SEEN:
00220
00221 if ( contents[0] == SSLv2_MT_SERVER_HELLO )
00222 connState = ServerHelloRecord(s, recordLength, contents);
00223 else if ( contents[0] == SSLv2_MT_ERROR )
00224 connState = ErrorRecord(s, recordLength, contents);
00225 else
00226 {
00227 Weird("SSLv2: State violation in CLIENT_HELLO_SEEN!");
00228 analyzeRecord(s, recordLength, contents);
00229 connState = ERROR_REQUIRED;
00230 }
00231 break;
00232
00233 case NEW_SESSION:
00234
00235 if ( contents[0] == SSLv2_MT_CLIENT_MASTER_KEY )
00236 connState = ClientMasterKeyRecord(s, recordLength, contents);
00237 else if ( contents[0] == SSLv2_MT_ERROR )
00238 connState = ErrorRecord(s, recordLength, contents);
00239 else
00240 {
00241 Weird("SSLv2: State violation in NEW_SESSION or encrypted record!");
00242 analyzeRecord(s, recordLength, contents);
00243 connState = ERROR_REQUIRED;
00244 }
00245
00246 delete pServerCipherSpecs;
00247 pServerCipherSpecs = 0;
00248 break;
00249
00250 case CACHED_SESSION:
00251 delete pServerCipherSpecs;
00252 pServerCipherSpecs = 0;
00253
00254
00255 case CLIENT_MASTERKEY_SEEN:
00256
00257 if ( contents[0] == SSLv2_MT_ERROR &&
00258 recordLength == SSLv2_ERROR_RECORD_SIZE )
00259 connState = ErrorRecord(s, recordLength, contents);
00260 else
00261 {
00262
00263
00264
00265 proxy->SetSkip(1);
00266 ++openedConnections;
00267 }
00268 break;
00269
00270 case ERROR_REQUIRED:
00271 if ( contents[0] == SSLv2_MT_ERROR )
00272 connState = ErrorRecord(s, recordLength, contents);
00273 else
00274 {
00275
00276 Weird("SSLv2: State inconsistency in ERROR_REQUIRED (lost tracking!)!");
00277 analyzeRecord(s, recordLength, contents);
00278 connState = ERROR_REQUIRED;
00279 }
00280 break;
00281
00282 case ERROR_SEEN:
00283
00284
00285 Weird("SSLv2: Traffic after error record!");
00286 analyzeRecord(s, recordLength, contents);
00287 break;
00288
00289 default:
00290 internal_error("SSLv2: unknown state");
00291 break;
00292 }
00293 }
00294
00304 void SSLv2_Interpreter::analyzeRecord(SSL_InterpreterEndpoint* s,
00305 int length, u_char* data)
00306 {
00307 switch ( data[0] ) {
00308 case SSLv2_MT_ERROR:
00309 ErrorRecord(s, length, data);
00310 break;
00311
00312 case SSLv2_MT_CLIENT_HELLO:
00313 ClientHelloRecord(s, length, data);
00314 break;
00315
00316 case SSLv2_MT_CLIENT_MASTER_KEY:
00317 ClientMasterKeyRecord(s, length, data);
00318 break;
00319
00320 case SSLv2_MT_SERVER_HELLO:
00321 ServerHelloRecord(s, length, data);
00322 break;
00323
00324 case SSLv2_MT_CLIENT_FINISHED:
00325 case SSLv2_MT_SERVER_VERIFY:
00326 case SSLv2_MT_SERVER_FINISHED:
00327 case SSLv2_MT_REQUEST_CERTIFICATE:
00328 case SSLv2_MT_CLIENT_CERTIFICATE:
00329 Weird("SSLv2: Encrypted record type seems to be in cleartext");
00330 break;
00331
00332 default:
00333
00334 Weird("SSLv2: Unknown record type or encrypted record");
00335 break;
00336 }
00337 }
00338
00348 SSLv2_States SSLv2_Interpreter::ClientHelloRecord(SSL_InterpreterEndpoint* s,
00349 int recordLength, u_char* recordData)
00350 {
00351
00352 ++clientHelloRecords;
00353
00354 if ( s != orig )
00355 Weird("SSLv2: CLIENT-HELLO record from server!");
00356
00357
00358
00359 if ( ((SSLv2_Endpoint*) s)->isDataPending() )
00360 Weird("SSLv2: Pending data in SSL_RecordBuilder after CLIENT-HELLO!");
00361
00362
00363 if ( recordLength < SSLv2_CLIENT_HELLO_HEADER_SIZE )
00364 {
00365 Weird("SSLv2: CLIENT-HELLO is too small!");
00366 return ERROR_REQUIRED;
00367 }
00368
00369
00370 SSLv2_ClientHelloHeader ch;
00371 ch.clientVersion = uint16(recordData[1] << 8) | recordData[2];
00372 ch.cipherSpecLength = uint16(recordData[3] << 8) | recordData[4];
00373 ch.sessionIdLength = uint16(recordData[5] << 8) | recordData[6];
00374 ch.challengeLength = uint16(recordData[7] << 8) | recordData[8];
00375
00376 if ( ch.clientVersion != SSL_ConnectionProxy::SSLv20 &&
00377 ch.clientVersion != SSL_ConnectionProxy::SSLv30 &&
00378 ch.clientVersion != SSL_ConnectionProxy::SSLv31 )
00379 {
00380 Weird("SSLv2: Unsupported SSL-Version in CLIENT-HELLO");
00381 return ERROR_REQUIRED;
00382 }
00383
00384 if ( ch.challengeLength + ch.cipherSpecLength + ch.sessionIdLength +
00385 SSLv2_CLIENT_HELLO_HEADER_SIZE != recordLength )
00386 {
00387 Weird("SSLv2: Size inconsistency in CLIENT-HELLO");
00388 return ERROR_REQUIRED;
00389 }
00390
00391
00392 if ( ch.cipherSpecLength == 0 || ch.cipherSpecLength % 3 != 0 )
00393 {
00394 Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in CLIENT-HELLO.");
00395 return ERROR_REQUIRED;
00396 }
00397
00398
00399 if ( ch.sessionIdLength != 0 && ch.sessionIdLength != 16 )
00400 Weird("SSLv2: Nonconform SESSION-ID-LENGTH in CLIENT-HELLO.");
00401
00402 if ( (ch.challengeLength < 16) || (ch.challengeLength > 32))
00403 Weird("SSLv2: Nonconform CHALLENGE-LENGTH in CLIENT-HELLO.");
00404
00405 u_char* ptr = recordData;
00406 ptr += SSLv2_CLIENT_HELLO_HEADER_SIZE + ch.cipherSpecLength;
00407
00408 pSessionId = new SSL_DataBlock(ptr, ch.sessionIdLength);
00409
00410
00411 if ( ssl_store_key_material && ch.challengeLength <= 32 )
00412 pChallenge = new SSL_DataBlock(ptr, ch.challengeLength);
00413
00414 bClientWantsCachedSession = ch.sessionIdLength != 0;
00415
00416 TableVal* currentCipherSuites =
00417 analyzeCiphers(s, ch.cipherSpecLength,
00418 recordData + SSLv2_CLIENT_HELLO_HEADER_SIZE);
00419
00420 fire_ssl_conn_attempt(ch.clientVersion, currentCipherSuites);
00421
00422 return CLIENT_HELLO_SEEN;
00423 }
00424
00434 SSLv2_States SSLv2_Interpreter::ServerHelloRecord(SSL_InterpreterEndpoint* s,
00435 int recordLength, u_char* recordData)
00436 {
00437 ++serverHelloRecords;
00438 TableVal* currentCipherSuites = NULL;
00439
00440 if ( s != resp )
00441 Weird("SSLv2: SERVER-HELLO from client!");
00442
00443 if ( recordLength < SSLv2_SERVER_HELLO_HEADER_SIZE )
00444 {
00445 Weird("SSLv2: SERVER-HELLO is too small!");
00446 return ERROR_REQUIRED;
00447 }
00448
00449
00450 SSLv2_ServerHelloHeader sh;
00451 sh.sessionIdHit = recordData[1];
00452 sh.certificateType = recordData[2];
00453 sh.serverVersion = uint16(recordData[3] << 8) | recordData[4];
00454 sh.certificateLength = uint16(recordData[5] << 8) | recordData[6];
00455 sh.cipherSpecLength = uint16(recordData[7] << 8) | recordData[8];
00456 sh.connectionIdLength = uint16(recordData[9] << 8) | recordData[10];
00457
00458 if ( sh.serverVersion != SSL_ConnectionProxy::SSLv20 )
00459 {
00460 Weird("SSLv2: Unsupported SSL-Version in SERVER-HELLO");
00461 return ERROR_REQUIRED;
00462 }
00463
00464 if ( sh.certificateLength + sh.cipherSpecLength +
00465 sh.connectionIdLength +
00466 SSLv2_SERVER_HELLO_HEADER_SIZE != recordLength )
00467 {
00468 Weird("SSLv2: Size inconsistency in SERVER-HELLO");
00469 return ERROR_REQUIRED;
00470 }
00471
00472
00473 if ( sh.connectionIdLength < 16 || sh.connectionIdLength > 32 )
00474 Weird("SSLv2: Nonconform CONNECTION-ID-LENGTH in SERVER-HELLO");
00475
00476
00477 if ( ssl_store_key_material && sh.connectionIdLength <= 32 )
00478 {
00479 u_char* ptr = recordData;
00480
00481 ptr += SSLv2_SERVER_HELLO_HEADER_SIZE + sh.cipherSpecLength +
00482 sh.certificateLength;
00483
00484 pConnectionId = new SSL_DataBlock(ptr, sh.connectionIdLength);
00485 }
00486
00487 if (sh.sessionIdHit == 0 )
00488 {
00489
00490 EventHandlerPtr event = ssl_session_insertion;
00491
00492 if ( event )
00493 {
00494 TableVal* sessionIDTable = new TableVal(SSL_sessionID);
00495 u_char* ptr = recordData;
00496 ptr += SSLv2_SERVER_HELLO_HEADER_SIZE +
00497 sh.certificateLength + sh.cipherSpecLength;
00498
00499 for ( int i = 0; i < sh.connectionIdLength; i += 4 )
00500 {
00501 uint32 temp =
00502 (((ptr[i] << 24) |
00503 ptr[i + 1] << 16) |
00504 ptr[i + 2] << 8) | ptr[i + 3];
00505 sessionIDTable->Assign(
00506 new Val(i / 4, TYPE_COUNT),
00507 new Val(temp, TYPE_COUNT));
00508 }
00509
00510 val_list* vl = new val_list;
00511 vl->append(proxy->BuildConnVal());
00512 vl->append(sessionIDTable);
00513
00514 proxy->ConnectionEvent(ssl_session_insertion, vl);
00515 }
00516 }
00517
00518 SSLv2_States nextState;
00519
00520 if ( sh.sessionIdHit != 0 )
00521 {
00522
00523
00524
00525
00526 if ( ((SSLv2_Endpoint*) s)->isDataPending() )
00527 {
00528
00529
00530 }
00531
00532
00533 if ( ! bClientWantsCachedSession )
00534 Weird("SSLv2: SESSION-ID hit in SERVER-HELLO, but no SESSION-ID in CLIENT-HELLO!");
00535
00536
00537
00538
00539 if ( sh.certificateType != 0 || sh.certificateLength != 0 ||
00540 sh.cipherSpecLength != 0 )
00541 Weird("SSLv2: SESSION-ID-HIT, but session data in SERVER-HELLO");
00542
00543
00544 if ( pSessionId )
00545 {
00546 fire_ssl_conn_reused(pSessionId);
00547 delete pSessionId;
00548 pSessionId = 0;
00549 }
00550
00551 nextState = CACHED_SESSION;
00552 }
00553 else
00554 {
00555
00556
00557
00558
00559 if ( ((SSLv2_Endpoint*) s)->isDataPending() )
00560 Weird("SSLv2: Pending data in SSL_RecordBuilder after SERVER-HELLO (new session)!");
00561
00562
00563 if ( sh.certificateLength == 0 )
00564 Weird("SSLv2: No certificate in SERVER-HELLO!");
00565
00566
00567 if ( sh.cipherSpecLength == 0 )
00568 Weird("SSLv2: No CIPHER-SPECS in SERVER-HELLO!");
00569
00570 if ( sh.cipherSpecLength % 3 != 0 )
00571 {
00572 Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in SERVER-HELLO");
00573 return ERROR_REQUIRED;
00574 }
00575
00576 u_char* ptr = recordData;
00577 ptr += sh.certificateLength + SSLv2_SERVER_HELLO_HEADER_SIZE;
00578 currentCipherSuites = analyzeCiphers(s, sh.cipherSpecLength, ptr);
00579
00580 nextState = NEW_SESSION;
00581 }
00582
00583
00584 if ( pClientCipherSpecs && pServerCipherSpecs )
00585 {
00586 bool bFound = false;
00587 for ( int i = 0; i < pClientCipherSpecs->len; i += 3 )
00588 {
00589 for ( int j = 0; j < pServerCipherSpecs->len; j += 3 )
00590 {
00591 if ( memcmp(pClientCipherSpecs + i,
00592 pServerCipherSpecs + j, 3) == 0 )
00593 {
00594 bFound = true;
00595 i = pClientCipherSpecs->len;
00596 break;
00597 }
00598 }
00599 }
00600
00601 if ( ! bFound )
00602 {
00603 Weird("SSLv2: Client's and server's CIPHER-SPECS don't match!");
00604 nextState = ERROR_REQUIRED;
00605 }
00606
00607 delete pClientCipherSpecs;
00608 pClientCipherSpecs = 0;
00609 }
00610
00611
00612 if ( sh.certificateLength > 0 && ssl_analyze_certificates != 0 )
00613 {
00614 analyzeCertificate(s, recordData + SSLv2_SERVER_HELLO_HEADER_SIZE,
00615 sh.certificateLength, sh.certificateType, false);
00616 }
00617
00618 if ( nextState == NEW_SESSION )
00619
00620 fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
00621
00622 else if ( nextState == CACHED_SESSION )
00623 {
00624 fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites);
00625
00626
00627
00628
00629 fire_ssl_conn_established(sh.serverVersion, 0xABCD);
00630 }
00631
00632 return nextState;
00633 }
00634
00644 SSLv2_States SSLv2_Interpreter::
00645 ClientMasterKeyRecord(SSL_InterpreterEndpoint* s, int recordLength,
00646 u_char* recordData)
00647 {
00648 ++clientMasterKeyRecords;
00649 SSLv2_States nextState = CLIENT_MASTERKEY_SEEN;
00650
00651 if ( s != orig )
00652 Weird("SSLv2: CLIENT-MASTER-KEY from server!");
00653
00654 if ( recordLength < SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE )
00655 {
00656 Weird("SSLv2: CLIENT-MASTER-KEY is too small!");
00657 return ERROR_REQUIRED;
00658 }
00659
00660
00661 SSLv2_ClientMasterKeyHeader cmk;
00662 cmk.cipherKind =
00663 ((recordData[1] << 16) | recordData[2] << 8) | recordData[3];
00664 cmk.clearKeyLength = uint16(recordData[4] << 8) | recordData[5];
00665 cmk.encryptedKeyLength = uint16(recordData[6] << 8) | recordData[7];
00666 cmk.keyArgLength = uint16(recordData[8] << 8) | recordData[9];
00667
00668 if ( cmk.clearKeyLength + cmk.encryptedKeyLength + cmk.keyArgLength +
00669 SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE != recordLength )
00670 {
00671 Weird("SSLv2: Size inconsistency in CLIENT-MASTER-KEY");
00672 return ERROR_REQUIRED;
00673 }
00674
00675
00676 if ( pServerCipherSpecs )
00677 {
00678 bool bFound = false;
00679 for ( int i = 0; i < pServerCipherSpecs->len; i += 3 )
00680 {
00681 uint32 cipherSpec =
00682 ((pServerCipherSpecs->data[i] << 16) |
00683 pServerCipherSpecs->data[i+1] << 8) |
00684 pServerCipherSpecs->data[i+2];
00685
00686 if ( cmk.cipherKind == cipherSpec )
00687 {
00688 bFound = true;
00689 break;
00690 }
00691 }
00692
00693 if ( ! bFound )
00694 {
00695 Weird("SSLv2: Client chooses unadvertised cipher in CLIENT-MASTER-KEY!");
00696 nextState = ERROR_REQUIRED;
00697 }
00698 else
00699 nextState = CLIENT_MASTERKEY_SEEN;
00700
00701 delete pServerCipherSpecs;
00702 pServerCipherSpecs = 0;
00703 }
00704
00705
00706
00707 SSL_CipherSpec* pCipherSpecTemp = 0;
00708
00709 HashKey h(cmk.cipherKind);
00710 pCipherSpecTemp = (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
00711 if ( ! pCipherSpecTemp || ! (pCipherSpecTemp->flags & SSL_FLAG_SSLv20) )
00712 Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-MASTER-KEY!");
00713 else
00714 {
00715 if ( cmk.clearKeyLength * 8 != pCipherSpecTemp->clearKeySize )
00716 {
00717 Weird("SSLv2: Inconsistency of clearKeyLength in CLIENT-MASTER-KEY!");
00718
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 }
00745
00746
00747 usedCipherSpec = SSLv2_CipherSpec(cmk.cipherKind);
00748
00749
00750 if ( ssl_store_key_material )
00751 {
00752 pMasterClearKey =
00753 new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE), cmk.clearKeyLength);
00754
00755 pMasterEncryptedKey =
00756 new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE + cmk.clearKeyLength ), cmk.encryptedKeyLength);
00757 }
00758
00759 if ( nextState == CLIENT_MASTERKEY_SEEN )
00760 fire_ssl_conn_established(SSL_ConnectionProxy::SSLv20,
00761 cmk.cipherKind);
00762
00763 return nextState;
00764 }
00765
00766
00776 SSLv2_States SSLv2_Interpreter::ErrorRecord(SSL_InterpreterEndpoint* s,
00777 int recordLength, u_char* recordData)
00778 {
00779 ++errorRecords;
00780
00781 if ( unsigned(recordLength) != SSLv2_ERROR_RECORD_SIZE )
00782 {
00783 Weird("SSLv2: Size mismatch in Error Record!");
00784 return ERROR_REQUIRED;
00785 }
00786
00787 SSLv2_ErrorRecord er;
00788 er.errorCode = (recordData[1] << 8) | recordData[2];
00789 SSL3x_AlertLevel al = SSL3x_AlertLevel(255);
00790
00791 switch ( er.errorCode ) {
00792 case SSLv2_PE_NO_CIPHER:
00793
00794
00795 al = SSL3x_ALERT_LEVEL_FATAL;
00796 break;
00797
00798 case SSLv2_PE_NO_CERTIFICATE:
00799 if ( s == orig )
00800
00801 al = SSL3x_ALERT_LEVEL_FATAL;
00802 else
00803
00804 al = SSL3x_ALERT_LEVEL_WARNING;
00805 break;
00806
00807 case SSLv2_PE_BAD_CERTIFICATE:
00808 if ( s == orig )
00809
00810 al = SSL3x_ALERT_LEVEL_FATAL;
00811 else
00812
00813 al = SSL3x_ALERT_LEVEL_WARNING;
00814 break;
00815
00816 case SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE:
00817 if ( s == orig )
00818
00819 al = SSL3x_ALERT_LEVEL_FATAL;
00820 else
00821
00822 al = SSL3x_ALERT_LEVEL_WARNING;
00823 break;
00824
00825 default:
00826 al = SSL3x_ALERT_LEVEL_FATAL;
00827 break;
00828 }
00829
00830 fire_ssl_conn_alert(SSL_ConnectionProxy::SSLv20, al, er.errorCode);
00831
00832 return ERROR_SEEN;
00833 }
00834
00845 TableVal* SSLv2_Interpreter::analyzeCiphers(SSL_InterpreterEndpoint* s,
00846 int length, u_char* data)
00847 {
00848 if ( length > MAX_CIPHERSPEC_SIZE )
00849 {
00850 if ( s == orig )
00851 Weird("SSLv2: Client has CipherSpecs > MAX_CIPHERSPEC_SIZE");
00852 else
00853 Weird("SSLv2: Server has CipherSpecs > MAX_CIPHERSPEC_SIZE");
00854 }
00855 else
00856 {
00857 if ( ssl_compare_cipherspecs )
00858 {
00859 if ( s == resp )
00860 pServerCipherSpecs =
00861 new SSL_DataBlock(data, length);
00862 else
00863 pClientCipherSpecs =
00864 new SSL_DataBlock(data, length);
00865 }
00866 }
00867
00868 u_char* pCipher = data;
00869 bool bExtractCipherSuite = false;
00870 TableVal* pCipherTable = 0;
00871
00872
00873
00874
00875
00876 if ( (s == orig && ssl_conn_attempt) ||
00877 (s == resp && ssl_conn_server_reply) )
00878 {
00879 pCipherTable = new TableVal(cipher_suites_list);
00880 bExtractCipherSuite = true;
00881 }
00882
00883 for ( int i = 0; i < length; i += 3 )
00884 {
00885 SSL_CipherSpec* pCurrentCipherSpec;
00886 uint32 cipherSpecID =
00887 ((pCipher[0] << 16) | pCipher[1] << 8) | pCipher[2];
00888
00889
00890 HashKey h(cipherSpecID);
00891 pCurrentCipherSpec =
00892 (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h);
00893
00894 if ( ! pCurrentCipherSpec )
00895 {
00896 if ( s == orig )
00897 Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-HELLO!");
00898 else
00899 Weird("SSLv2: Unknown CIPHER-SPEC in SERVER-HELLO!");
00900 }
00901
00902 if ( bExtractCipherSuite )
00903 {
00904 pCipherTable->Assign(new Val(i / 3, TYPE_COUNT),
00905 new Val(cipherSpecID, TYPE_COUNT));
00906 }
00907
00908 pCipher += 3;
00909 }
00910
00911 return pCipherTable;
00912 }
00913
00914
00915
00923 SSLv2_Endpoint::SSLv2_Endpoint(SSLv2_Interpreter* interpreter, int is_orig)
00924 : SSL_InterpreterEndpoint(interpreter, is_orig)
00925 {
00926 sentRecords = 0;
00927 }
00928
00932 SSLv2_Endpoint::~SSLv2_Endpoint()
00933 {
00934 }
00935
00945 void SSLv2_Endpoint::Deliver(double t, int seq, int len, u_char* data)
00946 {
00947 ++((SSLv2_Endpoint*)peer)->sentRecords;
00948
00949 ((SSLv2_Interpreter*)interpreter)->NewSSLRecord(this, len, data);
00950 }