imapext-2007
diff src/osdep/nt/ssl_old.c @ 0:ada5e610ab86
imap-2007e
author | yuuji@gentei.org |
---|---|
date | Mon, 14 Sep 2009 15:17:45 +0900 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/osdep/nt/ssl_old.c Mon Sep 14 15:17:45 2009 +0900 1.3 @@ -0,0 +1,625 @@ 1.4 +/* ======================================================================== 1.5 + * Copyright 1988-2008 University of Washington 1.6 + * 1.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.8 + * you may not use this file except in compliance with the License. 1.9 + * You may obtain a copy of the License at 1.10 + * 1.11 + * http://www.apache.org/licenses/LICENSE-2.0 1.12 + * 1.13 + * 1.14 + * ======================================================================== 1.15 + */ 1.16 + 1.17 +/* 1.18 + * Program: SSL authentication/encryption module for Windows 9x and NT 1.19 + * 1.20 + * Author: Mark Crispin 1.21 + * Networks and Distributed Computing 1.22 + * Computing & Communications 1.23 + * University of Washington 1.24 + * Administration Building, AG-44 1.25 + * Seattle, WA 98195 1.26 + * Internet: MRC@CAC.Washington.EDU 1.27 + * 1.28 + * Date: 22 September 1998 1.29 + * Last Edited: 13 January 2008 1.30 + */ 1.31 + 1.32 +#define SECURITY_WIN32 1.33 +#include <sspi.h> 1.34 +#if(_WIN32_WINNT < 0x0400) 1.35 +typedef unsigned int ALG_ID; 1.36 +#else 1.37 +#include <wincrypt.h> 1.38 +ALGIDDEF 1.39 +#endif 1.40 +#include <schnlsp.h> 1.41 +#include <issperr.h> 1.42 + 1.43 + /* in case a binary runs on Windows 2000 */ 1.44 +#ifndef ISC_REQ_MANUAL_CRED_VALIDATION 1.45 +#define ISC_REQ_MANUAL_CRED_VALIDATION 0x00080000 1.46 +#endif 1.47 +#ifndef SEC_E_UNTRUSTED_ROOT 1.48 +#define SEC_E_UNTRUSTED_ROOT ((HRESULT) 0x80090325L) 1.49 +#endif 1.50 +#ifndef SEC_E_CERT_EXPIRED 1.51 +#define SEC_E_CERT_EXPIRED ((HRESULT) 0x80090328L) 1.52 +#endif 1.53 + 1.54 + 1.55 +#define SSLBUFLEN 8192 1.56 + 1.57 + 1.58 +/* SSL I/O stream */ 1.59 + 1.60 +typedef struct ssl_stream { 1.61 + TCPSTREAM *tcpstream; /* TCP stream */ 1.62 + CredHandle cred; /* SSL credentials */ 1.63 + CtxtHandle context; /* SSL context */ 1.64 + /* stream encryption sizes */ 1.65 + SecPkgContext_StreamSizes sizes; 1.66 + size_t bufsize; 1.67 + int ictr; /* input counter */ 1.68 + char *iptr; /* input pointer */ 1.69 + int iextractr; /* extra input counter */ 1.70 + char *iextraptr; /* extra input pointer */ 1.71 + char *ibuf; /* input buffer */ 1.72 + char *obuf; /* output buffer */ 1.73 +} SSLSTREAM; 1.74 + 1.75 +#include "sslio.h" 1.76 + 1.77 + 1.78 +/* Function prototypes */ 1.79 + 1.80 +static SSLSTREAM *ssl_start(TCPSTREAM *tstream,char *host,unsigned long flags); 1.81 +static char *ssl_analyze_status (SECURITY_STATUS err,char *buf); 1.82 +static char *ssl_getline_work (SSLSTREAM *stream,unsigned long *size, 1.83 + long *contd); 1.84 +static long ssl_abort (SSLSTREAM *stream); 1.85 + 1.86 +/* Secure Sockets Layer network driver dispatch */ 1.87 + 1.88 +static struct ssl_driver ssldriver = { 1.89 + ssl_open, /* open connection */ 1.90 + ssl_aopen, /* open preauthenticated connection */ 1.91 + ssl_getline, /* get a line */ 1.92 + ssl_getbuffer, /* get a buffer */ 1.93 + ssl_soutr, /* output pushed data */ 1.94 + ssl_sout, /* output string */ 1.95 + ssl_close, /* close connection */ 1.96 + ssl_host, /* return host name */ 1.97 + ssl_remotehost, /* return remote host name */ 1.98 + ssl_port, /* return port number */ 1.99 + ssl_localhost /* return local host name */ 1.100 +}; 1.101 + 1.102 + /* security function table */ 1.103 +static SecurityFunctionTable *sft = NIL; 1.104 +static unsigned long ssltsz = 0;/* SSL maximum token length */ 1.105 + 1.106 +/* One-time SSL initialization */ 1.107 + 1.108 +static int sslonceonly = 0; 1.109 + 1.110 +void ssl_onceonlyinit (void) 1.111 +{ 1.112 + if (!sslonceonly++) { /* only need to call it once */ 1.113 + HINSTANCE lib; 1.114 + FARPROC pi; 1.115 + ULONG np; 1.116 + SecPkgInfo *pp; 1.117 + int i; 1.118 + /* get security library */ 1.119 + if (((lib = LoadLibrary ("schannel.dll")) || 1.120 + (lib = LoadLibrary ("security.dll"))) && 1.121 + (pi = GetProcAddress (lib,SECURITY_ENTRYPOINT)) && 1.122 + (sft = (SecurityFunctionTable *) pi ()) && 1.123 + !(sft->EnumerateSecurityPackages (&np,&pp))) { 1.124 + /* look for an SSL package */ 1.125 + for (i = 0; (i < (int) np); i++) if (!strcmp (pp[i].Name,UNISP_NAME)) { 1.126 + /* note maximum token size and name */ 1.127 + ssltsz = pp[i].cbMaxToken; 1.128 + /* apply runtime linkage */ 1.129 + mail_parameters (NIL,SET_SSLDRIVER,(void *) &ssldriver); 1.130 + mail_parameters (NIL,SET_SSLSTART,(void *) ssl_start); 1.131 + return; /* all done */ 1.132 + } 1.133 + } 1.134 + } 1.135 +} 1.136 + 1.137 +/* SSL open 1.138 + * Accepts: host name 1.139 + * contact service name 1.140 + * contact port number 1.141 + * Returns: SSL stream if success else NIL 1.142 + */ 1.143 + 1.144 +SSLSTREAM *ssl_open (char *host,char *service,unsigned long port) 1.145 +{ 1.146 + TCPSTREAM *stream = tcp_open (host,service,port); 1.147 + return stream ? ssl_start (stream,host,port) : NIL; 1.148 +} 1.149 + 1.150 + 1.151 +/* SSL authenticated open 1.152 + * Accepts: host name 1.153 + * service name 1.154 + * returned user name buffer 1.155 + * Returns: SSL stream if success else NIL 1.156 + */ 1.157 + 1.158 +SSLSTREAM *ssl_aopen (NETMBX *mb,char *service,char *usrbuf) 1.159 +{ 1.160 + return NIL; /* don't use this mechanism with SSL */ 1.161 +} 1.162 + 1.163 +/* Start SSL/TLS negotiations 1.164 + * Accepts: open TCP stream of session 1.165 + * user's host name 1.166 + * flags 1.167 + * Returns: SSL stream if success else NIL 1.168 + */ 1.169 + 1.170 +static SSLSTREAM *ssl_start (TCPSTREAM *tstream,char *host,unsigned long flags) 1.171 +{ 1.172 + SECURITY_STATUS e; 1.173 + ULONG a; 1.174 + TimeStamp t; 1.175 + SecBuffer ibuf[2],obuf[1]; 1.176 + SecBufferDesc ibufs,obufs; 1.177 + char tmp[MAILTMPLEN]; 1.178 + char *reason = NIL; 1.179 + ULONG req = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | 1.180 + ISC_REQ_CONFIDENTIALITY | ISC_REQ_USE_SESSION_KEY | 1.181 + ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM | ISC_REQ_EXTENDED_ERROR + 1.182 + ((flags & NET_NOVALIDATECERT) ? ISC_REQ_MANUAL_CRED_VALIDATION : 1.183 + ISC_REQ_MUTUAL_AUTH); 1.184 + SCHANNEL_CRED tlscred; 1.185 + char *buf = (char *) fs_get (ssltsz); 1.186 + unsigned long size = 0; 1.187 + sslfailure_t sf = (sslfailure_t) mail_parameters (NIL,GET_SSLFAILURE,NIL); 1.188 + SSLSTREAM *stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0, 1.189 + sizeof (SSLSTREAM)); 1.190 + stream->tcpstream = tstream; /* bind TCP stream */ 1.191 + /* initialize TLS credential */ 1.192 + memset (&tlscred,0,sizeof (SCHANNEL_CRED)); 1.193 + tlscred.dwVersion = SCHANNEL_CRED_VERSION; 1.194 + tlscred.grbitEnabledProtocols = SP_PROT_TLS1; 1.195 + 1.196 + /* acquire credentials */ 1.197 + if (sft->AcquireCredentialsHandle 1.198 + (NIL,UNISP_NAME,SECPKG_CRED_OUTBOUND,NIL,(flags & NET_TLSCLIENT) ? 1.199 + &tlscred : NIL,NIL,NIL,&stream->cred,&t) 1.200 + != SEC_E_OK) reason = "Acquire credentials handle failed"; 1.201 + else while (!reason) { /* negotiate security context */ 1.202 + /* initialize buffers */ 1.203 + ibuf[0].cbBuffer = size; ibuf[0].pvBuffer = buf; 1.204 + ibuf[1].cbBuffer = 0; ibuf[1].pvBuffer = NIL; 1.205 + obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL; 1.206 + ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN; 1.207 + ibuf[1].BufferType = SECBUFFER_EMPTY; 1.208 + /* initialize buffer descriptors */ 1.209 + ibufs.ulVersion = obufs.ulVersion = SECBUFFER_VERSION; 1.210 + ibufs.cBuffers = 2; obufs.cBuffers = 1; 1.211 + ibufs.pBuffers = ibuf; obufs.pBuffers = obuf; 1.212 + /* negotiate security */ 1.213 + e = sft->InitializeSecurityContext 1.214 + (&stream->cred,size ? &stream->context : NIL,host,req,0, 1.215 + SECURITY_NETWORK_DREP,size? &ibufs:NIL,0,&stream->context,&obufs,&a,&t); 1.216 + /* have an output buffer we need to send? */ 1.217 + if (obuf[0].pvBuffer && obuf[0].cbBuffer) { 1.218 + if (!tcp_sout (stream->tcpstream,obuf[0].pvBuffer,obuf[0].cbBuffer)) 1.219 + reason = "Unexpected TCP output disconnect"; 1.220 + /* free the buffer */ 1.221 + sft->FreeContextBuffer (obuf[0].pvBuffer); 1.222 + } 1.223 + if (!reason) switch (e) { /* negotiation state */ 1.224 + case SEC_I_INCOMPLETE_CREDENTIALS: 1.225 + break; /* server wants client auth */ 1.226 + case SEC_I_CONTINUE_NEEDED: 1.227 + if (size) { /* continue, read any data? */ 1.228 + /* yes, anything regurgiated back to us? */ 1.229 + if (ibuf[1].BufferType == SECBUFFER_EXTRA) { 1.230 + /* yes, set this as the new data */ 1.231 + memmove (buf,buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer); 1.232 + size = ibuf[1].cbBuffer; 1.233 + break; 1.234 + } 1.235 + size = 0; /* otherwise, read more stuff from server */ 1.236 + } 1.237 + case SEC_E_INCOMPLETE_MESSAGE: 1.238 + /* need to read more data from server */ 1.239 + if (!tcp_getdata (stream->tcpstream)) 1.240 + reason = "Unexpected TCP input disconnect"; 1.241 + else { 1.242 + memcpy (buf+size,stream->tcpstream->iptr,stream->tcpstream->ictr); 1.243 + size += stream->tcpstream->ictr; 1.244 + /* empty it from TCP's buffers */ 1.245 + stream->tcpstream->iptr += stream->tcpstream->ictr; 1.246 + stream->tcpstream->ictr = 0; 1.247 + } 1.248 + break; 1.249 + 1.250 + case SEC_E_OK: /* success, any data to be regurgitated? */ 1.251 + if (ibuf[1].BufferType == SECBUFFER_EXTRA) { 1.252 + /* yes, set this as the new data */ 1.253 + memmove (stream->tcpstream->iptr = stream->tcpstream->ibuf, 1.254 + buf + size - ibuf[1].cbBuffer,ibuf[1].cbBuffer); 1.255 + stream->tcpstream->ictr = ibuf[1].cbBuffer; 1.256 + } 1.257 + if (reason = ssl_analyze_status 1.258 + (sft->QueryContextAttributes 1.259 + (&stream->context,SECPKG_ATTR_STREAM_SIZES,&stream->sizes),buf)) 1.260 + break; /* error getting sizes */ 1.261 + fs_give ((void **) &buf); /* flush temporary buffer */ 1.262 + /* make maximum-sized buffers */ 1.263 + stream->bufsize = stream->sizes.cbHeader + 1.264 + stream->sizes.cbMaximumMessage + stream->sizes.cbTrailer; 1.265 + if (stream->sizes.cbMaximumMessage < SSLBUFLEN) 1.266 + fatal ("cbMaximumMessage is less than SSLBUFLEN!"); 1.267 + else if (stream->sizes.cbMaximumMessage < 16384) { 1.268 + sprintf (tmp,"WINDOWS BUG: cbMaximumMessage = %ld, should be 16384", 1.269 + (long) stream->sizes.cbMaximumMessage); 1.270 + mm_log (tmp,NIL); 1.271 + } 1.272 + stream->ibuf = (char *) fs_get (stream->bufsize); 1.273 + stream->obuf = (char *) fs_get (stream->bufsize); 1.274 + return stream; 1.275 + default: 1.276 + reason = ssl_analyze_status (e,buf); 1.277 + } 1.278 + } 1.279 + ssl_close (stream); /* failed to do SSL */ 1.280 + stream = NIL; /* no stream returned */ 1.281 + fs_give ((void **) &buf); /* flush temporary buffer */ 1.282 + switch (*reason) { /* analyze reason */ 1.283 + case '*': /* certificate failure */ 1.284 + ++reason; /* skip over certificate failure indication */ 1.285 + /* pass to error callback */ 1.286 + if (sf) (*sf) (host,reason,flags); 1.287 + else { /* no error callback, build error message */ 1.288 + sprintf (tmp,"Certificate failure for %.80s: %.512s",host,reason); 1.289 + mm_log (tmp,ERROR); 1.290 + } 1.291 + case '\0': /* user answered no to certificate callback */ 1.292 + if (flags & NET_TRYSSL) /* return dummy stream to stop tryssl */ 1.293 + stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0, 1.294 + sizeof (SSLSTREAM)); 1.295 + break; 1.296 + default: /* non-certificate failure */ 1.297 + if (flags & NET_TRYSSL); /* no error output if tryssl */ 1.298 + /* pass to error callback */ 1.299 + else if (sf) (*sf) (host,reason,flags); 1.300 + else { /* no error callback, build error message */ 1.301 + sprintf (tmp,"TLS/SSL failure for %.80s: %.512s",host,reason); 1.302 + mm_log (tmp,ERROR); 1.303 + } 1.304 + break; 1.305 + } 1.306 + return stream; 1.307 +} 1.308 + 1.309 +/* Generate error text from SSL error code 1.310 + * Accepts: SSL status 1.311 + * scratch buffer 1.312 + * Returns: text if error status, else NIL 1.313 + */ 1.314 + 1.315 +static char *ssl_analyze_status (SECURITY_STATUS err,char *buf) 1.316 +{ 1.317 + switch (err) { 1.318 + case SEC_E_OK: /* no error */ 1.319 + case SEC_I_CONTINUE_NEEDED: 1.320 + case SEC_I_INCOMPLETE_CREDENTIALS: 1.321 + case SEC_E_INCOMPLETE_MESSAGE: 1.322 + return NIL; 1.323 + case SEC_E_NO_AUTHENTICATING_AUTHORITY: 1.324 + return "*No authority could be contacted for authentication"; 1.325 + case SEC_E_WRONG_PRINCIPAL: 1.326 + return "*Server name does not match certificate"; 1.327 + case SEC_E_UNTRUSTED_ROOT: 1.328 + return "*Self-signed certificate or untrusted authority"; 1.329 + case SEC_E_CERT_EXPIRED: 1.330 + return "*Certificate has expired"; 1.331 + case SEC_E_INVALID_TOKEN: 1.332 + return "Invalid token, probably not an SSL server"; 1.333 + case SEC_E_UNSUPPORTED_FUNCTION: 1.334 + return "SSL not supported on this machine - upgrade your system software"; 1.335 + } 1.336 + sprintf (buf,"Unexpected SChannel error %lx - report this",err); 1.337 + return buf; 1.338 +} 1.339 + 1.340 +/* SSL receive line 1.341 + * Accepts: SSL stream 1.342 + * Returns: text line string or NIL if failure 1.343 + */ 1.344 + 1.345 +char *ssl_getline (SSLSTREAM *stream) 1.346 +{ 1.347 + unsigned long n,contd; 1.348 + char *ret = ssl_getline_work (stream,&n,&contd); 1.349 + if (ret && contd) { /* got a line needing continuation? */ 1.350 + STRINGLIST *stl = mail_newstringlist (); 1.351 + STRINGLIST *stc = stl; 1.352 + do { /* collect additional lines */ 1.353 + stc->text.data = (unsigned char *) ret; 1.354 + stc->text.size = n; 1.355 + stc = stc->next = mail_newstringlist (); 1.356 + ret = ssl_getline_work (stream,&n,&contd); 1.357 + } while (ret && contd); 1.358 + if (ret) { /* stash final part of line on list */ 1.359 + stc->text.data = (unsigned char *) ret; 1.360 + stc->text.size = n; 1.361 + /* determine how large a buffer we need */ 1.362 + for (n = 0, stc = stl; stc; stc = stc->next) n += stc->text.size; 1.363 + ret = fs_get (n + 1); /* copy parts into buffer */ 1.364 + for (n = 0, stc = stl; stc; n += stc->text.size, stc = stc->next) 1.365 + memcpy (ret + n,stc->text.data,stc->text.size); 1.366 + ret[n] = '\0'; 1.367 + } 1.368 + mail_free_stringlist (&stl);/* either way, done with list */ 1.369 + } 1.370 + return ret; 1.371 +} 1.372 + 1.373 +/* SSL receive line or partial line 1.374 + * Accepts: SSL stream 1.375 + * pointer to return size 1.376 + * pointer to return continuation flag 1.377 + * Returns: text line string, size and continuation flag, or NIL if failure 1.378 + */ 1.379 + 1.380 +static char *ssl_getline_work (SSLSTREAM *stream,unsigned long *size, 1.381 + long *contd) 1.382 +{ 1.383 + unsigned long n; 1.384 + char *s,*ret,c,d; 1.385 + *contd = NIL; /* assume no continuation */ 1.386 + /* make sure have data */ 1.387 + if (!ssl_getdata (stream)) return NIL; 1.388 + for (s = stream->iptr, n = 0, c = '\0'; stream->ictr--; n++, c = d) { 1.389 + d = *stream->iptr++; /* slurp another character */ 1.390 + if ((c == '\015') && (d == '\012')) { 1.391 + ret = (char *) fs_get (n--); 1.392 + memcpy (ret,s,*size = n); /* copy into a free storage string */ 1.393 + ret[n] = '\0'; /* tie off string with null */ 1.394 + return ret; 1.395 + } 1.396 + } 1.397 + /* copy partial string from buffer */ 1.398 + memcpy ((ret = (char *) fs_get (n)),s,*size = n); 1.399 + /* get more data from the net */ 1.400 + if (!ssl_getdata (stream)) fs_give ((void **) &ret); 1.401 + /* special case of newline broken by buffer */ 1.402 + else if ((c == '\015') && (*stream->iptr == '\012')) { 1.403 + stream->iptr++; /* eat the line feed */ 1.404 + stream->ictr--; 1.405 + ret[*size = --n] = '\0'; /* tie off string with null */ 1.406 + } 1.407 + else *contd = LONGT; /* continuation needed */ 1.408 + return ret; 1.409 +} 1.410 + 1.411 +/* SSL receive buffer 1.412 + * Accepts: SSL stream 1.413 + * size in bytes 1.414 + * buffer to read into 1.415 + * Returns: T if success, NIL otherwise 1.416 + */ 1.417 + 1.418 +long ssl_getbuffer (SSLSTREAM *stream,unsigned long size,char *buffer) 1.419 +{ 1.420 + unsigned long n; 1.421 + while (size > 0) { /* until request satisfied */ 1.422 + if (!ssl_getdata (stream)) return NIL; 1.423 + n = min (size,stream->ictr);/* number of bytes to transfer */ 1.424 + /* do the copy */ 1.425 + memcpy (buffer,stream->iptr,n); 1.426 + buffer += n; /* update pointer */ 1.427 + stream->iptr += n; 1.428 + size -= n; /* update # of bytes to do */ 1.429 + stream->ictr -= n; 1.430 + } 1.431 + buffer[0] = '\0'; /* tie off string */ 1.432 + return T; 1.433 +} 1.434 + 1.435 +/* SSL receive data 1.436 + * Accepts: TCP/IP stream 1.437 + * Returns: T if success, NIL otherwise 1.438 + */ 1.439 + 1.440 +long ssl_getdata (SSLSTREAM *stream) 1.441 +{ 1.442 + while (stream->ictr < 1) { /* decrypted buffer empty? */ 1.443 + SECURITY_STATUS status; 1.444 + SecBuffer buf[4]; 1.445 + SecBufferDesc msg; 1.446 + size_t i; 1.447 + size_t n = 0; /* initially no bytes to decrypt */ 1.448 + do { /* yes, make sure have data from TCP */ 1.449 + if (stream->iextractr) { /* have previous unread data? */ 1.450 + memcpy (stream->ibuf + n,stream->iextraptr,stream->iextractr); 1.451 + n += stream->iextractr; /* update number of bytes read */ 1.452 + stream->iextractr = 0; /* no more extra data */ 1.453 + } 1.454 + else { /* read from TCP */ 1.455 + if (!tcp_getdata (stream->tcpstream)) return ssl_abort (stream); 1.456 + /* maximum amount of data to copy */ 1.457 + if (!(i = min (stream->bufsize - n,stream->tcpstream->ictr))) 1.458 + fatal ("incomplete SecBuffer exceeds maximum buffer size"); 1.459 + /* do the copy */ 1.460 + memcpy (stream->ibuf + n,stream->tcpstream->iptr,i); 1.461 + stream->tcpstream->iptr += i; 1.462 + stream->tcpstream->ictr -= i; 1.463 + n += i; /* update number of bytes to decrypt */ 1.464 + } 1.465 + buf[0].cbBuffer = n; /* first SecBuffer gets data */ 1.466 + buf[0].pvBuffer = stream->ibuf; 1.467 + buf[0].BufferType = SECBUFFER_DATA; 1.468 + /* subsequent ones are for spares */ 1.469 + buf[1].BufferType = buf[2].BufferType = buf[3].BufferType = 1.470 + SECBUFFER_EMPTY; 1.471 + msg.ulVersion = SECBUFFER_VERSION; 1.472 + msg.cBuffers = 4; /* number of SecBuffers */ 1.473 + msg.pBuffers = buf; /* first SecBuffer */ 1.474 + 1.475 + } while ((status = ((DECRYPT_MESSAGE_FN) sft->Reserved4) 1.476 + (&stream->context,&msg,0,NIL)) == SEC_E_INCOMPLETE_MESSAGE); 1.477 + switch (status) { 1.478 + case SEC_E_OK: /* won */ 1.479 + case SEC_I_RENEGOTIATE: /* won but lost it after this buffer */ 1.480 + /* hunt for a buffer */ 1.481 + for (i = 0; (i < 4) && (buf[i].BufferType != SECBUFFER_DATA) ; i++); 1.482 + if (i < 4) { /* found a buffer? */ 1.483 + /* yes, set up pointer and counter */ 1.484 + stream->iptr = buf[i].pvBuffer; 1.485 + stream->ictr = buf[i].cbBuffer; 1.486 + /* any unprocessed data? */ 1.487 + while (++i < 4) if (buf[i].BufferType == SECBUFFER_EXTRA) { 1.488 + /* yes, note for next time around */ 1.489 + stream->iextraptr = buf[i].pvBuffer; 1.490 + stream->iextractr = buf[i].cbBuffer; 1.491 + } 1.492 + } 1.493 + break; 1.494 + default: /* anything else means we've lost */ 1.495 + return ssl_abort (stream); 1.496 + } 1.497 + } 1.498 + return LONGT; 1.499 +} 1.500 + 1.501 +/* SSL send string as record 1.502 + * Accepts: SSL stream 1.503 + * string pointer 1.504 + * Returns: T if success else NIL 1.505 + */ 1.506 + 1.507 +long ssl_soutr (SSLSTREAM *stream,char *string) 1.508 +{ 1.509 + return ssl_sout (stream,string,(unsigned long) strlen (string)); 1.510 +} 1.511 + 1.512 + 1.513 +/* SSL send string 1.514 + * Accepts: SSL stream 1.515 + * string pointer 1.516 + * byte count 1.517 + * Returns: T if success else NIL 1.518 + */ 1.519 + 1.520 +long ssl_sout (SSLSTREAM *stream,char *string,unsigned long size) 1.521 +{ 1.522 + SecBuffer buf[4]; 1.523 + SecBufferDesc msg; 1.524 + char *s = stream->ibuf; 1.525 + size_t n = 0; 1.526 + while (size) { /* until satisfied request */ 1.527 + /* header */ 1.528 + buf[0].BufferType = SECBUFFER_STREAM_HEADER; 1.529 + memset (buf[0].pvBuffer = stream->obuf,0, 1.530 + buf[0].cbBuffer = stream->sizes.cbHeader); 1.531 + /* message (up to maximum size) */ 1.532 + buf[1].BufferType = SECBUFFER_DATA; 1.533 + memcpy (buf[1].pvBuffer = stream->obuf + stream->sizes.cbHeader,string, 1.534 + buf[1].cbBuffer = min (size,SSLBUFLEN)); 1.535 + /* trailer */ 1.536 + buf[2].BufferType = SECBUFFER_STREAM_TRAILER; 1.537 + memset (buf[2].pvBuffer = ((char *) buf[1].pvBuffer) + buf[1].cbBuffer,0, 1.538 + buf[2].cbBuffer = stream->sizes.cbTrailer); 1.539 + /* spare */ 1.540 + buf[3].BufferType = SECBUFFER_EMPTY; 1.541 + msg.ulVersion = SECBUFFER_VERSION; 1.542 + msg.cBuffers = 4; /* number of SecBuffers */ 1.543 + msg.pBuffers = buf; /* first SecBuffer */ 1.544 + string += buf[1].cbBuffer; 1.545 + size -= buf[1].cbBuffer; /* this many bytes processed */ 1.546 + /* encrypt and send message */ 1.547 + if ((((ENCRYPT_MESSAGE_FN) sft->Reserved3) 1.548 + (&stream->context,0,&msg,NIL) != SEC_E_OK) || 1.549 + !tcp_sout (stream->tcpstream,stream->obuf, 1.550 + buf[0].cbBuffer + buf[1].cbBuffer + buf[2].cbBuffer)) 1.551 + return ssl_abort (stream);/* encryption or sending failed */ 1.552 + } 1.553 + return LONGT; 1.554 +} 1.555 + 1.556 +/* SSL close 1.557 + * Accepts: SSL stream 1.558 + */ 1.559 + 1.560 +void ssl_close (SSLSTREAM *stream) 1.561 +{ 1.562 + ssl_abort (stream); /* nuke the stream */ 1.563 + fs_give ((void **) &stream); /* flush the stream */ 1.564 +} 1.565 + 1.566 + 1.567 +/* SSL abort stream 1.568 + * Accepts: SSL stream 1.569 + * Returns: NIL always 1.570 + */ 1.571 + 1.572 +static long ssl_abort (SSLSTREAM *stream) 1.573 +{ 1.574 + if (stream->tcpstream) { /* close TCP stream */ 1.575 + sft->DeleteSecurityContext (&stream->context); 1.576 + sft->FreeCredentialHandle (&stream->cred); 1.577 + tcp_close (stream->tcpstream); 1.578 + stream->tcpstream = NIL; 1.579 + } 1.580 + if (stream->ibuf) fs_give ((void **) &stream->ibuf); 1.581 + if (stream->obuf) fs_give ((void **) &stream->obuf); 1.582 + return NIL; 1.583 +} 1.584 + 1.585 +/* SSL get host name 1.586 + * Accepts: SSL stream 1.587 + * Returns: host name for this stream 1.588 + */ 1.589 + 1.590 +char *ssl_host (SSLSTREAM *stream) 1.591 +{ 1.592 + return tcp_host (stream->tcpstream); 1.593 +} 1.594 + 1.595 + 1.596 +/* SSL get remote host name 1.597 + * Accepts: SSL stream 1.598 + * Returns: host name for this stream 1.599 + */ 1.600 + 1.601 +char *ssl_remotehost (SSLSTREAM *stream) 1.602 +{ 1.603 + return tcp_remotehost (stream->tcpstream); 1.604 +} 1.605 + 1.606 + 1.607 +/* SSL return port for this stream 1.608 + * Accepts: SSL stream 1.609 + * Returns: port number for this stream 1.610 + */ 1.611 + 1.612 +unsigned long ssl_port (SSLSTREAM *stream) 1.613 +{ 1.614 + return tcp_port (stream->tcpstream); 1.615 +} 1.616 + 1.617 + 1.618 +/* SSL get local host name 1.619 + * Accepts: SSL stream 1.620 + * Returns: local host name 1.621 + */ 1.622 + 1.623 +char *ssl_localhost (SSLSTREAM *stream) 1.624 +{ 1.625 + return tcp_localhost (stream->tcpstream); 1.626 +} 1.627 + 1.628 +#include "ssl_none.c" /* currently no server support */