46{
47 sasl_conn_t *saslconn = NULL;
48 sasl_interact_t *interaction = NULL;
49 int rc, irc;
50 char *buf = NULL;
51 size_t bufsize = 0;
52 const char *mech = NULL;
53 const char *pc = NULL;
54 unsigned int len = 0, olen = 0;
55 bool client_start;
56
58 {
61 }
62
63 rc = SASL_FAIL;
64
65
66 if (!method)
67 {
69
70
71
72
73
74
76 {
77 sasl_dispose(&saslconn);
79 }
80
84 {
85 rc = sasl_client_start(saslconn, "AUTH=ANONYMOUS", NULL, &pc, &olen, &mech);
86 }
87 }
89 {
90
91 sasl_dispose(&saslconn);
93 }
94
95 if ((rc != SASL_OK) && (rc != SASL_CONTINUE))
96 {
97 do
98 {
99 rc = sasl_client_start(saslconn, method, &interaction, &pc, &olen, &mech);
100 if (rc == SASL_INTERACT)
102 } while (rc == SASL_INTERACT);
103 }
104
105 client_start = (olen > 0);
106
107 if ((rc != SASL_OK) && (rc != SASL_CONTINUE))
108 {
109 if (method)
110 {
112 }
113 else
114 {
115 mutt_debug(
LL_DEBUG1,
"Failure starting authentication exchange. No shared mechanisms?\n");
116 }
117
118
119 sasl_dispose(&saslconn);
121 }
122
123
125
126 bufsize =
MAX((olen * 2), 1024);
128
129 snprintf(buf, bufsize, "AUTHENTICATE %s", mech);
131 {
133 buf[len++] = ' ';
134 if (sasl_encode64(pc, olen, buf + len, bufsize - len, &olen) != SASL_OK)
135 {
137 goto bail;
138 }
139 client_start = false;
140 olen = 0;
141 }
144
145
146 while ((rc == SASL_CONTINUE) || (olen > 0))
147 {
148 do
149 {
152
154 goto bail;
155
157 {
158
159 if (adata->
buf[1] ==
'\0')
160 {
161 buf[0] = '\0';
162 len = 0;
163 }
164 else
165 {
166 len = strlen(adata->
buf + 2);
167 if (len > bufsize)
168 {
169 bufsize = len;
171 }
172
173
174 if (sasl_decode64(adata->
buf + 2, len, buf, bufsize - 1, &len) != SASL_OK)
175 {
177 goto bail;
178 }
179 }
180 }
181
182
183
184
185 if (!client_start || buf[0])
186 {
187 do
188 {
189 rc = sasl_client_step(saslconn, buf, len, &interaction, &pc, &olen);
190 if (rc == SASL_INTERACT)
192 } while (rc == SASL_INTERACT);
193 }
194 else
195 {
196 client_start = false;
197 }
198
199
200 if (olen)
201 {
202 if ((olen * 2) > bufsize)
203 {
204 bufsize = olen * 2;
206 }
207 if (sasl_encode64(pc, olen, buf, bufsize, &olen) != SASL_OK)
208 {
210 goto bail;
211 }
212 }
213
215 {
218 }
219
220
221 if (rc < 0)
222 {
225 }
226
227 olen = 0;
228 }
229
231 {
234 break;
235 }
236
237 if (rc != SASL_OK)
238 goto bail;
239
241 {
245 }
246
247bail:
248 sasl_dispose(&saslconn);
250
251 if (method)
252 {
255 }
256
257
258 mutt_error(
_(
"%s authentication failed"),
"SASL ");
259
261}
@ IMAP_AUTH_FAILURE
Authentication failed.
@ IMAP_AUTH_SUCCESS
Authentication successful.
@ IMAP_AUTH_UNAVAIL
Authentication method not permitted.
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
#define mutt_message(...)
#define mutt_debug(LEVEL,...)
int imap_cmd_start(struct ImapAccountData *adata, const char *cmdstr)
Given an IMAP command, send it to the server.
int imap_cmd_step(struct ImapAccountData *adata)
Reads server responses from an IMAP command.
bool imap_code(const char *s)
Was the command successful.
#define IMAP_RES_RESPOND
+
#define IMAP_RES_OK
<tag> OK ...
#define IMAP_CAP_AUTH_ANONYMOUS
AUTH=ANONYMOUS.
#define IMAP_RES_NO
<tag> NO ...
#define IMAP_CAP_SASL_IR
SASL initial response draft.
#define IMAP_RES_CONTINUE
* ...
#define IMAP_RES_BAD
<tag> BAD ...
@ LL_DEBUG2
Log at debug level 2.
@ LL_DEBUG1
Log at debug level 1.
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
size_t mutt_str_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix.
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
int mutt_sasl_interact(sasl_interact_t *interaction)
Perform an SASL interaction with the user.
int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
Wrapper for sasl_client_new()
void mutt_sasl_setup_conn(struct Connection *conn, sasl_conn_t *saslconn)
Set up an SASL connection.
#define mutt_socket_send(conn, buf)
struct ConnAccount account
Account details: username, password, etc.
ImapCapFlags capabilities
Capability flags.
char * capstr
Capability string from the server.
struct Connection * conn
Connection to IMAP server.