Commit 66f4500a 66f4500a83dfa67f8e2bd4bdde2ddd9fadbcdfde by Sam Roberts

Implemented AUTH=ANON, the anonymous SASL mechanism.

1 parent 3839724b
...@@ -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;
......