Commit 39dec3bc 39dec3bccc1688d620e15a526f924cb8315f74ee by Alain Magloire

2001-04-23 Alain Magloire

	* pop3d/*.[ch]:  Rename all the pop function pop3d_xx()
	instead of pop3_xx() to be consistent with imap4d/*.

	* mailbox/mbx_pop.c (pop_user): This is sudden death; for many pop
	servers, it is important to let them time to remove locks or move
	the .user.pop files.  This happen when we do BUSY_CHECK().  For
	example, the user does not want to read the entire file, and wants
	start to read a new message, closing the connection and immediately
	contact the server again, and we'll end up having
	"-ERR Mail Lock busy" or something similar. To prevent this race
	condition we sleep 2 seconds.

2001-04-23 Sergey Poznyakoff

	It is often convenient to separte log outputs from POP and SMTP
	servers. --with-log-facility flag which allows to specify to which
	log facility the loggin output should be directed.
	System administrators often prefere to have more information about
	unsuccessfull authentications. I have added more verbose logging
	to pop3d/user.c. Both failed attempts and possible account probes
	(USER immediately followed by QUIT) are logged.
	Made pop3d to be less verbose about its WELCOME prompt. When the
	symbol TERSE_MODE is defined, pop3d introduces itself just as
	+OK POP3 ready <apop_hash>
	insead of divulging its type and version. This is a bit paranoid,
	but it is better to be on the safe side...
1 parent df064ef2
1 2001-04-23 Alain Magloire
2
3 * pop3d/*.[ch]: Rename all the pop function pop3d_xx()
4 instead of pop3_xx() to be consistent with imap4d/*.
5
6 * mailbox/mbx_pop.c (pop_user): This is sudden death; for many pop
7 servers, it is important to let them time to remove locks or move
8 the .user.pop files. This happen when we do BUSY_CHECK(). For
9 example, the user does not want to read the entire file, and wants
10 start to read a new message, closing the connection and immediately
11 contact the server again, and we'll end up having
12 "-ERR Mail Lock busy" or something similar. To prevent this race
13 condition we sleep 2 seconds.
14
15 2001-04-23 Sergey Poznyakoff
16
17 It is often convenient to separte log outputs from POP and SMTP
18 servers. --with-log-facility flag which allows to specify to which
19 log facility the loggin output should be directed.
20 System administrators often prefere to have more information about
21 unsuccessfull authentications. I have added more verbose logging
22 to pop3d/user.c. Both failed attempts and possible account probes
23 (USER immediately followed by QUIT) are logged.
24 Made pop3d to be less verbose about its WELCOME prompt. When the
25 symbol TERSE_MODE is defined, pop3d introduces itself just as
26 +OK POP3 ready <apop_hash>
27 insead of divulging its type and version. This is a bit paranoid,
28 but it is better to be on the safe side...
29
30 * configure.in: ARGPINC gets assigne a relative path, due
31 to which the compilation fails if the package is configure with
32 --srdir=<path> option.
33 * configure.in: --with-log-facility new option.
34 * acconfig.h: LOG_FACILITY
35
36 * doc/mailutils.texi: Typo.
37
38 * mailbox/mapfile_stream.c: Define MAP_FAILED.
39
40 * pop3d/extra.c (pop3_abquit): new case ERR_MBOX_SYNC.
41 (pop3_signal): Syslog the reason.
42 * pop3d/pop3d.c (pop_mainloop): Syslog the hostname of
43 the user on connect.
44 (pop3_daemon): Log to many children. Lacks call to exit(), so if
45 pop3d is run as a daemon, any child after exiting from
46 pop3_mainloop tries to accept() from already closed socket
47 and issues spurious error messages.
48 (pop3_mainloop): Check if the mailbox is uptodate if not
49 and the size shrink, bail out. Do not send version number.
50 * pop3d/pop3d.h: ERR_MBOX_SYNC define. WELCOME removed.
51 * pop3d/signal (pop3_sigchld): Lacks signal() call, due to which
52 the signal handler gets cleared after first SIGCHLD and all
53 subsequent children, when finished, just hang around like zombies.
54 * pop3d/user.c: Log to LOG_FACILITY all the errors.
55
1 2001-04-23 Alain Magloire 56 2001-04-23 Alain Magloire
2 57
3 Sergey Poznyakoff pointed out that errno change depending 58 Sergey Poznyakoff pointed out that errno changes depending
4 if _REENTRANT is set or not. So for enable thread we take 59 if _REENTRANT is set or not. So for enable thread we take
5 the approach of always defining _REENTRANT. 60 the approach of always defining _REENTRANT.
6 He also noted that when in standalone the child was not exiting. 61 He also noted that when in standalone the child was not exiting.
......
...@@ -32,3 +32,6 @@ ...@@ -32,3 +32,6 @@
32 32
33 /* Define _REENTRANT when using threads. */ 33 /* Define _REENTRANT when using threads. */
34 #undef _REENTRANT 34 #undef _REENTRANT
35
36 /* Define the default loggin facility. */
37 #undef LOG_FACILITY
......
...@@ -42,6 +42,15 @@ AC_ARG_WITH(db2, ...@@ -42,6 +42,15 @@ AC_ARG_WITH(db2,
42 *) AC_MSG_ERROR(bad value ${withval} for --with-db) ;; 42 *) AC_MSG_ERROR(bad value ${withval} for --with-db) ;;
43 esac],[usedb2=no]) 43 esac],[usedb2=no])
44 44
45 AC_MSG_CHECKING(for log facility)
46 log_facility="LOG_MAIL"
47 AC_ARG_WITH(log-facility,
48 [ --with-log-facility=facility enable logging to the given facility],
49 AC_TRY_COMPILE([#include <syslog.h>], int lf = $withval,
50 log_facility=$withval))
51 AC_DEFINE_UNQUOTED(LOG_FACILITY, $log_facility)
52 AC_MSG_RESULT($log_facility)
53
45 dnl Check for headers 54 dnl Check for headers
46 AC_HEADER_STDC 55 AC_HEADER_STDC
47 AC_HEADER_DIRENT 56 AC_HEADER_DIRENT
...@@ -79,7 +88,7 @@ if test x"$ac_cv_func_argp_parse" != xyes; then ...@@ -79,7 +88,7 @@ if test x"$ac_cv_func_argp_parse" != xyes; then
79 AC_REPLACE_FUNCS(strndup strnlen strchrnul) 88 AC_REPLACE_FUNCS(strndup strnlen strchrnul)
80 ARGPLIBS="../argp/libargp.a" 89 ARGPLIBS="../argp/libargp.a"
81 ARGPLIB="libargp.a" 90 ARGPLIB="libargp.a"
82 ARGPINCS="-I../argp" 91 ARGPINCS='-I$(top_srcdir)/argp'
83 AC_SUBST(ARGPLIBS) 92 AC_SUBST(ARGPLIBS)
84 AC_SUBST(ARGPLIB) 93 AC_SUBST(ARGPLIB)
85 AC_SUBST(ARGPINCS) 94 AC_SUBST(ARGPINCS)
......
...@@ -158,7 +158,7 @@ mailers. ...@@ -158,7 +158,7 @@ mailers.
158 @end group 158 @end group
159 @end example 159 @end example
160 160
161 For example writing a simple @command{from} command that will list the 161 For example writing a simple @code{from} command that will list the
162 @emph{From} and @emph{Subject} headers of every mail in a folder. 162 @emph{From} and @emph{Subject} headers of every mail in a folder.
163 163
164 @example 164 @example
......
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
34 #ifdef _POSIX_MAPPED_FILES 34 #ifdef _POSIX_MAPPED_FILES
35 #include <sys/mman.h> 35 #include <sys/mman.h>
36 36
37 #ifndef MAP_FAILED
38 # define MAP_FAILED (void*)-1
39 #endif
37 40
38 struct _mapfile_stream 41 struct _mapfile_stream
39 { 42 {
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
24 #include <stdlib.h> 24 #include <stdlib.h>
25 #include <stdio.h> 25 #include <stdio.h>
26 #include <string.h> 26 #include <string.h>
27 #include <sys/time.h>
28 #include <sys/types.h>
27 #include <unistd.h> 29 #include <unistd.h>
28 #include <fcntl.h> 30 #include <fcntl.h>
29 #include <stdarg.h> 31 #include <stdarg.h>
...@@ -112,6 +114,7 @@ static int pop_attr_flags __P ((attribute_t, int *)); ...@@ -112,6 +114,7 @@ static int pop_attr_flags __P ((attribute_t, int *));
112 static int pop_uidl __P ((message_t, char *, size_t, size_t *)); 114 static int pop_uidl __P ((message_t, char *, size_t, size_t *));
113 static int pop_uid __P ((message_t, size_t *)); 115 static int pop_uid __P ((message_t, size_t *));
114 static int fill_buffer __P ((pop_data_t, char *, size_t)); 116 static int fill_buffer __P ((pop_data_t, char *, size_t));
117 static int pop_sleep __P ((int));
115 static int pop_readline __P ((pop_data_t)); 118 static int pop_readline __P ((pop_data_t));
116 static int pop_read_ack __P ((pop_data_t)); 119 static int pop_read_ack __P ((pop_data_t));
117 static int pop_writeline __P ((pop_data_t, const char *, ...)); 120 static int pop_writeline __P ((pop_data_t, const char *, ...));
...@@ -512,7 +515,18 @@ pop_open (mailbox_t mbox, int flags) ...@@ -512,7 +515,18 @@ pop_open (mailbox_t mbox, int flags)
512 stream_setbufsiz (mbox->stream, BUFSIZ); 515 stream_setbufsiz (mbox->stream, BUFSIZ);
513 } 516 }
514 else 517 else
515 stream_close (mbox->stream); 518 {
519 /* This is sudden death: for many pop servers, it is important to
520 let them time to remove locks or move the .user.pop files. This
521 happen when we do BUSY_CHECK(). For example, the user does not
522 want to read the entire file, and wants start to read a new
523 message, closing the connection and immediately contact the
524 server again, and we'll end up having "-ERR Mail Lock busy" or
525 something similar. To prevent this race condition we sleep 2
526 seconds. */
527 stream_close (mbox->stream);
528 pop_sleep (2);
529 }
516 mpd->state = POP_OPEN_CONNECTION; 530 mpd->state = POP_OPEN_CONNECTION;
517 531
518 case POP_OPEN_CONNECTION: 532 case POP_OPEN_CONNECTION:
...@@ -1739,6 +1753,17 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset, ...@@ -1739,6 +1753,17 @@ pop_retr (pop_message_t mpm, char *buffer, size_t buflen, off_t offset,
1739 return 0; 1753 return 0;
1740 } 1754 }
1741 1755
1756 /* GRRRRR!! We can not use sleep in the library since this we'll
1757 muck up any alarm() done by the user. */
1758 static int
1759 pop_sleep (int seconds)
1760 {
1761 struct timeval tval;
1762 tval.tv_sec = seconds;
1763 tval.tv_usec = 0;
1764 return select (1, NULL, NULL, NULL, &tval);
1765 }
1766
1742 /* C99 says that a conforming implementation of snprintf () should return the 1767 /* C99 says that a conforming implementation of snprintf () should return the
1743 number of char that would have been call but many old GNU/Linux && BSD 1768 number of char that would have been call but many old GNU/Linux && BSD
1744 implementations return -1 on error. Worse QnX/Neutrino actually does not 1769 implementations return -1 on error. Worse QnX/Neutrino actually does not
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
20 /* Check if a username exists in APOP password file 20 /* Check if a username exists in APOP password file
21 returns pointer to password if found, otherwise NULL */ 21 returns pointer to password if found, otherwise NULL */
22 char * 22 char *
23 pop3_apopuser (const char *user) 23 pop3d_apopuser (const char *user)
24 { 24 {
25 char *password; 25 char *password;
26 char buf[POP_MAXCMDLEN]; 26 char buf[POP_MAXCMDLEN];
...@@ -88,7 +88,7 @@ pop3_apopuser (const char *user) ...@@ -88,7 +88,7 @@ pop3_apopuser (const char *user)
88 if (password == NULL) 88 if (password == NULL)
89 { 89 {
90 fclose (apop_file); 90 fclose (apop_file);
91 pop3_abquit (ERR_NO_MEM); 91 pop3d_abquit (ERR_NO_MEM);
92 } 92 }
93 password[0] = '\0'; 93 password[0] = '\0';
94 94
...@@ -122,7 +122,7 @@ pop3_apopuser (const char *user) ...@@ -122,7 +122,7 @@ pop3_apopuser (const char *user)
122 } 122 }
123 123
124 int 124 int
125 pop3_apop (const char *arg) 125 pop3d_apop (const char *arg)
126 { 126 {
127 char *tmp, *user_digest, *password; 127 char *tmp, *user_digest, *password;
128 struct passwd *pw; 128 struct passwd *pw;
...@@ -138,15 +138,15 @@ pop3_apop (const char *arg) ...@@ -138,15 +138,15 @@ pop3_apop (const char *arg)
138 if (strlen (arg) == 0) 138 if (strlen (arg) == 0)
139 return ERR_BAD_ARGS; 139 return ERR_BAD_ARGS;
140 140
141 username = pop3_cmd (arg); 141 username = pop3d_cmd (arg);
142 if (strlen (username) > (POP_MAXCMDLEN - APOP_DIGEST)) 142 if (strlen (username) > (POP_MAXCMDLEN - APOP_DIGEST))
143 { 143 {
144 free (username); 144 free (username);
145 return ERR_BAD_ARGS; 145 return ERR_BAD_ARGS;
146 } 146 }
147 user_digest = pop3_args (arg); 147 user_digest = pop3d_args (arg);
148 148
149 password = pop3_apopuser (username); 149 password = pop3d_apopuser (username);
150 if (password == NULL) 150 if (password == NULL)
151 { 151 {
152 free (username); 152 free (username);
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
20 /* AUTH is not yet implemented */ 20 /* AUTH is not yet implemented */
21 21
22 int 22 int
23 pop3_auth (const char *arg) 23 pop3d_auth (const char *arg)
24 { 24 {
25 (void)arg; 25 (void)arg;
26 if (state != AUTHORIZATION) 26 if (state != AUTHORIZATION)
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
18 #include "pop3d.h" 18 #include "pop3d.h"
19 19
20 int 20 int
21 pop3_capa (const char *arg) 21 pop3d_capa (const char *arg)
22 { 22 {
23 if (strlen (arg) != 0) 23 if (strlen (arg) != 0)
24 return ERR_BAD_ARGS; 24 return ERR_BAD_ARGS;
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
20 /* DELE adds a message number to the list of messages to be deleted on QUIT */ 20 /* DELE adds a message number to the list of messages to be deleted on QUIT */
21 21
22 int 22 int
23 pop3_dele (const char *arg) 23 pop3d_dele (const char *arg)
24 { 24 {
25 size_t num = 0; 25 size_t num = 0;
26 message_t msg; 26 message_t msg;
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
21 after the first space, or a zero length string if no space */ 21 after the first space, or a zero length string if no space */
22 22
23 char * 23 char *
24 pop3_args (const char *cmd) 24 pop3d_args (const char *cmd)
25 { 25 {
26 int space = -1, i = 0, len; 26 int space = -1, i = 0, len;
27 char *buf; 27 char *buf;
...@@ -29,7 +29,7 @@ pop3_args (const char *cmd) ...@@ -29,7 +29,7 @@ pop3_args (const char *cmd)
29 len = strlen (cmd) + 1; 29 len = strlen (cmd) + 1;
30 buf = malloc (len * sizeof (char)); 30 buf = malloc (len * sizeof (char));
31 if (buf == NULL) 31 if (buf == NULL)
32 pop3_abquit (ERR_NO_MEM); 32 pop3d_abquit (ERR_NO_MEM);
33 33
34 while (space < 0 && i < len) 34 while (space < 0 && i < len)
35 { 35 {
...@@ -58,7 +58,7 @@ pop3_args (const char *cmd) ...@@ -58,7 +58,7 @@ pop3_args (const char *cmd)
58 the string, whichever occurs first */ 58 the string, whichever occurs first */
59 59
60 char * 60 char *
61 pop3_cmd (const char *cmd) 61 pop3d_cmd (const char *cmd)
62 { 62 {
63 char *buf; 63 char *buf;
64 int i = 0, len; 64 int i = 0, len;
...@@ -66,7 +66,7 @@ pop3_cmd (const char *cmd) ...@@ -66,7 +66,7 @@ pop3_cmd (const char *cmd)
66 len = strlen (cmd) + 1; 66 len = strlen (cmd) + 1;
67 buf = malloc (len * sizeof (char)); 67 buf = malloc (len * sizeof (char));
68 if (buf == NULL) 68 if (buf == NULL)
69 pop3_abquit (ERR_NO_MEM); 69 pop3d_abquit (ERR_NO_MEM);
70 70
71 for (i = 0; i < len; i++) 71 for (i = 0; i < len; i++)
72 { 72 {
...@@ -84,7 +84,7 @@ pop3_cmd (const char *cmd) ...@@ -84,7 +84,7 @@ pop3_cmd (const char *cmd)
84 being killed on a signal */ 84 being killed on a signal */
85 85
86 int 86 int
87 pop3_abquit (int reason) 87 pop3d_abquit (int reason)
88 { 88 {
89 mailbox_close (mbox); 89 mailbox_close (mbox);
90 mailbox_destroy (&mbox); 90 mailbox_destroy (&mbox);
...@@ -118,6 +118,11 @@ pop3_abquit (int reason) ...@@ -118,6 +118,11 @@ pop3_abquit (int reason)
118 syslog (LOG_INFO, "No socket to send to"); 118 syslog (LOG_INFO, "No socket to send to");
119 break; 119 break;
120 120
121 case ERR_MBOX_SYNC:
122 syslog (LOG_ERR, "Mailbox was updated by other party: %s", username);
123 fprintf (ofile, "-ERR Mailbox updated by other party or corrupt\r\n");
124 break;
125
121 default: 126 default:
122 fprintf (ofile, "-ERR Quitting (reason unknown)\r\n"); 127 fprintf (ofile, "-ERR Quitting (reason unknown)\r\n");
123 syslog (LOG_ERR, "Unknown quit"); 128 syslog (LOG_ERR, "Unknown quit");
...@@ -133,7 +138,7 @@ pop3_abquit (int reason) ...@@ -133,7 +138,7 @@ pop3_abquit (int reason)
133 /* Prints out usage information and exits the program */ 138 /* Prints out usage information and exits the program */
134 139
135 void 140 void
136 pop3_usage (char *argv0) 141 pop3d_usage (char *argv0)
137 { 142 {
138 printf ("Usage: %s [OPTIONS]\n", argv0); 143 printf ("Usage: %s [OPTIONS]\n", argv0);
139 printf ("Runs the GNU POP3 daemon.\n\n"); 144 printf ("Runs the GNU POP3 daemon.\n\n");
...@@ -151,19 +156,20 @@ pop3_usage (char *argv0) ...@@ -151,19 +156,20 @@ pop3_usage (char *argv0)
151 exit (0); 156 exit (0);
152 } 157 }
153 158
154 /* Default signal handler to call the pop3_abquit() function */ 159 /* Default signal handler to call the pop3d_abquit() function */
155 160
156 void 161 void
157 pop3_signal (int signo) 162 pop3d_signal (int signo)
158 { 163 {
159 (void)signo; 164 (void)signo;
160 pop3_abquit (ERR_SIGNAL); 165 syslog (LOG_CRIT, "got signal %d", signo);
166 pop3d_abquit (ERR_SIGNAL);
161 } 167 }
162 168
163 /* Gets a line of input from the client */ 169 /* Gets a line of input from the client */
164 170
165 char * 171 char *
166 pop3_readline (int fd) 172 pop3d_readline (int fd)
167 { 173 {
168 fd_set rfds; 174 fd_set rfds;
169 struct timeval tv; 175 struct timeval tv;
...@@ -183,17 +189,17 @@ pop3_readline (int fd) ...@@ -183,17 +189,17 @@ pop3_readline (int fd)
183 { 189 {
184 available = select (fd + 1, &rfds, NULL, NULL, &tv); 190 available = select (fd + 1, &rfds, NULL, NULL, &tv);
185 if (!available) 191 if (!available)
186 pop3_abquit (ERR_TIMEOUT); 192 pop3d_abquit (ERR_TIMEOUT);
187 } 193 }
188 194
189 nread = read (fd, buf, sizeof (buf) - 1); 195 nread = read (fd, buf, sizeof (buf) - 1);
190 if (nread < 1) 196 if (nread < 1)
191 pop3_abquit (ERR_DEAD_SOCK); 197 pop3d_abquit (ERR_DEAD_SOCK);
192 198
193 buf[nread] = '\0'; 199 buf[nread] = '\0';
194 ret = realloc (ret, (total + nread + 1) * sizeof (char)); 200 ret = realloc (ret, (total + nread + 1) * sizeof (char));
195 if (ret == NULL) 201 if (ret == NULL)
196 pop3_abquit (ERR_NO_MEM); 202 pop3d_abquit (ERR_NO_MEM);
197 memcpy (ret + total, buf, nread + 1); 203 memcpy (ret + total, buf, nread + 1);
198 total += nread; 204 total += nread;
199 } 205 }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
20 /* Displays the size of message number arg or all messages (if no arg) */ 20 /* Displays the size of message number arg or all messages (if no arg) */
21 21
22 int 22 int
23 pop3_list (const char *arg) 23 pop3d_list (const char *arg)
24 { 24 {
25 size_t mesgno; 25 size_t mesgno;
26 size_t size = 0; 26 size_t size = 0;
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by 5 it under the terms of the GNU General Public License as published by
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
20 /* Does nothing */ 20 /* Does nothing */
21 21
22 int 22 int
23 pop3_noop (const char *arg) 23 pop3d_noop (const char *arg)
24 { 24 {
25 if (strlen (arg) != 0) 25 if (strlen (arg) != 0)
26 return ERR_BAD_ARGS; 26 return ERR_BAD_ARGS;
......
...@@ -74,7 +74,7 @@ main (int argc, char **argv) ...@@ -74,7 +74,7 @@ main (int argc, char **argv)
74 break; 74 break;
75 75
76 case 'h': 76 case 'h':
77 pop3_usage (argv[0]); 77 pop3d_usage (argv[0]);
78 break; 78 break;
79 79
80 case 'i': 80 case 'i':
...@@ -123,21 +123,21 @@ main (int argc, char **argv) ...@@ -123,21 +123,21 @@ main (int argc, char **argv)
123 } 123 }
124 124
125 /* Set the signal handlers. */ 125 /* Set the signal handlers. */
126 signal (SIGINT, pop3_signal); 126 signal (SIGINT, pop3d_signal);
127 signal (SIGQUIT, pop3_signal); 127 signal (SIGQUIT, pop3d_signal);
128 signal (SIGILL, pop3_signal); 128 signal (SIGILL, pop3d_signal);
129 signal (SIGBUS, pop3_signal); 129 signal (SIGBUS, pop3d_signal);
130 signal (SIGFPE, pop3_signal); 130 signal (SIGFPE, pop3d_signal);
131 signal (SIGSEGV, pop3_signal); 131 signal (SIGSEGV, pop3d_signal);
132 signal (SIGTERM, pop3_signal); 132 signal (SIGTERM, pop3d_signal);
133 signal (SIGSTOP, pop3_signal); 133 signal (SIGSTOP, pop3d_signal);
134 signal (SIGPIPE, pop3_signal); 134 signal (SIGPIPE, pop3d_signal);
135 135
136 if (timeout < 600) /* RFC 1939 says no less than 10 minutes. */ 136 if (timeout < 600) /* RFC 1939 says no less than 10 minutes. */
137 timeout = 0; /* So we'll turn it off. */ 137 timeout = 0; /* So we'll turn it off. */
138 138
139 if (mode == DAEMON) 139 if (mode == DAEMON)
140 pop3_daemon_init (); 140 pop3d_daemon_init ();
141 141
142 /* Change directory. */ 142 /* Change directory. */
143 chdir ("/"); 143 chdir ("/");
...@@ -149,10 +149,10 @@ main (int argc, char **argv) ...@@ -149,10 +149,10 @@ main (int argc, char **argv)
149 149
150 /* Actually run the daemon. */ 150 /* Actually run the daemon. */
151 if (mode == DAEMON) 151 if (mode == DAEMON)
152 pop3_daemon (maxchildren); 152 pop3d_daemon (maxchildren);
153 /* exit() -- no way out of daemon except a signal. */ 153 /* exit (0) -- no way out of daemon except a signal. */
154 else 154 else
155 status = pop3_mainloop (fileno (stdin), fileno (stdout)); 155 status = pop3d_mainloop (fileno (stdin), fileno (stdout));
156 156
157 /* Close the syslog connection and exit. */ 157 /* Close the syslog connection and exit. */
158 closelog (); 158 closelog ();
...@@ -161,7 +161,7 @@ main (int argc, char **argv) ...@@ -161,7 +161,7 @@ main (int argc, char **argv)
161 161
162 /* Sets things up for daemon mode. */ 162 /* Sets things up for daemon mode. */
163 void 163 void
164 pop3_daemon_init (void) 164 pop3d_daemon_init (void)
165 { 165 {
166 pid_t pid; 166 pid_t pid;
167 unsigned int i; 167 unsigned int i;
...@@ -171,7 +171,7 @@ pop3_daemon_init (void) ...@@ -171,7 +171,7 @@ pop3_daemon_init (void)
171 if (pid == -1) 171 if (pid == -1)
172 { 172 {
173 perror ("fork failed:"); 173 perror ("fork failed:");
174 exit (-1); 174 exit (1);
175 } 175 }
176 else if (pid > 0) 176 else if (pid > 0)
177 exit (0); /* Parent exits. */ 177 exit (0); /* Parent exits. */
...@@ -191,18 +191,18 @@ pop3_daemon_init (void) ...@@ -191,18 +191,18 @@ pop3_daemon_init (void)
191 191
192 /* Close inherited file descriptors. */ 192 /* Close inherited file descriptors. */
193 for (i = 0; i < MAXFD; ++i) 193 for (i = 0; i < MAXFD; ++i)
194 close(i); 194 close (i);
195 195
196 #ifdef HAVE_SIGACTION 196 #ifdef HAVE_SIGACTION
197 { 197 {
198 struct sigaction act; 198 struct sigaction act;
199 act.sa_handler = pop3_sigchld; 199 act.sa_handler = pop3d_sigchld;
200 sigemptyset (&act.sa_mask); 200 sigemptyset (&act.sa_mask);
201 act.sa_flags = 0; 201 act.sa_flags = 0;
202 sigaction (SIGCHLD, &act, NULL); 202 sigaction (SIGCHLD, &act, NULL);
203 } 203 }
204 #else 204 #else
205 signal (SIGCHLD, pop3_sigchld); 205 signal (SIGCHLD, pop3d_sigchld);
206 #endif 206 #endif
207 } 207 }
208 208
...@@ -210,7 +210,7 @@ pop3_daemon_init (void) ...@@ -210,7 +210,7 @@ pop3_daemon_init (void)
210 executes the proper functions. Also handles the bulk of error reporting. */ 210 executes the proper functions. Also handles the bulk of error reporting. */
211 211
212 int 212 int
213 pop3_mainloop (int infile, int outfile) 213 pop3d_mainloop (int infile, int outfile)
214 { 214 {
215 int status = OK; 215 int status = OK;
216 char *buf, *arg, *cmd; 216 char *buf, *arg, *cmd;
...@@ -220,17 +220,28 @@ pop3_mainloop (int infile, int outfile) ...@@ -220,17 +220,28 @@ pop3_mainloop (int infile, int outfile)
220 ifile = infile; 220 ifile = infile;
221 ofile = fdopen (outfile, "w"); 221 ofile = fdopen (outfile, "w");
222 if (ofile == NULL) 222 if (ofile == NULL)
223 pop3_abquit (ERR_NO_OFILE); 223 pop3d_abquit (ERR_NO_OFILE);
224 state = AUTHORIZATION; 224 state = AUTHORIZATION;
225 curr_time = time (NULL); 225 curr_time = time (NULL);
226 226
227 /* FIXME: Retreive hostname with getpeername() and log. */ 227 /* FIXME: Retreive hostname with getpeername() and log. */
228 syslog (LOG_INFO, "Incoming connection opened"); 228 syslog (LOG_INFO, "Incoming connection opened");
229 229
230 /* log information on the connecting client */
231 {
232 struct sockaddr_in cs;
233 int len = sizeof cs;
234 if (getpeername (infile, (struct sockaddr*)&cs, &len) < 0)
235 syslog (LOG_ERR, "can't obtain IP address of client: %s",
236 strerror (errno));
237 else
238 syslog (LOG_INFO, "connect from %s", inet_ntoa(cs.sin_addr));
239 }
240
230 /* Prepare the shared secret for APOP. */ 241 /* Prepare the shared secret for APOP. */
231 local_hostname = malloc (MAXHOSTNAMELEN + 1); 242 local_hostname = malloc (MAXHOSTNAMELEN + 1);
232 if (local_hostname == NULL) 243 if (local_hostname == NULL)
233 pop3_abquit (ERR_NO_MEM); 244 pop3d_abquit (ERR_NO_MEM);
234 245
235 gethostname (local_hostname, MAXHOSTNAMELEN); 246 gethostname (local_hostname, MAXHOSTNAMELEN);
236 htbuf = gethostbyname (local_hostname); 247 htbuf = gethostbyname (local_hostname);
...@@ -242,52 +253,64 @@ pop3_mainloop (int infile, int outfile) ...@@ -242,52 +253,64 @@ pop3_mainloop (int infile, int outfile)
242 253
243 md5shared = malloc (strlen (local_hostname) + 51); 254 md5shared = malloc (strlen (local_hostname) + 51);
244 if (md5shared == NULL) 255 if (md5shared == NULL)
245 pop3_abquit (ERR_NO_MEM); 256 pop3d_abquit (ERR_NO_MEM);
246 257
247 snprintf (md5shared, strlen (local_hostname) + 50, "<%u.%u@%s>", getpid (), 258 snprintf (md5shared, strlen (local_hostname) + 50, "<%u.%u@%s>", getpid (),
248 (int)time (NULL), local_hostname); 259 (int)time (NULL), local_hostname);
249 free (local_hostname); 260 free (local_hostname);
250 261
251 fprintf (ofile, "+OK POP3 " WELCOME " %s\r\n", md5shared); 262 fprintf (ofile, "+OK POP3 Ready %s\r\n", md5shared);
252 263
253 while (state != UPDATE) 264 while (state != UPDATE)
254 { 265 {
255 fflush (ofile); 266 fflush (ofile);
256 status = OK; 267 status = OK;
257 buf = pop3_readline (ifile); 268 buf = pop3d_readline (ifile);
258 cmd = pop3_cmd (buf); 269 cmd = pop3d_cmd (buf);
259 arg = pop3_args (buf); 270 arg = pop3d_args (buf);
271
272 if (state == TRANSACTION && !mailbox_is_updated (mbox))
273 {
274 static size_t mailbox_size;
275 size_t newsize = 0;
276 mailbox_get_size (mbox, &newsize);
277 /* Did we shrink? */
278 if (!mailbox_size)
279 mailbox_size = newsize;
280 else (newsize < mailbox_size)
281 pop3d_abquit (ERR_MBOX_SYNC);
282 }
260 283
261 if (strlen (arg) > POP_MAXCMDLEN || strlen (cmd) > POP_MAXCMDLEN) 284 if (strlen (arg) > POP_MAXCMDLEN || strlen (cmd) > POP_MAXCMDLEN)
262 status = ERR_TOO_LONG; 285 status = ERR_TOO_LONG;
263 else if (strlen (cmd) > 4) 286 else if (strlen (cmd) > 4)
264 status = ERR_BAD_CMD; 287 status = ERR_BAD_CMD;
265 else if (strncasecmp (cmd, "RETR", 4) == 0) 288 else if (strncasecmp (cmd, "RETR", 4) == 0)
266 status = pop3_retr (arg); 289 status = pop3d_retr (arg);
267 else if (strncasecmp (cmd, "DELE", 4) == 0) 290 else if (strncasecmp (cmd, "DELE", 4) == 0)
268 status = pop3_dele (arg); 291 status = pop3d_dele (arg);
269 else if (strncasecmp (cmd, "USER", 4) == 0) 292 else if (strncasecmp (cmd, "USER", 4) == 0)
270 status = pop3_user (arg); 293 status = pop3d_user (arg);
271 else if (strncasecmp (cmd, "QUIT", 4) == 0) 294 else if (strncasecmp (cmd, "QUIT", 4) == 0)
272 status = pop3_quit (arg); 295 status = pop3d_quit (arg);
273 else if (strncasecmp (cmd, "APOP", 4) == 0) 296 else if (strncasecmp (cmd, "APOP", 4) == 0)
274 status = pop3_apop (arg); 297 status = pop3d_apop (arg);
275 else if (strncasecmp (cmd, "AUTH", 4) == 0) 298 else if (strncasecmp (cmd, "AUTH", 4) == 0)
276 status = pop3_auth (arg); 299 status = pop3d_auth (arg);
277 else if (strncasecmp (cmd, "STAT", 4) == 0) 300 else if (strncasecmp (cmd, "STAT", 4) == 0)
278 status = pop3_stat (arg); 301 status = pop3d_stat (arg);
279 else if (strncasecmp (cmd, "LIST", 4) == 0) 302 else if (strncasecmp (cmd, "LIST", 4) == 0)
280 status = pop3_list (arg); 303 status = pop3d_list (arg);
281 else if (strncasecmp (cmd, "NOOP", 4) == 0) 304 else if (strncasecmp (cmd, "NOOP", 4) == 0)
282 status = pop3_noop (arg); 305 status = pop3d_noop (arg);
283 else if (strncasecmp (cmd, "RSET", 4) == 0) 306 else if (strncasecmp (cmd, "RSET", 4) == 0)
284 status = pop3_rset (arg); 307 status = pop3d_rset (arg);
285 else if ((strncasecmp (cmd, "TOP", 3) == 0) && (strlen (cmd) == 3)) 308 else if ((strncasecmp (cmd, "TOP", 3) == 0) && (strlen (cmd) == 3))
286 status = pop3_top (arg); 309 status = pop3d_top (arg);
287 else if (strncasecmp (cmd, "UIDL", 4) == 0) 310 else if (strncasecmp (cmd, "UIDL", 4) == 0)
288 status = pop3_uidl (arg); 311 status = pop3d_uidl (arg);
289 else if (strncasecmp (cmd, "CAPA", 4) == 0) 312 else if (strncasecmp (cmd, "CAPA", 4) == 0)
290 status = pop3_capa (arg); 313 status = pop3d_capa (arg);
291 else 314 else
292 status = ERR_BAD_CMD; 315 status = ERR_BAD_CMD;
293 316
...@@ -326,12 +349,12 @@ pop3_mainloop (int infile, int outfile) ...@@ -326,12 +349,12 @@ pop3_mainloop (int infile, int outfile)
326 } 349 }
327 350
328 /* Runs GNU POP3 in standalone daemon mode. This opens and binds to a port 351 /* Runs GNU POP3 in standalone daemon mode. This opens and binds to a port
329 (default 110) then executes a pop3_mainloop() upon accepting a connection. 352 (default 110) then executes a pop3d_mainloop() upon accepting a connection.
330 It starts maxchildren child processes to listen to and accept socket 353 It starts maxchildren child processes to listen to and accept socket
331 connections. */ 354 connections. */
332 355
333 void 356 void
334 pop3_daemon (unsigned int maxchildren) 357 pop3d_daemon (unsigned int maxchildren)
335 { 358 {
336 SA server, client; 359 SA server, client;
337 pid_t pid; 360 pid_t pid;
...@@ -342,7 +365,7 @@ pop3_daemon (unsigned int maxchildren) ...@@ -342,7 +365,7 @@ pop3_daemon (unsigned int maxchildren)
342 if (listenfd == -1) 365 if (listenfd == -1)
343 { 366 {
344 syslog (LOG_ERR, "socket: %s", strerror(errno)); 367 syslog (LOG_ERR, "socket: %s", strerror(errno));
345 exit (-1); 368 exit (1);
346 } 369 }
347 size = 1; /* Use size here to avoid making a new variable. */ 370 size = 1; /* Use size here to avoid making a new variable. */
348 setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size)); 371 setsockopt (listenfd, SOL_SOCKET, SO_REUSEADDR, &size, sizeof(size));
...@@ -355,19 +378,20 @@ pop3_daemon (unsigned int maxchildren) ...@@ -355,19 +378,20 @@ pop3_daemon (unsigned int maxchildren)
355 if (bind (listenfd, (struct sockaddr *)&server, size) == -1) 378 if (bind (listenfd, (struct sockaddr *)&server, size) == -1)
356 { 379 {
357 syslog (LOG_ERR, "bind: %s", strerror (errno)); 380 syslog (LOG_ERR, "bind: %s", strerror (errno));
358 exit (-1); 381 exit (1);
359 } 382 }
360 383
361 if (listen (listenfd, 128) == -1) 384 if (listen (listenfd, 128) == -1)
362 { 385 {
363 syslog (LOG_ERR, "listen: %s", strerror (errno)); 386 syslog (LOG_ERR, "listen: %s", strerror (errno));
364 exit (-1); 387 exit (1);
365 } 388 }
366 389
367 for (;;) 390 for (;;)
368 { 391 {
369 if (children > maxchildren) 392 if (children > maxchildren)
370 { 393 {
394 syslog (LOG_ERR, "too many children");
371 pause (); 395 pause ();
372 continue; 396 continue;
373 } 397 }
...@@ -377,7 +401,7 @@ pop3_daemon (unsigned int maxchildren) ...@@ -377,7 +401,7 @@ pop3_daemon (unsigned int maxchildren)
377 if (errno == EINTR) 401 if (errno == EINTR)
378 continue; 402 continue;
379 syslog (LOG_ERR, "accept: %s", strerror (errno)); 403 syslog (LOG_ERR, "accept: %s", strerror (errno));
380 exit (-1); 404 exit (1);
381 } 405 }
382 406
383 pid = fork (); 407 pid = fork ();
...@@ -387,8 +411,7 @@ pop3_daemon (unsigned int maxchildren) ...@@ -387,8 +411,7 @@ pop3_daemon (unsigned int maxchildren)
387 { 411 {
388 int status; 412 int status;
389 close (listenfd); 413 close (listenfd);
390 /* syslog(); FIXME log the info on the connecting client. */ 414 status = pop3d_mainloop (connfd, connfd);
391 status = pop3_mainloop (connfd, connfd);
392 closelog (); 415 closelog ();
393 exit (status); 416 exit (status);
394 } 417 }
......
...@@ -26,9 +26,6 @@ ...@@ -26,9 +26,6 @@
26 26
27 /* You can edit the messages the POP server prints out here */ 27 /* You can edit the messages the POP server prints out here */
28 28
29 /* Initial greeting */
30 #define WELCOME "Welcome to " IMPL " (" PACKAGE " " VERSION ")"
31
32 /* A command that doesn't exist */ 29 /* A command that doesn't exist */
33 #define BAD_COMMAND "Invalid command" 30 #define BAD_COMMAND "Invalid command"
34 31
...@@ -158,6 +155,7 @@ ...@@ -158,6 +155,7 @@
158 #define ERR_NO_OFILE 14 155 #define ERR_NO_OFILE 14
159 #define ERR_TIMEOUT 15 156 #define ERR_TIMEOUT 15
160 #define ERR_UNKNOWN 16 157 #define ERR_UNKNOWN 16
158 #define ERR_MBOX_SYNC 17
161 159
162 #ifndef __P 160 #ifndef __P
163 # ifdef __STDC__ 161 # ifdef __STDC__
...@@ -179,32 +177,30 @@ extern time_t curr_time; ...@@ -179,32 +177,30 @@ extern time_t curr_time;
179 extern char *md5shared; 177 extern char *md5shared;
180 extern unsigned int children; 178 extern unsigned int children;
181 179
182 extern int pop3_dele __P ((const char *arg)); 180 extern int pop3d_dele __P ((const char *arg));
183 extern int pop3_list __P ((const char *arg)); 181 extern int pop3d_list __P ((const char *arg));
184 extern int pop3_noop __P ((const char *arg)); 182 extern int pop3d_noop __P ((const char *arg));
185 extern int pop3_quit __P ((const char *arg)); 183 extern int pop3d_quit __P ((const char *arg));
186 extern int pop3_retr __P ((const char *arg)); 184 extern int pop3d_retr __P ((const char *arg));
187 extern int pop3_rset __P ((const char *arg)); 185 extern int pop3d_rset __P ((const char *arg));
188 extern int pop3_stat __P ((const char *arg)); 186 extern int pop3d_stat __P ((const char *arg));
189 extern int pop3_top __P ((const char *arg)); 187 extern int pop3d_top __P ((const char *arg));
190 extern int pop3_uidl __P ((const char *arg)); 188 extern int pop3d_uidl __P ((const char *arg));
191 extern int pop3_user __P ((const char *arg)); 189 extern int pop3d_user __P ((const char *arg));
192 extern int pop3_apop __P ((const char *arg)); 190 extern int pop3d_apop __P ((const char *arg));
193 extern int pop3_auth __P ((const char *arg)); 191 extern int pop3d_auth __P ((const char *arg));
194 extern int pop3_capa __P ((const char *arg)); 192 extern int pop3d_capa __P ((const char *arg));
195 extern char *pop3_args __P ((const char *cmd)); 193 extern char *pop3d_args __P ((const char *cmd));
196 extern char *pop3_cmd __P ((const char *cmd)); 194 extern char *pop3d_cmd __P ((const char *cmd));
197 extern int pop3_mesg_exist __P ((int mesg)); 195 extern int pop3d_abquit __P ((int reason));
198 extern int pop3_abquit __P ((int reason)); 196 extern int pop3d_lock __P ((void));
199 extern int pop3_lock __P ((void)); 197 extern int pop3d_unlock __P ((void));
200 extern int pop3_unlock __P ((void)); 198 extern int pop3d_mainloop __P ((int infile, int outfile));
201 extern int pop3_getsizes __P ((void)); 199 extern void pop3d_daemon __P ((unsigned int maxchildren));
202 extern int pop3_mainloop __P ((int infile, int outfile)); 200 extern void pop3d_usage __P ((char *argv0));
203 extern void pop3_daemon __P ((unsigned int maxchildren)); 201 extern void pop3d_signal __P ((int));
204 extern void pop3_usage __P ((char *argv0)); 202 extern void pop3d_sigchld __P ((int));
205 extern void pop3_signal __P ((int)); 203 extern void pop3d_daemon_init __P ((void));
206 extern void pop3_sigchld __P ((int)); 204 extern char *pop3d_apopuser __P ((const char *user));
207 extern void pop3_daemon_init __P ((void)); 205 extern char *pop3d_readline __P ((int fd));
208 extern char *pop3_apopuser __P ((const char *user));
209 extern char *pop3_readline __P ((int fd));
210 #endif /* _POP3D_H */ 206 #endif /* _POP3D_H */
......
...@@ -29,5 +29,10 @@ pop3_sigchld (int signo) ...@@ -29,5 +29,10 @@ pop3_sigchld (int signo)
29 errno = 0; 29 errno = 0;
30 while ( (pid = waitpid(-1, &status, WNOHANG)) > 0) 30 while ( (pid = waitpid(-1, &status, WNOHANG)) > 0)
31 --children; 31 --children;
32 #ifndef HAVE_SIGACTION
33 /* On some system, signal implements the unreliabe sematic and
34 has to be rearm. */
35 signal (SIGCHLD, pop3_sigchld);
36 #endif
32 errno = old_errno; 37 errno = old_errno;
33 } 38 }
......
...@@ -24,9 +24,8 @@ static char *_pwd; ...@@ -24,9 +24,8 @@ static char *_pwd;
24 static char *_user; 24 static char *_user;
25 static int _perr = 0; 25 static int _perr = 0;
26 26
27 #define PAM_ERROR if (_perr || (pamerror != PAM_SUCCESS)) { \ 27 #define PAM_ERROR if (_perr || (pamerror != PAM_SUCCESS)) \
28 pam_end(pamh, 0); \ 28 goto pam_errlab;
29 return ERR_BAD_LOGIN; }
30 29
31 static int 30 static int
32 PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) 31 PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
...@@ -119,6 +118,7 @@ pop3_user (const char *arg) ...@@ -119,6 +118,7 @@ pop3_user (const char *arg)
119 free (cmd); 118 free (cmd);
120 return ERR_BAD_CMD; 119 return ERR_BAD_CMD;
121 } 120 }
121
122 if ((strcasecmp (cmd, "PASS") == 0)) 122 if ((strcasecmp (cmd, "PASS") == 0))
123 { 123 {
124 free (cmd); 124 free (cmd);
...@@ -145,7 +145,10 @@ pop3_user (const char *arg) ...@@ -145,7 +145,10 @@ pop3_user (const char *arg)
145 spw = getspnam ((char *)arg); 145 spw = getspnam ((char *)arg);
146 if (spw == NULL || strcmp (spw->sp_pwdp, crypt (pass, spw->sp_pwdp))) 146 if (spw == NULL || strcmp (spw->sp_pwdp, crypt (pass, spw->sp_pwdp)))
147 #endif /* HAVE_SHADOW_H */ 147 #endif /* HAVE_SHADOW_H */
148 return ERR_BAD_LOGIN; 148 {
149 syslog (LOG_INFO, "User '%s': authentication failed", arg);
150 return ERR_BAD_LOGIN;
151 }
149 } 152 }
150 #else /* !USE_LIBPAM */ 153 #else /* !USE_LIBPAM */
151 _user = (char *) arg; 154 _user = (char *) arg;
...@@ -160,8 +163,14 @@ pop3_user (const char *arg) ...@@ -160,8 +163,14 @@ pop3_user (const char *arg)
160 PAM_ERROR; 163 PAM_ERROR;
161 pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED); 164 pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED);
162 PAM_ERROR; 165 PAM_ERROR;
166 pam_errlab:
163 pam_end (pamh, PAM_SUCCESS); 167 pam_end (pamh, PAM_SUCCESS);
164 openlog ("gnu-pop3d", LOG_PID, LOG_MAIL); 168 openlog ("gnu-pop3d", LOG_PID, LOG_FACILITY);
169 if (pamerror != PAM_SUCCESS)
170 {
171 syslog (LOG_INFO, "User '%s': authentication failed", _user);
172 return ERR_BAD_LOGIN;
173 }
165 #endif /* USE_LIBPAM */ 174 #endif /* USE_LIBPAM */
166 175
167 176
...@@ -210,6 +219,7 @@ pop3_user (const char *arg) ...@@ -210,6 +219,7 @@ pop3_user (const char *arg)
210 } 219 }
211 else if (strcasecmp (cmd, "QUIT") == 0) 220 else if (strcasecmp (cmd, "QUIT") == 0)
212 { 221 {
222 syslog (LOG_INFO, "Possible probe of account '%s'", arg);
213 free (cmd); 223 free (cmd);
214 return pop3_quit (pass); 224 return pop3_quit (pass);
215 } 225 }
......