]> granicus.if.org Git - mutt/blob - smtp.c
Convert pgp_app_handler to use buffer pool.
[mutt] / smtp.c
1 /* mutt - text oriented MIME mail user agent
2  * Copyright (C) 2002 Michael R. Elkins <me@mutt.org>
3  * Copyright (C) 2005-2009 Brendan Cully <brendan@kublai.com>
4  *
5  *     This program is free software; you can redistribute it and/or modify
6  *     it under the terms of the GNU General Public License as published by
7  *     the Free Software Foundation; either version 2 of the License, or
8  *     (at your option) any later version.
9  *
10  *     This program is distributed in the hope that it will be useful,
11  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *     GNU General Public License for more details.
14  *
15  *     You should have received a copy of the GNU General Public License
16  *     along with this program; if not, write to the Free Software
17  *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
18  */
19
20 /* This file contains code for direct SMTP delivery of email messages. */
21
22 #if HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "mutt.h"
27 #include "mutt_curses.h"
28 #include "mutt_socket.h"
29 #ifdef USE_SSL
30 # include "mutt_ssl.h"
31 #endif
32 #ifdef USE_SASL
33 #include "mutt_sasl.h"
34
35 #include <sasl/sasl.h>
36 #include <sasl/saslutil.h>
37 #endif
38
39 #include <netdb.h>
40 #include <netinet/in.h>
41 #include <stdio.h>
42 #include <sys/stat.h>
43
44 #define smtp_success(x) ((x)/100 == 2)
45 #define smtp_ready 334
46 #define smtp_continue 354
47
48 #define smtp_err_read -2
49 #define smtp_err_write -3
50 #define smtp_err_code -4
51
52 #define SMTP_PORT 25
53 #define SMTPS_PORT 465
54
55 #define SMTP_AUTH_SUCCESS 0
56 #define SMTP_AUTH_UNAVAIL 1
57 #define SMTP_AUTH_FAIL    -1
58
59 enum {
60   STARTTLS,
61   AUTH,
62   DSN,
63   EIGHTBITMIME,
64   SMTPUTF8,
65
66   CAPMAX
67 };
68
69 static int smtp_auth (CONNECTION* conn);
70 static int smtp_auth_oauth (CONNECTION* conn);
71 #ifdef USE_SASL
72 static int smtp_auth_sasl (CONNECTION* conn, const char* mechanisms);
73 #endif
74
75 static int smtp_fill_account (ACCOUNT* account);
76 static int smtp_open (CONNECTION* conn);
77
78 static int Esmtp = 0;
79 static char* AuthMechs = NULL;
80 static unsigned char Capabilities[(CAPMAX + 7)/ 8];
81
82 static int smtp_code (char *buf, size_t len, int *n)
83 {
84   char code[4];
85
86   if (len < 4)
87     return -1;
88   code[0] = buf[0];
89   code[1] = buf[1];
90   code[2] = buf[2];
91   code[3] = 0;
92   if (mutt_atoi (code, n) < 0)
93     return -1;
94   return 0;
95 }
96
97 /* Reads a command response from the SMTP server.
98  * Returns:
99  * 0    on success (2xx code) or continue (354 code)
100  * -1   write error, or any other response code
101  */
102 static int
103 smtp_get_resp (CONNECTION * conn)
104 {
105   int n;
106   char buf[1024];
107
108   do
109   {
110     n = mutt_socket_readln (buf, sizeof (buf), conn);
111     if (n < 4)
112     {
113       /* read error, or no response code */
114       return smtp_err_read;
115     }
116
117     if (!ascii_strncasecmp ("8BITMIME", buf + 4, 8))
118       mutt_bit_set (Capabilities, EIGHTBITMIME);
119     else if (!ascii_strncasecmp ("AUTH ", buf + 4, 5))
120     {
121       mutt_bit_set (Capabilities, AUTH);
122       FREE (&AuthMechs);
123       AuthMechs = safe_strdup (buf + 9);
124     }
125     else if (!ascii_strncasecmp ("DSN", buf + 4, 3))
126       mutt_bit_set (Capabilities, DSN);
127     else if (!ascii_strncasecmp ("STARTTLS", buf + 4, 8))
128       mutt_bit_set (Capabilities, STARTTLS);
129     else if (!ascii_strncasecmp ("SMTPUTF8", buf + 4, 8))
130       mutt_bit_set (Capabilities, SMTPUTF8);
131
132     if (smtp_code (buf, n, &n) < 0)
133       return smtp_err_code;
134
135   } while (buf[3] == '-');
136
137   if (smtp_success (n) || n == smtp_continue)
138     return 0;
139
140   mutt_error (_("SMTP session failed: %s"), buf);
141   return -1;
142 }
143
144 static int
145 smtp_rcpt_to (CONNECTION * conn, const ADDRESS * a)
146 {
147   char buf[1024];
148   int r;
149
150   while (a)
151   {
152     /* weed out group mailboxes, since those are for display only */
153     if (!a->mailbox || a->group)
154     {
155       a = a->next;
156       continue;
157     }
158     if (mutt_bit_isset (Capabilities, DSN) && DsnNotify)
159       snprintf (buf, sizeof (buf), "RCPT TO:<%s> NOTIFY=%s\r\n",
160                 a->mailbox, DsnNotify);
161     else
162       snprintf (buf, sizeof (buf), "RCPT TO:<%s>\r\n", a->mailbox);
163     if (mutt_socket_write (conn, buf) == -1)
164       return smtp_err_write;
165     if ((r = smtp_get_resp (conn)))
166       return r;
167     a = a->next;
168   }
169
170   return 0;
171 }
172
173 static int
174 smtp_data (CONNECTION * conn, const char *msgfile)
175 {
176   char buf[1024];
177   FILE *fp = 0;
178   progress_t progress;
179   struct stat st;
180   int r, term = 0;
181   size_t buflen = 0;
182
183   fp = fopen (msgfile, "r");
184   if (!fp)
185   {
186     mutt_error (_("SMTP session failed: unable to open %s"), msgfile);
187     return -1;
188   }
189   stat (msgfile, &st);
190   unlink (msgfile);
191   mutt_progress_init (&progress, _("Sending message..."), MUTT_PROGRESS_SIZE,
192                       NetInc, st.st_size);
193
194   snprintf (buf, sizeof (buf), "DATA\r\n");
195   if (mutt_socket_write (conn, buf) == -1)
196   {
197     safe_fclose (&fp);
198     return smtp_err_write;
199   }
200   if ((r = smtp_get_resp (conn)))
201   {
202     safe_fclose (&fp);
203     return r;
204   }
205
206   while (fgets (buf, sizeof (buf) - 1, fp))
207   {
208     buflen = mutt_strlen (buf);
209     term = buflen && buf[buflen-1] == '\n';
210     if (term && (buflen == 1 || buf[buflen - 2] != '\r'))
211       snprintf (buf + buflen - 1, sizeof (buf) - buflen + 1, "\r\n");
212     if (buf[0] == '.')
213     {
214       if (mutt_socket_write_d (conn, ".", -1, MUTT_SOCK_LOG_FULL) == -1)
215       {
216         safe_fclose (&fp);
217         return smtp_err_write;
218       }
219     }
220     if (mutt_socket_write_d (conn, buf, -1, MUTT_SOCK_LOG_FULL) == -1)
221     {
222       safe_fclose (&fp);
223       return smtp_err_write;
224     }
225     mutt_progress_update (&progress, ftell (fp), -1);
226   }
227   if (!term && buflen &&
228       mutt_socket_write_d (conn, "\r\n", -1, MUTT_SOCK_LOG_FULL) == -1)
229   {
230     safe_fclose (&fp);
231     return smtp_err_write;
232   }
233   safe_fclose (&fp);
234
235   /* terminate the message body */
236   if (mutt_socket_write (conn, ".\r\n") == -1)
237     return smtp_err_write;
238
239   if ((r = smtp_get_resp (conn)))
240     return r;
241
242   return 0;
243 }
244
245
246 /* Returns 1 if a contains at least one 8-bit character, 0 if none do.
247  */
248 static int address_uses_unicode(const char *a)
249 {
250   if (!a)
251     return 0;
252
253   while (*a)
254   {
255     if ((unsigned char) *a & (1<<7))
256       return 1;
257     a++;
258   }
259
260   return 0;
261 }
262
263
264 /* Returns 1 if any address in a contains at least one 8-bit
265  * character, 0 if none do.
266  */
267 static int addresses_use_unicode(const ADDRESS* a)
268 {
269   while (a)
270   {
271     if (a->mailbox && !a->group && address_uses_unicode(a->mailbox))
272       return 1;
273     a = a->next;
274   }
275   return 0;
276 }
277
278
279 int
280 mutt_smtp_send (const ADDRESS* from, const ADDRESS* to, const ADDRESS* cc,
281                 const ADDRESS* bcc, const char *msgfile, int eightbit)
282 {
283   CONNECTION *conn;
284   ACCOUNT account;
285   const char* envfrom;
286   char buf[1024];
287   int ret = -1;
288
289   /* it might be better to synthesize an envelope from from user and host
290    * but this condition is most likely arrived at accidentally */
291   if (EnvFrom)
292     envfrom = EnvFrom->mailbox;
293   else if (from)
294     envfrom = from->mailbox;
295   else
296   {
297     mutt_error (_("No from address given"));
298     return -1;
299   }
300
301   if (smtp_fill_account (&account) < 0)
302     return ret;
303
304   if (!(conn = mutt_conn_find (NULL, &account)))
305     return -1;
306
307   Esmtp = eightbit;
308
309   do
310   {
311     /* send our greeting */
312     if (( ret = smtp_open (conn)))
313       break;
314     FREE (&AuthMechs);
315
316     /* send the sender's address */
317     ret = snprintf (buf, sizeof (buf), "MAIL FROM:<%s>", envfrom);
318     if (eightbit && mutt_bit_isset (Capabilities, EIGHTBITMIME))
319     {
320       safe_strncat (buf, sizeof (buf), " BODY=8BITMIME", 15);
321       ret += 14;
322     }
323     if (DsnReturn && mutt_bit_isset (Capabilities, DSN))
324       ret += snprintf (buf + ret, sizeof (buf) - ret, " RET=%s", DsnReturn);
325     if (mutt_bit_isset (Capabilities, SMTPUTF8) &&
326         (address_uses_unicode(envfrom) ||
327          addresses_use_unicode(to) ||
328          addresses_use_unicode(cc) ||
329          addresses_use_unicode(bcc)))
330       ret += snprintf (buf + ret, sizeof (buf) - ret, " SMTPUTF8");
331     safe_strncat (buf, sizeof (buf), "\r\n", 3);
332     if (mutt_socket_write (conn, buf) == -1)
333     {
334       ret = smtp_err_write;
335       break;
336     }
337     if ((ret = smtp_get_resp (conn)))
338       break;
339
340     /* send the recipient list */
341     if ((ret = smtp_rcpt_to (conn, to)) || (ret = smtp_rcpt_to (conn, cc))
342         || (ret = smtp_rcpt_to (conn, bcc)))
343       break;
344
345     /* send the message data */
346     if ((ret = smtp_data (conn, msgfile)))
347       break;
348
349     mutt_socket_write (conn, "QUIT\r\n");
350
351     ret = 0;
352   }
353   while (0);
354
355   if (conn)
356     mutt_socket_close (conn);
357
358   if (ret == smtp_err_read)
359     mutt_error (_("SMTP session failed: read error"));
360   else if (ret == smtp_err_write)
361     mutt_error (_("SMTP session failed: write error"));
362   else if (ret == smtp_err_code)
363     mutt_error (_("Invalid server response"));
364
365   return ret;
366 }
367
368 static int smtp_fill_account (ACCOUNT* account)
369 {
370   static unsigned short SmtpPort = 0;
371
372   struct servent* service;
373   ciss_url_t url;
374   char* urlstr;
375
376   account->flags = 0;
377   account->port = 0;
378   account->type = MUTT_ACCT_TYPE_SMTP;
379
380   urlstr = safe_strdup (SmtpUrl);
381   url_parse_ciss (&url, urlstr);
382   if ((url.scheme != U_SMTP && url.scheme != U_SMTPS)
383       || mutt_account_fromurl (account, &url) < 0)
384   {
385     FREE (&urlstr);
386     mutt_error (_("Invalid SMTP URL: %s"), SmtpUrl);
387     mutt_sleep (1);
388     return -1;
389   }
390   FREE (&urlstr);
391
392   if (url.scheme == U_SMTPS)
393     account->flags |= MUTT_ACCT_SSL;
394
395   if (!account->port)
396   {
397     if (account->flags & MUTT_ACCT_SSL)
398       account->port = SMTPS_PORT;
399     else
400     {
401       if (!SmtpPort)
402       {
403         service = getservbyname ("smtp", "tcp");
404         if (service)
405           SmtpPort = ntohs (service->s_port);
406         else
407           SmtpPort = SMTP_PORT;
408         dprint (3, (debugfile, "Using default SMTP port %d\n", SmtpPort));
409       }
410       account->port = SmtpPort;
411     }
412   }
413
414   return 0;
415 }
416
417 static int smtp_helo (CONNECTION* conn)
418 {
419   char buf[LONG_STRING];
420   const char* fqdn;
421
422   memset (Capabilities, 0, sizeof (Capabilities));
423
424   if (!Esmtp)
425   {
426     /* if TLS or AUTH are requested, use EHLO */
427     if (conn->account.flags & MUTT_ACCT_USER)
428       Esmtp = 1;
429 #ifdef USE_SSL
430     if (option (OPTSSLFORCETLS) || quadoption (OPT_SSLSTARTTLS) != MUTT_NO)
431       Esmtp = 1;
432 #endif
433   }
434
435   if (!(fqdn = mutt_fqdn (0)))
436     fqdn = NONULL (Hostname);
437
438   snprintf (buf, sizeof (buf), "%s %s\r\n", Esmtp ? "EHLO" : "HELO", fqdn);
439   /* XXX there should probably be a wrapper in mutt_socket.c that
440    * repeatedly calls conn->write until all data is sent.  This
441    * currently doesn't check for a short write.
442    */
443   if (mutt_socket_write (conn, buf) == -1)
444     return smtp_err_write;
445   return smtp_get_resp (conn);
446 }
447
448 static int smtp_open (CONNECTION* conn)
449 {
450   int rc;
451
452   if (mutt_socket_open (conn))
453     return -1;
454
455   /* get greeting string */
456   if ((rc = smtp_get_resp (conn)))
457     return rc;
458
459   if ((rc = smtp_helo (conn)))
460     return rc;
461
462 #ifdef USE_SSL
463   if (conn->ssf)
464     rc = MUTT_NO;
465   else if (option (OPTSSLFORCETLS))
466     rc = MUTT_YES;
467   else if (mutt_bit_isset (Capabilities, STARTTLS) &&
468            (rc = query_quadoption (OPT_SSLSTARTTLS,
469                                    _("Secure connection with TLS?"))) == -1)
470     return rc;
471
472   if (rc == MUTT_YES)
473   {
474     if (mutt_socket_write (conn, "STARTTLS\r\n") < 0)
475       return smtp_err_write;
476     if ((rc = smtp_get_resp (conn)))
477       return rc;
478
479     if (mutt_ssl_starttls (conn))
480     {
481       mutt_error (_("Could not negotiate TLS connection"));
482       mutt_sleep (1);
483       return -1;
484     }
485
486     /* re-EHLO to get authentication mechanisms */
487     if ((rc = smtp_helo (conn)))
488       return rc;
489   }
490 #endif
491
492   if (conn->account.flags & MUTT_ACCT_USER)
493   {
494     if (!mutt_bit_isset (Capabilities, AUTH))
495     {
496       mutt_error (_("SMTP server does not support authentication"));
497       mutt_sleep (1);
498       return -1;
499     }
500
501     return smtp_auth (conn);
502   }
503
504   return 0;
505 }
506
507 static int smtp_auth (CONNECTION* conn)
508 {
509   int r = SMTP_AUTH_UNAVAIL;
510
511   if (SmtpAuthenticators)
512   {
513     char* methods = safe_strdup (SmtpAuthenticators);
514     char* method;
515     char* delim;
516
517     for (method = methods; method; method = delim)
518     {
519       delim = strchr (method, ':');
520       if (delim)
521         *delim++ = '\0';
522       if (! method[0])
523         continue;
524
525       dprint (2, (debugfile, "smtp_authenticate: Trying method %s\n", method));
526
527       if (!strcmp (method, "oauthbearer"))
528       {
529         r = smtp_auth_oauth (conn);
530       }
531       else
532       {
533 #ifdef USE_SASL
534         r = smtp_auth_sasl (conn, method);
535 #else
536         mutt_error (_("SMTP authentication method %s requires SASL"), method);
537         mutt_sleep (1);
538         continue;
539 #endif
540       }
541       if (r == SMTP_AUTH_FAIL && delim)
542       {
543         mutt_error (_("%s authentication failed, trying next method"), method);
544         mutt_sleep (1);
545       }
546       else if (r != SMTP_AUTH_UNAVAIL)
547         break;
548     }
549
550     FREE (&methods);
551   }
552   else
553   {
554 #ifdef USE_SASL
555     r = smtp_auth_sasl (conn, AuthMechs);
556 #else
557     mutt_error (_("SMTP authentication requires SASL"));
558     mutt_sleep (1);
559     r = SMTP_AUTH_UNAVAIL;
560 #endif
561   }
562
563   if (r != SMTP_AUTH_SUCCESS)
564     mutt_account_unsetpass (&conn->account);
565
566   if (r == SMTP_AUTH_FAIL)
567   {
568     mutt_error (_("SASL authentication failed"));
569     mutt_sleep (1);
570   }
571   else if (r == SMTP_AUTH_UNAVAIL)
572   {
573     mutt_error (_("No authenticators available"));
574     mutt_sleep (1);
575   }
576
577   return r == SMTP_AUTH_SUCCESS ? 0 : -1;
578 }
579
580 #ifdef USE_SASL
581 static int smtp_auth_sasl (CONNECTION* conn, const char* mechlist)
582 {
583   sasl_conn_t* saslconn;
584   sasl_interact_t* interaction = NULL;
585   const char* mech;
586   const char* data = NULL;
587   unsigned int len;
588   char *buf = NULL;
589   size_t bufsize = 0;
590   int rc, saslrc;
591
592   if (mutt_sasl_client_new (conn, &saslconn) < 0)
593     return SMTP_AUTH_FAIL;
594
595   do
596   {
597     rc = sasl_client_start (saslconn, mechlist, &interaction, &data, &len, &mech);
598     if (rc == SASL_INTERACT)
599       mutt_sasl_interact (interaction);
600   }
601   while (rc == SASL_INTERACT);
602
603   if (rc != SASL_OK && rc != SASL_CONTINUE)
604   {
605     dprint (2, (debugfile, "smtp_auth_sasl: %s unavailable\n", mech));
606     sasl_dispose (&saslconn);
607     return SMTP_AUTH_UNAVAIL;
608   }
609
610   if (!option(OPTNOCURSES))
611     mutt_message (_("Authenticating (%s)..."), mech);
612
613   bufsize = ((len * 2) > LONG_STRING) ? (len * 2) : LONG_STRING;
614   buf = safe_malloc (bufsize);
615
616   snprintf (buf, bufsize, "AUTH %s", mech);
617   if (len)
618   {
619     safe_strcat (buf, bufsize, " ");
620     if (sasl_encode64 (data, len, buf + mutt_strlen (buf),
621                        bufsize - mutt_strlen (buf), &len) != SASL_OK)
622     {
623       dprint (1, (debugfile, "smtp_auth_sasl: error base64-encoding client response.\n"));
624       goto fail;
625     }
626   }
627   safe_strcat (buf, bufsize, "\r\n");
628
629   do
630   {
631     if (mutt_socket_write (conn, buf) < 0)
632       goto fail;
633     if ((rc = mutt_socket_readln (buf, bufsize, conn)) < 0)
634       goto fail;
635     if (smtp_code (buf, rc, &rc) < 0)
636       goto fail;
637
638     if (rc != smtp_ready)
639       break;
640
641     if (sasl_decode64 (buf+4, strlen (buf+4), buf, bufsize - 1, &len) != SASL_OK)
642     {
643       dprint (1, (debugfile, "smtp_auth_sasl: error base64-decoding server response.\n"));
644       goto fail;
645     }
646
647     do
648     {
649       saslrc = sasl_client_step (saslconn, buf, len, &interaction, &data, &len);
650       if (saslrc == SASL_INTERACT)
651         mutt_sasl_interact (interaction);
652     }
653     while (saslrc == SASL_INTERACT);
654
655     if (len)
656     {
657       if ((len * 2) > bufsize)
658       {
659         bufsize = len * 2;
660         safe_realloc (&buf, bufsize);
661       }
662       if (sasl_encode64 (data, len, buf, bufsize, &len) != SASL_OK)
663       {
664         dprint (1, (debugfile, "smtp_auth_sasl: error base64-encoding client response.\n"));
665         goto fail;
666       }
667     }
668     strfcpy (buf + len, "\r\n", bufsize - len);
669   } while (rc == smtp_ready && saslrc != SASL_FAIL);
670
671   if (smtp_success (rc))
672   {
673     mutt_sasl_setup_conn (conn, saslconn);
674     FREE (&buf);
675     return SMTP_AUTH_SUCCESS;
676   }
677
678 fail:
679   sasl_dispose (&saslconn);
680   FREE (&buf);
681   return SMTP_AUTH_FAIL;
682 }
683 #endif /* USE_SASL */
684
685
686 /* smtp_auth_oauth: AUTH=OAUTHBEARER support. See RFC 7628 */
687 static int smtp_auth_oauth (CONNECTION* conn)
688 {
689   char* ibuf = NULL;
690   char* oauthbearer = NULL;
691   int ilen;
692   int rc;
693
694   mutt_message _("Authenticating (OAUTHBEARER)...");
695
696   /* We get the access token from the smtp_oauth_refresh_command */
697   oauthbearer = mutt_account_getoauthbearer (&conn->account);
698   if (oauthbearer == NULL)
699     return SMTP_AUTH_FAIL;
700
701   ilen = strlen (oauthbearer) + 30;
702   ibuf = safe_malloc (ilen);
703
704   snprintf (ibuf, ilen, "AUTH OAUTHBEARER %s\r\n", oauthbearer);
705
706   rc = mutt_socket_write (conn, ibuf);
707   FREE (&oauthbearer);
708   FREE (&ibuf);
709
710   if (rc == -1)
711     return SMTP_AUTH_FAIL;
712   if (smtp_get_resp (conn) != 0)
713     return SMTP_AUTH_FAIL;
714
715   return SMTP_AUTH_SUCCESS;
716 }