⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_nt.c

📁 广泛使用的邮件服务器!同时
💻 C
📖 第 1 页 / 共 2 页
字号:
/* ======================================================================== * Copyright 1988-2008 University of Washington * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * *  * ======================================================================== *//* * Program:	SSL authentication/encryption module for Windows 9x and NT * * Author:	Mark Crispin *		Networks and Distributed Computing *		Computing & Communications *		University of Washington *		Administration Building, AG-44 *		Seattle, WA  98195 *		Internet: MRC@CAC.Washington.EDU * * Date:	22 September 1998 * Last Edited:	13 January 2008 */#define SECURITY_WIN32#include <sspi.h>#include <schannel.h>#define SSLBUFLEN 8192/* SSL I/O stream */typedef struct ssl_stream {  TCPSTREAM *tcpstream;		/* TCP stream */  CredHandle cred;		/* SSL credentials */  CtxtHandle context;		/* SSL context */				/* stream encryption sizes */  SecPkgContext_StreamSizes sizes;  size_t bufsize;  int ictr;			/* input counter */  char *iptr;			/* input pointer */  int iextractr;		/* extra input counter */  char *iextraptr;		/* extra input pointer */  char *ibuf;			/* input buffer */  char *obuf;			/* output buffer */} SSLSTREAM;#include "sslio.h"/* Function prototypes */static SSLSTREAM *ssl_start(TCPSTREAM *tstream,char *host,unsigned long flags);static char *ssl_analyze_status (SECURITY_STATUS err,char *buf);static char *ssl_getline_work (SSLSTREAM *stream,unsigned long *size,			       long *contd);static long ssl_abort (SSLSTREAM *stream);/* Secure Sockets Layer network driver dispatch */static struct ssl_driver ssldriver = {  ssl_open,			/* open connection */  ssl_aopen,			/* open preauthenticated connection */  ssl_getline,			/* get a line */  ssl_getbuffer,		/* get a buffer */  ssl_soutr,			/* output pushed data */  ssl_sout,			/* output string */  ssl_close,			/* close connection */  ssl_host,			/* return host name */  ssl_remotehost,		/* return remote host name */  ssl_port,			/* return port number */  ssl_localhost			/* return local host name */};				/* security function table */static SecurityFunctionTable *sft = NIL;static unsigned long ssltsz = 0;/* SSL maximum token length *//* Define crypt32.dll stuff here in case a pre-IE5 Win9x system */typedef DWORD (CALLBACK *CNTS) (DWORD,PCERT_NAME_BLOB,DWORD,LPSTR,DWORD);typedef BOOL (CALLBACK *CGCC) (HCERTCHAINENGINE,PCCERT_CONTEXT,LPFILETIME,			       HCERTSTORE,PCERT_CHAIN_PARA,DWORD,LPVOID,			       PCCERT_CHAIN_CONTEXT *);typedef BOOL (CALLBACK *CVCCP) (LPCSTR,PCCERT_CHAIN_CONTEXT,				PCERT_CHAIN_POLICY_PARA,				PCERT_CHAIN_POLICY_STATUS);typedef VOID (CALLBACK *CFCC) (PCCERT_CHAIN_CONTEXT);typedef BOOL (CALLBACK *CFCCX) (PCCERT_CONTEXT);static CNTS certNameToStr = NIL;static CGCC certGetCertificateChain = NIL;static CVCCP certVerifyCertificateChainPolicy = NIL;static CFCC certFreeCertificateChain = NIL;static CFCCX certFreeCertificateContext = NIL;/* One-time SSL initialization */static int sslonceonly = 0;void ssl_onceonlyinit (void){  if (!sslonceonly++) {		/* only need to call it once */    HINSTANCE lib;    FARPROC pi;    ULONG np;    SecPkgInfo *pp;    int i;				/* get security library */    if (((lib = LoadLibrary ("schannel.dll")) ||	 (lib = LoadLibrary ("security.dll"))) &&	(pi = GetProcAddress (lib,SECURITY_ENTRYPOINT)) &&	(sft = (SecurityFunctionTable *) pi ()) &&	!(sft->EnumerateSecurityPackages (&np,&pp))) {				/* look for an SSL package */      for (i = 0; (i < (int) np); i++) if (!strcmp (pp[i].Name,UNISP_NAME)) {				/* note maximum token size and name */	ssltsz = pp[i].cbMaxToken;				/* apply runtime linkage */	mail_parameters (NIL,SET_SSLDRIVER,(void *) &ssldriver);	mail_parameters (NIL,SET_SSLSTART,(void *) ssl_start);	if ((lib = LoadLibrary ("crypt32.dll")) &&	    (certGetCertificateChain = (CGCC)	     GetProcAddress (lib,"CertGetCertificateChain")) &&	    (certVerifyCertificateChainPolicy = (CVCCP)	     GetProcAddress (lib,"CertVerifyCertificateChainPolicy")) &&	    (certFreeCertificateChain = (CFCC)	     GetProcAddress (lib,"CertFreeCertificateChain")) &&	    (certFreeCertificateContext = (CFCCX)	     GetProcAddress (lib,"CertFreeCertificateContext")))	  certNameToStr = (CNTS) GetProcAddress (lib,"CertNameToStrA");	return;			/* all done */      }    }  }}/* SSL open * Accepts: host name *	    contact service name *	    contact port number * Returns: SSL stream if success else NIL */SSLSTREAM *ssl_open (char *host,char *service,unsigned long port){  TCPSTREAM *stream = tcp_open (host,service,port);  return stream ? ssl_start (stream,host,port) : NIL;}  /* SSL authenticated open * Accepts: host name *	    service name *	    returned user name buffer * Returns: SSL stream if success else NIL */SSLSTREAM *ssl_aopen (NETMBX *mb,char *service,char *usrbuf){  return NIL;			/* don't use this mechanism with SSL */}/* Start SSL/TLS negotiations * Accepts: open TCP stream of session *	    user's host name *	    flags * Returns: SSL stream if success else NIL */static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags){  SECURITY_STATUS e;  ULONG a;  TimeStamp t;  SecBuffer ibuf[2],obuf[1];  SecBufferDesc ibufs,obufs;  SCHANNEL_CRED tlscred;  CERT_CONTEXT *cert = NIL;  CERT_CHAIN_PARA chparam;  CERT_CHAIN_CONTEXT *chain;  SSL_EXTRA_CERT_CHAIN_POLICY_PARA policy;  CERT_CHAIN_POLICY_PARA polparam;  CERT_CHAIN_POLICY_STATUS status;  char tmp[MAILTMPLEN],certname[256];  char *reason = NIL;  ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT |    ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY |      ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR |	ISC_REQ_MANUAL_CRED_VALIDATION;  LPSTR usage[] = {    szOID_PKIX_KP_SERVER_AUTH,    szOID_SERVER_GATED_CRYPTO,    szOID_SGC_NETSCAPE  };  PWSTR whost = NIL;  char *buf = (char *) fs_get (ssltsz);  unsigned long size = 0;  sslcertificatequery_t scq =    (sslcertificatequery_t) mail_parameters (NIL,GET_SSLCERTIFICATEQUERY,NIL);  sslfailure_t sf = (sslfailure_t) mail_parameters (NIL,GET_SSLFAILURE,NIL);  SSLSTREAM *stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0,					    sizeof (SSLSTREAM));  stream->tcpstream = tstream;	/* bind TCP stream */				/* initialize TLS credential */  memset (&tlscred,0,sizeof (SCHANNEL_CRED));  tlscred.dwVersion = SCHANNEL_CRED_VERSION;  tlscred.grbitEnabledProtocols = SP_PROT_TLS1;				/* acquire credentials */  if (sft->AcquireCredentialsHandle      (NIL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NIL,(flags & NET_TLSCLIENT) ?       &tlscred : NIL,NIL,NIL,&stream->cred,&t)      != SEC_E_OK) reason = "Acquire credentials handle failed";  else while (!reason) {	/* negotiate security context */				/* initialize buffers */    ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = buf;    ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NIL;    obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL;    ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;    ibuf[1].BufferType = SECBUFFER_EMPTY;				/* initialize buffer descriptors */    ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION;    ibufs.cBuffers = 2; obufs.cBuffers = 1;    ibufs.pBuffers = ibuf; obufs.pBuffers = obuf;				/* negotiate security */    e = sft->InitializeSecurityContext      (&stream->cred,size ? &stream->context : NIL,host,req,0,       SECURITY_NETWORK_DREP,size? &ibufs:NIL,0,&stream->context,&obufs,&a,&t);				/* have an output buffer we need to send? */    if (obuf[0].pvBuffer && obuf[0].cbBuffer) {      if (!tcp_sout (stream->tcpstream,obuf[0].pvBuffer,obuf[0].cbBuffer))	reason = "Unexpected TCP output disconnect";				/* free the buffer */      sft->FreeContextBuffer (obuf[0].pvBuffer);    }    if (!reason) switch (e) {	/* negotiation state */    case SEC_I_INCOMPLETE_CREDENTIALS:      break;			/* server wants client auth */    case SEC_I_CONTINUE_NEEDED:      if (size) {		/* continue, read any data? */				/* yes, anything regurgiated back to us? */	if (ibuf[1].BufferType == SECBUFFER_EXTRA) {				/* yes, set this as the new data */	  memmove (buf,buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);	  size = ibuf[1].cbBuffer;	  break;	}	size = 0;		/* otherwise, read more stuff from server */      }    case SEC_E_INCOMPLETE_MESSAGE:				/* need to read more data from server */      if (!tcp_getdata (stream->tcpstream))	reason = "Unexpected TCP input disconnect";      else {	memcpy (buf+size,stream->tcpstream->iptr,stream->tcpstream->ictr);	size += stream->tcpstream->ictr;				/* empty it from TCP's buffers */	stream->tcpstream->iptr += stream->tcpstream->ictr;	stream->tcpstream->ictr = 0;      }      break;    case SEC_E_OK:		/* success, any data to be regurgitated? */      if (ibuf[1].BufferType == SECBUFFER_EXTRA) {				/* yes, set this as the new data */	memmove (stream->tcpstream->iptr = stream->tcpstream->ibuf,		 buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer);	stream->tcpstream->ictr = ibuf[1].cbBuffer;      }      if (certNameToStr && !(flags & NET_NOVALIDATECERT)) {				/* need validation, make wchar of host */	if (!((size = MultiByteToWideChar (CP_ACP,0,host,-1,NIL,0)) &&	      (whost = (PWSTR) fs_get (size*sizeof (WCHAR))) &&	      MultiByteToWideChar (CP_ACP,0,host,-1,whost,size)))	  fatal ("Can't make wchar of host name!");				/* get certificate */	if ((sft->QueryContextAttributes	     (&stream->context,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&cert) !=	     SEC_E_OK) || !cert) {	  reason = "*Unable to get certificate";	  strcpy (certname,"<no certificate>");	}	else {			/* get certificate subject name */	  (*certNameToStr) (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,			    &cert->pCertInfo->Subject,CERT_X500_NAME_STR,			    certname,255);				/* build certificate chain */	  memset (&chparam,0,sizeof (chparam));	  chparam.cbSize = sizeof (chparam);	  chparam.RequestedUsage.dwType = USAGE_MATCH_TYPE_OR;	  chparam.RequestedUsage.Usage.rgpszUsageIdentifier = usage;	  chparam.RequestedUsage.Usage.cUsageIdentifier =	    sizeof (usage) / sizeof (LPSTR);	  if (!(*certGetCertificateChain)	      (NIL,cert,NIL,cert->hCertStore,&chparam,NIL,NIL,&chain))	    reason = ssl_analyze_status (GetLastError (),tmp);	  else {		/* validate certificate chain */	    memset (&policy,0,sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA));	    policy.cbStruct = sizeof (SSL_EXTRA_CERT_CHAIN_POLICY_PARA);	    policy.dwAuthType = AUTHTYPE_SERVER;	    policy.fdwChecks = NIL;	    policy.pwszServerName = whost;	    memset (&polparam,0,sizeof (polparam));	    polparam.cbSize = sizeof (polparam);	    polparam.pvExtraPolicyPara = &policy;	    memset (&status,0,sizeof (status));	    status.cbSize = sizeof (status);	    if (!(*certVerifyCertificateChainPolicy)		(CERT_CHAIN_POLICY_SSL,chain,&polparam,&status))	      reason = ssl_analyze_status (GetLastError (),tmp);	    else if (status.dwError)	      reason = ssl_analyze_status (status.dwError,tmp);	    (*certFreeCertificateChain) (chain);	  }	  (*certFreeCertificateContext) (cert);	}	if (whost) fs_give ((void **) &whost);	if (reason) {		/* got an error? */				/* application callback */	  if (scq) reason = (*scq) ((*reason == '*') ? reason + 1 : reason,				    host,certname) ? NIL : "";	  else if (*certname) {	/* error message to return via mm_log() */	    sprintf (buf,"*%.128s: %.255s",		     (*reason == '*') ? reason + 1 : reason,certname);	    reason = buf;	  }	}      }      if (reason ||	  (reason = ssl_analyze_status	   (sft->QueryContextAttributes	    (&stream->context,SECPKG_ATTR_STREAM_SIZES,&stream->sizes),buf)))	break;			/* error in certificate or getting sizes */      fs_give ((void **) &buf);	/* flush temporary buffer */				/* make maximum-sized buffers */      stream->bufsize = stream->sizes.cbHeader +	stream->sizes.cbMaximumMessage + stream->sizes.cbTrailer;      if (stream->sizes.cbMaximumMessage < SSLBUFLEN)	fatal ("cbMaximumMessage is less than SSLBUFLEN!");      else if (stream->sizes.cbMaximumMessage < 16384) {	sprintf (tmp,"WINDOWS BUG: cbMaximumMessage = %ld, should be 16384",		 (long) stream->sizes.cbMaximumMessage);	mm_log (tmp,NIL);      }      stream->ibuf = (char *) fs_get (stream->bufsize);      stream->obuf = (char *) fs_get (stream->bufsize);      return stream;    default:      reason = ssl_analyze_status (e,buf);    }  }  ssl_close (stream);		/* failed to do SSL */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -