105{
106 gss_buffer_desc request_buf, send_token;
107 gss_buffer_t sec_token;
108 gss_name_t target_name;
109 gss_ctx_id_t context;
110 gss_OID mech_name;
111 char server_conf_flags;
112 gss_qop_t quality;
113 int cflags;
114 OM_uint32 maj_stat, min_stat;
115 unsigned long buf_size;
117
120
123
126
127
129 request_buf.value = buf1->
data;
130 request_buf.length =
buf_len(buf1);
131
133 maj_stat = gss_import_name(&min_stat, &request_buf, gss_nt_service_name, &target_name);
134 if (maj_stat != GSS_S_COMPLETE)
135 {
138 goto cleanup;
139 }
140 else if (c_debug_level >= 2)
141 {
142 gss_display_name(&min_stat, target_name, &request_buf, &mech_name);
144 gss_release_buffer(&min_stat, &request_buf);
145 }
146
147 sec_token = GSS_C_NO_BUFFER;
148 context = GSS_C_NO_CONTEXT;
149
150
151 maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &context, target_name,
152 GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
153 0, GSS_C_NO_CHANNEL_BINDINGS, sec_token, NULL,
154 &send_token, (unsigned int *) &cflags, NULL);
155 if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED))
156 {
159 gss_release_name(&min_stat, &target_name);
160
162 goto cleanup;
163 }
164
165
166
168
170
171
172 do
173 {
176
178 {
180 gss_release_name(&min_stat, &target_name);
181 goto bail;
182 }
183
184
187 gss_release_buffer(&min_stat, &send_token);
190
191 while (maj_stat == GSS_S_CONTINUE_NEEDED)
192 {
193
194 do
195 {
198
200 {
202 gss_release_name(&min_stat, &target_name);
203 goto bail;
204 }
205
207 {
209 gss_release_name(&min_stat, &target_name);
210 goto err_abort_cmd;
211 }
212 request_buf.value = buf2->
data;
213 request_buf.length =
buf_len(buf2);
214 sec_token = &request_buf;
215
216
217 maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &context, target_name,
218 GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
219 0, GSS_C_NO_CHANNEL_BINDINGS, sec_token, NULL,
220 &send_token, (unsigned int *) &cflags, NULL);
221 if ((maj_stat != GSS_S_COMPLETE) && (maj_stat != GSS_S_CONTINUE_NEEDED))
222 {
225 gss_release_name(&min_stat, &target_name);
226
227 goto err_abort_cmd;
228 }
230 gss_release_buffer(&min_stat, &send_token);
233 }
234
235 gss_release_name(&min_stat, &target_name);
236
237
238 do
239 {
242
244 {
246 goto bail;
247 }
249 {
251 goto err_abort_cmd;
252 }
253 request_buf.value = buf2->
data;
254 request_buf.length =
buf_len(buf2);
255
256 maj_stat = gss_unwrap(&min_stat, context, &request_buf, &send_token, &cflags, &quality);
257 if (maj_stat != GSS_S_COMPLETE)
258 {
261 gss_release_buffer(&min_stat, &send_token);
262 goto err_abort_cmd;
263 }
265
266
267 server_conf_flags = ((char *) send_token.value)[0];
269 {
271 gss_release_buffer(&min_stat, &send_token);
272 goto err_abort_cmd;
273 }
274
275
276 ((char *) send_token.value)[0] = '\0';
277 buf_size = ntohl(*((long *) send_token.value));
278 gss_release_buffer(&min_stat, &send_token);
284
285
286 buf_size = htonl(buf_size);
290
292 request_buf.value = buf1->
data;
293 request_buf.length =
buf_len(buf1);
294 maj_stat = gss_wrap(&min_stat, context, 0, GSS_C_QOP_DEFAULT, &request_buf,
295 &cflags, &send_token);
296 if (maj_stat != GSS_S_COMPLETE)
297 {
299 goto err_abort_cmd;
300 }
301
306
307
308 do
309 {
313 {
315 goto err_abort_cmd;
316 }
318 {
319
321 maj_stat = gss_delete_sec_context(&min_stat, &context, &send_token);
322 if (maj_stat != GSS_S_COMPLETE)
324
325
326
327
328
329 gss_release_buffer(&min_stat, &send_token);
330
332 goto cleanup;
333 }
334 else
335 {
336 goto bail;
337 }
338
339err_abort_cmd:
341 do
342 {
345
346bail:
347
348 mutt_error(
_(
"%s authentication failed"),
"GSSAPI");
350
351cleanup:
354
355 return retval;
356}
@ IMAP_AUTH_FAILURE
Authentication failed.
@ IMAP_AUTH_SUCCESS
Authentication successful.
@ IMAP_AUTH_UNAVAIL
Authentication method not permitted.
static void print_gss_error(OM_uint32 err_maj, OM_uint32 err_min)
Print detailed error message to the debug log.
#define GSS_AUTH_P_PRIVACY
#define GSS_AUTH_P_INTEGRITY
size_t mutt_b64_buffer_encode(struct Buffer *buf, const char *in, size_t len)
Convert raw bytes to null-terminated base64 string.
int mutt_b64_buffer_decode(struct Buffer *buf, const char *in)
Convert null-terminated base64 string to raw bytes.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
size_t buf_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
int mutt_account_getuser(struct ConnAccount *cac)
Retrieve username into ConnAccount, if necessary.
#define mutt_message(...)
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_CAP_AUTH_GSSAPI
RFC1731: GSSAPI authentication.
#define IMAP_RES_CONTINUE
* ...
@ LL_DEBUG1
Log at debug level 1.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
#define mutt_socket_send(conn, buf)
String manipulation buffer.
char * data
Pointer to data.
char host[128]
Server to login to.
struct ConnAccount account
Account details: username, password, etc.
ImapCapFlags capabilities
Capability flags.
struct Connection * conn
Connection to IMAP server.
Container for Accounts, Notifications.
struct ConfigSubset * sub
Inherited config items.