VirtualBox

source: vbox/trunk/src/libs/curl-7.87.0/lib/curl_sasl.c@ 98929

Last change on this file since 98929 was 98326, checked in by vboxsync, 2 years ago

curl-7.87.0: Applied and adjusted our curl changes to 7.83.1. bugref:10356

  • Property svn:eol-style set to native
File size: 24.0 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2012 - 2022, Daniel Stenberg, <[email protected]>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 * SPDX-License-Identifier: curl
22 *
23 * RFC2195 CRAM-MD5 authentication
24 * RFC2617 Basic and Digest Access Authentication
25 * RFC2831 DIGEST-MD5 authentication
26 * RFC4422 Simple Authentication and Security Layer (SASL)
27 * RFC4616 PLAIN authentication
28 * RFC5802 SCRAM-SHA-1 authentication
29 * RFC7677 SCRAM-SHA-256 authentication
30 * RFC6749 OAuth 2.0 Authorization Framework
31 * RFC7628 A Set of SASL Mechanisms for OAuth
32 * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
33 *
34 ***************************************************************************/
35
36#include "curl_setup.h"
37
38#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
39 !defined(CURL_DISABLE_POP3)
40
41#include <curl/curl.h>
42#include "urldata.h"
43
44#include "curl_base64.h"
45#include "curl_md5.h"
46#include "vauth/vauth.h"
47#include "cfilters.h"
48#include "vtls/vtls.h"
49#include "curl_hmac.h"
50#include "curl_sasl.h"
51#include "warnless.h"
52#include "strtok.h"
53#include "sendf.h"
54/* The last 3 #include files should be in this order */
55#include "curl_printf.h"
56#include "curl_memory.h"
57#include "memdebug.h"
58
59/* Supported mechanisms */
60static const struct {
61 const char *name; /* Name */
62 size_t len; /* Name length */
63 unsigned short bit; /* Flag bit */
64} mechtable[] = {
65 { "LOGIN", 5, SASL_MECH_LOGIN },
66 { "PLAIN", 5, SASL_MECH_PLAIN },
67 { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 },
68 { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 },
69 { "GSSAPI", 6, SASL_MECH_GSSAPI },
70 { "EXTERNAL", 8, SASL_MECH_EXTERNAL },
71 { "NTLM", 4, SASL_MECH_NTLM },
72 { "XOAUTH2", 7, SASL_MECH_XOAUTH2 },
73 { "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER },
74 { "SCRAM-SHA-1", 11, SASL_MECH_SCRAM_SHA_1 },
75 { "SCRAM-SHA-256",13, SASL_MECH_SCRAM_SHA_256 },
76 { ZERO_NULL, 0, 0 }
77};
78
79/*
80 * Curl_sasl_cleanup()
81 *
82 * This is used to cleanup any libraries or curl modules used by the sasl
83 * functions.
84 *
85 * Parameters:
86 *
87 * conn [in] - The connection data.
88 * authused [in] - The authentication mechanism used.
89 */
90void Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused)
91{
92 (void)conn;
93 (void)authused;
94
95#if defined(USE_KERBEROS5)
96 /* Cleanup the gssapi structure */
97 if(authused == SASL_MECH_GSSAPI) {
98 Curl_auth_cleanup_gssapi(&conn->krb5);
99 }
100#endif
101
102#if defined(USE_GSASL)
103 /* Cleanup the GSASL structure */
104 if(authused & (SASL_MECH_SCRAM_SHA_1 | SASL_MECH_SCRAM_SHA_256)) {
105 Curl_auth_gsasl_cleanup(&conn->gsasl);
106 }
107#endif
108
109#if defined(USE_NTLM)
110 /* Cleanup the NTLM structure */
111 if(authused == SASL_MECH_NTLM) {
112 Curl_auth_cleanup_ntlm(&conn->ntlm);
113 }
114#endif
115}
116
117/*
118 * Curl_sasl_decode_mech()
119 *
120 * Convert a SASL mechanism name into a token.
121 *
122 * Parameters:
123 *
124 * ptr [in] - The mechanism string.
125 * maxlen [in] - Maximum mechanism string length.
126 * len [out] - If not NULL, effective name length.
127 *
128 * Returns the SASL mechanism token or 0 if no match.
129 */
130unsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen,
131 size_t *len)
132{
133 unsigned int i;
134 char c;
135
136 for(i = 0; mechtable[i].name; i++) {
137 if(maxlen >= mechtable[i].len &&
138 !memcmp(ptr, mechtable[i].name, mechtable[i].len)) {
139 if(len)
140 *len = mechtable[i].len;
141
142 if(maxlen == mechtable[i].len)
143 return mechtable[i].bit;
144
145 c = ptr[mechtable[i].len];
146 if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_')
147 return mechtable[i].bit;
148 }
149 }
150
151 return 0;
152}
153
154/*
155 * Curl_sasl_parse_url_auth_option()
156 *
157 * Parse the URL login options.
158 */
159CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
160 const char *value, size_t len)
161{
162 CURLcode result = CURLE_OK;
163 size_t mechlen;
164
165 if(!len)
166 return CURLE_URL_MALFORMAT;
167
168 if(sasl->resetprefs) {
169 sasl->resetprefs = FALSE;
170 sasl->prefmech = SASL_AUTH_NONE;
171 }
172
173 if(!strncmp(value, "*", len))
174 sasl->prefmech = SASL_AUTH_DEFAULT;
175 else {
176 unsigned short mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
177 if(mechbit && mechlen == len)
178 sasl->prefmech |= mechbit;
179 else
180 result = CURLE_URL_MALFORMAT;
181 }
182
183 return result;
184}
185
186/*
187 * Curl_sasl_init()
188 *
189 * Initializes the SASL structure.
190 */
191void Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data,
192 const struct SASLproto *params)
193{
194 unsigned long auth = data->set.httpauth;
195
196 sasl->params = params; /* Set protocol dependent parameters */
197 sasl->state = SASL_STOP; /* Not yet running */
198 sasl->curmech = NULL; /* No mechanism yet. */
199 sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */
200 sasl->prefmech = params->defmechs; /* Default preferred mechanisms */
201 sasl->authused = SASL_AUTH_NONE; /* The authentication mechanism used */
202 sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */
203 sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */
204 sasl->force_ir = FALSE; /* Respect external option */
205
206 if(auth != CURLAUTH_BASIC) {
207 sasl->resetprefs = FALSE;
208 sasl->prefmech = SASL_AUTH_NONE;
209 if(auth & CURLAUTH_BASIC)
210 sasl->prefmech |= SASL_MECH_PLAIN | SASL_MECH_LOGIN;
211 if(auth & CURLAUTH_DIGEST)
212 sasl->prefmech |= SASL_MECH_DIGEST_MD5;
213 if(auth & CURLAUTH_NTLM)
214 sasl->prefmech |= SASL_MECH_NTLM;
215 if(auth & CURLAUTH_BEARER)
216 sasl->prefmech |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2;
217 if(auth & CURLAUTH_GSSAPI)
218 sasl->prefmech |= SASL_MECH_GSSAPI;
219 }
220}
221
222/*
223 * state()
224 *
225 * This is the ONLY way to change SASL state!
226 */
227static void state(struct SASL *sasl, struct Curl_easy *data,
228 saslstate newstate)
229{
230#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
231 /* for debug purposes */
232 static const char * const names[]={
233 "STOP",
234 "PLAIN",
235 "LOGIN",
236 "LOGIN_PASSWD",
237 "EXTERNAL",
238 "CRAMMD5",
239 "DIGESTMD5",
240 "DIGESTMD5_RESP",
241 "NTLM",
242 "NTLM_TYPE2MSG",
243 "GSSAPI",
244 "GSSAPI_TOKEN",
245 "GSSAPI_NO_DATA",
246 "OAUTH2",
247 "OAUTH2_RESP",
248 "GSASL",
249 "CANCEL",
250 "FINAL",
251 /* LAST */
252 };
253
254 if(sasl->state != newstate)
255 infof(data, "SASL %p state change from %s to %s",
256 (void *)sasl, names[sasl->state], names[newstate]);
257#else
258 (void) data;
259#endif
260
261 sasl->state = newstate;
262}
263
264/* Get the SASL server message and convert it to binary. */
265static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data,
266 struct bufref *out)
267{
268 CURLcode result = CURLE_OK;
269
270 result = sasl->params->getmessage(data, out);
271 if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) {
272 unsigned char *msg;
273 size_t msglen;
274 const char *serverdata = (const char *) Curl_bufref_ptr(out);
275
276 if(!*serverdata || *serverdata == '=')
277 Curl_bufref_set(out, NULL, 0, NULL);
278 else {
279 result = Curl_base64_decode(serverdata, &msg, &msglen);
280 if(!result)
281 Curl_bufref_set(out, msg, msglen, curl_free);
282 }
283 }
284 return result;
285}
286
287/* Encode the outgoing SASL message. */
288static CURLcode build_message(struct SASL *sasl, struct bufref *msg)
289{
290 CURLcode result = CURLE_OK;
291
292 if(sasl->params->flags & SASL_FLAG_BASE64) {
293 if(!Curl_bufref_ptr(msg)) /* Empty message. */
294 Curl_bufref_set(msg, "", 0, NULL);
295 else if(!Curl_bufref_len(msg)) /* Explicit empty response. */
296 Curl_bufref_set(msg, "=", 1, NULL);
297 else {
298 char *base64;
299 size_t base64len;
300
301 result = Curl_base64_encode((const char *) Curl_bufref_ptr(msg),
302 Curl_bufref_len(msg), &base64, &base64len);
303 if(!result)
304 Curl_bufref_set(msg, base64, base64len, curl_free);
305 }
306 }
307
308 return result;
309}
310
311/*
312 * Curl_sasl_can_authenticate()
313 *
314 * Check if we have enough auth data and capabilities to authenticate.
315 */
316bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data)
317{
318 /* Have credentials been provided? */
319 if(data->state.aptr.user)
320 return TRUE;
321
322 /* EXTERNAL can authenticate without a user name and/or password */
323 if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL)
324 return TRUE;
325
326 return FALSE;
327}
328
329/*
330 * Curl_sasl_start()
331 *
332 * Calculate the required login details for SASL authentication.
333 */
334CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data,
335 bool force_ir, saslprogress *progress)
336{
337 CURLcode result = CURLE_OK;
338 struct connectdata *conn = data->conn;
339 unsigned short enabledmechs;
340 const char *mech = NULL;
341 struct bufref resp;
342 saslstate state1 = SASL_STOP;
343 saslstate state2 = SASL_FINAL;
344 const char *hostname, *disp_hostname;
345 int port;
346#if defined(USE_KERBEROS5) || defined(USE_NTLM)
347 const char *service = data->set.str[STRING_SERVICE_NAME] ?
348 data->set.str[STRING_SERVICE_NAME] :
349 sasl->params->service;
350#endif
351 const char *oauth_bearer = data->set.str[STRING_BEARER];
352 struct bufref nullmsg;
353
354 Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
355 Curl_bufref_init(&nullmsg);
356 Curl_bufref_init(&resp);
357 sasl->force_ir = force_ir; /* Latch for future use */
358 sasl->authused = 0; /* No mechanism used yet */
359 enabledmechs = sasl->authmechs & sasl->prefmech;
360 *progress = SASL_IDLE;
361
362 /* Calculate the supported authentication mechanism, by decreasing order of
363 security, as well as the initial response where appropriate */
364 if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) {
365 mech = SASL_MECH_STRING_EXTERNAL;
366 state1 = SASL_EXTERNAL;
367 sasl->authused = SASL_MECH_EXTERNAL;
368
369 if(force_ir || data->set.sasl_ir)
370 result = Curl_auth_create_external_message(conn->user, &resp);
371 }
372 else if(data->state.aptr.user) {
373#if defined(USE_KERBEROS5)
374 if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
375 Curl_auth_user_contains_domain(conn->user)) {
376 sasl->mutual_auth = FALSE;
377 mech = SASL_MECH_STRING_GSSAPI;
378 state1 = SASL_GSSAPI;
379 state2 = SASL_GSSAPI_TOKEN;
380 sasl->authused = SASL_MECH_GSSAPI;
381
382 if(force_ir || data->set.sasl_ir)
383 result = Curl_auth_create_gssapi_user_message(data, conn->user,
384 conn->passwd,
385 service,
386 conn->host.name,
387 sasl->mutual_auth,
388 NULL, &conn->krb5,
389 &resp);
390 }
391 else
392#endif
393#ifdef USE_GSASL
394 if((enabledmechs & SASL_MECH_SCRAM_SHA_256) &&
395 Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256,
396 &conn->gsasl)) {
397 mech = SASL_MECH_STRING_SCRAM_SHA_256;
398 sasl->authused = SASL_MECH_SCRAM_SHA_256;
399 state1 = SASL_GSASL;
400 state2 = SASL_GSASL;
401
402 result = Curl_auth_gsasl_start(data, conn->user,
403 conn->passwd, &conn->gsasl);
404 if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
405 result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
406 }
407 else if((enabledmechs & SASL_MECH_SCRAM_SHA_1) &&
408 Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1,
409 &conn->gsasl)) {
410 mech = SASL_MECH_STRING_SCRAM_SHA_1;
411 sasl->authused = SASL_MECH_SCRAM_SHA_1;
412 state1 = SASL_GSASL;
413 state2 = SASL_GSASL;
414
415 result = Curl_auth_gsasl_start(data, conn->user,
416 conn->passwd, &conn->gsasl);
417 if(result == CURLE_OK && (force_ir || data->set.sasl_ir))
418 result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp);
419 }
420 else
421#endif
422#ifndef CURL_DISABLE_CRYPTO_AUTH
423 if((enabledmechs & SASL_MECH_DIGEST_MD5) &&
424 Curl_auth_is_digest_supported()) {
425 mech = SASL_MECH_STRING_DIGEST_MD5;
426 state1 = SASL_DIGESTMD5;
427 sasl->authused = SASL_MECH_DIGEST_MD5;
428 }
429 else if(enabledmechs & SASL_MECH_CRAM_MD5) {
430 mech = SASL_MECH_STRING_CRAM_MD5;
431 state1 = SASL_CRAMMD5;
432 sasl->authused = SASL_MECH_CRAM_MD5;
433 }
434 else
435#endif
436#ifdef USE_NTLM
437 if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) {
438 mech = SASL_MECH_STRING_NTLM;
439 state1 = SASL_NTLM;
440 state2 = SASL_NTLM_TYPE2MSG;
441 sasl->authused = SASL_MECH_NTLM;
442
443 if(force_ir || data->set.sasl_ir)
444 result = Curl_auth_create_ntlm_type1_message(data,
445 conn->user, conn->passwd,
446 service,
447 hostname,
448 &conn->ntlm, &resp);
449 }
450 else
451#endif
452 if((enabledmechs & SASL_MECH_OAUTHBEARER) && oauth_bearer) {
453 mech = SASL_MECH_STRING_OAUTHBEARER;
454 state1 = SASL_OAUTH2;
455 state2 = SASL_OAUTH2_RESP;
456 sasl->authused = SASL_MECH_OAUTHBEARER;
457
458 if(force_ir || data->set.sasl_ir)
459 result = Curl_auth_create_oauth_bearer_message(conn->user,
460 hostname,
461 port,
462 oauth_bearer,
463 &resp);
464 }
465 else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) {
466 mech = SASL_MECH_STRING_XOAUTH2;
467 state1 = SASL_OAUTH2;
468 sasl->authused = SASL_MECH_XOAUTH2;
469
470 if(force_ir || data->set.sasl_ir)
471 result = Curl_auth_create_xoauth_bearer_message(conn->user,
472 oauth_bearer,
473 &resp);
474 }
475 else if(enabledmechs & SASL_MECH_PLAIN) {
476 mech = SASL_MECH_STRING_PLAIN;
477 state1 = SASL_PLAIN;
478 sasl->authused = SASL_MECH_PLAIN;
479
480 if(force_ir || data->set.sasl_ir)
481 result = Curl_auth_create_plain_message(conn->sasl_authzid,
482 conn->user, conn->passwd,
483 &resp);
484 }
485 else if(enabledmechs & SASL_MECH_LOGIN) {
486 mech = SASL_MECH_STRING_LOGIN;
487 state1 = SASL_LOGIN;
488 state2 = SASL_LOGIN_PASSWD;
489 sasl->authused = SASL_MECH_LOGIN;
490
491 if(force_ir || data->set.sasl_ir)
492 result = Curl_auth_create_login_message(conn->user, &resp);
493 }
494 }
495
496 if(!result && mech) {
497 sasl->curmech = mech;
498 if(Curl_bufref_ptr(&resp))
499 result = build_message(sasl, &resp);
500
501 if(sasl->params->maxirlen &&
502 strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen)
503 Curl_bufref_free(&resp);
504
505 if(!result)
506 result = sasl->params->sendauth(data, mech, &resp);
507
508 if(!result) {
509 *progress = SASL_INPROGRESS;
510 state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1);
511 }
512 }
513
514 Curl_bufref_free(&resp);
515 return result;
516}
517
518/*
519 * Curl_sasl_continue()
520 *
521 * Continue the authentication.
522 */
523CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data,
524 int code, saslprogress *progress)
525{
526 CURLcode result = CURLE_OK;
527 struct connectdata *conn = data->conn;
528 saslstate newstate = SASL_FINAL;
529 struct bufref resp;
530 const char *hostname, *disp_hostname;
531 int port;
532#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
533 defined(USE_NTLM)
534 const char *service = data->set.str[STRING_SERVICE_NAME] ?
535 data->set.str[STRING_SERVICE_NAME] :
536 sasl->params->service;
537#endif
538 const char *oauth_bearer = data->set.str[STRING_BEARER];
539 struct bufref serverdata;
540
541 Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port);
542 Curl_bufref_init(&serverdata);
543 Curl_bufref_init(&resp);
544 *progress = SASL_INPROGRESS;
545
546 if(sasl->state == SASL_FINAL) {
547 if(code != sasl->params->finalcode)
548 result = CURLE_LOGIN_DENIED;
549 *progress = SASL_DONE;
550 state(sasl, data, SASL_STOP);
551 return result;
552 }
553
554 if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
555 code != sasl->params->contcode) {
556 *progress = SASL_DONE;
557 state(sasl, data, SASL_STOP);
558 return CURLE_LOGIN_DENIED;
559 }
560
561 switch(sasl->state) {
562 case SASL_STOP:
563 *progress = SASL_DONE;
564 return result;
565 case SASL_PLAIN:
566 result = Curl_auth_create_plain_message(conn->sasl_authzid,
567 conn->user, conn->passwd, &resp);
568 break;
569 case SASL_LOGIN:
570 result = Curl_auth_create_login_message(conn->user, &resp);
571 newstate = SASL_LOGIN_PASSWD;
572 break;
573 case SASL_LOGIN_PASSWD:
574 result = Curl_auth_create_login_message(conn->passwd, &resp);
575 break;
576 case SASL_EXTERNAL:
577 result = Curl_auth_create_external_message(conn->user, &resp);
578 break;
579#ifndef CURL_DISABLE_CRYPTO_AUTH
580#ifdef USE_GSASL
581 case SASL_GSASL:
582 result = get_server_message(sasl, data, &serverdata);
583 if(!result)
584 result = Curl_auth_gsasl_token(data, &serverdata, &conn->gsasl, &resp);
585 if(!result && Curl_bufref_len(&resp) > 0)
586 newstate = SASL_GSASL;
587 break;
588#endif
589 case SASL_CRAMMD5:
590 result = get_server_message(sasl, data, &serverdata);
591 if(!result)
592 result = Curl_auth_create_cram_md5_message(&serverdata, conn->user,
593 conn->passwd, &resp);
594 break;
595 case SASL_DIGESTMD5:
596 result = get_server_message(sasl, data, &serverdata);
597 if(!result)
598 result = Curl_auth_create_digest_md5_message(data, &serverdata,
599 conn->user, conn->passwd,
600 service, &resp);
601 if(!result && (sasl->params->flags & SASL_FLAG_BASE64))
602 newstate = SASL_DIGESTMD5_RESP;
603 break;
604 case SASL_DIGESTMD5_RESP:
605 /* Keep response NULL to output an empty line. */
606 break;
607#endif
608
609#ifdef USE_NTLM
610 case SASL_NTLM:
611 /* Create the type-1 message */
612 result = Curl_auth_create_ntlm_type1_message(data,
613 conn->user, conn->passwd,
614 service, hostname,
615 &conn->ntlm, &resp);
616 newstate = SASL_NTLM_TYPE2MSG;
617 break;
618 case SASL_NTLM_TYPE2MSG:
619 /* Decode the type-2 message */
620 result = get_server_message(sasl, data, &serverdata);
621 if(!result)
622 result = Curl_auth_decode_ntlm_type2_message(data, &serverdata,
623 &conn->ntlm);
624 if(!result)
625 result = Curl_auth_create_ntlm_type3_message(data, conn->user,
626 conn->passwd, &conn->ntlm,
627 &resp);
628 break;
629#endif
630
631#if defined(USE_KERBEROS5)
632 case SASL_GSSAPI:
633 result = Curl_auth_create_gssapi_user_message(data, conn->user,
634 conn->passwd,
635 service,
636 conn->host.name,
637 sasl->mutual_auth, NULL,
638 &conn->krb5,
639 &resp);
640 newstate = SASL_GSSAPI_TOKEN;
641 break;
642 case SASL_GSSAPI_TOKEN:
643 result = get_server_message(sasl, data, &serverdata);
644 if(!result) {
645 if(sasl->mutual_auth) {
646 /* Decode the user token challenge and create the optional response
647 message */
648 result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
649 NULL, NULL,
650 sasl->mutual_auth,
651 &serverdata,
652 &conn->krb5,
653 &resp);
654 newstate = SASL_GSSAPI_NO_DATA;
655 }
656 else
657 /* Decode the security challenge and create the response message */
658 result = Curl_auth_create_gssapi_security_message(data,
659 conn->sasl_authzid,
660 &serverdata,
661 &conn->krb5,
662 &resp);
663 }
664 break;
665 case SASL_GSSAPI_NO_DATA:
666 /* Decode the security challenge and create the response message */
667 result = get_server_message(sasl, data, &serverdata);
668 if(!result)
669 result = Curl_auth_create_gssapi_security_message(data,
670 conn->sasl_authzid,
671 &serverdata,
672 &conn->krb5,
673 &resp);
674 break;
675#endif
676
677 case SASL_OAUTH2:
678 /* Create the authorization message */
679 if(sasl->authused == SASL_MECH_OAUTHBEARER) {
680 result = Curl_auth_create_oauth_bearer_message(conn->user,
681 hostname,
682 port,
683 oauth_bearer,
684 &resp);
685
686 /* Failures maybe sent by the server as continuations for OAUTHBEARER */
687 newstate = SASL_OAUTH2_RESP;
688 }
689 else
690 result = Curl_auth_create_xoauth_bearer_message(conn->user,
691 oauth_bearer,
692 &resp);
693 break;
694
695 case SASL_OAUTH2_RESP:
696 /* The continuation is optional so check the response code */
697 if(code == sasl->params->finalcode) {
698 /* Final response was received so we are done */
699 *progress = SASL_DONE;
700 state(sasl, data, SASL_STOP);
701 return result;
702 }
703 else if(code == sasl->params->contcode) {
704 /* Acknowledge the continuation by sending a 0x01 response. */
705 Curl_bufref_set(&resp, "\x01", 1, NULL);
706 break;
707 }
708 else {
709 *progress = SASL_DONE;
710 state(sasl, data, SASL_STOP);
711 return CURLE_LOGIN_DENIED;
712 }
713
714 case SASL_CANCEL:
715 /* Remove the offending mechanism from the supported list */
716 sasl->authmechs ^= sasl->authused;
717
718 /* Start an alternative SASL authentication */
719 return Curl_sasl_start(sasl, data, sasl->force_ir, progress);
720 default:
721 failf(data, "Unsupported SASL authentication mechanism");
722 result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
723 break;
724 }
725
726 Curl_bufref_free(&serverdata);
727
728 switch(result) {
729 case CURLE_BAD_CONTENT_ENCODING:
730 /* Cancel dialog */
731 result = sasl->params->cancelauth(data, sasl->curmech);
732 newstate = SASL_CANCEL;
733 break;
734 case CURLE_OK:
735 result = build_message(sasl, &resp);
736 if(!result)
737 result = sasl->params->contauth(data, sasl->curmech, &resp);
738 break;
739 default:
740 newstate = SASL_STOP; /* Stop on error */
741 *progress = SASL_DONE;
742 break;
743 }
744
745 Curl_bufref_free(&resp);
746
747 state(sasl, data, newstate);
748
749 return result;
750}
751#endif /* protocols are enabled that use SASL */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette