📄 auth_snt.c
字号:
(*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 * alternate /etc/services service name or NIL * SASL service name or NIL * clock interrupt handler * kiss-of-death interrupt handler * hangup interrupt handler * termination interrupt handler */void server_init (char *server,char *service,char *altservice,char *sasl, void *clkint,void *kodint,void *hupint,void *trmint){ struct servent *sv; long port; if (server) { /* set server name in syslog */ openlog (server,LOG_PID,LOG_MAIL); fclose (stderr); /* possibly save a process ID */ } /* Use SSL if alt service, or if server starts with "s" and not service */ if (service && altservice && ((port = tcp_serverport ()) >= 0) && (((sv = getservbyname (altservice,"tcp")) && (port == ntohs (sv->s_port))) || ((*server == 's') && (!(sv = getservbyname (service,"tcp")) || (port != ntohs (sv->s_port)))))) sslstdio = ssl_server_init (server); else auth_ssl.server = NIL; /* server forbids PLAIN if not SSL */ /* now call c-client's version */ Server_init (NIL,service,altservice,sasl,clkint,kodint,hupint,trmint);} /* link to the real one */#define server_init Server_init/* Wait for stdin input * Accepts: timeout in seconds * Returns: T if have input on stdin, else NIL */long server_input_wait (long seconds){ SECURITY_STATUS status; SecBuffer buf[4]; SecBufferDesc msg; struct timeval tmo; fd_set fds,efd; size_t n = 0; size_t i; SSLSTREAM *stream; if (!sslstdio) return Server_input_wait (seconds); /* if no input available in buffer */ while ((stream = sslstdio->sslstream)->ictr <= 0) { do { 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 { /* if nothing in TCP buffer */ if (stream->tcpstream->ictr < 1) { FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efd); /* initialize selection vector */ FD_SET (stream->tcpstream->tcpsi,&fds); FD_SET (stream->tcpstream->tcpsi,&efd); tmo.tv_sec = seconds; tmo.tv_usec = 0; /* sniff and block until timeout */ if (!select (stream->tcpstream->tcpsi+1,&fds,0,&efd,&tmo)) return NIL; } /* now read that data */ if (!tcp_getdata (stream->tcpstream)) return LONGT; /* 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 = ((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're sick */ return LONGT; } } return LONGT;} /* link to the other one */#define server_input_wait Server_input_wait/* Start TLS * Accepts: /etc/services service name * Returns: cpystr'd error string if TLS failed, else NIL for success */char *ssl_start_tls (char *server){ if (start_tls) return cpystr ("TLS already started"); if (sslstdio) return cpystr ("Already in an SSL session"); start_tls = server; /* start TLS now */ return NIL;}/* Init server for SSL * Accepts: server name * Returns: SSL stdio stream always */SSLSTDIOSTREAM *ssl_server_init (char *server){ SECURITY_STATUS e; ULONG a; TimeStamp t; SecBuffer ibuf[2],obuf[1]; SecBufferDesc ibufs,obufs; SSLSTDIOSTREAM *ret; SSLSTREAM *stream = (SSLSTREAM *) memset (fs_get (sizeof (SSLSTREAM)),0, sizeof (SSLSTREAM)); ULONG req = ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_USE_SESSION_KEY | ASC_REQ_ALLOCATE_MEMORY | ASC_REQ_STREAM | ASC_REQ_EXTENDED_ERROR; int done = 0; int failed = T; int repeat = 0; char spn[MAILTMPLEN]; char *buf = (char *) fs_get (ssltsz); unsigned long size; ssl_onceonlyinit (); /* make sure algorithms added */ sprintf (spn,"%s/%s",(char *) mail_parameters (NIL,GET_SERVICENAME,NIL), tcp_serverhost ()); /* create dummy TCPSTREAM */ stream->tcpstream = (TCPSTREAM *) memset (fs_get (sizeof (TCPSTREAM)),0, sizeof (TCPSTREAM)); /* in case someone cares */ stream->tcpstream->host = cpystr (""); stream->tcpstream->tcpso = 1; /* standard output */ /* get credentials and initial client data */ if ((sft->AcquireCredentialsHandle (spn,UNISP_NAME,SECPKG_CRED_INBOUND,NIL,NIL,NIL,NIL,&stream->cred,&t) == SEC_E_OK) && tcp_getdata (stream->tcpstream)) { /* transfer initial client data */ memcpy (buf,stream->tcpstream->iptr,size = stream->tcpstream->ictr); /* empty it from TCP's buffers */ stream->tcpstream->iptr += stream->tcpstream->ictr; stream->tcpstream->ictr = 0; while (!done) { /* negotiate 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->AcceptSecurityContext (&stream->cred,repeat ? &stream->context : NIL,&ibufs,req, SECURITY_NETWORK_DREP,&stream->context,&obufs,&a,&t); repeat = T; /* next call will use the context */ /* have an output buffer we need to send? */ if (obuf[0].pvBuffer && obuf[0].cbBuffer) { if ((done >= 0) && /* do so if in good state */ !tcp_sout (stream->tcpstream,obuf[0].pvBuffer, obuf[0].cbBuffer)) done = -1; /* free the buffer */ sft->FreeContextBuffer (obuf[0].pvBuffer); } switch (e) { /* negotiation state */ case SEC_E_OK: done = T; /* got security context, all done */ /* 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 (sft->QueryContextAttributes (&stream->context,SECPKG_ATTR_STREAM_SIZES,&stream->sizes) == SEC_E_OK) { /* get stream sizes */ /* maximum SSL buffer size */ size_t i = stream->sizes.cbHeader + stream->sizes.cbMaximumMessage + stream->sizes.cbTrailer; /* make buffers */ stream->ibuf = (char *) fs_get (i); stream->obuf = (char *) fs_get (i); failed = NIL; /* mark success */ } break; 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)) { 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; } default: /* anything else is an error */ done = -1; break; } } } fs_give ((void **) &buf); /* flush temporary buffer */ if (failed) { /* failed to negotiate SSL */ ssl_close (stream); /* punt stream */ exit (1); /* punt this program too */ } ret = (SSLSTDIOSTREAM *) /* success, return SSL stdio stream */ memset (fs_get (sizeof(SSLSTDIOSTREAM)),0,sizeof(SSLSTDIOSTREAM)); ret->sslstream = stream; /* stream to do SSL I/O */ ret->octr = SSLBUFLEN; /* available space in output buffer */ ret->optr = ret->obuf; /* current output buffer pointer */ return ret;}/* Get character * Returns: character or EOF */int ssl_getchar (void){ if (!sslstdio) return getchar (); if (!ssl_getdata (sslstdio->sslstream)) return EOF; /* one last byte available */ sslstdio->sslstream->ictr--; return (int) *(sslstdio->sslstream->iptr)++;}/* Get string * Accepts: destination string pointer * number of bytes available * Returns: destination string pointer or NIL if EOF */char *ssl_gets (char *s,int n){ int i,c; if (start_tls) { /* doing a start TLS? */ /* yes, allow PLAIN authenticator again */ auth_ssl.server = auth_plain_server; /* enter the mode */ sslstdio = ssl_server_init (start_tls); start_tls = NIL; /* don't do this again */ } if (!sslstdio) return fgets (s,n,stdin); for (i = c = 0, n-- ; (c != '\n') && (i < n); sslstdio->sslstream->ictr--) { if ((sslstdio->sslstream->ictr <= 0) && !ssl_getdata (sslstdio->sslstream)) return NIL; /* read error */ c = s[i++] = *(sslstdio->sslstream->iptr)++; } s[i] = '\0'; /* tie off string */ return s;}/* Put character * Accepts: character * Returns: character written or EOF */int ssl_putchar (int c){ if (!sslstdio) return putchar (c); /* flush buffer if full */ if (!sslstdio->octr && ssl_flush ()) return EOF; sslstdio->octr--; /* count down one character */ *sslstdio->optr++ = c; /* write character */ return c; /* return that character */}/* Put string * Accepts: destination string pointer * Returns: 0 or EOF if error */int ssl_puts (char *s){ if (!sslstdio) return fputs (s,stdout); while (*s) { /* flush buffer if full */ if (!sslstdio->octr && ssl_flush ()) return EOF; *sslstdio->optr++ = *s++; /* write one more character */ sslstdio->octr--; /* count down one character */ } return 0; /* success */}/* Flush output * Returns: 0 or EOF if error */int ssl_flush (void){ if (!sslstdio) return fflush (stdout); /* force out buffer */ if (!ssl_sout (sslstdio->sslstream,sslstdio->obuf, SSLBUFLEN - sslstdio->octr)) return EOF; /* renew output buffer */ sslstdio->optr = sslstdio->obuf; sslstdio->octr = SSLBUFLEN; return 0; /* success */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -