1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010-2021 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This library 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 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <mailutils/diag.h>
24 #include <mailutils/errno.h>
25 #include <mailutils/smtp.h>
26 #include <mailutils/sys/smtp.h>
27 #include <mailutils/mailbox.h> /* Strange, mu_ticket_file is declared here */
28 #include <mailutils/util.h>
29 #include <mailutils/auth.h>
30 #include <mailutils/url.h>
31
32 #if defined(WITH_GSASL)
33 static int
get_ticket(mu_ticket_t * pticket)34 get_ticket (mu_ticket_t *pticket)
35 {
36 char *filename = mu_tilde_expansion (mu_ticket_file,
37 MU_HIERARCHY_DELIMITER, NULL);
38 mu_wicket_t wicket;
39 int rc;
40
41 rc = mu_file_wicket_create (&wicket, filename);
42
43 if (rc == 0)
44 rc = mu_wicket_get_ticket (wicket, NULL, pticket);
45 mu_wicket_destroy (&wicket);
46 free (filename);
47 return rc;
48 }
49
50 #define _HAS_USERNAME 0x01
51 #define _HAS_PASSWORD 0x02
52
53 static int
_mu_smtp_fixup_params(mu_smtp_t smtp)54 _mu_smtp_fixup_params (mu_smtp_t smtp)
55 {
56 const char *str;
57 mu_ticket_t ticket = NULL;
58 int flags = 0;
59 int rc;
60
61 if (smtp->param[MU_SMTP_PARAM_USERNAME])
62 flags |= _HAS_USERNAME;
63
64 if (smtp->secret)
65 flags |= _HAS_PASSWORD;
66
67 if ((flags & (_HAS_USERNAME|_HAS_PASSWORD)) == (_HAS_USERNAME|_HAS_PASSWORD))
68 return 0; /* Nothing to do */
69
70 if (!smtp->url)
71 return 0;
72
73 if (!(flags & _HAS_USERNAME))
74 {
75 rc = mu_url_sget_user (smtp->url, &str);
76 if (rc == 0 &&
77 mu_smtp_set_param (smtp, MU_SMTP_PARAM_USERNAME, str) == 0)
78 flags |= _HAS_USERNAME;
79 }
80
81 if (!(flags & _HAS_PASSWORD) &&
82 mu_url_get_secret (smtp->url, &smtp->secret) == 0)
83 flags |= _HAS_PASSWORD;
84
85 if ((!(flags & _HAS_USERNAME) ||
86 !(flags & _HAS_PASSWORD)) &&
87 get_ticket (&ticket) == 0)
88 {
89 if (!(flags & _HAS_USERNAME) &&
90 mu_ticket_get_cred (ticket, smtp->url, "SMTP User: ",
91 &smtp->param[MU_SMTP_PARAM_USERNAME],
92 NULL) == 0)
93 flags |= _HAS_USERNAME;
94
95 if (!(flags & _HAS_PASSWORD) && !smtp->secret)
96 mu_ticket_get_cred (ticket, smtp->url, "SMTP Passwd: ",
97 NULL, &smtp->secret);
98 mu_ticket_destroy (&ticket);
99 }
100
101 return 0;
102 }
103 #endif
104
105 int
mu_smtp_auth(mu_smtp_t smtp)106 mu_smtp_auth (mu_smtp_t smtp)
107 {
108 if (!smtp)
109 return EINVAL;
110 if (MU_SMTP_FISSET (smtp, _MU_SMTP_ERR))
111 return MU_ERR_FAILURE;
112 if (MU_SMTP_FISSET (smtp, _MU_SMTP_AUTH))
113 return MU_ERR_SEQ;
114 if (smtp->state != MU_SMTP_MAIL)
115 return MU_ERR_SEQ;
116
117 #if defined(WITH_GSASL)
118 /* Obtain missing authentication credentials either from the
119 URL (when supplied) or from the user ticket file, or by
120 asking the user, if anything else fails.
121
122 FIXME: This needs some more work. First of all, it should
123 be called only when really needed (e.g. by mu_smtp_get_param).
124 Secondly, it should ask the user even if no URL was supplied
125 (presently it does not). Thirdly, there should be an API to
126 let caller determine the way of inputting missing data (by
127 default it does that on tty, which obviously will not suite
128 GUI applications). */
129 _mu_smtp_fixup_params (smtp);
130 if (!smtp->param[MU_SMTP_PARAM_USERNAME] && !smtp->secret)
131 return MU_ERR_AUTH_NO_CRED;
132 return _mu_smtp_gsasl_auth (smtp);
133 #else
134 /* FIXME: Provide support for some basic authentication methods.
135 Once done, make sure _mu_smtp_fixup_params is called for this
136 branch as well (though see the fixme above). */
137 return ENOSYS;
138 #endif
139 }
140