📄 auth_ssl.c
字号:
* 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->sizes.cbMaximumMessage - n, stream->tcpstream->ictr))) fatal ("incomplete SecBuffer already cbMaximumMessage"); /* 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 = DecryptMessage (&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 = stream->ibuf; size_t n = 0; while (size) { /* until satisfied request */ /* 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,stream->sizes.cbMaximumMessage)); /* 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 ((EncryptMessage (&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 */long ssl_abort (SSLSTREAM *stream){ if (stream->tcpstream) { /* close TCP stream */ DeleteSecurityContext (&stream->context); 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);}/* Client authenticator * Accepts: challenger function * responder function * parsed network mailbox structure * stream argument for functions * pointer to current trial count * returned user name * Returns: T if success, NIL otherwise, number of trials incremented if retry */long auth_plain_client (authchallenge_t challenger,authrespond_t responder, NETMBX *mb,void *stream,unsigned long *trial, char *user){ char *s,*t,*u,pwd[MAILTMPLEN]; void *chal; unsigned long cl,sl; if (!mb->altflag) /* snarl if not secure session */ mm_log ("SECURITY PROBLEM: insecure server advertised AUTH=PLAIN",WARN); /* get initial (empty) challenge */ if ((chal = (*challenger) (stream,&cl)) && !cl) { fs_give ((void **) &chal); /* prompt user */ mm_login (mb,user,pwd,*trial); if (!pwd[0]) { /* user requested abort */ (*responder) (stream,NIL,0); *trial = 0; /* don't retry */ return T; /* will get a NO response back */ } t = s = (char *) fs_get (sl = strlen (mb->authuser) + strlen (user) + strlen (pwd) + 2); /* copy authorization id */ if (mb->authuser[0]) for (u = user; *u; *t++ = *u++); *t++ = '\0'; /* delimiting NUL */ /* copy authentication id */ for (u = mb->authuser[0] ? mb->authuser : user; *u; *t++ = *u++); *t++ = '\0'; /* delimiting NUL */ /* copy password */ for (u = pwd; *u; *t++ = *u++); /* send credentials */ if ((*responder) (stream,s,sl) && !(chal = (*challenger) (stream,&cl))) { fs_give ((void **) &s); /* free response */ ++*trial; /* can try again if necessary */ return T; /* check the authentication */ } fs_give ((void **) &s); /* free response */ } if (chal) fs_give ((void **) &chal); *trial = 0; /* don't retry */ return NIL; /* failed */}/* Check if PLAIN valid on this system * Returns: T, always */long auth_plain_valid (void){ return T; /* PLAIN is otherwise valid */}/* Server authenticator * Accepts: responder function * argument count * argument vector * Returns: authenticated user name or NIL */char *auth_plain_server (authresponse_t responder,int argc,char *argv[]){ char *ret = NIL; char *user,*aid,*pass; unsigned long len; /* get user name */ if (aid = (*responder) ("",0,&len)) { /* note: responders null-terminate */ if ((((unsigned long) ((user = aid + strlen (aid) + 1) - aid)) < len) && (((unsigned long) ((pass = user + strlen (user) + 1) - aid)) < len) && (((unsigned long) ((pass + strlen (pass)) - aid)) == len) && (*aid ? server_login (aid,pass,user,argc,argv) : server_login (user,pass,NIL,argc,argv))) ret = myusername (); fs_give ((void **) &aid); } return ret;}/* Init server for SSL * Accepts: server name for syslog or NIL * /etc/services service name or NIL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -