ipop3d.c | ipop3d.c | |||
---|---|---|---|---|
/* ======================================================================== | /* ======================================================================== | |||
* Copyright 1988-2007 University of Washington | * Copyright 1988-2008 University of Washington | |||
* | * | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | * Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | * you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | * You may obtain a copy of the License at | |||
* | * | |||
* http://www.apache.org/licenses/LICENSE-2.0 | * http://www.apache.org/licenses/LICENSE-2.0 | |||
* | * | |||
* | * | |||
* ======================================================================== | * ======================================================================== | |||
*/ | */ | |||
/* | /* | |||
* Program: IPOP3D - IMAP to POP3 conversion server | * Program: IPOP3D - IMAP to POP3 conversion server | |||
* | * | |||
* Author: Mark Crispin | * Author: Mark Crispin | |||
* Networks and Distributed Computing | * UW Technology | |||
* Computing & Communications | ||||
* University of Washington | * University of Washington | |||
* Administration Building, AG-44 | ||||
* Seattle, WA 98195 | * Seattle, WA 98195 | |||
* Internet: MRC@CAC.Washington.EDU | * Internet: MRC@Washington.EDU | |||
* | * | |||
* Date: 1 November 1990 | * Date: 1 November 1990 | |||
* Last Edited: 17 September 2007 | * Last Edited: 19 February 2008 | |||
*/ | */ | |||
/* Parameter files */ | /* Parameter files */ | |||
#include <stdio.h> | #include <stdio.h> | |||
#include <ctype.h> | #include <ctype.h> | |||
#include <errno.h> | #include <errno.h> | |||
extern int errno; /* just in case */ | extern int errno; /* just in case */ | |||
#include <signal.h> | #include <signal.h> | |||
#include <time.h> | #include <time.h> | |||
#include "c-client.h" | #include "c-client.h" | |||
skipping to change at line 58 | skipping to change at line 56 | |||
#define TRANSACTION 1 | #define TRANSACTION 1 | |||
#define UPDATE 2 | #define UPDATE 2 | |||
#define LOGOUT 3 | #define LOGOUT 3 | |||
/* Eudora food */ | /* Eudora food */ | |||
#define STATUS "Status: %s%s\015\012" | #define STATUS "Status: %s%s\015\012" | |||
#define SLEN (sizeof (STATUS)-3) | #define SLEN (sizeof (STATUS)-3) | |||
/* Global storage */ | /* Global storage */ | |||
char *version = "101"; /* edit number of this server */ | char *version = "104"; /* edit number of this server */ | |||
short state = AUTHORIZATION; /* server state */ | short state = AUTHORIZATION; /* server state */ | |||
short critical = NIL; /* non-zero if in critical code */ | short critical = NIL; /* non-zero if in critical code */ | |||
MAILSTREAM *stream = NIL; /* mailbox stream */ | MAILSTREAM *stream = NIL; /* mailbox stream */ | |||
time_t idletime = 0; /* time we went idle */ | time_t idletime = 0; /* time we went idle */ | |||
unsigned long nmsgs = 0; /* current number of messages */ | unsigned long nmsgs = 0; /* current number of messages */ | |||
unsigned long ndele = 0; /* number of deletes */ | unsigned long ndele = 0; /* number of deletes */ | |||
unsigned long nseen = 0; /* number of mark-seens */ | unsigned long nseen = 0; /* number of mark-seens */ | |||
unsigned long last = 0; /* highest message accessed */ | unsigned long last = 0; /* highest message accessed */ | |||
unsigned long il = 0; /* initial last message */ | unsigned long il = 0; /* initial last message */ | |||
char challenge[128]; /* challenge */ | char challenge[128]; /* challenge */ | |||
skipping to change at line 112 | skipping to change at line 110 | |||
char *s,*t; | char *s,*t; | |||
char tmp[MAILTMPLEN]; | char tmp[MAILTMPLEN]; | |||
time_t autologouttime; | time_t autologouttime; | |||
char *pgmname = (argc && argv[0]) ? | char *pgmname = (argc && argv[0]) ? | |||
(((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ? | (((s = strrchr (argv[0],'/')) || (s = strrchr (argv[0],'\\'))) ? | |||
s+1 : argv[0]) : "ipop3d"; | s+1 : argv[0]) : "ipop3d"; | |||
/* set service name before linkage */ | /* set service name before linkage */ | |||
mail_parameters (NIL,SET_SERVICENAME,(void *) "pop"); | mail_parameters (NIL,SET_SERVICENAME,(void *) "pop"); | |||
#include "linkage.c" | #include "linkage.c" | |||
/* initialize server */ | /* initialize server */ | |||
server_init (pgmname,"pop3","pop3s",clkint,kodint,hupint,trmint); | 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 */ | { /* set up MD5 challenge */ | |||
AUTHENTICATOR *auth = mail_lookup_auth (1); | AUTHENTICATOR *auth = mail_lookup_auth (1); | |||
while (auth && compare_cstring (auth->name,"CRAM-MD5")) auth = auth->ne xt; | while (auth && compare_cstring (auth->name,"CRAM-MD5")) auth = auth->ne xt; | |||
/* build challenge -- less than 128 chars */ | /* build challenge -- less than 128 chars */ | |||
if (auth && auth->server && !(auth->flags & AU_DISABLE)) | if (auth && auth->server && !(auth->flags & AU_DISABLE)) | |||
sprintf (challenge,"<%lx.%lx@%.64s>",(unsigned long) getpid (), | sprintf (challenge,"<%lx.%lx@%.64s>",(unsigned long) getpid (), | |||
(unsigned long) time (0),tcp_serverhost ()); | (unsigned long) time (0),tcp_serverhost ()); | |||
else challenge[0] = '\0'; /* no MD5 authentication */ | else challenge[0] = '\0'; /* no MD5 authentication */ | |||
} | } | |||
/* There are reports of POP3 clients which get upset if anything appears | /* There are reports of POP3 clients which get upset if anything appears | |||
skipping to change at line 154 | skipping to change at line 159 | |||
alarm ((state == TRANSACTION) ? TIMEOUT : LOGINTIMEOUT); | alarm ((state == TRANSACTION) ? TIMEOUT : LOGINTIMEOUT); | |||
clearerr (stdin); /* clear stdin errors */ | clearerr (stdin); /* clear stdin errors */ | |||
/* read command line */ | /* read command line */ | |||
while (!PSIN (tmp,MAILTMPLEN)) { | while (!PSIN (tmp,MAILTMPLEN)) { | |||
/* ignore if some interrupt */ | /* ignore if some interrupt */ | |||
if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); | if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); | |||
else { | else { | |||
char *e = ferror (stdin) ? | char *e = ferror (stdin) ? | |||
strerror (errno) : "Unexpected client disconnect"; | strerror (errno) : "Unexpected client disconnect"; | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
sprintf (logout = tmp,"%.80s, while reading line",e); | sprintf (logout = tmp,"%.80s, while reading line",e); | |||
goodbye = NIL; | goodbye = NIL; | |||
rset (); /* try to gracefully close the stream */ | rset (); /* try to gracefully close the stream */ | |||
if (state == TRANSACTION) mail_close (stream); | if (state == TRANSACTION) mail_close (stream); | |||
stream = NIL; | stream = NIL; | |||
state = LOGOUT; | state = LOGOUT; | |||
sayonara (1); | sayonara (1); | |||
} | } | |||
} | } | |||
alarm (0); /* make sure timeout disabled */ | alarm (0); /* make sure timeout disabled */ | |||
skipping to change at line 206 | skipping to change at line 211 | |||
} | } | |||
else switch (state) { /* else dispatch based on state */ | else switch (state) { /* else dispatch based on state */ | |||
case AUTHORIZATION: /* waiting to get logged in */ | case AUTHORIZATION: /* waiting to get logged in */ | |||
if (!strcmp (s,"AUTH")) { | if (!strcmp (s,"AUTH")) { | |||
if (t && *t) { /* mechanism given? */ | if (t && *t) { /* mechanism given? */ | |||
if (host) fs_give ((void **) &host); | if (host) fs_give ((void **) &host); | |||
if (user) fs_give ((void **) &user); | if (user) fs_give ((void **) &user); | |||
if (pass) fs_give ((void **) &pass); | if (pass) fs_give ((void **) &pass); | |||
s = strtok (t," "); /* get mechanism name */ | s = strtok (t," "); /* get mechanism name */ | |||
/* get initial response */ | /* get initial response */ | |||
initial = strtok (NIL,"\015\012"); | 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)))) { | if (!(user = cpystr (mail_auth (s,responder,argc,argv)))) { | |||
PSOUT ("-ERR Bad authentication\015\012"); | PSOUT ("-ERR Bad authentication\015\012"); | |||
syslog (LOG_INFO,"AUTHENTICATE %s failure host=%.80s",s, | syslog (LOG_INFO,"AUTHENTICATE %s failure host=%.80s",s, | |||
tcp_clienthost ()); | tcp_clienthost ()); | |||
} | } | |||
else if ((state = mbxopen ("INBOX")) == TRANSACTION) | else if ((state = mbxopen ("INBOX")) == TRANSACTION) | |||
syslog (LOG_INFO,"Auth user=%.80s host=%.80s nmsgs=%lu/%lu", | syslog (LOG_INFO,"Auth user=%.80s host=%.80s nmsgs=%lu/%lu", | |||
user,tcp_clienthost (),nmsgs,stream->nmsgs); | user,tcp_clienthost (),nmsgs,stream->nmsgs); | |||
else syslog (LOG_INFO,"Auth user=%.80s host=%.80s no mailbox", | else syslog (LOG_INFO,"Auth user=%.80s host=%.80s no mailbox", | |||
user,tcp_clienthost ()); | user,tcp_clienthost ()); | |||
skipping to change at line 540 | skipping to change at line 548 | |||
/* do logout hook if needed */ | /* do logout hook if needed */ | |||
if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL)); | if (lgoh) (*lgoh) (mail_parameters (NIL,GET_LOGOUTDATA,NIL)); | |||
_exit (status); /* all done */ | _exit (status); /* all done */ | |||
} | } | |||
/* Clock interrupt | /* Clock interrupt | |||
*/ | */ | |||
void clkint () | void clkint () | |||
{ | { | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
goodbye = "-ERR Autologout; idle for too long\015\012"; | goodbye = "-ERR Autologout; idle for too long\015\012"; | |||
logout = "Autologout"; | logout = "Autologout"; | |||
if (critical) state = LOGOUT; /* badly hosed if in critical code * / | if (critical) state = LOGOUT; /* badly hosed if in critical code * / | |||
else { /* try to gracefully close the stream */ | else { /* try to gracefully close the stream */ | |||
if ((state == TRANSACTION) && !stream->lock) { | if ((state == TRANSACTION) && !stream->lock) { | |||
rset (); | rset (); | |||
mail_close (stream); | mail_close (stream); | |||
} | } | |||
state = LOGOUT; | state = LOGOUT; | |||
stream = NIL; | stream = NIL; | |||
skipping to change at line 563 | skipping to change at line 571 | |||
} | } | |||
/* Kiss Of Death interrupt | /* Kiss Of Death interrupt | |||
*/ | */ | |||
void kodint () | void kodint () | |||
{ | { | |||
/* only if idle */ | /* only if idle */ | |||
if (idletime && ((time (0) - idletime) > KODTIMEOUT)) { | if (idletime && ((time (0) - idletime) > KODTIMEOUT)) { | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
goodbye = "-ERR Received Kiss of Death\015\012"; | goodbye = "-ERR Received Kiss of Death\015\012"; | |||
logout = "Killed (lost mailbox lock)"; | logout = "Killed (lost mailbox lock)"; | |||
if (critical) state =LOGOUT;/* must defer if in critical code */ | if (critical) state =LOGOUT;/* must defer if in critical code */ | |||
else { /* try to gracefully close the stream */ | else { /* try to gracefully close the stream */ | |||
if ((state == TRANSACTION) && !stream->lock) { | if ((state == TRANSACTION) && !stream->lock) { | |||
rset (); | rset (); | |||
mail_close (stream); | mail_close (stream); | |||
} | } | |||
state = LOGOUT; | state = LOGOUT; | |||
stream = NIL; | stream = NIL; | |||
skipping to change at line 585 | skipping to change at line 593 | |||
} | } | |||
} | } | |||
} | } | |||
/* Hangup interrupt | /* Hangup interrupt | |||
*/ | */ | |||
void hupint () | void hupint () | |||
{ | { | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
goodbye = NIL; /* nobody left to talk to */ | goodbye = NIL; /* nobody left to talk to */ | |||
logout = "Hangup"; | logout = "Hangup"; | |||
if (critical) state = LOGOUT; /* must defer if in critical code */ | if (critical) state = LOGOUT; /* must defer if in critical code */ | |||
else { /* try to gracefully close the stream */ | else { /* try to gracefully close the stream */ | |||
if ((state == TRANSACTION) && !stream->lock) { | if ((state == TRANSACTION) && !stream->lock) { | |||
rset (); | rset (); | |||
mail_close (stream); | mail_close (stream); | |||
} | } | |||
state = LOGOUT; | state = LOGOUT; | |||
stream = NIL; | stream = NIL; | |||
sayonara (1); /* die die die */ | sayonara (1); /* die die die */ | |||
} | } | |||
} | } | |||
/* Termination interrupt | /* Termination interrupt | |||
*/ | */ | |||
void trmint () | void trmint () | |||
{ | { | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
goodbye = "-ERR Killed\015\012"; | goodbye = "-ERR Killed\015\012"; | |||
logout = "Killed"; | logout = "Killed"; | |||
if (critical) state = LOGOUT; /* must defer if in critical code */ | if (critical) state = LOGOUT; /* must defer if in critical code */ | |||
/* Make no attempt at graceful closure since a shutdown may be in | /* Make no attempt at graceful closure since a shutdown may be in | |||
* progress, and we won't have any time to do mail_close() actions. | * progress, and we won't have any time to do mail_close() actions. | |||
*/ | */ | |||
else sayonara (1); /* die die die */ | else sayonara (1); /* die die die */ | |||
} | } | |||
/* Parse PASS command | /* Parse PASS command | |||
* Accepts: pointer to command argument | * Accepts: pointer to command argument | |||
skipping to change at line 697 | skipping to change at line 705 | |||
alarm (LOGINTIMEOUT); /* get a response under timeout */ | alarm (LOGINTIMEOUT); /* get a response under timeout */ | |||
clearerr (stdin); /* clear stdin errors */ | clearerr (stdin); /* clear stdin errors */ | |||
/* read buffer */ | /* read buffer */ | |||
while (!PSIN ((char *) resp,RESPBUFLEN)) { | while (!PSIN ((char *) resp,RESPBUFLEN)) { | |||
/* ignore if some interrupt */ | /* ignore if some interrupt */ | |||
if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); | if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); | |||
else { | else { | |||
char *e = ferror (stdin) ? | char *e = ferror (stdin) ? | |||
strerror (errno) : "Command stream end of file"; | strerror (errno) : "Command stream end of file"; | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
sprintf (logout = tmp,"%.80s, while reading authentication",e); | sprintf (logout = tmp,"%.80s, while reading authentication",e); | |||
goodbye = NIL; | goodbye = NIL; | |||
state = LOGOUT; | state = LOGOUT; | |||
sayonara (1); | sayonara (1); | |||
} | } | |||
} | } | |||
if (!(t = (unsigned char *) strchr ((char *) resp,'\012'))) { | if (!(t = (unsigned char *) strchr ((char *) resp,'\012'))) { | |||
int c; | int c; | |||
while ((c = PBIN ()) != '\012') if (c == EOF) { | while ((c = PBIN ()) != '\012') if (c == EOF) { | |||
/* ignore if some interrupt */ | /* ignore if some interrupt */ | |||
if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); | if (ferror (stdin) && (errno == EINTR)) clearerr (stdin); | |||
else { | else { | |||
char *e = ferror (stdin) ? | char *e = ferror (stdin) ? | |||
strerror (errno) : "Command stream end of file"; | strerror (errno) : "Command stream end of file"; | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
sprintf (logout = tmp,"%.80s, while reading auth char",e); | sprintf (logout = tmp,"%.80s, while reading auth char",e); | |||
goodbye = NIL; | goodbye = NIL; | |||
state = LOGOUT; | state = LOGOUT; | |||
sayonara (1); | sayonara (1); | |||
} | } | |||
} | } | |||
return NIL; | return NIL; | |||
} | } | |||
alarm (0); /* make sure timeout disabled */ | alarm (0); /* make sure timeout disabled */ | |||
if (t[-1] == '\015') --t; /* remove CR */ | if (t[-1] == '\015') --t; /* remove CR */ | |||
skipping to change at line 938 | skipping to change at line 946 | |||
case NIL: /* information message */ | case NIL: /* information message */ | |||
case PARSE: /* parse glitch */ | case PARSE: /* parse glitch */ | |||
break; /* too many of these to log */ | break; /* too many of these to log */ | |||
case WARN: /* warning */ | case WARN: /* warning */ | |||
syslog (LOG_DEBUG,"%s",string); | syslog (LOG_DEBUG,"%s",string); | |||
break; | break; | |||
case BYE: /* driver broke connection */ | case BYE: /* driver broke connection */ | |||
if (state != UPDATE) { | if (state != UPDATE) { | |||
char tmp[MAILTMPLEN]; | char tmp[MAILTMPLEN]; | |||
alarm (0); /* disable all interrupts */ | alarm (0); /* disable all interrupts */ | |||
server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | server_init (NIL,NIL,NIL,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN,SIG_IGN); | |||
sprintf (logout = tmp,"Mailbox closed (%.80s)",string); | sprintf (logout = tmp,"Mailbox closed (%.80s)",string); | |||
goodbye = NIL; | goodbye = NIL; | |||
state = LOGOUT; | state = LOGOUT; | |||
sayonara (1); | sayonara (1); | |||
} | } | |||
break; | break; | |||
case ERROR: /* error that broke command */ | case ERROR: /* error that broke command */ | |||
default: /* default should never happen */ | default: /* default should never happen */ | |||
syslog (LOG_NOTICE,"%s",string); | syslog (LOG_NOTICE,"%s",string); | |||
break; | break; | |||
End of changes. 16 change blocks. | ||||
17 lines changed or deleted | 25 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |