sslinfo.c revision 868fa2fe829687343ffae624259930155e16dbd8
1/* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4/* $Id$ */ 5#include "ssl.h" 6#include "sslimpl.h" 7#include "sslproto.h" 8 9static const char * 10ssl_GetCompressionMethodName(SSLCompressionMethod compression) 11{ 12 switch (compression) { 13 case ssl_compression_null: 14 return "NULL"; 15#ifdef NSS_ENABLE_ZLIB 16 case ssl_compression_deflate: 17 return "DEFLATE"; 18#endif 19 default: 20 return "???"; 21 } 22} 23 24SECStatus 25SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len) 26{ 27 sslSocket * ss; 28 SSLChannelInfo inf; 29 sslSessionID * sid; 30 PRBool enoughFirstHsDone = PR_FALSE; 31 32 if (!info || len < sizeof inf.length) { 33 PORT_SetError(SEC_ERROR_INVALID_ARGS); 34 return SECFailure; 35 } 36 37 ss = ssl_FindSocket(fd); 38 if (!ss) { 39 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetChannelInfo", 40 SSL_GETPID(), fd)); 41 return SECFailure; 42 } 43 44 memset(&inf, 0, sizeof inf); 45 inf.length = PR_MIN(sizeof inf, len); 46 47 if (ss->firstHsDone) { 48 enoughFirstHsDone = PR_TRUE; 49 } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 && 50 ssl3_CanFalseStart(ss)) { 51 enoughFirstHsDone = PR_TRUE; 52 } 53 54 if (ss->opt.useSecurity && enoughFirstHsDone) { 55 sid = ss->sec.ci.sid; 56 inf.protocolVersion = ss->version; 57 inf.authKeyBits = ss->sec.authKeyBits; 58 inf.keaKeyBits = ss->sec.keaKeyBits; 59 if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ 60 inf.cipherSuite = ss->sec.cipherType | 0xff00; 61 inf.compressionMethod = ssl_compression_null; 62 inf.compressionMethodName = "N/A"; 63 } else if (ss->ssl3.initialized) { /* SSL3 and TLS */ 64 ssl_GetSpecReadLock(ss); 65 /* XXX The cipher suite should be in the specs and this 66 * function should get it from cwSpec rather than from the "hs". 67 * See bug 275744 comment 69 and bug 766137. 68 */ 69 inf.cipherSuite = ss->ssl3.hs.cipher_suite; 70 inf.compressionMethod = ss->ssl3.cwSpec->compression_method; 71 ssl_ReleaseSpecReadLock(ss); 72 inf.compressionMethodName = 73 ssl_GetCompressionMethodName(inf.compressionMethod); 74 } 75 if (sid) { 76 inf.creationTime = sid->creationTime; 77 inf.lastAccessTime = sid->lastAccessTime; 78 inf.expirationTime = sid->expirationTime; 79 if (ss->version < SSL_LIBRARY_VERSION_3_0) { /* SSL2 */ 80 inf.sessionIDLength = SSL2_SESSIONID_BYTES; 81 memcpy(inf.sessionID, sid->u.ssl2.sessionID, 82 SSL2_SESSIONID_BYTES); 83 } else { 84 unsigned int sidLen = sid->u.ssl3.sessionIDLength; 85 sidLen = PR_MIN(sidLen, sizeof inf.sessionID); 86 inf.sessionIDLength = sidLen; 87 memcpy(inf.sessionID, sid->u.ssl3.sessionID, sidLen); 88 } 89 } 90 } 91 92 memcpy(info, &inf, inf.length); 93 94 return SECSuccess; 95} 96 97 98#define CS(x) x, #x 99#define CK(x) x | 0xff00, #x 100 101#define S_DSA "DSA", ssl_auth_dsa 102#define S_RSA "RSA", ssl_auth_rsa 103#define S_KEA "KEA", ssl_auth_kea 104#define S_ECDSA "ECDSA", ssl_auth_ecdsa 105 106#define K_DHE "DHE", kt_dh 107#define K_RSA "RSA", kt_rsa 108#define K_KEA "KEA", kt_kea 109#define K_ECDH "ECDH", kt_ecdh 110#define K_ECDHE "ECDHE", kt_ecdh 111 112#define C_SEED "SEED", calg_seed 113#define C_CAMELLIA "CAMELLIA", calg_camellia 114#define C_AES "AES", calg_aes 115#define C_RC4 "RC4", calg_rc4 116#define C_RC2 "RC2", calg_rc2 117#define C_DES "DES", calg_des 118#define C_3DES "3DES", calg_3des 119#define C_NULL "NULL", calg_null 120#define C_SJ "SKIPJACK", calg_sj 121 122#define B_256 256, 256, 256 123#define B_128 128, 128, 128 124#define B_3DES 192, 156, 112 125#define B_SJ 96, 80, 80 126#define B_DES 64, 56, 56 127#define B_56 128, 56, 56 128#define B_40 128, 40, 40 129#define B_0 0, 0, 0 130 131#define M_SHA256 "SHA256", ssl_hmac_sha256, 256 132#define M_SHA "SHA1", ssl_mac_sha, 160 133#define M_MD5 "MD5", ssl_mac_md5, 128 134 135static const SSLCipherSuiteInfo suiteInfo[] = { 136/* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */ 137{0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, }, 138{0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, }, 139{0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0, }, 140{0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, }, 141{0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0, }, 142{0,CS(TLS_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, 0, 0, 0, }, 143{0,CS(TLS_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, 1, 0, 0, }, 144{0,CS(TLS_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, 1, 0, 0, }, 145 146{0,CS(TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, }, 147{0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, }, 148{0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0, }, 149{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0, }, 150{0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, }, 151{0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0, }, 152{0,CS(TLS_RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0, }, 153{0,CS(TLS_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, 0, 0, 0, }, 154{0,CS(SSL_RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, 0, 0, 0, }, 155{0,CS(SSL_RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0, }, 156{0,CS(TLS_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, 1, 0, 0, }, 157{0,CS(TLS_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, 1, 0, 0, }, 158 159{0,CS(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, }, 160{0,CS(SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0, }, 161{0,CS(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 1, }, 162{0,CS(SSL_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 0, }, 163 164{0,CS(SSL_DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, }, 165{0,CS(SSL_DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0, }, 166{0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 1, }, 167{0,CS(SSL_RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 0, }, 168 169{0,CS(TLS_RSA_EXPORT1024_WITH_RC4_56_SHA), S_RSA, K_RSA, C_RC4, B_56, M_SHA, 0, 1, 0, }, 170{0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 1, 0, }, 171{0,CS(SSL_RSA_EXPORT_WITH_RC4_40_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0, }, 172{0,CS(SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0, }, 173{0,CS(TLS_RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL,B_0, M_SHA256, 0, 1, 0, }, 174{0,CS(SSL_RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL,B_0, M_SHA, 0, 1, 0, }, 175{0,CS(SSL_RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL,B_0, M_MD5, 0, 1, 0, }, 176 177#ifdef NSS_ENABLE_ECC 178/* ECC cipher suites */ 179{0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, }, 180{0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, }, 181{0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, }, 182{0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, }, 183{0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, }, 184 185{0,CS(TLS_ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0, }, 186{0,CS(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0, }, 187{0,CS(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0, }, 188{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, }, 189{0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0, }, 190{0,CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0, }, 191 192{0,CS(TLS_ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0, }, 193{0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0, }, 194{0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0, }, 195{0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0, }, 196{0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0, }, 197 198{0,CS(TLS_ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0, }, 199{0,CS(TLS_ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0, }, 200{0,CS(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0, }, 201{0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0, }, 202{0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0, }, 203{0,CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0, }, 204#endif /* NSS_ENABLE_ECC */ 205 206/* SSL 2 table */ 207{0,CK(SSL_CK_RC4_128_WITH_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0, }, 208{0,CK(SSL_CK_RC2_128_CBC_WITH_MD5), S_RSA, K_RSA, C_RC2, B_128, M_MD5, 0, 0, 0, }, 209{0,CK(SSL_CK_DES_192_EDE3_CBC_WITH_MD5), S_RSA, K_RSA, C_3DES,B_3DES,M_MD5, 0, 0, 0, }, 210{0,CK(SSL_CK_DES_64_CBC_WITH_MD5), S_RSA, K_RSA, C_DES, B_DES, M_MD5, 0, 0, 0, }, 211{0,CK(SSL_CK_RC4_128_EXPORT40_WITH_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0, }, 212{0,CK(SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0, } 213}; 214 215#define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0])) 216 217 218SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite, 219 SSLCipherSuiteInfo *info, PRUintn len) 220{ 221 unsigned int i; 222 223 len = PR_MIN(len, sizeof suiteInfo[0]); 224 if (!info || len < sizeof suiteInfo[0].length) { 225 PORT_SetError(SEC_ERROR_INVALID_ARGS); 226 return SECFailure; 227 } 228 for (i = 0; i < NUM_SUITEINFOS; i++) { 229 if (suiteInfo[i].cipherSuite == cipherSuite) { 230 memcpy(info, &suiteInfo[i], len); 231 info->length = len; 232 return SECSuccess; 233 } 234 } 235 PORT_SetError(SEC_ERROR_INVALID_ARGS); 236 return SECFailure; 237} 238 239/* This function might be a candidate to be public. 240 * Disables all export ciphers in the default set of enabled ciphers. 241 */ 242SECStatus 243SSL_DisableDefaultExportCipherSuites(void) 244{ 245 const SSLCipherSuiteInfo * pInfo = suiteInfo; 246 unsigned int i; 247 SECStatus rv; 248 249 for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) { 250 if (pInfo->isExportable) { 251 rv = SSL_CipherPrefSetDefault(pInfo->cipherSuite, PR_FALSE); 252 PORT_Assert(rv == SECSuccess); 253 } 254 } 255 return SECSuccess; 256} 257 258/* This function might be a candidate to be public, 259 * except that it takes an sslSocket pointer as an argument. 260 * A Public version would take a PRFileDesc pointer. 261 * Disables all export ciphers in the default set of enabled ciphers. 262 */ 263SECStatus 264SSL_DisableExportCipherSuites(PRFileDesc * fd) 265{ 266 const SSLCipherSuiteInfo * pInfo = suiteInfo; 267 unsigned int i; 268 SECStatus rv; 269 270 for (i = 0; i < NUM_SUITEINFOS; ++i, ++pInfo) { 271 if (pInfo->isExportable) { 272 rv = SSL_CipherPrefSet(fd, pInfo->cipherSuite, PR_FALSE); 273 PORT_Assert(rv == SECSuccess); 274 } 275 } 276 return SECSuccess; 277} 278 279/* Tells us if the named suite is exportable 280 * returns false for unknown suites. 281 */ 282PRBool 283SSL_IsExportCipherSuite(PRUint16 cipherSuite) 284{ 285 unsigned int i; 286 for (i = 0; i < NUM_SUITEINFOS; i++) { 287 if (suiteInfo[i].cipherSuite == cipherSuite) { 288 return (PRBool)(suiteInfo[i].isExportable); 289 } 290 } 291 return PR_FALSE; 292} 293 294SECItem* 295SSL_GetNegotiatedHostInfo(PRFileDesc *fd) 296{ 297 SECItem *sniName = NULL; 298 sslSocket *ss; 299 char *name = NULL; 300 301 ss = ssl_FindSocket(fd); 302 if (!ss) { 303 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo", 304 SSL_GETPID(), fd)); 305 return NULL; 306 } 307 308 if (ss->sec.isServer) { 309 if (ss->version > SSL_LIBRARY_VERSION_3_0 && 310 ss->ssl3.initialized) { /* TLS */ 311 SECItem *crsName; 312 ssl_GetSpecReadLock(ss); /*********************************/ 313 crsName = &ss->ssl3.cwSpec->srvVirtName; 314 if (crsName->data) { 315 sniName = SECITEM_DupItem(crsName); 316 } 317 ssl_ReleaseSpecReadLock(ss); /*----------------------------*/ 318 } 319 return sniName; 320 } 321 name = SSL_RevealURL(fd); 322 if (name) { 323 sniName = PORT_ZNew(SECItem); 324 if (!sniName) { 325 PORT_Free(name); 326 return NULL; 327 } 328 sniName->data = (void*)name; 329 sniName->len = PORT_Strlen(name); 330 } 331 return sniName; 332} 333 334SECStatus 335SSL_ExportKeyingMaterial(PRFileDesc *fd, 336 const char *label, unsigned int labelLen, 337 PRBool hasContext, 338 const unsigned char *context, unsigned int contextLen, 339 unsigned char *out, unsigned int outLen) 340{ 341 sslSocket *ss; 342 unsigned char *val = NULL; 343 unsigned int valLen, i; 344 SECStatus rv = SECFailure; 345 346 ss = ssl_FindSocket(fd); 347 if (!ss) { 348 SSL_DBG(("%d: SSL[%d]: bad socket in ExportKeyingMaterial", 349 SSL_GETPID(), fd)); 350 return SECFailure; 351 } 352 353 ssl_GetRecvBufLock(ss); 354 ssl_GetSSL3HandshakeLock(ss); 355 356 if (ss->version < SSL_LIBRARY_VERSION_3_1_TLS) { 357 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION); 358 ssl_ReleaseSSL3HandshakeLock(ss); 359 ssl_ReleaseRecvBufLock(ss); 360 return SECFailure; 361 } 362 363 /* construct PRF arguments */ 364 valLen = SSL3_RANDOM_LENGTH * 2; 365 if (hasContext) { 366 valLen += 2 /* uint16 length */ + contextLen; 367 } 368 val = PORT_Alloc(valLen); 369 if (!val) { 370 ssl_ReleaseSSL3HandshakeLock(ss); 371 ssl_ReleaseRecvBufLock(ss); 372 return SECFailure; 373 } 374 i = 0; 375 376 PORT_Memcpy(val + i, &ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH); 377 i += SSL3_RANDOM_LENGTH; 378 PORT_Memcpy(val + i, &ss->ssl3.hs.server_random.rand, SSL3_RANDOM_LENGTH); 379 i += SSL3_RANDOM_LENGTH; 380 381 if (hasContext) { 382 val[i++] = contextLen >> 8; 383 val[i++] = contextLen; 384 PORT_Memcpy(val + i, context, contextLen); 385 i += contextLen; 386 } 387 PORT_Assert(i == valLen); 388 389 /* Allow TLS keying material to be exported sooner, when the master 390 * secret is available and we have sent ChangeCipherSpec. 391 */ 392 ssl_GetSpecReadLock(ss); 393 if (!ss->ssl3.cwSpec->master_secret && !ss->ssl3.cwSpec->msItem.len) { 394 PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED); 395 rv = SECFailure; 396 } else { 397 rv = ssl3_TLSPRFWithMasterSecret(ss->ssl3.cwSpec, label, labelLen, val, 398 valLen, out, outLen); 399 } 400 ssl_ReleaseSpecReadLock(ss); 401 ssl_ReleaseSSL3HandshakeLock(ss); 402 ssl_ReleaseRecvBufLock(ss); 403 404 PORT_ZFree(val, valLen); 405 return rv; 406} 407