ssl_nt.c
来自「这是用C编写IMAP源代码」· C语言 代码 · 共 684 行 · 第 1/2 页
C
684 行
reason = ssl_analyze_status (e,buf); } } ssl_close (stream); /* failed to do SSL */ stream = NIL; /* no stream returned */ switch (*reason) { /* analyze reason */ case '*': /* certificate failure */ ++reason; /* skip over certificate failure indication */ /* pass to error callback */ if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ sprintf (tmp,"Certificate failure for %.80s: %.512s",host,reason); mm_log (tmp,ERROR); } case '\0': /* user answered no to certificate callback */ if (flags & NET_TRYSSL) /* return dummy stream to stop tryssl */ stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0, sizeof (SSLSTREAM)); break; default: /* non-certificate failure */ if (flags & NET_TRYSSL); /* no error output if tryssl */ /* pass to error callback */ else if (sf) (*sf) (host,reason,flags); else { /* no error callback, build error message */ sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); mm_log (tmp,ERROR); } break; } fs_give ((void **) &buf); /* flush temporary buffer */ return stream;}/* Generate error text from SSL error code * Accepts: SSL status * scratch buffer * Returns: text if error status, else NIL */static char *ssl_analyze_status (SECURITY_STATUS err,char *buf){ switch (err) { case SEC_E_OK: /* no error */ case SEC_I_CONTINUE_NEEDED: case SEC_I_INCOMPLETE_CREDENTIALS: case SEC_E_INCOMPLETE_MESSAGE: return NIL; case SEC_E_NO_AUTHENTICATING_AUTHORITY: mm_log ("unexpected SEC_E_NO_AUTHENTICATING_AUTHORITY",NIL); return "*No authority could be contacted for authentication"; case SEC_E_WRONG_PRINCIPAL: mm_log ("unexpected SEC_E_WRONG_PRINCIPAL",NIL); case CERT_E_CN_NO_MATCH: return "*Server name does not match certificate"; case SEC_E_UNTRUSTED_ROOT: mm_log ("unexpected SEC_E_UNTRUSTED_ROOT",NIL); case CERT_E_UNTRUSTEDROOT: return "*Self-signed certificate or untrusted authority"; case SEC_E_CERT_EXPIRED: mm_log ("unexpected SEC_E_CERT_EXPIRED",NIL); case CERT_E_EXPIRED: return "*Certificate has expired"; case CERT_E_REVOKED: return "*Certificate revoked"; case SEC_E_INVALID_TOKEN: return "Invalid token, probably not an SSL server"; case SEC_E_UNSUPPORTED_FUNCTION: return "SSL not supported on this machine - upgrade your system software"; } sprintf (buf,"Unexpected SSPI or certificate error %lx - report this",err); return buf;}/* SSL receive line * Accepts: SSL stream * Returns: text line string or NIL if failure */char *ssl_getline (SSLSTREAM *stream){ int n,m; char *st,*ret,*stp; char c = '\0'; char d; /* make sure have data */ if (!ssl_getdata (stream)) return NIL; st = stream->iptr; /* save start of string */ n = 0; /* init string count */ while (stream->ictr--) { /* look for end of line */ d = *stream->iptr++; /* slurp another character */ if ((c == '\015') && (d == '\012')) { ret = (char *) fs_get (n--); memcpy (ret,st,n); /* copy into a free storage string */ ret[n] = '\0'; /* tie off string with null */ return ret; } n++; /* count another character searched */ c = d; /* remember previous character */ } /* copy partial string from buffer */ memcpy ((ret = stp = (char *) fs_get (n)),st,n); /* get more data from the net */ if (!ssl_getdata (stream)) fs_give ((void **) &ret); /* special case of newline broken by buffer */ else if ((c == '\015') && (*stream->iptr == '\012')) { stream->iptr++; /* eat the line feed */ stream->ictr--; ret[n - 1] = '\0'; /* tie off string with null */ } /* else recurse to get remainder */ else if (st = ssl_getline (stream)) { ret = (char *) fs_get (n + 1 + (m = strlen (st))); memcpy (ret,stp,n); /* copy first part */ memcpy (ret + n,st,m); /* and second part */ fs_give ((void **) &stp); /* flush first part */ fs_give ((void **) &st); /* flush second part */ ret[n + m] = '\0'; /* tie off string with null */ } return ret;}/* SSL receive buffer * Accepts: SSL stream * size in bytes * buffer to read into * Returns: T if success, NIL otherwise */long ssl_getbuffer (SSLSTREAM *stream,unsigned long size,char *buffer){ unsigned long n; while (size > 0) { /* until request satisfied */ if (!ssl_getdata (stream)) return NIL; n = min (size,stream->ictr);/* number of bytes to transfer */ /* do the copy */ memcpy (buffer,stream->iptr,n); buffer += n; /* update pointer */ stream->iptr += n; size -= n; /* update # of bytes to do */ stream->ictr -= n; } buffer[0] = '\0'; /* tie off string */ return T;}/* SSL receive data * Accepts: TCP/IP stream * Returns: T if success, NIL otherwise */long ssl_getdata (SSLSTREAM *stream){ SECURITY_STATUS status; SecBuffer buf[4]; SecBufferDesc msg; size_t n = 0; size_t i; while (stream->ictr < 1) { /* decrypted buffer empty? */ do { /* yes, make sure have data from TCP */ if (stream->iextractr) { /* have previous unread data? */ memcpy (stream->ibuf + n,stream->iextraptr,stream->iextractr); n += stream->iextractr; /* update number of bytes read */ stream->iextractr = 0; /* no more extra data */ } else { /* read from TCP */ if (!tcp_getdata (stream->tcpstream)) return ssl_abort (stream); /* maximum amount of data to copy */ if (!(i = min (stream->bufsize - n,stream->tcpstream->ictr))) fatal ("incomplete SecBuffer exceeds maximum buffer size"); /* do the copy */ memcpy (stream->ibuf + n,stream->tcpstream->iptr,i); stream->tcpstream->iptr += i; stream->tcpstream->ictr -= i; n += i; /* update number of bytes to decrypt */ } buf[0].cbBuffer = n; /* first SecBuffer gets data */ buf[0].pvBuffer = stream->ibuf; buf[0].BufferType = SECBUFFER_DATA; /* subsequent ones are for spares */ buf[1].BufferType = buf[2].BufferType = buf[3].BufferType = SECBUFFER_EMPTY; msg.ulVersion = SECBUFFER_VERSION; msg.cBuffers = 4; /* number of SecBuffers */ msg.pBuffers = buf; /* first SecBuffer */ } while ((status = ((DECRYPT_MESSAGE_FN) sft->Reserved4) (&stream->context,&msg,0,NIL)) == SEC_E_INCOMPLETE_MESSAGE); switch (status) { case SEC_E_OK: /* won */ case SEC_I_RENEGOTIATE: /* won but lost it after this buffer */ /* hunt for a buffer */ for (i = 0; (i < 4) && (buf[i].BufferType != SECBUFFER_DATA) ; i++); if (i < 4) { /* found a buffer? */ /* yes, set up pointer and counter */ stream->iptr = buf[i].pvBuffer; stream->ictr = buf[i].cbBuffer; /* any unprocessed data? */ while (++i < 4) if (buf[i].BufferType == SECBUFFER_EXTRA) { /* yes, note for next time around */ stream->iextraptr = buf[i].pvBuffer; stream->iextractr = buf[i].cbBuffer; } } break; default: /* anything else means we've lost */ return ssl_abort (stream); } } return LONGT;}/* SSL send string as record * Accepts: SSL stream * string pointer * Returns: T if success else NIL */long ssl_soutr (SSLSTREAM *stream,char *string){ return ssl_sout (stream,string,(unsigned long) strlen (string));}/* SSL send string * Accepts: SSL stream * string pointer * byte count * Returns: T if success else NIL */long ssl_sout (SSLSTREAM *stream,char *string,unsigned long size){ SecBuffer buf[4]; SecBufferDesc msg; char *s; size_t n; if (!stream->tcpstream) return NIL; /* until request satisfied */ for (s = stream->ibuf,n = 0; size;) { /* header */ buf[0].BufferType = SECBUFFER_STREAM_HEADER; memset (buf[0].pvBuffer = stream->obuf,0, buf[0].cbBuffer = stream->sizes.cbHeader); /* message (up to maximum size) */ buf[1].BufferType = SECBUFFER_DATA; memcpy (buf[1].pvBuffer = stream->obuf + stream->sizes.cbHeader,string, buf[1].cbBuffer = min (size,SSLBUFLEN)); /* trailer */ buf[2].BufferType = SECBUFFER_STREAM_TRAILER; memset (buf[2].pvBuffer = ((char *) buf[1].pvBuffer) + buf[1].cbBuffer,0, buf[2].cbBuffer = stream->sizes.cbTrailer); /* spare */ buf[3].BufferType = SECBUFFER_EMPTY; msg.ulVersion = SECBUFFER_VERSION; msg.cBuffers = 4; /* number of SecBuffers */ msg.pBuffers = buf; /* first SecBuffer */ string += buf[1].cbBuffer; size -= buf[1].cbBuffer; /* this many bytes processed */ /* encrypt and send message */ if ((((ENCRYPT_MESSAGE_FN) sft->Reserved3) (&stream->context,0,&msg,NIL) != SEC_E_OK) || !tcp_sout (stream->tcpstream,stream->obuf, buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer)) return ssl_abort (stream);/* encryption or sending failed */ } return LONGT;}/* SSL close * Accepts: SSL stream */void ssl_close (SSLSTREAM *stream){ ssl_abort (stream); /* nuke the stream */ fs_give ((void **) &stream); /* flush the stream */}/* SSL abort stream * Accepts: SSL stream * Returns: NIL always */static long ssl_abort (SSLSTREAM *stream){ if (stream->tcpstream) { /* close TCP stream */ sft->DeleteSecurityContext (&stream->context); sft->FreeCredentialHandle (&stream->cred); tcp_close (stream->tcpstream); stream->tcpstream = NIL; } if (stream->ibuf) fs_give ((void **) &stream->ibuf); if (stream->obuf) fs_give ((void **) &stream->obuf); return NIL;}/* SSL get host name * Accepts: SSL stream * Returns: host name for this stream */char *ssl_host (SSLSTREAM *stream){ return tcp_host (stream->tcpstream);}/* SSL get remote host name * Accepts: SSL stream * Returns: host name for this stream */char *ssl_remotehost (SSLSTREAM *stream){ return tcp_remotehost (stream->tcpstream);}/* SSL return port for this stream * Accepts: SSL stream * Returns: port number for this stream */unsigned long ssl_port (SSLSTREAM *stream){ return tcp_port (stream->tcpstream);}/* SSL get local host name * Accepts: SSL stream * Returns: local host name */char *ssl_localhost (SSLSTREAM *stream){ return tcp_localhost (stream->tcpstream);}#include "ssl_none.c" /* currently no server support */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?