Implemented AUTH=ANON, the anonymous SASL mechanism.
Showing
3 changed files
with
195 additions
and
34 deletions
... | @@ -153,8 +153,8 @@ folder_imap_destroy (folder_t folder) | ... | @@ -153,8 +153,8 @@ folder_imap_destroy (folder_t folder) |
153 | } | 153 | } |
154 | 154 | ||
155 | /* Simple User/pass authentication for imap. */ | 155 | /* Simple User/pass authentication for imap. */ |
156 | static int | 156 | int |
157 | imap_user (authority_t auth) | 157 | authenticate_imap_login (authority_t auth) |
158 | { | 158 | { |
159 | folder_t folder = authority_get_owner (auth); | 159 | folder_t folder = authority_get_owner (auth); |
160 | f_imap_t f_imap = folder->data; | 160 | f_imap_t f_imap = folder->data; |
... | @@ -230,6 +230,131 @@ imap_user (authority_t auth) | ... | @@ -230,6 +230,131 @@ imap_user (authority_t auth) |
230 | return 0; | 230 | return 0; |
231 | } | 231 | } |
232 | 232 | ||
233 | /* | ||
234 | The anonymous SASL mechanism is defined in rfc2245.txt as a single | ||
235 | message from client to server: | ||
236 | |||
237 | message = [email / token] | ||
238 | |||
239 | So the message is optional. | ||
240 | |||
241 | The command is: | ||
242 | |||
243 | C: <tag> authenticate anonymous | ||
244 | |||
245 | The server responds with a request for continuation data (the "message" | ||
246 | in the SASL syntax). We respond with no data, which is legal. | ||
247 | |||
248 | S: + | ||
249 | C: | ||
250 | |||
251 | The server should then respond with OK on success, or else a failure | ||
252 | code (NO or BAD). | ||
253 | |||
254 | If OK, then we are authenticated! | ||
255 | |||
256 | So, states are: | ||
257 | |||
258 | AUTH_ANON_REQ | ||
259 | |||
260 | > g%u AUTHENTICATE ANONYMOUS | ||
261 | |||
262 | AUTH_ANON_WAIT_CONT | ||
263 | |||
264 | < + | ||
265 | |||
266 | AUTH_ANON_MSG | ||
267 | |||
268 | > | ||
269 | |||
270 | AUTH_ANON_WAIT_RESP | ||
271 | |||
272 | < NO/BAD/OK | ||
273 | |||
274 | |||
275 | |||
276 | */ | ||
277 | |||
278 | int | ||
279 | authenticate_imap_sasl_anon (authority_t auth) | ||
280 | { | ||
281 | folder_t folder = authority_get_owner (auth); | ||
282 | f_imap_t f_imap = folder->data; | ||
283 | int status = 0; | ||
284 | |||
285 | assert (f_imap->state == IMAP_AUTH); | ||
286 | |||
287 | switch (f_imap->auth_state) | ||
288 | { | ||
289 | case IMAP_AUTH_ANON_REQ_WRITE: | ||
290 | { | ||
291 | FOLDER_DEBUG1 (folder, MU_DEBUG_PROT, "g%u AUTHENTICATE ANONYMOUS\n", | ||
292 | f_imap->seq); | ||
293 | |||
294 | status = imap_writeline (f_imap, "g%u AUTHENTICATE ANONYMOUS\r\n", | ||
295 | f_imap->seq); | ||
296 | |||
297 | f_imap->seq++; | ||
298 | |||
299 | CHECK_ERROR_CLOSE (folder, f_imap, status); | ||
300 | |||
301 | f_imap->state = IMAP_AUTH_ANON_REQ_SEND; | ||
302 | } | ||
303 | |||
304 | case IMAP_AUTH_ANON_REQ_SEND: | ||
305 | status = imap_send (f_imap); | ||
306 | |||
307 | CHECK_EAGAIN (f_imap, status); | ||
308 | |||
309 | f_imap->state = IMAP_AUTH_ANON_WAIT_CONT; | ||
310 | |||
311 | case IMAP_AUTH_ANON_WAIT_CONT: | ||
312 | status = imap_parse (f_imap); | ||
313 | |||
314 | CHECK_EAGAIN (f_imap, status); | ||
315 | |||
316 | FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); | ||
317 | |||
318 | if (strncmp ("+", f_imap->buffer, 2) == 0) | ||
319 | { | ||
320 | f_imap->state = IMAP_AUTH_ANON_MSG; | ||
321 | } | ||
322 | else | ||
323 | { | ||
324 | /* something is wrong! */ | ||
325 | } | ||
326 | f_imap->state = IMAP_AUTH_ANON_MSG; | ||
327 | |||
328 | case IMAP_AUTH_ANON_MSG: | ||
329 | FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, "\n"); | ||
330 | |||
331 | status = imap_writeline (f_imap, "\r\n"); | ||
332 | |||
333 | CHECK_ERROR_CLOSE (folder, f_imap, status); | ||
334 | |||
335 | f_imap->state = IMAP_AUTH_ANON_MSG_SEND; | ||
336 | |||
337 | case IMAP_AUTH_ANON_MSG_SEND: | ||
338 | status = imap_send (f_imap); | ||
339 | |||
340 | CHECK_EAGAIN (f_imap, status); | ||
341 | |||
342 | f_imap->state = IMAP_AUTH_ANON_WAIT_RESP; | ||
343 | |||
344 | case IMAP_AUTH_ANON_WAIT_RESP: | ||
345 | status = imap_parse (f_imap); | ||
346 | |||
347 | CHECK_EAGAIN (f_imap, status); | ||
348 | |||
349 | FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); | ||
350 | |||
351 | default: | ||
352 | break; /* We're outta here. */ | ||
353 | } | ||
354 | CLEAR_STATE (f_imap); | ||
355 | return 0; | ||
356 | } | ||
357 | |||
233 | /* Create/Open the stream for IMAP. */ | 358 | /* Create/Open the stream for IMAP. */ |
234 | static int | 359 | static int |
235 | folder_imap_open (folder_t folder, int flags) | 360 | folder_imap_open (folder_t folder, int flags) |
... | @@ -239,7 +364,6 @@ folder_imap_open (folder_t folder, int flags) | ... | @@ -239,7 +364,6 @@ folder_imap_open (folder_t folder, int flags) |
239 | long port = 143; /* default imap port. */ | 364 | long port = 143; /* default imap port. */ |
240 | int status = 0; | 365 | int status = 0; |
241 | size_t len = 0; | 366 | size_t len = 0; |
242 | int preauth = 0; /* Do we have "preauth"orisation ? */ | ||
243 | 367 | ||
244 | /* If we are already open for business, noop. */ | 368 | /* If we are already open for business, noop. */ |
245 | monitor_wrlock (folder->monitor); | 369 | monitor_wrlock (folder->monitor); |
... | @@ -252,7 +376,7 @@ folder_imap_open (folder_t folder, int flags) | ... | @@ -252,7 +376,7 @@ folder_imap_open (folder_t folder, int flags) |
252 | } | 376 | } |
253 | monitor_unlock (folder->monitor); | 377 | monitor_unlock (folder->monitor); |
254 | 378 | ||
255 | /* Fetch the pop server name and the port in the url_t. */ | 379 | /* Fetch the server name and the port in the url_t. */ |
256 | status = url_get_host (folder->url, NULL, 0, &len); | 380 | status = url_get_host (folder->url, NULL, 0, &len); |
257 | if (status != 0) | 381 | if (status != 0) |
258 | return status; | 382 | return status; |
... | @@ -320,38 +444,22 @@ folder_imap_open (folder_t folder, int flags) | ... | @@ -320,38 +444,22 @@ folder_imap_open (folder_t folder, int flags) |
320 | /* Are they open for business ? The server send an untag response | 444 | /* Are they open for business ? The server send an untag response |
321 | for greeting. Thenically it can be OK/PREAUTH/BYE. The BYE is | 445 | for greeting. Thenically it can be OK/PREAUTH/BYE. The BYE is |
322 | the one that we do not want, server being unfriendly. */ | 446 | the one that we do not want, server being unfriendly. */ |
323 | preauth = (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0); | 447 | if (strncasecmp (f_imap->buffer, "* PREAUTH", 9) == 0) |
324 | if (strncasecmp (f_imap->buffer, "* OK", 4) != 0 && ! preauth) | 448 | { |
325 | { | 449 | f_imap->state = IMAP_AUTH_DONE; |
326 | CHECK_ERROR_CLOSE (folder, f_imap, EACCES); | 450 | } |
327 | } | 451 | else |
328 | 452 | { | |
329 | if (folder->authority == NULL && !preauth) | 453 | if (strncasecmp (f_imap->buffer, "* OK", 4) != 0) |
330 | { | 454 | CHECK_ERROR_CLOSE (folder, f_imap, EACCES); |
331 | char auth[64] = ""; | 455 | f_imap->state = IMAP_AUTH; |
332 | size_t n = 0; | 456 | } |
333 | url_get_auth (folder->url, auth, 64, &n); | ||
334 | if (n == 0 || strcasecmp (auth, "*") == 0) | ||
335 | { | ||
336 | authority_create (&(folder->authority), folder->ticket, | ||
337 | folder); | ||
338 | authority_set_authenticate (folder->authority, imap_user, | ||
339 | folder); | ||
340 | } | ||
341 | else | ||
342 | { | ||
343 | /* No other type of Authentication is supported yet. */ | ||
344 | /* What can we do ? flag an error ? */ | ||
345 | CHECK_ERROR_CLOSE (folder, f_imap, ENOSYS); | ||
346 | } | ||
347 | } | ||
348 | f_imap->state = IMAP_AUTH; | ||
349 | } | 457 | } |
350 | 458 | ||
351 | case IMAP_AUTH: | 459 | case IMAP_AUTH: |
352 | case IMAP_LOGIN: | 460 | case IMAP_LOGIN: |
353 | case IMAP_LOGIN_ACK: | 461 | case IMAP_LOGIN_ACK: |
354 | if (!preauth) | 462 | assert (folder->authority); |
355 | { | 463 | { |
356 | status = authority_authenticate (folder->authority); | 464 | status = authority_authenticate (folder->authority); |
357 | CHECK_EAGAIN (f_imap, status); | 465 | CHECK_EAGAIN (f_imap, status); | ... | ... |
... | @@ -25,6 +25,7 @@ | ... | @@ -25,6 +25,7 @@ |
25 | #include <folder0.h> | 25 | #include <folder0.h> |
26 | #include <mailbox0.h> | 26 | #include <mailbox0.h> |
27 | #include <registrar0.h> | 27 | #include <registrar0.h> |
28 | #include <auth0.h> | ||
28 | 29 | ||
29 | #ifdef __cplusplus | 30 | #ifdef __cplusplus |
30 | extern "C" { | 31 | extern "C" { |
... | @@ -118,6 +119,18 @@ enum imap_state | ... | @@ -118,6 +119,18 @@ enum imap_state |
118 | IMAP_UNSUBSCRIBE, IMAP_UNSUBSCRIBE_ACK | 119 | IMAP_UNSUBSCRIBE, IMAP_UNSUBSCRIBE_ACK |
119 | }; | 120 | }; |
120 | 121 | ||
122 | enum imap_auth_state | ||
123 | { | ||
124 | /* ANONYMOUS */ | ||
125 | IMAP_AUTH_ANON_REQ_WRITE, | ||
126 | IMAP_AUTH_ANON_REQ_SEND, | ||
127 | IMAP_AUTH_ANON_WAIT_CONT, | ||
128 | IMAP_AUTH_ANON_MSG, | ||
129 | IMAP_AUTH_ANON_MSG_SEND, | ||
130 | IMAP_AUTH_ANON_WAIT_RESP, | ||
131 | |||
132 | }; | ||
133 | |||
121 | struct literal_string | 134 | struct literal_string |
122 | { | 135 | { |
123 | char *buffer; | 136 | char *buffer; |
... | @@ -169,6 +182,9 @@ struct _f_imap | ... | @@ -169,6 +182,9 @@ struct _f_imap |
169 | /* Login */ | 182 | /* Login */ |
170 | char *user; | 183 | char *user; |
171 | char *passwd; | 184 | char *passwd; |
185 | |||
186 | /* AUTHENTICATE states */ | ||
187 | enum imap_auth_state auth_state; | ||
172 | }; | 188 | }; |
173 | 189 | ||
174 | struct _m_imap | 190 | struct _m_imap |
... | @@ -215,7 +231,10 @@ int imap_write __P ((f_imap_t)); | ... | @@ -215,7 +231,10 @@ int imap_write __P ((f_imap_t)); |
215 | int imap_send __P ((f_imap_t)); | 231 | int imap_send __P ((f_imap_t)); |
216 | int imap_parse __P ((f_imap_t)); | 232 | int imap_parse __P ((f_imap_t)); |
217 | int imap_readline __P ((f_imap_t)); | 233 | int imap_readline __P ((f_imap_t)); |
218 | char *section_name __P ((msg_imap_t)); | 234 | char *section_name __P ((msg_imap_t)); |
235 | |||
236 | int authenticate_imap_login __P ((authority_t auth)); | ||
237 | int authenticate_imap_sasl_anon __P ((authority_t auth)); | ||
219 | 238 | ||
220 | #ifdef __cplusplus | 239 | #ifdef __cplusplus |
221 | } | 240 | } | ... | ... |
... | @@ -34,6 +34,8 @@ | ... | @@ -34,6 +34,8 @@ |
34 | #include <mailbox0.h> | 34 | #include <mailbox0.h> |
35 | #include <registrar0.h> | 35 | #include <registrar0.h> |
36 | #include <imap0.h> | 36 | #include <imap0.h> |
37 | #include <url0.h> | ||
38 | |||
37 | #undef min | 39 | #undef min |
38 | #define min(a,b) ((a) < (b) ? (a) : (b)) | 40 | #define min(a,b) ((a) < (b) ? (a) : (b)) |
39 | 41 | ||
... | @@ -107,7 +109,13 @@ _mailbox_imap_init (mailbox_t mailbox) | ... | @@ -107,7 +109,13 @@ _mailbox_imap_init (mailbox_t mailbox) |
107 | { | 109 | { |
108 | m_imap_t m_imap; | 110 | m_imap_t m_imap; |
109 | size_t name_len = 0; | 111 | size_t name_len = 0; |
110 | m_imap = mailbox->data = calloc (1, sizeof *m_imap); | 112 | folder_t folder = NULL; |
113 | |||
114 | assert(mailbox); | ||
115 | |||
116 | folder = mailbox->folder; | ||
117 | |||
118 | m_imap = mailbox->data = calloc (1, sizeof (*m_imap)); | ||
111 | if (m_imap == NULL) | 119 | if (m_imap == NULL) |
112 | return ENOMEM; | 120 | return ENOMEM; |
113 | 121 | ||
... | @@ -156,6 +164,33 @@ _mailbox_imap_init (mailbox_t mailbox) | ... | @@ -156,6 +164,33 @@ _mailbox_imap_init (mailbox_t mailbox) |
156 | mailbox_get_property (mailbox, &property); | 164 | mailbox_get_property (mailbox, &property); |
157 | property_set_value (property, "TYPE", "IMAP4", 1); | 165 | property_set_value (property, "TYPE", "IMAP4", 1); |
158 | } | 166 | } |
167 | |||
168 | assert(folder); | ||
169 | assert(folder->url); | ||
170 | |||
171 | if (folder->authority == NULL) | ||
172 | { | ||
173 | const char *auth = folder->url->auth; | ||
174 | |||
175 | if (auth == NULL || strcasecmp (auth, "*") == 0) | ||
176 | { | ||
177 | authority_create (&(folder->authority), folder->ticket, folder); | ||
178 | authority_set_authenticate (folder->authority, | ||
179 | authenticate_imap_login, folder); | ||
180 | } | ||
181 | else if (strcasecmp (auth, "anon") == 0) | ||
182 | { | ||
183 | authority_create (&(folder->authority), folder->ticket, folder); | ||
184 | authority_set_authenticate (folder->authority, | ||
185 | authenticate_imap_sasl_anon, folder); | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | /* Not a supported authentication mechanism. */ | ||
190 | return ENOTSUP; | ||
191 | } | ||
192 | } | ||
193 | |||
159 | return 0; | 194 | return 0; |
160 | } | 195 | } |
161 | 196 | ||
... | @@ -759,7 +794,6 @@ imap_expunge (mailbox_t mailbox) | ... | @@ -759,7 +794,6 @@ imap_expunge (mailbox_t mailbox) |
759 | static int | 794 | static int |
760 | imap_append_message (mailbox_t mailbox, message_t msg) | 795 | imap_append_message (mailbox_t mailbox, message_t msg) |
761 | { | 796 | { |
762 | size_t total; | ||
763 | int status = 0; | 797 | int status = 0; |
764 | m_imap_t m_imap = mailbox->data; | 798 | m_imap_t m_imap = mailbox->data; |
765 | f_imap_t f_imap = m_imap->f_imap; | 799 | f_imap_t f_imap = m_imap->f_imap; | ... | ... |
-
Please register or sign in to post a comment