pop3d: make tls more configurable
The "tls" statement can be used both within a server declaration and in the global scope, the former overriding the latter. Its argument can be one of the following: no TLS is not used. The STLS command won't be available even if the tls configuration is otherwise complete. ondemand TLS is initiated when the user issues the STLS command. This is the default when TLS is configured. required Same as above, but the use of STLS is mandatory. The authentication state is entered only after TLS negotiation has succeeded. connection TLS is always forced when the connection is established (pops). For compatibility with prior versions the tls-required statement is retained, but is considered deprecated. It is synonymous with "tls required". The "tls" statement allows for the following alias values: false, off, 0 same as no stls same as ondemand yes, true, on, 1 same as connection Internally, all handler functions receive a pointer to the POP session structure, which configures the current session. In particular, it contains the TLS mode and capability list. * pop3d/capa.c (pop3d_capa): Traverse the capability list, outputting each of its elements. (pop3d_session_init) (pop3d_session_free): New functions. * pop3d/logindelay.c (login_delay_capa): Change signature. * pop3d/pop3d.c (tls_required): Remove. (tls_mode): New variable. (pop3d_srv_config) <tls>: Remove. (pop3d_srv_config) <tls_mode>: New member. (pop3d_srv_param): Change definition of the "tls" statement. (pop3d_cfg_param): New statement "tls". Mark "tls-required" as deprecated. (pop3d_mainloop): Change type of the tls argument. Initialize session and pass it to each handler. (pop3d_connection): Decide whether and how to use TLS using global and per-session settings, the latter overriding the former. * pop3d/pop3d.h (login_delay_capa): Change signature. (tls_mode): New enum. (pop3d_capa_type): New enum. (pop3d_capa, pop3d_session): New structs. (pop3d_session_init) (pop3d_session_free): New protos. (pop3d_command_handler_t): Change signature. All handlers and their uses are changed accordingly. * pop3d/stls.c (pop3d_stls): Return error if session does not allow tls.
Showing
17 changed files
with
289 additions
and
76 deletions
... | @@ -164,7 +164,7 @@ pop3d_apopuser (const char *user) | ... | @@ -164,7 +164,7 @@ pop3d_apopuser (const char *user) |
164 | } | 164 | } |
165 | 165 | ||
166 | int | 166 | int |
167 | pop3d_apop (char *arg) | 167 | pop3d_apop (char *arg, struct pop3d_session *sess) |
168 | { | 168 | { |
169 | char *p, *password, *user_digest, *user; | 169 | char *p, *password, *user_digest, *user; |
170 | struct mu_md5_ctx md5context; | 170 | struct mu_md5_ctx md5context; | ... | ... |
... | @@ -19,7 +19,7 @@ | ... | @@ -19,7 +19,7 @@ |
19 | /* AUTH is not yet implemented */ | 19 | /* AUTH is not yet implemented */ |
20 | 20 | ||
21 | int | 21 | int |
22 | pop3d_auth (char *arg MU_ARG_UNUSED) | 22 | pop3d_auth (char *arg MU_ARG_UNUSED, struct pop3d_session *sess MU_ARG_UNUSED) |
23 | { | 23 | { |
24 | if (state != AUTHORIZATION) | 24 | if (state != AUTHORIZATION) |
25 | return ERR_WRONG_STATE; | 25 | return ERR_WRONG_STATE; | ... | ... |
... | @@ -26,38 +26,134 @@ | ... | @@ -26,38 +26,134 @@ |
26 | 26 | ||
27 | Capabilities available in the AUTHORIZATION state MUST be announced | 27 | Capabilities available in the AUTHORIZATION state MUST be announced |
28 | in both states. */ | 28 | in both states. */ |
29 | |||
30 | static int | ||
31 | print_capa (void *item, void *data) | ||
32 | { | ||
33 | struct pop3d_capa *cp = item; | ||
34 | struct pop3d_session *session = data; | ||
35 | if (cp->type == capa_func) | ||
36 | { | ||
37 | cp->value.func (cp->name, session); | ||
38 | } | ||
39 | else | ||
40 | { | ||
41 | pop3d_outf ("%s", cp->name); | ||
42 | if (cp->value.string) | ||
43 | pop3d_outf ("%s", cp->value.string); | ||
44 | pop3d_outf ("\n"); | ||
45 | } | ||
46 | return 0; | ||
47 | } | ||
48 | |||
29 | int | 49 | int |
30 | pop3d_capa (char *arg) | 50 | pop3d_capa (char *arg, struct pop3d_session *sess) |
31 | { | 51 | { |
32 | if (strlen (arg) != 0) | 52 | if (strlen (arg) != 0) |
33 | return ERR_BAD_ARGS; | 53 | return ERR_BAD_ARGS; |
34 | 54 | ||
35 | pop3d_outf ("+OK Capability list follows\n"); | 55 | pop3d_outf ("+OK Capability list follows\n"); |
36 | pop3d_outf ("TOP\n"); | 56 | mu_list_foreach (sess->capa, print_capa, sess); |
37 | pop3d_outf ("USER\n"); | 57 | pop3d_outf (".\n"); |
38 | pop3d_outf ("UIDL\n"); | 58 | return OK; |
39 | pop3d_outf ("RESP-CODES\n"); | 59 | } |
40 | pop3d_outf ("PIPELINING\n"); | 60 | |
41 | if (pop3d_xlines) | 61 | static void |
42 | pop3d_outf ("XLINES\n"); | 62 | pop3d_append_capa_string (struct pop3d_session *sess, const char *name, |
43 | 63 | const char *value) | |
64 | { | ||
65 | struct pop3d_capa *cp; | ||
66 | |||
67 | cp = mu_alloc (sizeof (*cp)); | ||
68 | cp->type = capa_string; | ||
69 | cp->name = name; | ||
70 | cp->value.string = value ? mu_strdup (value) : NULL; | ||
71 | if (mu_list_append (sess->capa, cp)) | ||
72 | mu_alloc_die (); | ||
73 | } | ||
74 | |||
75 | static void | ||
76 | pop3d_append_capa_func (struct pop3d_session *sess, const char *name, | ||
77 | void (*func) (const char *, struct pop3d_session *)) | ||
78 | { | ||
79 | struct pop3d_capa *cp; | ||
80 | |||
81 | if (!func) | ||
82 | return; | ||
83 | cp = mu_alloc (sizeof (*cp)); | ||
84 | cp->type = capa_func; | ||
85 | cp->name = name; | ||
86 | cp->value.func = func; | ||
87 | if (mu_list_append (sess->capa, cp)) | ||
88 | mu_alloc_die (); | ||
89 | } | ||
90 | |||
91 | static void | ||
92 | capa_free (void *p) | ||
93 | { | ||
94 | struct pop3d_capa *cp = p; | ||
95 | if (cp->type == capa_string && cp->value.string) | ||
96 | free (cp->value.string); | ||
97 | free (cp); | ||
98 | } | ||
99 | |||
100 | static void | ||
101 | capa_implementation (const char *name, struct pop3d_session *session) | ||
102 | { | ||
103 | if (state == TRANSACTION) /* let's not advertise to just anyone */ | ||
104 | pop3d_outf ("%s %s\n", name, PACKAGE_STRING); | ||
105 | } | ||
106 | |||
44 | #ifdef WITH_TLS | 107 | #ifdef WITH_TLS |
45 | if (tls_available && tls_done == 0) | 108 | static void |
46 | pop3d_outf ("STLS\n"); | 109 | capa_stls (const char *name, struct pop3d_session *session) |
110 | { | ||
111 | if ((session->tls == tls_ondemand || session->tls == tls_required) | ||
112 | && tls_available && tls_done == 0) | ||
113 | pop3d_outf ("%s\n", name); | ||
114 | } | ||
115 | #else | ||
116 | # define capa_stls NULL | ||
47 | #endif /* WITH_TLS */ | 117 | #endif /* WITH_TLS */ |
48 | 118 | ||
49 | login_delay_capa (); | 119 | static void |
50 | /* This can be implemented by setting an header field on the message. */ | 120 | capa_user (const char *name, struct pop3d_session *session) |
51 | if (expire == EXPIRE_NEVER) | 121 | { |
52 | pop3d_outf ("EXPIRE NEVER\n"); | ||
53 | else | ||
54 | pop3d_outf ("EXPIRE %s\n", mu_umaxtostr (0, expire)); | ||
55 | |||
56 | if (state == INITIAL) | 122 | if (state == INITIAL) |
57 | pop3d_outf ("XTLSREQUIRED\n"); | 123 | pop3d_outf ("XTLSREQUIRED\n"); |
58 | 124 | else | |
59 | if (state == TRANSACTION) /* let's not advertise to just anyone */ | 125 | pop3d_outf ("USER\n"); |
60 | pop3d_outf ("IMPLEMENTATION %s\n", PACKAGE_STRING); | 126 | } |
61 | pop3d_outf (".\n"); | 127 | |
62 | return OK; | 128 | void |
129 | pop3d_session_init (struct pop3d_session *session) | ||
130 | { | ||
131 | if (mu_list_create (&session->capa)) | ||
132 | mu_alloc_die (); | ||
133 | mu_list_set_destroy_item (session->capa, capa_free); | ||
134 | |||
135 | /* Initialize the capability list */ | ||
136 | pop3d_append_capa_string (session, "TOP", NULL); | ||
137 | pop3d_append_capa_string (session, "UIDL", NULL); | ||
138 | pop3d_append_capa_string (session, "RESP-CODES", NULL); | ||
139 | pop3d_append_capa_string (session, "PIPELINING", NULL); | ||
140 | if (pop3d_xlines) | ||
141 | pop3d_append_capa_string (session, "XLINES", NULL); | ||
142 | |||
143 | pop3d_append_capa_func (session, "LOGIN-DELAY", login_delay_capa); | ||
144 | |||
145 | /* This can be implemented by setting an header field on the message. */ | ||
146 | pop3d_append_capa_string (session, "EXPIRE", | ||
147 | (expire == EXPIRE_NEVER) ? | ||
148 | "NEVER" : mu_umaxtostr (0, expire)); | ||
149 | |||
150 | pop3d_append_capa_func (session, NULL, capa_user); | ||
151 | pop3d_append_capa_func (session, "STLS", capa_stls); | ||
152 | pop3d_append_capa_func (session, "IMPLEMENTATION", capa_implementation); | ||
153 | } | ||
154 | |||
155 | void | ||
156 | pop3d_session_free (struct pop3d_session *session) | ||
157 | { | ||
158 | mu_list_destroy (&session->capa); | ||
63 | } | 159 | } | ... | ... |
... | @@ -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 | pop3d_dele (char *arg) | 23 | pop3d_dele (char *arg, struct pop3d_session *sess) |
24 | { | 24 | { |
25 | size_t num; | 25 | size_t num; |
26 | mu_message_t msg; | 26 | mu_message_t msg; | ... | ... |
... | @@ -39,7 +39,7 @@ | ... | @@ -39,7 +39,7 @@ |
39 | XLINES capability. | 39 | XLINES capability. |
40 | */ | 40 | */ |
41 | int | 41 | int |
42 | pop3d_list (char *arg) | 42 | pop3d_list (char *arg, struct pop3d_session *sess) |
43 | { | 43 | { |
44 | size_t mesgno; | 44 | size_t mesgno; |
45 | mu_message_t msg = NULL; | 45 | mu_message_t msg = NULL; | ... | ... |
... | @@ -141,13 +141,13 @@ update_login_delay (char *username) | ... | @@ -141,13 +141,13 @@ update_login_delay (char *username) |
141 | } | 141 | } |
142 | 142 | ||
143 | void | 143 | void |
144 | login_delay_capa () | 144 | login_delay_capa (const char *name, struct pop3d_session *session) |
145 | { | 145 | { |
146 | mu_dbm_file_t db; | 146 | mu_dbm_file_t db; |
147 | 147 | ||
148 | if (login_delay && (db = open_stat_db (MU_STREAM_RDWR)) != NULL) | 148 | if (login_delay && (db = open_stat_db (MU_STREAM_RDWR)) != NULL) |
149 | { | 149 | { |
150 | pop3d_outf ("LOGIN-DELAY %s\n", mu_umaxtostr (0, login_delay)); | 150 | pop3d_outf ("%lu\n", (unsigned long) login_delay); |
151 | mu_dbm_destroy (&db); | 151 | mu_dbm_destroy (&db); |
152 | } | 152 | } |
153 | } | 153 | } | ... | ... |
... | @@ -20,7 +20,7 @@ | ... | @@ -20,7 +20,7 @@ |
20 | /* Does nothing */ | 20 | /* Does nothing */ |
21 | 21 | ||
22 | int | 22 | int |
23 | pop3d_noop (char *arg) | 23 | pop3d_noop (char *arg, struct pop3d_session *sess) |
24 | { | 24 | { |
25 | if (strlen (arg) != 0) | 25 | if (strlen (arg) != 0) |
26 | return ERR_BAD_ARGS; | 26 | return ERR_BAD_ARGS; | ... | ... |
... | @@ -18,6 +18,7 @@ | ... | @@ -18,6 +18,7 @@ |
18 | #include "mailutils/pam.h" | 18 | #include "mailutils/pam.h" |
19 | #include "mailutils/libargp.h" | 19 | #include "mailutils/libargp.h" |
20 | #include "mailutils/pop3.h" | 20 | #include "mailutils/pop3.h" |
21 | #include "mailutils/kwd.h" | ||
21 | #include "tcpwrap.h" | 22 | #include "tcpwrap.h" |
22 | 23 | ||
23 | mu_mailbox_t mbox; | 24 | mu_mailbox_t mbox; |
... | @@ -29,13 +30,14 @@ mu_m_server_t server; | ... | @@ -29,13 +30,14 @@ mu_m_server_t server; |
29 | unsigned int idle_timeout; | 30 | unsigned int idle_timeout; |
30 | int pop3d_transcript; | 31 | int pop3d_transcript; |
31 | int debug_mode; | 32 | int debug_mode; |
32 | int tls_required; | ||
33 | int pop3d_xlines; | 33 | int pop3d_xlines; |
34 | char *apop_database_name = APOP_PASSFILE; | 34 | char *apop_database_name = APOP_PASSFILE; |
35 | int apop_database_safety = MU_FILE_SAFETY_ALL; | 35 | int apop_database_safety = MU_FILE_SAFETY_ALL; |
36 | uid_t apop_database_owner; | 36 | uid_t apop_database_owner; |
37 | int apop_database_owner_set; | 37 | int apop_database_owner_set; |
38 | 38 | ||
39 | enum tls_mode tls_mode; | ||
40 | |||
39 | #ifdef WITH_TLS | 41 | #ifdef WITH_TLS |
40 | int tls_available; | 42 | int tls_available; |
41 | int tls_done; | 43 | int tls_done; |
... | @@ -137,13 +139,61 @@ cb_bulletin_db (void *data, mu_config_value_t *val) | ... | @@ -137,13 +139,61 @@ cb_bulletin_db (void *data, mu_config_value_t *val) |
137 | struct pop3d_srv_config | 139 | struct pop3d_srv_config |
138 | { | 140 | { |
139 | struct mu_srv_config m_cfg; | 141 | struct mu_srv_config m_cfg; |
140 | int tls; | 142 | enum tls_mode tls_mode; |
141 | }; | 143 | }; |
142 | 144 | ||
145 | #ifdef WITH_TLS | ||
146 | static int | ||
147 | cb_tls (void *data, mu_config_value_t *val) | ||
148 | { | ||
149 | int *res = data; | ||
150 | static struct mu_kwd tls_kwd[] = { | ||
151 | { "no", tls_no }, | ||
152 | { "false", tls_no }, | ||
153 | { "off", tls_no }, | ||
154 | { "0", tls_no }, | ||
155 | { "ondemand", tls_ondemand }, | ||
156 | { "stls", tls_ondemand }, | ||
157 | { "required", tls_required }, | ||
158 | { "connection", tls_connection }, | ||
159 | /* For compatibility with prior versions: */ | ||
160 | { "yes", tls_connection }, | ||
161 | { "true", tls_connection }, | ||
162 | { "on", tls_connection }, | ||
163 | { "1", tls_connection }, | ||
164 | { NULL } | ||
165 | }; | ||
166 | |||
167 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
168 | return 1; | ||
169 | |||
170 | if (mu_kwd_xlat_name (tls_kwd, val->v.string, res)) | ||
171 | mu_error (_("not a valid tls keyword: %s"), val->v.string); | ||
172 | return 0; | ||
173 | } | ||
174 | #endif | ||
175 | |||
176 | static int | ||
177 | cb_tls_required (void *data, mu_config_value_t *val) | ||
178 | { | ||
179 | int *res = data; | ||
180 | int bv; | ||
181 | |||
182 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
183 | return 1; | ||
184 | if (mu_cfg_parse_boolean (val->v.string, &bv)) | ||
185 | mu_error (_("Not a boolean value")); | ||
186 | else | ||
187 | *res = tls_required; | ||
188 | return 0; | ||
189 | } | ||
190 | |||
143 | static struct mu_cfg_param pop3d_srv_param[] = { | 191 | static struct mu_cfg_param pop3d_srv_param[] = { |
144 | { "tls", mu_cfg_bool, NULL, mu_offsetof (struct pop3d_srv_config, tls), NULL, | 192 | #ifdef WITH_TLS |
145 | N_("Use TLS encryption for this server") | 193 | { "tls", mu_cfg_callback, |
146 | }, | 194 | NULL, mu_offsetof (struct pop3d_srv_config, tls_mode), cb_tls, |
195 | N_("Kind of TLS encryption to use for this server") }, | ||
196 | #endif | ||
147 | { NULL } | 197 | { NULL } |
148 | }; | 198 | }; |
149 | 199 | ||
... | @@ -178,8 +228,11 @@ static struct mu_cfg_param pop3d_cfg_param[] = { | ... | @@ -178,8 +228,11 @@ static struct mu_cfg_param pop3d_cfg_param[] = { |
178 | N_("arg: list") }, | 228 | N_("arg: list") }, |
179 | 229 | ||
180 | #ifdef WITH_TLS | 230 | #ifdef WITH_TLS |
181 | { "tls-required", mu_cfg_bool, &tls_required, 0, NULL, | 231 | { "tls", mu_cfg_callback, &tls_mode, 0, cb_tls, |
182 | N_("Always require STLS before entering authentication phase.") }, | 232 | N_("Kind of TLS encryption to use") }, |
233 | { "tls-required", mu_cfg_callback, &tls_mode, 0, cb_tls_required, | ||
234 | N_("Always require STLS before entering authentication phase.\n" | ||
235 | "Deprecated, use \"tls required\" instead.") }, | ||
183 | #endif | 236 | #endif |
184 | #ifdef ENABLE_LOGIN_DELAY | 237 | #ifdef ENABLE_LOGIN_DELAY |
185 | { "login-delay", mu_cfg_time, &login_delay, 0, NULL, | 238 | { "login-delay", mu_cfg_time, &login_delay, 0, NULL, |
... | @@ -292,19 +345,36 @@ pop3d_get_client_address (int fd, struct sockaddr_in *pcs) | ... | @@ -292,19 +345,36 @@ pop3d_get_client_address (int fd, struct sockaddr_in *pcs) |
292 | ofd -- output descriptor | 345 | ofd -- output descriptor |
293 | tls -- initiate encrypted connection */ | 346 | tls -- initiate encrypted connection */ |
294 | int | 347 | int |
295 | pop3d_mainloop (int ifd, int ofd, int tls) | 348 | pop3d_mainloop (int ifd, int ofd, enum tls_mode tls) |
296 | { | 349 | { |
297 | int status = OK; | 350 | int status = OK; |
298 | char buffer[512]; | 351 | char buffer[512]; |
299 | static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, | 352 | static int sigtab[] = { SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSTOP, SIGPIPE, |
300 | SIGABRT, SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGALRM }; | 353 | SIGABRT, SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGALRM }; |
301 | 354 | struct pop3d_session session; | |
355 | |||
302 | mu_set_signals (pop3d_child_signal, sigtab, MU_ARRAY_SIZE (sigtab)); | 356 | mu_set_signals (pop3d_child_signal, sigtab, MU_ARRAY_SIZE (sigtab)); |
303 | 357 | ||
304 | pop3d_setio (ifd, ofd, tls); | 358 | if (tls == tls_unspecified) |
359 | tls = tls_available ? tls_ondemand : tls_no; | ||
360 | else if (tls != tls_no && !tls_available) | ||
361 | { | ||
362 | mu_error (_("TLS is not configured, but requested in the " | ||
363 | "configuration")); | ||
364 | tls = tls_no; | ||
365 | } | ||
366 | |||
367 | pop3d_setio (ifd, ofd, tls == tls_connection); | ||
305 | 368 | ||
306 | state = tls ? AUTHORIZATION : initial_state; | 369 | if (tls == tls_required) |
370 | initial_state = INITIAL; | ||
371 | |||
372 | state = tls == tls_connection ? AUTHORIZATION : initial_state; | ||
307 | 373 | ||
374 | pop3d_session_init (&session); | ||
375 | session.tls = tls; | ||
376 | /* FIXME: state should also be in the session? */ | ||
377 | |||
308 | /* Prepare the shared secret for APOP. */ | 378 | /* Prepare the shared secret for APOP. */ |
309 | { | 379 | { |
310 | char *local_hostname; | 380 | char *local_hostname; |
... | @@ -353,7 +423,7 @@ pop3d_mainloop (int ifd, int ofd, int tls) | ... | @@ -353,7 +423,7 @@ pop3d_mainloop (int ifd, int ofd, int tls) |
353 | manlock_touchlock (mbox); | 423 | manlock_touchlock (mbox); |
354 | 424 | ||
355 | if ((handler = pop3d_find_command (cmd)) != NULL) | 425 | if ((handler = pop3d_find_command (cmd)) != NULL) |
356 | status = handler (arg); | 426 | status = handler (arg, &session); |
357 | else | 427 | else |
358 | status = ERR_BAD_CMD; | 428 | status = ERR_BAD_CMD; |
359 | 429 | ||
... | @@ -361,6 +431,8 @@ pop3d_mainloop (int ifd, int ofd, int tls) | ... | @@ -361,6 +431,8 @@ pop3d_mainloop (int ifd, int ofd, int tls) |
361 | pop3d_outf ("-ERR %s\n", pop3d_error_string (status)); | 431 | pop3d_outf ("-ERR %s\n", pop3d_error_string (status)); |
362 | } | 432 | } |
363 | 433 | ||
434 | pop3d_session_free (&session); | ||
435 | |||
364 | pop3d_bye (); | 436 | pop3d_bye (); |
365 | 437 | ||
366 | return status; | 438 | return status; |
... | @@ -445,8 +517,9 @@ pop3d_connection (int fd, struct sockaddr *sa, int salen, | ... | @@ -445,8 +517,9 @@ pop3d_connection (int fd, struct sockaddr *sa, int salen, |
445 | rc = set_strerr_flt (); | 517 | rc = set_strerr_flt (); |
446 | else | 518 | else |
447 | rc = 1; | 519 | rc = 1; |
448 | 520 | ||
449 | pop3d_mainloop (fd, fd, cfg->tls); | 521 | pop3d_mainloop (fd, fd, |
522 | cfg->tls_mode == tls_unspecified ? tls_mode : cfg->tls_mode); | ||
450 | 523 | ||
451 | if (rc == 0) | 524 | if (rc == 0) |
452 | clr_strerr_flt (); | 525 | clr_strerr_flt (); |
... | @@ -517,9 +590,6 @@ main (int argc, char **argv) | ... | @@ -517,9 +590,6 @@ main (int argc, char **argv) |
517 | argc, argv, 0, NULL, server)) | 590 | argc, argv, 0, NULL, server)) |
518 | exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */ | 591 | exit (EX_CONFIG); /* FIXME: No way to discern from EX_USAGE? */ |
519 | 592 | ||
520 | if (tls_required) | ||
521 | initial_state = INITIAL; | ||
522 | |||
523 | if (expire == 0) | 593 | if (expire == 0) |
524 | expire_on_exit = 1; | 594 | expire_on_exit = 1; |
525 | 595 | ||
... | @@ -589,7 +659,7 @@ main (int argc, char **argv) | ... | @@ -589,7 +659,7 @@ main (int argc, char **argv) |
589 | { | 659 | { |
590 | /* Make sure we are in the root directory. */ | 660 | /* Make sure we are in the root directory. */ |
591 | chdir ("/"); | 661 | chdir ("/"); |
592 | status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, 0); | 662 | status = pop3d_mainloop (MU_STDIN_FD, MU_STDOUT_FD, tls_no); |
593 | } | 663 | } |
594 | 664 | ||
595 | if (status) | 665 | if (status) | ... | ... |
... | @@ -42,17 +42,19 @@ | ... | @@ -42,17 +42,19 @@ |
42 | # undef ENABLE_LOGIN_DELAY | 42 | # undef ENABLE_LOGIN_DELAY |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | struct pop3d_session; | ||
46 | |||
45 | #ifdef ENABLE_LOGIN_DELAY | 47 | #ifdef ENABLE_LOGIN_DELAY |
46 | # define LOGIN_STAT_FILE "/var/run/pop3-login" | 48 | # define LOGIN_STAT_FILE "/var/run/pop3-login" |
47 | extern time_t login_delay; | 49 | extern time_t login_delay; |
48 | extern char *login_stat_file; | 50 | extern char *login_stat_file; |
49 | extern int check_login_delay (char *username); | 51 | extern int check_login_delay (char *username); |
50 | extern void update_login_delay (char *username); | 52 | extern void update_login_delay (char *username); |
51 | extern void login_delay_capa (void); | 53 | extern void login_delay_capa (const char *, struct pop3d_session *); |
52 | #else | 54 | #else |
53 | # define check_login_delay(u) 0 | 55 | # define check_login_delay(u) 0 |
54 | # define update_login_delay(u) | 56 | # define update_login_delay(u) |
55 | # define login_delay_capa() | 57 | # define login_delay_capa NULL |
56 | #endif | 58 | #endif |
57 | 59 | ||
58 | /* Minimum advertise retention time for messages. */ | 60 | /* Minimum advertise retention time for messages. */ |
... | @@ -166,8 +168,44 @@ extern int expire_on_exit; | ... | @@ -166,8 +168,44 @@ extern int expire_on_exit; |
166 | #define ERR_LOGIN_DELAY 22 | 168 | #define ERR_LOGIN_DELAY 22 |
167 | #define ERR_TERMINATE 23 | 169 | #define ERR_TERMINATE 23 |
168 | 170 | ||
171 | enum tls_mode | ||
172 | { | ||
173 | tls_unspecified, | ||
174 | tls_no, | ||
175 | tls_ondemand, | ||
176 | tls_required, | ||
177 | tls_connection | ||
178 | }; | ||
179 | |||
180 | enum pop3d_capa_type | ||
181 | { | ||
182 | capa_string, | ||
183 | capa_func | ||
184 | }; | ||
185 | |||
186 | struct pop3d_capa | ||
187 | { | ||
188 | enum pop3d_capa_type type; | ||
189 | const char *name; | ||
190 | union | ||
191 | { | ||
192 | char *string; | ||
193 | void (*func) (const char *, struct pop3d_session *); | ||
194 | } value; | ||
195 | }; | ||
196 | |||
197 | struct pop3d_session | ||
198 | { | ||
199 | mu_list_t capa; | ||
200 | enum tls_mode tls; | ||
201 | }; | ||
202 | |||
203 | void pop3d_session_init (struct pop3d_session *session); | ||
204 | void pop3d_session_free (struct pop3d_session *session); | ||
205 | |||
206 | |||
169 | typedef struct mu_pop_server *mu_pop_server_t; | 207 | typedef struct mu_pop_server *mu_pop_server_t; |
170 | typedef int (*pop3d_command_handler_t) (char *); | 208 | typedef int (*pop3d_command_handler_t) (char *, struct pop3d_session *sess); |
171 | 209 | ||
172 | struct pop3d_command | 210 | struct pop3d_command |
173 | { | 211 | { |
... | @@ -214,19 +252,19 @@ extern int apop_database_owner_set; | ... | @@ -214,19 +252,19 @@ extern int apop_database_owner_set; |
214 | 252 | ||
215 | extern pop3d_command_handler_t pop3d_find_command (const char *name); | 253 | extern pop3d_command_handler_t pop3d_find_command (const char *name); |
216 | 254 | ||
217 | extern int pop3d_stat (char *); | 255 | extern int pop3d_stat (char *, struct pop3d_session *); |
218 | extern int pop3d_top (char *); | 256 | extern int pop3d_top (char *, struct pop3d_session *); |
219 | extern int pop3d_uidl (char *); | 257 | extern int pop3d_uidl (char *, struct pop3d_session *); |
220 | extern int pop3d_user (char *); | 258 | extern int pop3d_user (char *, struct pop3d_session *); |
221 | extern int pop3d_apop (char *); | 259 | extern int pop3d_apop (char *, struct pop3d_session *); |
222 | extern int pop3d_auth (char *); | 260 | extern int pop3d_auth (char *, struct pop3d_session *); |
223 | extern int pop3d_capa (char *); | 261 | extern int pop3d_capa (char *, struct pop3d_session *); |
224 | extern int pop3d_dele (char *); | 262 | extern int pop3d_dele (char *, struct pop3d_session *); |
225 | extern int pop3d_list (char *); | 263 | extern int pop3d_list (char *, struct pop3d_session *); |
226 | extern int pop3d_noop (char *); | 264 | extern int pop3d_noop (char *, struct pop3d_session *); |
227 | extern int pop3d_quit (char *); | 265 | extern int pop3d_quit (char *, struct pop3d_session *); |
228 | extern int pop3d_retr (char *); | 266 | extern int pop3d_retr (char *, struct pop3d_session *); |
229 | extern int pop3d_rset (char *); | 267 | extern int pop3d_rset (char *, struct pop3d_session *); |
230 | 268 | ||
231 | void pop3d_send_payload (mu_stream_t stream, mu_stream_t linestr, | 269 | void pop3d_send_payload (mu_stream_t stream, mu_stream_t linestr, |
232 | size_t maxlines); | 270 | size_t maxlines); |
... | @@ -242,7 +280,7 @@ extern RETSIGTYPE pop3d_master_signal (int); | ... | @@ -242,7 +280,7 @@ extern RETSIGTYPE pop3d_master_signal (int); |
242 | extern RETSIGTYPE pop3d_child_signal (int); | 280 | extern RETSIGTYPE pop3d_child_signal (int); |
243 | 281 | ||
244 | #ifdef WITH_TLS | 282 | #ifdef WITH_TLS |
245 | extern int pop3d_stls (char *); | 283 | extern int pop3d_stls (char *, struct pop3d_session *); |
246 | extern void enable_stls (void); | 284 | extern void enable_stls (void); |
247 | #endif /* WITH_TLS */ | 285 | #endif /* WITH_TLS */ |
248 | extern void pop3d_outf (const char *fmt, ...) MU_PRINTFLIKE(1,2); | 286 | extern void pop3d_outf (const char *fmt, ...) MU_PRINTFLIKE(1,2); | ... | ... |
... | @@ -26,7 +26,7 @@ | ... | @@ -26,7 +26,7 @@ |
26 | static void pop3d_fix_mark (); | 26 | static void pop3d_fix_mark (); |
27 | 27 | ||
28 | int | 28 | int |
29 | pop3d_quit (char *arg) | 29 | pop3d_quit (char *arg, struct pop3d_session *sess) |
30 | { | 30 | { |
31 | int err = OK; | 31 | int err = OK; |
32 | if (strlen (arg) != 0) | 32 | if (strlen (arg) != 0) | ... | ... |
... | @@ -64,7 +64,7 @@ pop3d_send_payload (mu_stream_t stream, mu_stream_t linestr, size_t maxlines) | ... | @@ -64,7 +64,7 @@ pop3d_send_payload (mu_stream_t stream, mu_stream_t linestr, size_t maxlines) |
64 | /* Prints out the specified message */ | 64 | /* Prints out the specified message */ |
65 | 65 | ||
66 | int | 66 | int |
67 | pop3d_retr (char *arg) | 67 | pop3d_retr (char *arg, struct pop3d_session *sess) |
68 | { | 68 | { |
69 | size_t mesgno; | 69 | size_t mesgno; |
70 | mu_message_t msg = NULL; | 70 | mu_message_t msg = NULL; | ... | ... |
... | @@ -20,7 +20,7 @@ | ... | @@ -20,7 +20,7 @@ |
20 | /* Resets the connection so that no messages are marked as deleted */ | 20 | /* Resets the connection so that no messages are marked as deleted */ |
21 | 21 | ||
22 | int | 22 | int |
23 | pop3d_rset (char *arg) | 23 | pop3d_rset (char *arg, struct pop3d_session *sess) |
24 | { | 24 | { |
25 | size_t i; | 25 | size_t i; |
26 | size_t total = 0; | 26 | size_t total = 0; | ... | ... |
... | @@ -20,7 +20,7 @@ | ... | @@ -20,7 +20,7 @@ |
20 | /* Prints the number of messages and the total size of all messages */ | 20 | /* Prints the number of messages and the total size of all messages */ |
21 | 21 | ||
22 | int | 22 | int |
23 | pop3d_stat (char *arg) | 23 | pop3d_stat (char *arg, struct pop3d_session *sess) |
24 | { | 24 | { |
25 | size_t mesgno; | 25 | size_t mesgno; |
26 | size_t size = 0; | 26 | size_t size = 0; | ... | ... |
... | @@ -21,7 +21,7 @@ | ... | @@ -21,7 +21,7 @@ |
21 | #ifdef WITH_TLS | 21 | #ifdef WITH_TLS |
22 | 22 | ||
23 | int | 23 | int |
24 | pop3d_stls (char *arg) | 24 | pop3d_stls (char *arg, struct pop3d_session *session) |
25 | { | 25 | { |
26 | if (strlen (arg) != 0) | 26 | if (strlen (arg) != 0) |
27 | return ERR_BAD_ARGS; | 27 | return ERR_BAD_ARGS; |
... | @@ -29,6 +29,15 @@ pop3d_stls (char *arg) | ... | @@ -29,6 +29,15 @@ pop3d_stls (char *arg) |
29 | if (state != initial_state) | 29 | if (state != initial_state) |
30 | return ERR_WRONG_STATE; | 30 | return ERR_WRONG_STATE; |
31 | 31 | ||
32 | switch (session->tls) | ||
33 | { | ||
34 | case tls_ondemand: | ||
35 | case tls_required: | ||
36 | break; | ||
37 | default: | ||
38 | return ERR_WRONG_STATE; | ||
39 | } | ||
40 | |||
32 | if (tls_done) | 41 | if (tls_done) |
33 | return ERR_TLS_ACTIVE; | 42 | return ERR_TLS_ACTIVE; |
34 | 43 | ||
... | @@ -45,7 +54,7 @@ pop3d_stls (char *arg) | ... | @@ -45,7 +54,7 @@ pop3d_stls (char *arg) |
45 | } | 54 | } |
46 | 55 | ||
47 | state = AUTHORIZATION; /* Confirm we're in this state. Necessary for | 56 | state = AUTHORIZATION; /* Confirm we're in this state. Necessary for |
48 | --tls-required to work */ | 57 | "tls required" to work */ |
49 | 58 | ||
50 | return OK; | 59 | return OK; |
51 | } | 60 | } | ... | ... |
... | @@ -20,7 +20,7 @@ | ... | @@ -20,7 +20,7 @@ |
20 | /* Prints the header of a message plus a specified number of lines. */ | 20 | /* Prints the header of a message plus a specified number of lines. */ |
21 | 21 | ||
22 | int | 22 | int |
23 | pop3d_top (char *arg) | 23 | pop3d_top (char *arg, struct pop3d_session *sess) |
24 | { | 24 | { |
25 | size_t mesgno; | 25 | size_t mesgno; |
26 | unsigned long lines; | 26 | unsigned long lines; | ... | ... |
... | @@ -72,7 +72,7 @@ pop3d_begin_session () | ... | @@ -72,7 +72,7 @@ pop3d_begin_session () |
72 | } | 72 | } |
73 | 73 | ||
74 | int | 74 | int |
75 | pop3d_user (char *arg) | 75 | pop3d_user (char *arg, struct pop3d_session *sess) |
76 | { | 76 | { |
77 | char *buf, *pass, *cmd; | 77 | char *buf, *pass, *cmd; |
78 | char buffer[512]; | 78 | char buffer[512]; |
... | @@ -129,7 +129,7 @@ pop3d_user (char *arg) | ... | @@ -129,7 +129,7 @@ pop3d_user (char *arg) |
129 | else if (mu_c_strcasecmp (cmd, "QUIT") == 0) | 129 | else if (mu_c_strcasecmp (cmd, "QUIT") == 0) |
130 | { | 130 | { |
131 | mu_diag_output (MU_DIAG_INFO, _("possible probe of account `%s'"), arg); | 131 | mu_diag_output (MU_DIAG_INFO, _("possible probe of account `%s'"), arg); |
132 | return pop3d_quit (pass); | 132 | return pop3d_quit (pass, sess); |
133 | } | 133 | } |
134 | else | 134 | else |
135 | { | 135 | { | ... | ... |
-
Please register or sign in to post a comment