📄 ipop3d.c
字号:
/* ======================================================================== * 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: IPOP3D - IMAP to POP3 conversion server * * Author: Mark Crispin * UW Technology * University of Washington * Seattle, WA 98195 * Internet: MRC@Washington.EDU * * Date: 1 November 1990 * Last Edited: 19 February 2008 *//* Parameter files */#include <stdio.h>#include <ctype.h>#include <errno.h>extern int errno; /* just in case */#include <signal.h>#include <time.h>#include "c-client.h"#define CRLF PSOUT ("\015\012") /* primary output terpri *//* Autologout timer */#define KODTIMEOUT 60*5#define LOGINTIMEOUT 60*3#define TIMEOUT 60*10/* Server states */#define AUTHORIZATION 0#define TRANSACTION 1#define UPDATE 2#define LOGOUT 3/* Eudora food */#define STATUS "Status: %s%s\015\012"#define SLEN (sizeof (STATUS)-3)/* Global storage */char *version = "104"; /* edit number of this server */short state = AUTHORIZATION; /* server state */short critical = NIL; /* non-zero if in critical code */MAILSTREAM *stream = NIL; /* mailbox stream */time_t idletime = 0; /* time we went idle */unsigned long nmsgs = 0; /* current number of messages */unsigned long ndele = 0; /* number of deletes */unsigned long nseen = 0; /* number of mark-seens */unsigned long last = 0; /* highest message accessed */unsigned long il = 0; /* initial last message */char challenge[128]; /* challenge */char *host = NIL; /* remote host name */char *user = NIL; /* user name */char *pass = NIL; /* password */char *initial = NIL; /* initial response */long *msg = NIL; /* message translation vector */short *flags = NIL; /* flags */char *logout = "Logout";char *goodbye = "+OK Sayonara\015\012";/* POP3 flags */#define DELE 0x1#define SEEN 0x2/* Function prototypes */int main (int argc,char *argv[]);void sayonara (int status);void clkint ();void kodint ();void hupint ();void trmint ();int pass_login (char *t,int argc,char *argv[]);char *apop_login (char *chal,char *user,char *md5,int argc,char *argv[]);char *responder (void *challenge,unsigned long clen,unsigned long *rlen);int mbxopen (char *mailbox);long blat (char *text,long lines,unsigned long size,STRING *st);void rset ();/* Main program */int main (int argc,char *argv[]){ unsigned long i,j,k; char *s,*t; char tmp[MAILTMPLEN]; time_t autologouttime; char *pgmname = (argc && argv[0]) ? (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ? s+1 : argv[0]) : "ipop3d"; /* set service name before linkage */ mail_parameters (NIL,SET_SERVICENAME,(void *) "pop");#include "linkage.c" /* initialize server */ server_init (pgmname,"pop3","pop3s",clkint,kodint,hupint,trmint,NIL); mail_parameters (NIL,SET_BLOCKENVINIT,VOIDT); s = myusername_full (&i); /* get user name and flags */ mail_parameters (NIL,SET_BLOCKENVINIT,NIL); if (i == MU_LOGGEDIN) { /* allow EXTERNAL if logged in already */ mail_parameters (NIL,UNHIDE_AUTHENTICATOR,(void *) "EXTERNAL"); mail_parameters (NIL,SET_EXTERNALAUTHID,(void *) s); } { /* set up MD5 challenge */ AUTHENTICATOR *auth = mail_lookup_auth (1); while (auth && compare_cstring (auth->name,"CRAM-MD5")) auth = auth->next; /* build challenge -- less than 128 chars */ if (auth && auth->server && !(auth->flags & AU_DISABLE)) sprintf (challenge,"<%lx.%lx@%.64s>",(unsigned long) getpid (), (unsigned long) time (0),tcp_serverhost ()); else challenge[0] = '\0'; /* no MD5 authentication */ } /* There are reports of POP3 clients which get upset if anything appears * between the "+OK" and the "POP3" in the greeting. */ PSOUT ("+OK POP3 "); if (!challenge[0]) { /* if no MD5 enable, output host name */ PSOUT (tcp_serverhost ()); PBOUT (' '); } PSOUT (CCLIENTVERSION); PBOUT ('.'); PSOUT (version); PSOUT (" server ready"); if (challenge[0]) { /* if MD5 enable, output challenge here */ PBOUT (' '); PSOUT (challenge); } CRLF; PFLUSH (); /* dump output buffer */ autologouttime = time (0) + LOGINTIMEOUT; /* command processing loop */ while ((state != UPDATE) && (state != LOGOUT)) { idletime = time (0); /* get a command under timeout */ alarm ((state == TRANSACTION) ? TIMEOUT : LOGINTIMEOUT); clearerr (stdin); /* clear stdin errors */ /* read command line */ while (!PSIN (tmp,MAILTMPLEN)) { /* ignore if some interrupt */ if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); else { char *e = ferror (stdin) ? strerror (errno) : "Unexpected client disconnect"; alarm (0); /* disable all interrupts */ server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); sprintf (logout = tmp,"%.80s, while reading line",e); goodbye = NIL; rset (); /* try to gracefully close the stream */ if (state == TRANSACTION) mail_close (stream); stream = NIL; state = LOGOUT; sayonara (1); } } alarm (0); /* make sure timeout disabled */ idletime = 0; /* no longer idle */ if (!strchr (tmp,'\012')) /* find end of line */ PSOUT ("-ERR Command line too long\015\012"); else if (!(s = strtok (tmp," \015\012"))) PSOUT ("-ERR Null command\015\012"); else { /* dispatch based on command */ ucase (s); /* canonicalize case */ /* snarf argument */ t = strtok (NIL,"\015\012"); /* QUIT command always valid */ if (!strcmp (s,"QUIT")) state = UPDATE; else if (!strcmp (s,"CAPA")) { AUTHENTICATOR *auth; PSOUT ("+OK Capability list follows:\015\012"); PSOUT ("TOP\015\012LOGIN-DELAY 180\015\012UIDL\015\012"); if (s = ssl_start_tls (NIL)) fs_give ((void **) &s); else PSOUT ("STLS\015\012"); if (i = !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL)) PSOUT ("USER\015\012"); /* display secure server authenticators */ for (auth = mail_lookup_auth (1), s = "SASL"; auth; auth = auth->next) if (auth->server && !(auth->flags & AU_DISABLE) && !(auth->flags & AU_HIDE) && (i || (auth->flags & AU_SECURE))) { if (s) { PSOUT (s); s = NIL; } PBOUT (' '); PSOUT (auth->name); } PSOUT (s ? ".\015\012" : "\015\012.\015\012"); } else switch (state) { /* else dispatch based on state */ case AUTHORIZATION: /* waiting to get logged in */ if (!strcmp (s,"AUTH")) { if (t && *t) { /* mechanism given? */ if (host) fs_give ((void **) &host); if (user) fs_give ((void **) &user); if (pass) fs_give ((void **) &pass); s = strtok (t," "); /* get mechanism name */ /* get initial response */ if (initial = strtok (NIL,"\015\012")) { if ((*initial == '=') && !initial[1]) ++initial; else if (!*initial) initial = NIL; } if (!(user = cpystr (mail_auth (s,responder,argc,argv)))) { PSOUT ("-ERR Bad authentication\015\012"); syslog (LOG_INFO,"AUTHENTICATE %s failure host=%.80s",s, tcp_clienthost ()); } else if ((state = mbxopen ("INBOX")) == TRANSACTION) syslog (LOG_INFO,"Auth user=%.80s host=%.80s nmsgs=%lu/%lu", user,tcp_clienthost (),nmsgs,stream->nmsgs); else syslog (LOG_INFO,"Auth user=%.80s host=%.80s no mailbox", user,tcp_clienthost ()); } else { AUTHENTICATOR *auth; PSOUT ("+OK Supported authentication mechanisms:\015\012"); i = !mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL); for (auth = mail_lookup_auth (1); auth; auth = auth->next) if (auth->server && !(auth->flags & AU_DISABLE) && !(auth->flags & AU_HIDE) && (i || (auth->flags & AU_SECURE))) { PSOUT (auth->name); CRLF; } PBOUT ('.'); CRLF; } } else if (!strcmp (s,"APOP")) { if (challenge[0]) { /* can do it if have an MD5 challenge */ if (host) fs_give ((void **) &host); if (user) fs_give ((void **) &user); if (pass) fs_give ((void **) &pass); /* get user name */ if (!(t && *t && (s = strtok (t," ")) && (t = strtok(NIL,"\012")))) PSOUT ("-ERR Missing APOP argument\015\012"); else if (!(user = apop_login (challenge,s,t,argc,argv))) PSOUT ("-ERR Bad APOP\015\012"); else if ((state = mbxopen ("INBOX")) == TRANSACTION) syslog (LOG_INFO,"APOP user=%.80s host=%.80s nmsgs=%lu/%lu", user,tcp_clienthost (),nmsgs,stream->nmsgs); else syslog (LOG_INFO,"APOP user=%.80s host=%.80s no mailbox", user,tcp_clienthost ()); } else PSOUT ("-ERR Not supported\015\012"); } /* (chuckle) */ else if (!strcmp (s,"RPOP")) PSOUT ("-ERR Nice try, bunkie\015\012"); else if (!strcmp (s,"STLS")) { if (t = ssl_start_tls (pgmname)) { PSOUT ("-ERR STLS failed: "); PSOUT (t); CRLF; } else PSOUT ("+OK STLS completed\015\012"); } else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) && !strcmp (s,"USER")) { if (host) fs_give ((void **) &host); if (user) fs_give ((void **) &user); if (pass) fs_give ((void **) &pass); if (t && *t) { /* if user name given */ /* skip leading whitespace (bogus clients!) */ while (*t == ' ') ++t; /* remote user name? */ if (s = strchr (t,':')) { *s++ = '\0'; /* tie off host name */ host = cpystr (t);/* copy host name */ user = cpystr (s);/* copy user name */ } /* local user name */ else user = cpystr (t); PSOUT ("+OK User name accepted, password please\015\012"); } else PSOUT ("-ERR Missing username argument\015\012"); } else if (!mail_parameters (NIL,GET_DISABLEPLAINTEXT,NIL) && user && *user && !strcmp (s,"PASS")) state = pass_login (t,argc,argv); else PSOUT ("-ERR Unknown AUTHORIZATION state command\015\012"); break; case TRANSACTION: /* logged in */ if (!strcmp (s,"STAT")) { for (i = 1,j = 0,k = 0; i <= nmsgs; i++) /* message still exists? */ if (msg[i] && !(flags[i] & DELE)) { j++; /* count one more undeleted message */ k += mail_elt (stream,msg[i])->rfc822_size + SLEN; } sprintf (tmp,"+OK %lu %lu\015\012",j,k); PSOUT (tmp); } else if (!strcmp (s,"LIST")) { if (t && *t) { /* argument do single message */ if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] && !(flags[i] & DELE)) { sprintf (tmp,"+OK %lu %lu\015\012",i, mail_elt(stream,msg[i])->rfc822_size + SLEN); PSOUT (tmp); } else PSOUT ("-ERR No such message\015\012"); } else { /* entire mailbox */ PSOUT ("+OK Mailbox scan listing follows\015\012"); for (i = 1,j = 0,k = 0; i <= nmsgs; i++) if (msg[i] && !(flags[i] & DELE)) { sprintf (tmp,"%lu %lu\015\012",i, mail_elt (stream,msg[i])->rfc822_size + SLEN); PSOUT (tmp); } PBOUT ('.'); /* end of list */ CRLF; } } else if (!strcmp (s,"UIDL")) { if (t && *t) { /* argument do single message */ if ((i = strtoul (t,NIL,10)) && (i <= nmsgs) && msg[i] && !(flags[i] & DELE)) { sprintf (tmp,"+OK %lu %08lx%08lx\015\012",i,stream->uid_validity, mail_uid (stream,msg[i])); PSOUT (tmp); } else PSOUT ("-ERR No such message\015\012"); } else { /* entire mailbox */ PSOUT ("+OK Unique-ID listing follows\015\012"); for (i = 1,j = 0,k = 0; i <= nmsgs; i++) if (msg[i] && !(flags[i] & DELE)) { sprintf (tmp,"%lu %08lx%08lx\015\012",i,stream->uid_validity, mail_uid (stream,msg[i])); PSOUT (tmp); } PBOUT ('.'); /* end of list */ CRLF; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -