|
ssl_nt
ssl_nt
/*
* 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: 11 December 2003
*
* The IMAP toolkit provided in this Distribution is
* Copyright 1988-2003 University of Washington.
* The full text of our legal notices is contained in the file called
* CPYRIGHT, included with this Distribution.
*/
#define SECURITY_WIN32
#include
#include
#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 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);
static CNTS certNameToStr = NIL;
static CGCC certGetCertificateChain = NIL;
static CVCCP certVerifyCertificateChainPolicy = NIL;
static CFCC certFreeCertificateChain = 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")))
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;
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,"");
}
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);
}
}
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 */
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 */
Cheap PHP Web Hosting
/*----------------------------------------------------------------------
$Id: os-pt1.h,v 1.47 2003/05/23 16:05:21 hubert Exp $
T H E P I N E M A I L S Y S T E M
Laurence Lundblade and Mike Seibel
Networks and Distributed Computing
Computing and Communications
University of Washington
Administration Builiding, AG-44
Seattle, Washington, 98195, USA
Internet: lgl@CAC.Washington.EDU
mikes@CAC.Washington.EDU
Please address all bugs and comments to "pine-bugs@cac.washington.edu"
Pine and Pico are registered trademarks of the University of Washington.
No commercial use of these trademarks may be made without prior written
permission of the University of Washington.
Pine, Pico, and Pilot software and its included text are Copyright
1989-1998 by the University of Washington.
The full text of our legal notices is contained in the file called
CPYRIGHT, included with this distribution.
Pine is in part based on The Elm Mail System:
***********************************************************************
* The Elm Mail System - Revision: 2.13 *
* *
* Copyright (c) 1986, 1987 Dave Taylor *
* Copyright (c) 1988, 1989 USENET Community Trust *
***********************************************************************
----------------------------------------------------------------------*/
#ifndef _OS_INCLUDED
#define _OS_INCLUDED
#include "../c-client/osdep.h"
/*----------------------------------------------------------------------
This first section has some constants that you may want to change
for your configuration. This is the Dynix/PTX 1.4 version of the os.h file.
Further down in the file are os-dependent things that need to be set up
correctly for each os. They aren't interesting, they just have to be
right. There are also a few constants down there that may be of
interest to some.
----*/
/*----------------------------------------------------------------------
Define this if you want the disk quota to be checked on startup.
Of course, this only makes sense if your system has quotas. If it doesn't,
there should be a dummy disk_quota() routine in os-xxx.c so that defining
this won't be harmful anyway.
----*/
/* #define USE_QUOTAS */
/*----------------------------------------------------------------------
Define this if you want to be sure to not allow users to change their
From header line when they send out mail. Even if you don't define
this the default is to not allow From to be changed. The user would have
to edit (by hand) "allow-changing-from" into their .pinerc feature list
or the sys-admin would have to include it in the default feature-list.
Even after that, the user still has to include it in either their
default-composer-hdrs or customized-hdrs to get at it. Instead of
defining NEVER_ALLOW_CHANGING_FROM, an easier way of preventing From
changing is to put the feature "no-allow-changing-from" in the
/usr/local/lib/pine.conf.fixed file.
----*/
/* #define NEVER_ALLOW_CHANGING_FROM */
/*----------------------------------------------------------------------
Define this if you want to allow users to turn on the feature that
enables sending to take place in a fork()'d child. This may reduce
the time on the user's wall clock it takes to post mail.
NOTE: You'll also have to make sure the appropriate osdep/postreap.*
file is included in the os-*.ic file for your system.
----*/
/* #define BACKGROUND_POST */
/*----------------------------------------------------------------------
Turn this on if you want to disable the keyboard lock function.
----*/
/* #define NO_KEYBOARD_LOCK */
/*----------------------------------------------------------------------
Turn this on to trigger QP encoding of sent message text if it contains
"From " at the beginning of a line or "." on a line by itself.
----*/
/* #define ENCODE_FROMS */
/*----------------------------------------------------------------------
Timeouts (seconds)
----*/
#ifndef DF_MAILCHECK
#define DF_MAILCHECK "150" /* How often to check for new mail, by
default. There's some expense in doing
this so it shouldn't be done too
frequently. (Can be set in config
file now.) */
#endif
/*----------------------------------------------------------------------
Check pointing (seconds)
----*/
#define CHECK_POINT_TIME (7*60) /* Check point the mail file (write changes
to disk) if more than CHECK_POINT_TIME
seconds have passed since the first
change was made. Depending on what is
happening, we may wait up to three times
this long, since we don't want to do the
slow check pointing and irritate the user. */
#define CHECK_POINT_FREQ (12) /* Check point the mail file if there have been
at least this many (status) changes to the
current mail file. We may wait longer if
it isn't a good time to do the checkpoint. */
/*----------------------------------------------------------------------
In scrolling through text, the number of lines from the previous
screen to overlap when showing the next screen. Usually set to two.
----*/
#define DF_OVERLAP "2"
/*----------------------------------------------------------------------
When scrolling screens, the number of lines from top and bottom of
the screen to initiate single-line scrolling.
----*/
#define DF_MARGIN "0"
/*----------------------------------------------------------------------
Default fill column for pine composer and maximum fill column. The max
is used to stop people from setting their custom fill column higher than
that number. Note that DF_FILLCOL is a string but MAX_FILLCOL is an integer.
----*/
#define DF_FILLCOL "74"
#define MAX_FILLCOL 80
/*----- System-wide config file ----------------------------------------*/
#ifndef SYSTEM_PINERC
#define SYSTEM_PINERC "/usr/local/lib/pine.conf"
#endif
#ifndef SYSTEM_PINERC_FIXED
#define SYSTEM_PINERC_FIXED "/usr/local/lib/pine.conf.fixed"
#endif
/*----------------------------------------------------------------------
The default folder names and folder directories (some for backwards
compatibility). Think hard before changing any of these.
----*/
#define DF_DEFAULT_FCC "sent-mail"
#define DEFAULT_SAVE "saved-messages"
#define POSTPONED_MAIL "postponed-mail"
#define POSTPONED_MSGS "postponed-msgs"
#define INTERRUPTED_MAIL ".pine-interrupted-mail"
#define DEADLETTER "dead.letter"
#define DF_MAIL_DIRECTORY "mail"
#define INBOX_NAME "INBOX"
#define DF_SIGNATURE_FILE ".signature"
#define DF_ELM_STYLE_SAVE "no"
#define DF_HEADER_IN_REPLY "no"
#define DF_OLD_STYLE_REPLY "no"
#define DF_USE_ONLY_DOMAIN_NAME "no"
#define DF_FEATURE_LEVEL "sapling"
#define DF_SAVE_BY_SENDER "no"
#define DF_SORT_KEY "arrival"
#define DF_AB_SORT_RULE "fullname-with-lists-last"
#define DF_FLD_SORT_RULE "alphabetical"
#define DF_SAVED_MSG_NAME_RULE "default-folder"
#define DF_FCC_RULE "default-fcc"
#define DF_STANDARD_PRINTER "lpr"
#define ANSI_PRINTER "attached-to-ansi"
#define DF_ADDRESSBOOK ".addressbook"
#define DF_BUGS_FULLNAME "Pine Developers"
#define DF_BUGS_ADDRESS "pine-bugs@cac.washington.edu"
#define DF_SUGGEST_FULLNAME "Pine Developers"
#define DF_SUGGEST_ADDRESS "pine-suggestions@cac.washington.edu"
#define DF_PINEINFO_FULLNAME "Pine-Info News Group"
#define DF_PINEINFO_ADDRESS "pine-info@cac.washington.edu"
#define DF_LOCAL_FULLNAME "Local Support"
#define DF_LOCAL_ADDRESS "postmaster"
#define DF_KBLOCK_PASSWD_COUNT "1"
#define DF_REMOTE_ABOOK_HISTORY "3"
/*----------------------------------------------------------------------
The default printer when pine starts up for the first time with no printer
----*/
#define DF_DEFAULT_PRINTER ANSI_PRINTER
/*----- The usual sendmail configuration for sending mail on Unix ------*/
#ifndef SENDMAIL
#define SENDMAIL "/usr/lib/sendmail"
#endif
#ifndef SENDMAILFLAGS
#define SENDMAILFLAGS "-bs -odb -oem" /* send via smtp with backgroud
delivery and mail back errors */
#endif
/*----------------------------------------------------------------------
If no nntp-servers are defined, this program will be used to post news.
----*/
/* #define SENDNEWS "/usr/local/bin/inews -h" */
/*--------- Program employed by users to change their password ---------*/
#ifndef PASSWD_PROG
#define PASSWD_PROG "/bin/passwd"
#endif
/*-------------- A couple constants used to size arrays ----------------*/
#include /* Get it from param.h if available */
#undef MAXPATH /* Sometimes defined in param.h differently */
#define MAXPATH MAXPATHLEN /* Longest pathname we ever expect */
/* #define MAXPATH (512) */ /* Longest pathname we ever expect */
#define MAXFOLDER (128) /* Longest foldername we ever expect */
/*-- Max screen pine will display on. Used to define some array sizes --*/
#define MAX_SCREEN_COLS (170)
#define MAX_SCREEN_ROWS (200)
/*----------------------------------------------------------------------
Where to put the output of pine in debug mode. Files are created
in the user's home directory and have a number appended to them when
there is more than one.
----*/
#define DEBUGFILE ".pine-debug"
/*----------------------------------------------------------------------
The number of debug files to save in the user's home diretory. The files
are useful for figuring out what a user did when he complains that something
went wrong. It's important to keep a bunch around, usually 4, so that the
debug file in question will still be around when the problem gets
investigated. Users tend to go in and out of Pine a few times and there
is one file for each pine invocation
----*/
#define NUMDEBUGFILES 4
/*----------------------------------------------------------------------
The default debug level to set (approximate meanings):
1 logs only highest level events and errors
2 logs events like file writes
3
4 logs each command
5
6
7 logs details of command execution (7 is highest to run any production)
8
9 logs gross details of command execution
----*/
#define DEFAULT_DEBUG 2
/*----------------------------------------------------------------------
Various maximum field lengths, probably shouldn't be changed.
----*/
#define MAX_FULLNAME (100)
#define MAX_NICKNAME (80)
#define MAX_ADDRESS (500)
#define MAX_NEW_LIST (500) /* Max addrs to be added when creating list */
#define MAX_SEARCH (100) /* Longest string to search for */
#define MAX_ADDR_EXPN (1000) /* Longest expanded addr */
#define MAX_ADDR_FIELD (10000) /* Longest fully-expanded addr field */
#endif /* _OS_INCLUDED */
Page:
1
2
3
4
5
6
7
8
9
10
Cheap PHP Web Hosting
PHP Hosting
JSP PHP Hosting
PHP Hosting plans
|