sslsock.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,856 行 · 第 1/4 页
C
1,856 行
opt.value.non_blocking = PR_FALSE; status = PR_GetSocketOption(fd, &opt); if (status != PR_SUCCESS) return PR_FALSE; return (PRBool)!opt.value.non_blocking;}PRBoolssl_SocketIsBlocking(sslSocket *ss){ return ssl_FdIsBlocking(ss->fd);}PRInt32 sslFirstBufSize = 8 * 1024;PRInt32 sslCopyLimit = 1024;static PRInt32 PR_CALLBACKssl_WriteV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 vectors, PRIntervalTime timeout){ PRInt32 bufLen; PRInt32 left; PRInt32 rv; PRInt32 sent = 0; const PRInt32 first_len = sslFirstBufSize; const PRInt32 limit = sslCopyLimit; PRBool blocking; PRIOVec myIov = { 0, 0 }; char buf[MAX_FRAGMENT_LENGTH]; if (vectors > PR_MAX_IOVECTOR_SIZE) { PORT_SetError(PR_BUFFER_OVERFLOW_ERROR); return -1; } blocking = ssl_FdIsBlocking(fd);#define K16 sizeof(buf)#define KILL_VECTORS while (vectors && !iov->iov_len) { ++iov; --vectors; }#define GET_VECTOR do { myIov = *iov++; --vectors; KILL_VECTORS } while (0)#define HANDLE_ERR(rv, len) \ if (rv != len) { \ if (rv < 0) { \ if (blocking \ && (PR_GetError() == PR_WOULD_BLOCK_ERROR) \ && (sent > 0)) { \ return sent; \ } else { \ return -1; \ } \ } \ /* Only a nonblocking socket can have partial sends */ \ PR_ASSERT(blocking); \ return sent; \ } #define SEND(bfr, len) \ do { \ rv = ssl_Send(fd, bfr, len, 0, timeout); \ HANDLE_ERR(rv, len) \ sent += len; \ } while (0) /* Make sure the first write is at least 8 KB, if possible. */ KILL_VECTORS if (!vectors) return 0; GET_VECTOR; if (!vectors) { return ssl_Send(fd, myIov.iov_base, myIov.iov_len, 0, timeout); } if (myIov.iov_len < first_len) { PORT_Memcpy(buf, myIov.iov_base, myIov.iov_len); bufLen = myIov.iov_len; left = first_len - bufLen; while (vectors && left) { int toCopy; GET_VECTOR; toCopy = PR_MIN(left, myIov.iov_len); PORT_Memcpy(buf + bufLen, myIov.iov_base, toCopy); bufLen += toCopy; left -= toCopy; myIov.iov_base += toCopy; myIov.iov_len -= toCopy; } SEND( buf, bufLen ); } while (vectors || myIov.iov_len) { PRInt32 addLen; if (!myIov.iov_len) { GET_VECTOR; } while (myIov.iov_len >= K16) { SEND(myIov.iov_base, K16); myIov.iov_base += K16; myIov.iov_len -= K16; } if (!myIov.iov_len) continue; if (!vectors || myIov.iov_len > limit) { addLen = 0; } else if ((addLen = iov->iov_len % K16) + myIov.iov_len <= limit) { /* Addlen is already computed. */; } else if (vectors > 1 && iov[1].iov_len % K16 + addLen + myIov.iov_len <= 2 * limit) { addLen = limit - myIov.iov_len; } else addLen = 0; if (!addLen) { SEND( myIov.iov_base, myIov.iov_len ); myIov.iov_len = 0; continue; } PORT_Memcpy(buf, myIov.iov_base, myIov.iov_len); bufLen = myIov.iov_len; do { GET_VECTOR; PORT_Memcpy(buf + bufLen, myIov.iov_base, addLen); myIov.iov_base += addLen; myIov.iov_len -= addLen; bufLen += addLen; left = PR_MIN( limit, K16 - bufLen); if (!vectors /* no more left */ || myIov.iov_len > 0 /* we didn't use that one all up */ || bufLen >= K16 /* it's full. */ ) { addLen = 0; } else if ((addLen = iov->iov_len % K16) <= left) { /* Addlen is already computed. */; } else if (vectors > 1 && iov[1].iov_len % K16 + addLen <= left + limit) { addLen = left; } else addLen = 0; } while (addLen); SEND( buf, bufLen ); } return sent;}/* * These functions aren't implemented. */static PRInt32 PR_CALLBACKssl_Available(PRFileDesc *fd){ PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return SECFailure;}static PRInt64 PR_CALLBACKssl_Available64(PRFileDesc *fd){ PRInt64 res; PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); LL_I2L(res, -1L); return res;}static PRStatus PR_CALLBACKssl_FSync(PRFileDesc *fd){ PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE;}static PRInt32 PR_CALLBACKssl_Seek(PRFileDesc *fd, PRInt32 offset, PRSeekWhence how) { PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return SECFailure;}static PRInt64 PR_CALLBACKssl_Seek64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence how) { PRInt64 res; PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); LL_I2L(res, -1L); return res;}static PRStatus PR_CALLBACKssl_FileInfo(PRFileDesc *fd, PRFileInfo *info){ PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE;}static PRStatus PR_CALLBACKssl_FileInfo64(PRFileDesc *fd, PRFileInfo64 *info){ PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE;}static PRInt32 PR_CALLBACKssl_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout){ PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return SECFailure;}static PRInt32 PR_CALLBACKssl_SendTo(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout){ PORT_Assert(0); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return SECFailure;}static const PRIOMethods ssl_methods = { PR_DESC_LAYERED, ssl_Close, /* close */ ssl_Read, /* read */ ssl_Write, /* write */ ssl_Available, /* available */ ssl_Available64, /* available64 */ ssl_FSync, /* fsync */ ssl_Seek, /* seek */ ssl_Seek64, /* seek64 */ ssl_FileInfo, /* fileInfo */ ssl_FileInfo64, /* fileInfo64 */ ssl_WriteV, /* writev */ ssl_Connect, /* connect */ ssl_Accept, /* accept */ ssl_Bind, /* bind */ ssl_Listen, /* listen */ ssl_Shutdown, /* shutdown */ ssl_Recv, /* recv */ ssl_Send, /* send */ ssl_RecvFrom, /* recvfrom */ ssl_SendTo, /* sendto */ ssl_Poll, /* poll */ ssl_EmulateAcceptRead, /* acceptread */ ssl_EmulateTransmitFile, /* transmitfile */ ssl_GetSockName, /* getsockname */ ssl_GetPeerName, /* getpeername */ NULL, /* getsockopt OBSOLETE */ NULL, /* setsockopt OBSOLETE */ NULL, /* getsocketoption */ NULL, /* setsocketoption */ ssl_EmulateSendFile, /* Send a (partial) file with header/trailer*/ NULL, /* reserved for future use */ NULL, /* reserved for future use */ NULL, /* reserved for future use */ NULL, /* reserved for future use */ NULL /* reserved for future use */};static PRIOMethods combined_methods;static voidssl_SetupIOMethods(void){ PRIOMethods *new_methods = &combined_methods; const PRIOMethods *nspr_methods = PR_GetDefaultIOMethods(); const PRIOMethods *my_methods = &ssl_methods; *new_methods = *nspr_methods; new_methods->file_type = my_methods->file_type; new_methods->close = my_methods->close; new_methods->read = my_methods->read; new_methods->write = my_methods->write; new_methods->available = my_methods->available; new_methods->available64 = my_methods->available64; new_methods->fsync = my_methods->fsync; new_methods->seek = my_methods->seek; new_methods->seek64 = my_methods->seek64; new_methods->fileInfo = my_methods->fileInfo; new_methods->fileInfo64 = my_methods->fileInfo64; new_methods->writev = my_methods->writev; new_methods->connect = my_methods->connect; new_methods->accept = my_methods->accept; new_methods->bind = my_methods->bind; new_methods->listen = my_methods->listen; new_methods->shutdown = my_methods->shutdown; new_methods->recv = my_methods->recv; new_methods->send = my_methods->send; new_methods->recvfrom = my_methods->recvfrom; new_methods->sendto = my_methods->sendto; new_methods->poll = my_methods->poll; new_methods->acceptread = my_methods->acceptread; new_methods->transmitfile = my_methods->transmitfile; new_methods->getsockname = my_methods->getsockname; new_methods->getpeername = my_methods->getpeername;/* new_methods->getsocketoption = my_methods->getsocketoption; *//* new_methods->setsocketoption = my_methods->setsocketoption; */ new_methods->sendfile = my_methods->sendfile;}static PRCallOnceType initIoLayerOnce;static PRStatus ssl_InitIOLayer(void){ ssl_layer_id = PR_GetUniqueIdentity("SSL"); ssl_SetupIOMethods(); ssl_inited = PR_TRUE; return PR_SUCCESS;}static PRStatusssl_PushIOLayer(sslSocket *ns, PRFileDesc *stack, PRDescIdentity id){ PRFileDesc *layer = NULL; PRStatus status; if (!ssl_inited) { PR_CallOnce(&initIoLayerOnce, &ssl_InitIOLayer); } if (ns == NULL) goto loser; layer = PR_CreateIOLayerStub(ssl_layer_id, &combined_methods); if (layer == NULL) goto loser; layer->secret = (PRFilePrivate *)ns; /* Here, "stack" points to the PRFileDesc on the top of the stack. ** "layer" points to a new FD that is to be inserted into the stack. ** If layer is being pushed onto the top of the stack, then ** PR_PushIOLayer switches the contents of stack and layer, and then ** puts stack on top of layer, so that after it is done, the top of ** stack is the same "stack" as it was before, and layer is now the ** FD for the former top of stack. ** After this call, stack always points to the top PRFD on the stack. ** If this function fails, the contents of stack and layer are as ** they were before the call. */ status = PR_PushIOLayer(stack, id, layer); if (status != PR_SUCCESS) goto loser; ns->fd = (id == PR_TOP_IO_LAYER) ? stack : layer; return PR_SUCCESS;loser: if (layer) { layer->dtor(layer); /* free layer */ } return PR_FAILURE;}/*** Create a newsocket structure for a file descriptor.*/static sslSocket *ssl_NewSocket(void){ sslSocket *ss;#ifdef DEBUG static int firsttime = 1;#endif#ifdef DEBUG#if defined(XP_UNIX) || defined(XP_WIN32) if (firsttime) { firsttime = 0; { char *ev = getenv("SSLDEBUG"); if (ev && ev[0]) { ssl_debug = atoi(ev); SSL_TRACE(("SSL: debugging set to %d", ssl_debug)); } }#ifdef TRACE { char *ev = getenv("SSLTRACE"); if (ev && ev[0]) { ssl_trace = atoi(ev); SSL_TRACE(("SSL: tracing set to %d", ssl_trace)); } }#endif /* TRACE */ }#endif /* XP_UNIX || XP_WIN32 */#endif /* DEBUG */ /* Make a new socket and get it ready */ ss = (sslSocket*) PORT_ZAlloc(sizeof(sslSocket)); if (ss) { /* This should be of type SSLKEAType, but CC on IRIX * complains during the for loop. */ int i; ss->useSecurity = ssl_defaults.useSecurity; ss->useSocks = ssl_defaults.useSocks; ss->requestCertificate = ssl_defaults.requestCertificate; ss->requireCertificate = ssl_defaults.requireCertificate; ss->handshakeAsClient = ssl_defaults.handshakeAsClient; ss->handshakeAsServer = ssl_defaults.handshakeAsServer; ss->enableSSL2 = ssl_defaults.enableSSL2; ss->enableSSL3 = ssl_defaults.enableSSL3; ss->enableTLS = ssl_defaults.enableTLS ; ss->fdx = ssl_defaults.fdx; ss->v2CompatibleHello = ssl_defaults.v2CompatibleHello; ss->detectRollBack = ssl_defaults.detectRollBack; memset(&ss->peer, 0, sizeof(ss->peer)); ss->port = 0; ss->noCache = ssl_defaults.noCache; ss->peerID = NULL; ss->rTimeout = PR_INTERVAL_NO_TIMEOUT; ss->wTimeout = PR_INTERVAL_NO_TIMEOUT; ss->cTimeout = PR_INTERVAL_NO_TIMEOUT; ss->cipherSpecs = NULL; ss->sizeCipherSpecs = 0; /* produced lazily */ ss->preferredCipher = NULL; ss->url = NULL; for (i=kt_null; i < kt_kea_size; i++) { ss->serverCert[i] = NULL; ss->serverCertChain[i] = NULL; ss->serverKey[i] = NULL; } ss->stepDownKeyPair = NULL; ss->dbHandle = CERT_GetDefaultCertDB(); /* Provide default implementation of hooks */ ss->authCertificate = SSL_AuthCertificate; ss->authCertificateArg = (void *)ss->dbHandle; ss->getClientAuthData = NULL; ss->handleBadCert = NULL; ss->badCertArg = NULL; ss->pkcs11PinArg = NULL; ssl_ChooseOps(ss); ssl2_InitSocketPolicy(ss); ssl3_InitSocketPolicy(ss); ss->firstHandshakeLock = PR_NewMonitor(); ss->ssl3HandshakeLock = PR_NewMonitor(); ss->specLock = NSSRWLock_New(SSL_LOCK_RANK_SPEC, NULL); ss->recvBufLock = PR_NewMonitor(); ss->xmitBufLock = PR_NewMonitor(); if (ssl_lock_readers) { ss->recvLock = PR_NewLock(); ss->sendLock = PR_NewLock(); } } return ss;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?