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)
111 else
112 {
113 mutt_debug(
LL_DEBUG1,
"Failure starting authentication exchange. No shared mechanisms?\n");
114 }
115
116
117 sasl_dispose(&saslconn);
119 }
120
121
123
124 bufsize =
MAX((olen * 2), 1024);
126
127 snprintf(buf, bufsize, "AUTHENTICATE %s", mech);
129 {
131 buf[len++] = ' ';
132 if (sasl_encode64(pc, olen, buf + len, bufsize - len, &olen) != SASL_OK)
133 {
135 goto bail;
136 }
137 client_start = false;
138 olen = 0;
139 }
142
143
144 while ((rc == SASL_CONTINUE) || (olen > 0))
145 {
146 do
147 {
150
152 goto bail;
153
155 {
156
157 if (adata->
buf[1] ==
'\0')
158 {
159 buf[0] = '\0';
160 len = 0;
161 }
162 else
163 {
164 len = strlen(adata->
buf + 2);
165 if (len > bufsize)
166 {
167 bufsize = len;
169 }
170
171
172 if (sasl_decode64(adata->
buf + 2, len, buf, bufsize - 1, &len) != SASL_OK)
173 {
175 goto bail;
176 }
177 }
178 }
179
180
181
182
183 if (!client_start || buf[0])
184 {
185 do
186 {
187 rc = sasl_client_step(saslconn, buf, len, &interaction, &pc, &olen);
188 if (rc == SASL_INTERACT)
190 } while (rc == SASL_INTERACT);
191 }
192 else
193 client_start = false;
194
195
196 if (olen)
197 {
198 if ((olen * 2) > bufsize)
199 {
200 bufsize = olen * 2;
202 }
203 if (sasl_encode64(pc, olen, buf, bufsize, &olen) != SASL_OK)
204 {
206 goto bail;
207 }
208 }
209
211 {
214 }
215
216
217 if (rc < 0)
218 {
221 }
222
223 olen = 0;
224 }
225
227 {
230 break;
231 }
232
233 if (rc != SASL_OK)
234 goto bail;
235
237 {
241 }
242
243bail:
244 sasl_dispose(&saslconn);
246
247 if (method)
248 {
251 }
252
253
254 mutt_error(
_(
"%s authentication failed"),
"SASL ");
255
257}
@ 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.