Commit 8bf58774 8bf587746ac8af3afc03214f03b08b72d1971b9b by Jakob Kaivo

Actually add the files, not just the directory, to CVS

1 parent 767d2006
1 INCLUDES =-I$(srcdir) -I$(top_srcdir)/libsrc -I$(top_srcdir)/libmailbox
2
3 sbin_PROGRAMS = pop3d
4
5 pop3d_DEPENDENDENCIES = ../libmailbox/libmailbox.la ../libsrc/libgetopt.la\
6 ../libsrc/libmd5.la
7 pop3d_SOURCES = apop.c auth.c capa.c dele.c extra.c pop3d.c pop3d.h\
8 list.c noop.c quit.c retr.c rset.c stat.c top.c uidl.c user.c
9 pop3d_LDADD = ../libmailbox/libmailbox.la
...\ No newline at end of file ...\ No newline at end of file
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 #ifdef _USE_APOP
21
22 /* Check if a username exists in APOP password file
23 returns pinter to password if found, otherwise NULL */
24 char *
25 pop3_apopuser (const char *user)
26 {
27 char *password;
28 char buf[POP_MAXCMDLEN];
29 struct stat st;
30 #ifdef BDB2
31 int errno;
32 DB *dbp;
33 DBT key, data;
34
35 if (stat (APOP_PASSFILE ".db", &st) != -1)
36 #else
37 char *tmp;
38 FILE *apop_file;
39
40 if (stat (APOP_PASSFILE ".passwd", &st) != -1)
41 #endif
42 if ((st.st_mode & 0777) != 0600)
43 {
44 syslog (LOG_INFO, "Bad permissions on APOP password file");
45 return NULL;
46 }
47
48 #ifdef BDB2
49 if ((errno = db_open (APOP_PASSFILE ".db", DB_HASH, DB_RDONLY, 0600,
50 NULL, NULL, &dbp)) != 0)
51 {
52 syslog (LOG_ERR, "Unable to open APOP database: %s", strerror (errno));
53 return NULL;
54 }
55
56 memset (&key, 0, sizeof (DBT));
57 memset (&data, 0, sizeof (DBT));
58
59 strncpy (buf, user, sizeof (buf));
60 key.data = buf;
61 key.size = strlen (user);
62 if ((errno = dbp->get (dbp, NULL, &key, &data, 0)) != 0)
63 {
64 syslog (LOG_ERR, "db_get error: %s", strerror (errno));
65 dbp->close (dbp, 0);
66 return NULL;
67 }
68
69 if ((password = malloc (sizeof (char) * data.size)) == NULL)
70 {
71 dbp->close (dbp, 0);
72 return NULL;
73 }
74
75 sprintf (password, "%.*s", (int) data.size, (char *) data.data);
76 dbp->close (dbp, 0);
77 return password;
78 #else /* !BDBD2 */
79 if ((apop_file = fopen (APOP_PASSFILE ".passwd", "r")) == NULL)
80 {
81 syslog (LOG_INFO, "Unable to open APOP password file");
82 return NULL;
83 }
84
85 if ((password = malloc (sizeof (char) * APOP_DIGEST)) == NULL)
86 {
87 fclose (apop_file);
88 pop3_abquit (ERR_NO_MEM);
89 }
90 password[0] = '\0';
91
92 while (fgets (buf, sizeof (buf) - 1, apop_file) != NULL)
93 {
94 tmp = index (buf, ':');
95 *tmp = '\0';
96 tmp++;
97
98 if (strncmp (user, buf, strlen (user)))
99 continue;
100
101 strncpy (password, tmp, strlen (tmp));
102 tmp = index (password, '\n');
103 *tmp = '\0';
104 break;
105 }
106
107 fclose (apop_file);
108 if (strlen (password) == 0)
109 {
110 free (password);
111 return NULL;
112 }
113
114 return password;
115 #endif /* BDB2 */
116 }
117
118 int
119 pop3_apop (const char *arg)
120 {
121 char *tmp, *user_digest, *password;
122 struct passwd *pw;
123 char buf[POP_MAXCMDLEN];
124 struct md5_ctx md5context;
125 unsigned char md5digest[16];
126 int i;
127
128 if (state != AUTHORIZATION)
129 return ERR_WRONG_STATE;
130 if (strlen (arg) == 0)
131 return ERR_BAD_ARGS;
132
133 tmp = pop3_cmd (arg);
134 if (strlen (tmp) > (POP_MAXCMDLEN - APOP_DIGEST))
135 return ERR_BAD_ARGS;
136 if ((username = strdup (tmp)) == NULL)
137 pop3_abquit (ERR_NO_MEM);
138 free (tmp);
139
140 tmp = pop3_args (arg);
141 if (strlen (tmp) > APOP_DIGEST)
142 return ERR_BAD_ARGS;
143 if ((user_digest = strdup (tmp)) == NULL)
144 pop3_abquit (ERR_NO_MEM);
145 free (tmp);
146
147 if ((password = pop3_apopuser (username)) == NULL)
148 return ERR_BAD_LOGIN;
149
150 md5_init_ctx (&md5context);
151 md5_process_bytes (md5shared, strlen (md5shared), &md5context);
152 md5_process_bytes (password, strlen (password), &md5context);
153 /* pop3_wipestr (password); */
154 free (password);
155 md5_finish_ctx (&md5context, md5digest);
156
157 tmp = buf;
158 for (i = 0; i < 16; i++, tmp += 2)
159 sprintf (tmp, "%02x", md5digest[i]);
160
161 *tmp++ = '\0';
162
163 if (strcmp (user_digest, buf))
164 return ERR_BAD_LOGIN;
165
166 if ((pw = getpwnam (username)) == NULL)
167 return ERR_BAD_LOGIN;
168
169 #ifdef MAILSPOOLHOME
170 mailbox = malloc ((strlen (pw->pw_dir) + strlen (MAILSPOOLHOME) + 1) * sizeof (char));
171 if (mailbox == NULL)
172 pop3_abquit (ERR_NO_MEM);
173 strcpy (mailbox, pw->pw_dir);
174 strcat (mailbox, MAILSPOOLHOME);
175 mbox = fopen (mailbox, "r");
176 if (mbox == NULL)
177 {
178 free (mailbox);
179 chdir (_PATH_MAILDIR);
180 #endif
181 mailbox = malloc (sizeof (char) * (strlen (_PATH_MAILDIR) + strlen (username) + 2));
182 strcpy (mailbox, _PATH_MAILDIR "/");
183 strcat (mailbox, username);
184 if (mailbox == NULL)
185 pop3_abquit (ERR_NO_MEM);
186
187 mbox = fopen (mailbox, "r");
188 if (mbox == NULL)
189 {
190 mailbox = strdup ("/dev/null");
191 if (mailbox == NULL)
192 pop3_abquit (ERR_NO_MEM);
193 mbox = fopen (mailbox, "r");
194 }
195 #ifdef MAILSPOOLHOME
196 }
197 else
198 #endif
199 if (pop3_lock () != OK)
200 {
201 pop3_unlock ();
202 free (mailbox);
203 state = AUTHORIZATION;
204 return ERR_MBOX_LOCK;
205 }
206
207 if ((pw->pw_uid < 1)
208 #ifdef MAILSPOOLHOME
209 /* Drop mail group for home dirs */
210 || setgid (pw->pw_gid) == -1
211 #endif
212 || setuid (pw->pw_uid) == -1)
213 {
214 pop3_unlock ();
215 free (mailbox);
216 return ERR_BAD_LOGIN;
217 }
218
219 state = TRANSACTION;
220 messages = NULL;
221 pop3_getsizes ();
222 fprintf (ofile, "+OK opened mailbox for %s\r\n", username);
223 syslog (LOG_INFO, "User %s logged in with mailbox %s", username, mailbox);
224 cursor = 0;
225 return OK;
226 }
227
228 #else
229
230 int
231 pop3_apop (const char *foo)
232 {
233 return ERR_NOT_IMPL;
234 }
235
236 #endif
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* AUTH is not yet implemented */
21
22 int
23 pop3_auth (const char *arg)
24 {
25 if (state != AUTHORIZATION)
26 return ERR_WRONG_STATE;
27 return ERR_NOT_IMPL;
28 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2
3 * Code for capa support by Sean 'Shaleh' Perry <shaleh@debian.org>
4 * added 4/2/1999
5 *
6 */
7 #include "pop3d.h"
8
9 int
10 pop3_capa (const char *arg)
11 {
12 if (strlen (arg) != 0)
13 return ERR_BAD_ARGS;
14
15 if (state != AUTHORIZATION && state != TRANSACTION)
16 return ERR_WRONG_STATE;
17
18 fprintf (ofile, "+OK Capability list follows\r\n");
19 fprintf (ofile, "TOP\r\n");
20 fprintf (ofile, "USER\r\n");
21 fprintf (ofile, "RESP-CODES\r\n");
22 if (state == TRANSACTION) /* let's not advertise to just anyone */
23 fprintf (ofile, "IMPLEMENTATION %s %s\r\n", IMPL, VERSION);
24 fprintf (ofile, ".\r\n");
25 return OK;
26 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* DELE adds a message number to the list of messages to be deleted on QUIT */
21
22 int
23 pop3_dele (const char *arg)
24 {
25 int num = 0;
26
27 if ((arg == NULL) || (strchr (arg, ' ') != NULL))
28 return ERR_BAD_ARGS;
29
30 if (state != TRANSACTION)
31 return ERR_WRONG_STATE;
32
33 num = atoi (arg) - 1;
34 if (mbox_delete(mbox, num) != 0)
35 return ERR_NO_MESG;
36
37 fprintf (ofile, "+OK Message %d marked\r\n", num + 1);
38 return OK;
39 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Takes a string as input and returns either the remainder of the string
21 after the first space, or a zero length string if no space */
22
23 char *
24 pop3_args (const char *cmd)
25 {
26 int space = -1, i = 0, len;
27 char *buf;
28
29 len = strlen (cmd) + 1;
30 buf = malloc (len * sizeof (char));
31 if (buf == NULL)
32 pop3_abquit (ERR_NO_MEM);
33
34 while (space < 0 && i < len)
35 {
36 if (cmd[i] == ' ')
37 space = i + 1;
38 else if (cmd[i] == '\0' || cmd[i] == '\r' || cmd[i] == '\n')
39 len = i;
40 i++;
41 }
42
43 if (space < 0)
44 buf[0] = '\0';
45 else
46 {
47 for (i = space; i < len; i++)
48 if (cmd[i] == '\0' || cmd[i] == '\r' || cmd[i] == '\n')
49 buf[i - space] = '\0';
50 else
51 buf[i - space] = cmd[i];
52 }
53
54 return buf;
55 }
56
57 /* This takes a string and returns the string up to the first space or end of
58 the string, whichever occurs first */
59
60 char *
61 pop3_cmd (const char *cmd)
62 {
63 char *buf;
64 int i = 0, len;
65
66 len = strlen (cmd) + 1;
67 buf = malloc (len * sizeof (char));
68 if (buf == NULL)
69 pop3_abquit (ERR_NO_MEM);
70
71 for (i = 0; i < len; i++)
72 {
73 if (cmd[i] == ' ' || cmd[i] == '\0' || cmd[i] == '\r' || cmd[i] == '\n')
74 len = i;
75 else
76 buf[i] = cmd[i];
77 }
78 buf[i - 1] = '\0';
79 return buf;
80 }
81
82 /* This is called if GNU POP needs to quit without going to the UPDATE stage.
83 This is used for conditions such as out of memory, a broken socket, or
84 being killed on a signal */
85
86 int
87 pop3_abquit (int reason)
88 {
89 mbox_close(mbox);
90
91 switch (reason)
92 {
93 case ERR_NO_MEM:
94 fprintf (ofile, "-ERR Out of memory, quitting\r\n");
95 syslog (LOG_ERR, "Out of memory");
96 break;
97 case ERR_DEAD_SOCK:
98 fprintf (ofile, "-ERR Socket closed, quitting\r\n");
99 syslog (LOG_ERR, "Socket closed");
100 break;
101 case ERR_SIGNAL:
102 fprintf (ofile, "-ERR Quitting on signal\r\n");
103 syslog (LOG_ERR, "Quitting on signal");
104 break;
105 case ERR_TIMEOUT:
106 fprintf (ofile, "-ERR Session timed out\r\n");
107 if (state == TRANSACTION)
108 syslog (LOG_INFO, "Session timed out for user: %s", username);
109 else
110 syslog (LOG_INFO, "Session timed out for no user");
111 break;
112 default:
113 fprintf (ofile, "-ERR Quitting (reason unknown)\r\n");
114 syslog (LOG_ERR, "Unknown quit");
115 break;
116 }
117 fflush (ofile);
118 exit (1);
119 }
120
121 /* Prints out usage information and exits the program */
122
123 void
124 pop3_usage (char *argv0)
125 {
126 printf ("Usage: %s [OPTIONS]\n", argv0);
127 printf ("Runs the GNU POP3 daemon.\n\n");
128 printf (" -d, --daemon=MAXCHILDREN runs in daemon mode with a maximum\n");
129 printf (" of MAXCHILDREN child processes\n");
130 printf (" -h, --help display this help and exit\n");
131 printf (" -i, --inetd runs in inetd mode (default)\n");
132 printf (" -p, --port=PORT specifies port to listen on, implies -d\n");
133 printf (" defaults to 110, which need not be specified\n");
134 printf (" -t, --timeout=TIMEOUT sets idle timeout to TIMEOUT seconds\n");
135 printf (" TIMEOUT must be at least 600 (10 minutes) or\n");
136 printf (" it will be disabled\n");
137 printf (" -v, --version display version information and exit\n");
138 printf ("\nReport bugs to gnu-pop-list@nodomainname.net\n");
139 exit (0);
140 }
141
142 /* Default signal handler to call the pop3_abquit() function */
143
144 void
145 pop3_signal (int signal)
146 {
147 if (signal == SIGCHLD)
148 {
149 int stat;
150 while (waitpid (-1, &stat, WNOHANG) > 0);
151 return;
152 }
153 else
154 pop3_abquit (ERR_SIGNAL);
155 }
156
157 /* Gets a line of input from the client */
158
159 char *
160 pop3_readline (int fd)
161 {
162 fd_set rfds;
163 struct timeval tv;
164 char buf[1024], *ret = NULL;
165 int available;
166
167 FD_ZERO (&rfds);
168 FD_SET (fd, &rfds);
169 tv.tv_sec = timeout;
170 tv.tv_usec = 0;
171 memset (buf, '\0', 1024);
172
173 while (strchr (buf, '\n') == NULL)
174 {
175 if (timeout > 0)
176 {
177 available = select (fd + 1, &rfds, NULL, NULL, &tv);
178 if (!available)
179 pop3_abquit (ERR_TIMEOUT);
180 }
181
182 if (read (fd, buf, 1024) < 1)
183 pop3_abquit (ERR_DEAD_SOCK);
184
185 if (ret == NULL)
186 {
187 ret = malloc ((strlen (buf) + 1) * sizeof (char));
188 strcpy (ret, buf);
189 }
190 else
191 {
192 ret = realloc (ret, (strlen (ret) + strlen (buf) + 1) * sizeof (char));
193 strcat (ret, buf);
194 }
195 }
196 return ret;
197 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Displays the size of message number arg or all messages (if no arg) */
21
22 int
23 pop3_list (const char *arg)
24 {
25 int mesg = 0;
26
27 if (state != TRANSACTION)
28 return ERR_WRONG_STATE;
29
30 if (strchr (arg, ' ') != NULL)
31 return ERR_BAD_ARGS;
32
33 if (strlen (arg) == 0)
34 {
35 fprintf (ofile, "+OK\r\n");
36 for (mesg = 0; mesg < mbox->messages ; mesg++)
37 if (!mbox_is_deleted(mbox, mesg))
38 fprintf (ofile, "%d %d\r\n", mesg + 1, mbox->sizes[mesg]);
39 fprintf (ofile, ".\r\n");
40 }
41 else
42 {
43 mesg = atoi (arg) - 1;
44 if (mesg > mbox->messages || mbox_is_deleted(mbox, mesg))
45 return ERR_NO_MESG;
46 fprintf (ofile, "+OK %d %d\r\n", mesg + 1, mbox->sizes[mesg]);
47 }
48
49 return OK;
50 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Does nothing */
21
22 int
23 pop3_noop (const char *arg)
24 {
25 if (strlen (arg) != 0)
26 return ERR_BAD_ARGS;
27 if (state != TRANSACTION)
28 return ERR_WRONG_STATE;
29 fprintf (ofile, "+OK\r\n");
30 return OK;
31 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 static struct option long_options[] =
21 {
22 {"daemon", 2, 0, 'd'},
23 {"help", 0, 0, 'h'},
24 {"inetd", 0, 0, 'i'},
25 {"port", 1, 0, 'p'},
26 {"timeout", 1, 0, 't'},
27 {"version", 0, 0, 'v'},
28 {0, 0, 0, 0}
29 };
30
31 int
32 main (int argc, char **argv)
33 {
34 struct group *gr;
35 static int mode;
36 int maxchildren = 10;
37 int option_index = 0;
38 int c = 0;
39
40 port = 110; /* Default POP3 port */
41 timeout = 0; /* Default timeout of 0 */
42
43 while ((c = getopt_long (argc, argv, "d::hip:t:v", long_options, &option_index)) && c != -1)
44 {
45 switch (c)
46 {
47 case 'd':
48 mode = DAEMON;
49 maxchildren = optarg ? atoi (optarg) : 10;
50 break;
51 case 'h':
52 pop3_usage (argv[0]);
53 break;
54 case 'i':
55 mode = INTERACTIVE;
56 break;
57 case 'p':
58 mode = DAEMON;
59 port = atoi (optarg);
60 break;
61 case 't':
62 timeout = atoi (optarg);
63 break;
64 case 'v':
65 printf (IMPL " ("PACKAGE " " VERSION ")\n");
66 exit (0);
67 break;
68 default:
69 break;
70 }
71 }
72
73 /* First we want our group to be mail so we can access the spool */
74 gr = getgrnam ("mail");
75 if (gr == NULL)
76 {
77 perror ("Error getting group");
78 exit (1);
79 }
80
81 if (setgid (gr->gr_gid) == -1)
82 {
83 perror ("Error setting group");
84 exit (1);
85 }
86
87 /* Set the signal handlers */
88 signal (SIGINT, pop3_signal);
89 signal (SIGQUIT, pop3_signal);
90 signal (SIGILL, pop3_signal);
91 signal (SIGBUS, pop3_signal);
92 signal (SIGFPE, pop3_signal);
93 signal (SIGSEGV, pop3_signal);
94 signal (SIGTERM, pop3_signal);
95 signal (SIGSTOP, pop3_signal);
96
97 if (timeout < 600) /* RFC 1939 says no less than 10 minutes */
98 timeout = 0; /* So we'll turn it off */
99
100 if (mode == DAEMON)
101 pop3_daemon_init ();
102
103 /* change directories */
104 #ifdef MAILSPOOLHOME
105 chdir ("/");
106 #else
107 chdir (_PATH_MAILDIR);
108 #endif
109
110 /* Set up for syslog */
111 openlog ("gnu-pop3d", LOG_PID, LOG_MAIL);
112
113 umask (S_IROTH | S_IWOTH | S_IXOTH); /* 007 */
114
115 /* Actually run the daemon */
116 switch (mode)
117 {
118 case DAEMON:
119 if (maxchildren < 10)
120 maxchildren = 10;
121 pop3_daemon (maxchildren);
122 break;
123 case INTERACTIVE:
124 default:
125 pop3_mainloop (fileno (stdin), fileno (stdout));
126 break;
127 }
128
129 /* Close the syslog connection and exit */
130 closelog ();
131 return OK;
132 }
133
134 /* Sets things up for daemon mode */
135
136 void
137 pop3_daemon_init (void)
138 {
139 if (fork ())
140 exit (0); /* parent exits */
141 setsid (); /* become session leader */
142
143 if (fork ())
144 exit (0); /* new parent exits */
145
146 /* close inherited file descriptors */
147 close (0);
148 close (1);
149 close (2);
150
151 signal (SIGHUP, SIG_IGN); /* ignore SIGHUP */
152 signal (SIGCHLD, pop3_signal); /* for forking */
153 }
154
155 /* The main part of the daemon. This function reads input from the client and
156 executes the proper functions. Also handles the bulk of error reporting. */
157
158 int
159 pop3_mainloop (int infile, int outfile)
160 {
161 int status = OK;
162 char *buf, *arg, *cmd;
163 struct hostent *htbuf;
164 char *local_hostname;
165
166 ifile = infile;
167 ofile = fdopen (outfile, "w+");
168 if (ofile == NULL)
169 pop3_abquit (ERR_NO_OFILE);
170 state = AUTHORIZATION;
171 curr_time = time (NULL);
172
173 syslog (LOG_INFO, "Incoming connection opened");
174
175 /* Prepare the shared secret for APOP */
176 local_hostname = malloc (MAXHOSTNAMELEN + 1);
177 if (local_hostname == NULL)
178 pop3_abquit (ERR_NO_MEM);
179
180 gethostname (local_hostname, MAXHOSTNAMELEN);
181 htbuf = gethostbyname (local_hostname);
182 if (htbuf)
183 {
184 free (local_hostname);
185 local_hostname = strdup (htbuf->h_name);
186 }
187
188 md5shared = malloc (strlen (local_hostname) + 51);
189 if (md5shared == NULL)
190 pop3_abquit (ERR_NO_MEM);
191
192 snprintf (md5shared, strlen (local_hostname) + 50, "<%d.%ld@%s>", getpid (),
193 time (NULL), local_hostname);
194 free (local_hostname);
195
196 fflush (ofile);
197 fprintf (ofile, "+OK POP3 " WELCOME " %s\r\n", md5shared);
198
199 while (state != UPDATE)
200 {
201 fflush (ofile);
202 status = OK;
203 buf = pop3_readline (ifile);
204 cmd = pop3_cmd (buf);
205 arg = pop3_args (buf);
206
207 if (strlen (arg) > POP_MAXCMDLEN || strlen (cmd) > POP_MAXCMDLEN)
208 status = ERR_TOO_LONG;
209 else if (strlen (cmd) > 4)
210 status = ERR_BAD_CMD;
211 else if (strncasecmp (cmd, "USER", 4) == 0)
212 status = pop3_user (arg);
213 else if (strncasecmp (cmd, "QUIT", 4) == 0)
214 status = pop3_quit (arg);
215 else if (strncasecmp (cmd, "APOP", 4) == 0)
216 status = pop3_apop (arg);
217 else if (strncasecmp (cmd, "AUTH", 4) == 0)
218 status = pop3_auth (arg);
219 else if (strncasecmp (cmd, "STAT", 4) == 0)
220 status = pop3_stat (arg);
221 else if (strncasecmp (cmd, "LIST", 4) == 0)
222 status = pop3_list (arg);
223 else if (strncasecmp (cmd, "RETR", 4) == 0)
224 status = pop3_retr (arg);
225 else if (strncasecmp (cmd, "DELE", 4) == 0)
226 status = pop3_dele (arg);
227 else if (strncasecmp (cmd, "NOOP", 4) == 0)
228 status = pop3_noop (arg);
229 else if (strncasecmp (cmd, "RSET", 4) == 0)
230 status = pop3_rset (arg);
231 else if ((strncasecmp (cmd, "TOP", 3) == 0) && (strlen (cmd) == 3))
232 status = pop3_top (arg);
233 else if (strncasecmp (cmd, "UIDL", 4) == 0)
234 status = pop3_uidl (arg);
235 else if (strncasecmp (cmd, "CAPA", 4) == 0)
236 status = pop3_capa (arg);
237 else
238 status = ERR_BAD_CMD;
239
240 if (status == OK)
241 fflush (ofile);
242 else if (status == ERR_WRONG_STATE)
243 fprintf (ofile, "-ERR " BAD_STATE "\r\n");
244 else if (status == ERR_BAD_ARGS)
245 fprintf (ofile, "-ERR " BAD_ARGS "\r\n");
246 else if (status == ERR_NO_MESG)
247 fprintf (ofile, "-ERR " NO_MESG "\r\n");
248 else if (status == ERR_NOT_IMPL)
249 fprintf (ofile, "-ERR " NOT_IMPL "\r\n");
250 else if (status == ERR_BAD_CMD)
251 fprintf (ofile, "-ERR " BAD_COMMAND "\r\n");
252 else if (status == ERR_BAD_LOGIN)
253 fprintf (ofile, "-ERR " BAD_LOGIN "\r\n");
254 else if (status == ERR_MBOX_LOCK)
255 fprintf (ofile, "-ERR [IN-USE] " MBOX_LOCK "\r\n");
256 else if (status == ERR_TOO_LONG)
257 fprintf (ofile, "-ERR " TOO_LONG "\r\n");
258
259 free (buf);
260 free (cmd);
261 free (arg);
262 }
263
264 fflush (ofile);
265 return OK;
266 }
267
268 /* Runs GNU POP in standalone daemon mode. This opens and binds to a port
269 (default 110) then executes a pop3_mainloop() upon accepting a connection.
270 It starts maxchildren child processes to listen to and accept socket
271 connections */
272
273 int
274 pop3_daemon (int maxchildren)
275 {
276 int children = 0;
277 struct sockaddr_in client;
278 int sock, sock2;
279 unsigned int socksize;
280
281 sock = socket (PF_INET, SOCK_STREAM, (getprotobyname ("tcp"))->p_proto);
282 if (sock < 0)
283 {
284 syslog (LOG_ERR, "%s\n", strerror (errno));
285 exit (1);
286 }
287 memset (&client, 0, sizeof (struct sockaddr_in));
288 client.sin_family = AF_INET;
289 client.sin_port = htons (port);
290 client.sin_addr.s_addr = htonl (INADDR_ANY);
291 socksize = sizeof (client);
292 if (bind (sock, (struct sockaddr *) &client, socksize))
293 {
294 perror ("Couldn't bind to socket");
295 exit (1);
296 }
297 listen (sock, 128);
298 while (1)
299 {
300 if (children < maxchildren)
301 {
302 if (!fork ())
303 {
304 sock2 = accept (sock, &client, &socksize);
305 pop3_mainloop (sock2, sock2);
306 close (sock2);
307 exit (OK);
308 }
309 else
310 {
311 /* wait (NULL); */
312 children++;
313 }
314 }
315 else
316 {
317 wait (NULL);
318 children--;
319 }
320 }
321 return OK;
322 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #ifndef _POP3D_H
19 #define _POP3D_H 1
20 #include "config.h"
21
22 /* The implementation */
23 #define IMPL "GNU POP3 Daemon"
24
25 /* You can edit the messages the POP server prints out here */
26
27 /* Initial greeting */
28 #define WELCOME "Welcome to " IMPL " (" PACKAGE " " VERSION ")"
29
30 /* A command that doesn't exist */
31 #define BAD_COMMAND "Invalid command"
32
33 /* Incorrect number of arguments passed to a command */
34 #define BAD_ARGS "Invalid arguments"
35
36 /* Command issued in wrong state */
37 #define BAD_STATE "Incorrect state"
38
39 /* An action on a message that doesn't exist */
40 #define NO_MESG "No such message"
41
42 /* A command that is known but not implemented */
43 #define NOT_IMPL "Not implemented"
44
45 /* Invalid username or password */
46 #define BAD_LOGIN "Bad login"
47
48 /* User authenticated, but mailbox is locked */
49 #define MBOX_LOCK "Mailbox in use"
50
51 /* The command argument was > 40 characters */
52 #define TOO_LONG "Argument too long"
53
54 /* APOP password file, without .db or .passwd, which are added based on file
55 type automatically */
56 #define APOP_PASSFILE "/etc/apop"
57
58 /* Size of the MD5 digest for APOP */
59 #define APOP_DIGEST 70
60
61 /* Maximum length of a hostname (is this defined somewhere else?) */
62 #define MAXHOSTNAMELEN 64
63
64 /* Longest legal POP command */
65 #define POP_MAXCMDLEN 255
66
67 #define _GNU_SOURCE
68 #include <stdarg.h>
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <string.h>
72 #include <time.h>
73 #include <unistd.h>
74 #include <fcntl.h>
75 #include <errno.h>
76 #include <signal.h>
77 #include <sys/file.h>
78 #include <sys/types.h>
79 #include <sys/time.h>
80 #include <sys/stat.h>
81 #include <sys/wait.h>
82 #include <sys/socket.h>
83 #include <netinet/in.h>
84 #include <netdb.h>
85 #include <pwd.h>
86 #include <grp.h>
87 #include <syslog.h>
88 #include <ctype.h>
89 #include "md5.h"
90 #include "getopt.h"
91 #include "mailbox.h"
92
93 /* For Berkley DB2 APOP password file */
94 #ifdef BDB2
95 #include <db2/db.h>
96 #endif
97
98 /* The path to the mail spool files */
99 #ifdef HAVE_PATHS_H
100 #include <paths.h>
101 #else
102 #define _PATH_MAILDIR "/usr/spool/mail"
103 #endif
104
105 #ifdef HAVE_SECURITY_PAM_APPL_H
106 #include <security/pam_appl.h>
107 #endif
108
109 #ifdef HAVE_SHADOW_H
110 #include <shadow.h>
111 #endif
112
113 #define AUTHORIZATION 0
114 #define TRANSACTION 1
115 #define UPDATE 2
116
117 #define INTERACTIVE 0
118 #define DAEMON 1
119
120 #define OK 0
121 #define ERR_WRONG_STATE 1
122 #define ERR_BAD_ARGS 2
123 #define ERR_BAD_LOGIN 3
124 #define ERR_NO_MESG 4
125 #define ERR_NOT_IMPL 5
126 #define ERR_BAD_CMD 6
127 #define ERR_MBOX_LOCK 7
128 #define ERR_TOO_LONG 8
129 #define ERR_NO_MEM 9
130 #define ERR_DEAD_SOCK 10
131 #define ERR_SIGNAL 11
132 #define ERR_FILE 12
133 #define ERR_NO_OFILE 13
134 #define ERR_TIMEOUT 14
135
136 mailbox *mbox;
137
138 unsigned int port;
139 unsigned int timeout;
140 int state;
141 char *username;
142 int ifile;
143 FILE *ofile;
144 time_t curr_time;
145 char *md5shared;
146
147 int pop3_dele (const char *arg);
148 int pop3_list (const char *arg);
149 int pop3_noop (const char *arg);
150 int pop3_quit (const char *arg);
151 int pop3_retr (const char *arg);
152 int pop3_rset (const char *arg);
153 int pop3_stat (const char *arg);
154 int pop3_top (const char *arg);
155 int pop3_uidl (const char *arg);
156 int pop3_user (const char *arg);
157 int pop3_apop (const char *arg);
158 int pop3_auth (const char *arg);
159 int pop3_capa (const char *arg);
160 char *pop3_args (const char *cmd);
161 char *pop3_cmd (const char *cmd);
162 int pop3_mesg_exist (int mesg);
163 int pop3_abquit (int reason);
164 int pop3_lock (void);
165 int pop3_unlock (void);
166 int pop3_getsizes (void);
167 int pop3_mainloop (int infile, int outfile);
168 int pop3_daemon (int maxchildren);
169 void pop3_usage (char *argv0);
170 void pop3_signal (int signal);
171 void pop3_daemon_init (void);
172 #ifdef _USE_APOP
173 char *pop3_apopuser (const char *user);
174 #endif
175 char *pop3_readline (int fd);
176
177 #endif /* _POP3D_H */
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Enters the UPDATE phase and deletes marked messages */
21
22 int
23 pop3_quit (const char *arg)
24 {
25 if (strlen (arg) != 0)
26 return ERR_BAD_ARGS;
27
28 if (state == TRANSACTION)
29 {
30 mbox_expunge (mbox);
31 mbox_close (mbox);
32 syslog (LOG_INFO, "Session ended for user: %s", username);
33 }
34 else
35 syslog (LOG_INFO, "Session ended for no user");
36
37 state = UPDATE;
38 free (username);
39 free (md5shared);
40
41 fprintf (ofile, "+OK\r\n");
42 return OK;
43 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Prints out the specified message */
21
22 int
23 pop3_retr (const char *arg)
24 {
25 int mesg;
26 char *buf;
27
28 if ((strlen (arg) == 0) || (strchr (arg, ' ') != NULL))
29 return ERR_BAD_ARGS;
30
31 if (state != TRANSACTION)
32 return ERR_WRONG_STATE;
33
34 mesg = atoi (arg) - 1;
35
36 if (mesg > mbox->messages || mbox_is_deleted(mbox, mesg))
37 return ERR_NO_MESG;
38
39 fprintf (ofile, "+OK\r\n");
40 buf = mbox_get_header (mbox, mesg);
41 fprintf (ofile, "%s", buf);
42 free (buf);
43 buf = mbox_get_body (mbox, mesg);
44 fprintf (ofile, "%s", buf);
45 free (buf);
46 fprintf (ofile, ".\r\n");
47 return OK;
48 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Resets the connection so that no messages are marked as deleted */
21
22 int
23 pop3_rset (const char *arg)
24 {
25 int i;
26
27 if (strlen (arg) != 0)
28 return ERR_BAD_ARGS;
29
30 if (state != TRANSACTION)
31 return ERR_WRONG_STATE;
32
33 for (i = 0; i < mbox->messages; i++)
34 mbox_undelete (mbox, i);
35
36 fprintf (ofile, "+OK\r\n");
37 return OK;
38 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Prints the number of messages and the total size of all messages */
21
22 int
23 pop3_stat (const char *arg)
24 {
25 int size = 0;
26 int i;
27
28 if (strlen (arg) != 0)
29 return ERR_BAD_ARGS;
30
31 if (state != TRANSACTION)
32 return ERR_WRONG_STATE;
33
34 for (i = 0; i < mbox->messages ; i++)
35 if (!mbox_is_deleted (mbox, i))
36 size += mbox->sizes[i];
37
38 fprintf (ofile, "+OK %d %d\r\n", mbox->messages - mbox->num_deleted, size);
39 return OK;
40 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 /* Prints the header of a message plus a specified number of lines */
21
22 int
23 pop3_top (const char *arg)
24 {
25 #ifdef _HAVE_BLACK_MAGIC
26 int i = 0, header = 1, done = 0;
27 int mesg, lines;
28 char *mesgc, *linesc;
29 char *buf, buf2[80];
30
31 if (strlen (arg) == 0)
32 return ERR_BAD_ARGS;
33
34 if (state != TRANSACTION)
35 return ERR_WRONG_STATE;
36
37 mesgc = pop3_cmd (arg);
38 linesc = pop3_args (arg);
39 mesg = atoi (mesgc) - 1;
40 lines = strlen (linesc) > 0 ? atoi (linesc) : -1;
41 free (mesgc);
42 free (linesc);
43
44 if (lines < 0)
45 return ERR_BAD_ARGS;
46
47 if (pop3_mesg_exist (mesg) != OK)
48 return ERR_NO_MESG;
49
50 mbox = freopen (mailbox, "r", mbox);
51 if (mbox == NULL)
52 return ERR_FILE;
53 fsetpos (mbox, &(messages[mesg].header));
54
55 fprintf (ofile, "+OK\r\n");
56 buf = malloc (sizeof (char) * 80);
57 if (buf == NULL)
58 pop3_abquit (ERR_NO_MEM);
59
60 while (fgets (buf, 80, mbox) && !done)
61 {
62 while (strchr (buf, '\n') == NULL)
63 {
64 buf = realloc (buf, sizeof (char) * (strlen (buf) + 81));
65 if (buf == NULL)
66 pop3_abquit (ERR_NO_MEM);
67 fgets (buf2, 80, mbox);
68 strncat (buf, buf2, 80);
69 }
70 if (!strncmp (buf, "From ", 5))
71 done = 1;
72 else
73 {
74 buf[strlen (buf) - 1] = '\0';
75 if (header == 1)
76 {
77 if (buf[0] == '.')
78 fprintf (ofile, ".%s\r\n", buf);
79 else
80 fprintf (ofile, "%s\r\n", buf);
81 if ((buf[0] == '\r') || (buf[0] == '\n') || (buf[0]) == '\0')
82 header = 0;
83 }
84 else
85 {
86 if (++i <= lines)
87 {
88 if (buf[0] == '.')
89 fprintf (ofile, ".%s\r\n", buf);
90 else
91 fprintf (ofile, "%s\r\n", buf);
92 }
93 else
94 done = 1;
95 }
96 }
97 buf = realloc (buf, sizeof (char) * 80);
98 if (buf == NULL)
99 pop3_abquit (ERR_NO_MEM);
100 }
101
102 free (buf);
103 fprintf (ofile, ".\r\n");
104 return OK;
105 #else
106 return ERR_NOT_IMPL;
107 #endif
108 }
109
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 int
21 pop3_uidl (const char *arg)
22 {
23 if (state != TRANSACTION)
24 return ERR_WRONG_STATE;
25
26 return ERR_NOT_IMPL;
27 }
1 /* GNU POP3 - a small, fast, and efficient POP3 daemon
2 Copyright (C) 1999 Jakob 'sparky' Kaivo <jkaivo@nodomainname.net>
3
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
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 #include "pop3d.h"
19
20 #ifdef USE_LIBPAM
21 #define COPY_STRING(s) (s) ? strdup(s) : NULL
22
23 static char *_pwd;
24 static char *_user;
25 static int _perr = 0;
26
27 #define PAM_ERROR if (_perr || (pamerror != PAM_SUCCESS)) { \
28 pam_end(pamh, 0); \
29 return ERR_BAD_LOGIN; }
30
31 static int
32 PAM_gnupop3d_conv (int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
33 {
34 int replies = 0;
35 struct pam_response *reply = NULL;
36
37 reply = (struct pam_response *) malloc (sizeof (struct pam_response) * num_msg);
38 if (!reply)
39 return PAM_CONV_ERR;
40
41 for (replies = 0; replies < num_msg; replies++)
42 {
43 switch (msg[replies]->msg_style)
44 {
45 case PAM_PROMPT_ECHO_ON:
46 reply[replies].resp_retcode = PAM_SUCCESS;
47 reply[replies].resp = COPY_STRING (_user);
48 /* PAM frees resp */
49 break;
50 case PAM_PROMPT_ECHO_OFF:
51 reply[replies].resp_retcode = PAM_SUCCESS;
52 reply[replies].resp = COPY_STRING (_pwd);
53 /* PAM frees resp */
54 break;
55 case PAM_TEXT_INFO:
56 case PAM_ERROR_MSG:
57 reply[replies].resp_retcode = PAM_SUCCESS;
58 reply[replies].resp = NULL;
59 break;
60 default:
61 free (reply);
62 _perr = 1;
63 return PAM_CONV_ERR;
64 }
65 }
66 *resp = reply;
67 return PAM_SUCCESS;
68 }
69
70 static struct pam_conv PAM_conversation =
71 {&PAM_gnupop3d_conv, NULL};
72 #endif /* USE_LIBPAM */
73
74 /* Basic user authentication. This also takes the PASS command and verifies
75 the user name and password. Calls setuid() upon successful verification,
76 otherwise it will (likely) return ERR_BAD_LOGIN */
77
78 int
79 pop3_user (const char *arg)
80 {
81 char *buf, pass[POP_MAXCMDLEN], *tmp, *cmd;
82 #ifdef USE_LIBPAM
83 pam_handle_t *pamh;
84 int pamerror;
85 #endif /* !USE_LIBPAM */
86 struct passwd *pw;
87
88 if (state != AUTHORIZATION)
89 return ERR_WRONG_STATE;
90
91 if ((strlen (arg) == 0) || (strchr (arg, ' ') != NULL))
92 return ERR_BAD_ARGS;
93
94 fprintf (ofile, "+OK\r\n");
95 fflush (ofile);
96
97 buf = pop3_readline (ifile);
98 cmd = pop3_cmd (buf);
99 tmp = pop3_args (buf);
100 free (buf);
101
102 if (strlen (tmp) > POP_MAXCMDLEN)
103 {
104 free (tmp);
105 return ERR_TOO_LONG;
106 }
107 else
108 {
109 strncpy (pass, tmp, POP_MAXCMDLEN);
110 free (tmp);
111 }
112
113 if (strlen (cmd) > 4)
114 {
115 free (cmd);
116 return ERR_BAD_CMD;
117 }
118 if ((strcasecmp (cmd, "PASS") == 0))
119 {
120 free (cmd);
121
122 #ifdef _USE_APOP
123 /* Check to see if they have an APOP password. If so, refuse USER/PASS */
124 tmp = pop3_apopuser (arg);
125 if (tmp != NULL)
126 {
127 syslog (LOG_INFO, "APOP user %s tried to log in with USER", arg);
128 free (tmp);
129 return ERR_BAD_LOGIN;
130 }
131 free (tmp);
132 #endif
133
134 pw = getpwnam (arg);
135 #ifndef USE_LIBPAM
136 if (pw == NULL)
137 return ERR_BAD_LOGIN;
138 if (pw->pw_uid < 1)
139 return ERR_BAD_LOGIN;
140 if (strcmp (pw->pw_passwd, crypt (pass, pw->pw_passwd)))
141 {
142 #ifdef HAVE_SHADOW_H
143 struct spwd *spw;
144 spw = getspnam (arg);
145 if (spw == NULL)
146 return ERR_BAD_LOGIN;
147 if (strcmp (spw->sp_pwdp, crypt (pass, spw->sp_pwdp)))
148 #endif /* HAVE_SHADOW_H */
149 return ERR_BAD_LOGIN;
150 }
151 #else /* USE_LIBPAM */
152 _user = (char *) arg;
153 _pwd = pass;
154 /* libpam doesn't log to LOG_MAIL */
155 closelog ();
156 pamerror = pam_start ("gnu-pop3d", arg, &PAM_conversation, &pamh);
157 PAM_ERROR;
158 pamerror = pam_authenticate (pamh, 0);
159 PAM_ERROR;
160 pamerror = pam_acct_mgmt (pamh, 0);
161 PAM_ERROR;
162 pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED);
163 PAM_ERROR;
164 pam_end (pamh, PAM_SUCCESS);
165 openlog ("gnu-pop3d", LOG_PID, LOG_MAIL);
166 #endif /* USE_LIBPAM */
167
168 #ifdef MAILSPOOLHOME
169 chdir (pw->pw_dir);
170 mbox = mbox_open (MAILSPOOLHOME);
171 if (mbox == NULL)
172 {
173 /* See comments below... */
174 chdir (_PATH_MAILDIR);
175 #endif /* MAILSPOOLHOME */
176 mbox = mbox_open (arg);
177 if (mbox == NULL)
178 {
179 /* Check the error type... */
180 /* Until then, though */
181 state = AUTHORIZATION;
182 return ERR_MBOX_LOCK;
183 }
184 #ifdef MAILSPOOLHOME
185 }
186 #endif
187 username = strdup (arg);
188 if (username == NULL)
189 pop3_abquit (ERR_NO_MEM);
190 state = TRANSACTION;
191
192 if (pw != NULL && pw->pw_uid > 1)
193 setuid (pw->pw_uid);
194
195 fprintf (ofile, "+OK opened mailbox for %s\r\n", username);
196 syslog (LOG_INFO, "User '%s' logged in with mailbox '%s'", username,
197 mbox->name);
198 return OK;
199 }
200 else if (strcasecmp (cmd, "QUIT") == 0)
201 {
202 free (cmd);
203 return pop3_quit (pass);
204 }
205
206 free (cmd);
207 return ERR_BAD_LOGIN;
208 }