Annotation of embedaddon/curl/lib/curl_sasl.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, 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.haxx.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: * RFC2195 CRAM-MD5 authentication
! 22: * RFC2617 Basic and Digest Access Authentication
! 23: * RFC2831 DIGEST-MD5 authentication
! 24: * RFC4422 Simple Authentication and Security Layer (SASL)
! 25: * RFC4616 PLAIN authentication
! 26: * RFC6749 OAuth 2.0 Authorization Framework
! 27: * RFC7628 A Set of SASL Mechanisms for OAuth
! 28: * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt>
! 29: *
! 30: ***************************************************************************/
! 31:
! 32: #include "curl_setup.h"
! 33:
! 34: #if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \
! 35: !defined(CURL_DISABLE_POP3)
! 36:
! 37: #include <curl/curl.h>
! 38: #include "urldata.h"
! 39:
! 40: #include "curl_base64.h"
! 41: #include "curl_md5.h"
! 42: #include "vauth/vauth.h"
! 43: #include "vtls/vtls.h"
! 44: #include "curl_hmac.h"
! 45: #include "curl_sasl.h"
! 46: #include "warnless.h"
! 47: #include "strtok.h"
! 48: #include "sendf.h"
! 49: #include "non-ascii.h" /* included for Curl_convert_... prototypes */
! 50: /* The last 3 #include files should be in this order */
! 51: #include "curl_printf.h"
! 52: #include "curl_memory.h"
! 53: #include "memdebug.h"
! 54:
! 55: /* Supported mechanisms */
! 56: static const struct {
! 57: const char *name; /* Name */
! 58: size_t len; /* Name length */
! 59: unsigned int bit; /* Flag bit */
! 60: } mechtable[] = {
! 61: { "LOGIN", 5, SASL_MECH_LOGIN },
! 62: { "PLAIN", 5, SASL_MECH_PLAIN },
! 63: { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 },
! 64: { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 },
! 65: { "GSSAPI", 6, SASL_MECH_GSSAPI },
! 66: { "EXTERNAL", 8, SASL_MECH_EXTERNAL },
! 67: { "NTLM", 4, SASL_MECH_NTLM },
! 68: { "XOAUTH2", 7, SASL_MECH_XOAUTH2 },
! 69: { "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER },
! 70: { ZERO_NULL, 0, 0 }
! 71: };
! 72:
! 73: /*
! 74: * Curl_sasl_cleanup()
! 75: *
! 76: * This is used to cleanup any libraries or curl modules used by the sasl
! 77: * functions.
! 78: *
! 79: * Parameters:
! 80: *
! 81: * conn [in] - The connection data.
! 82: * authused [in] - The authentication mechanism used.
! 83: */
! 84: void Curl_sasl_cleanup(struct connectdata *conn, unsigned int authused)
! 85: {
! 86: #if defined(USE_KERBEROS5)
! 87: /* Cleanup the gssapi structure */
! 88: if(authused == SASL_MECH_GSSAPI) {
! 89: Curl_auth_cleanup_gssapi(&conn->krb5);
! 90: }
! 91: #endif
! 92:
! 93: #if defined(USE_NTLM)
! 94: /* Cleanup the NTLM structure */
! 95: if(authused == SASL_MECH_NTLM) {
! 96: Curl_auth_cleanup_ntlm(&conn->ntlm);
! 97: }
! 98: #endif
! 99:
! 100: #if !defined(USE_KERBEROS5) && !defined(USE_NTLM)
! 101: /* Reserved for future use */
! 102: (void)conn;
! 103: (void)authused;
! 104: #endif
! 105: }
! 106:
! 107: /*
! 108: * Curl_sasl_decode_mech()
! 109: *
! 110: * Convert a SASL mechanism name into a token.
! 111: *
! 112: * Parameters:
! 113: *
! 114: * ptr [in] - The mechanism string.
! 115: * maxlen [in] - Maximum mechanism string length.
! 116: * len [out] - If not NULL, effective name length.
! 117: *
! 118: * Returns the SASL mechanism token or 0 if no match.
! 119: */
! 120: unsigned int Curl_sasl_decode_mech(const char *ptr, size_t maxlen, size_t *len)
! 121: {
! 122: unsigned int i;
! 123: char c;
! 124:
! 125: for(i = 0; mechtable[i].name; i++) {
! 126: if(maxlen >= mechtable[i].len &&
! 127: !memcmp(ptr, mechtable[i].name, mechtable[i].len)) {
! 128: if(len)
! 129: *len = mechtable[i].len;
! 130:
! 131: if(maxlen == mechtable[i].len)
! 132: return mechtable[i].bit;
! 133:
! 134: c = ptr[mechtable[i].len];
! 135: if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_')
! 136: return mechtable[i].bit;
! 137: }
! 138: }
! 139:
! 140: return 0;
! 141: }
! 142:
! 143: /*
! 144: * Curl_sasl_parse_url_auth_option()
! 145: *
! 146: * Parse the URL login options.
! 147: */
! 148: CURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl,
! 149: const char *value, size_t len)
! 150: {
! 151: CURLcode result = CURLE_OK;
! 152: size_t mechlen;
! 153:
! 154: if(!len)
! 155: return CURLE_URL_MALFORMAT;
! 156:
! 157: if(sasl->resetprefs) {
! 158: sasl->resetprefs = FALSE;
! 159: sasl->prefmech = SASL_AUTH_NONE;
! 160: }
! 161:
! 162: if(!strncmp(value, "*", len))
! 163: sasl->prefmech = SASL_AUTH_DEFAULT;
! 164: else {
! 165: unsigned int mechbit = Curl_sasl_decode_mech(value, len, &mechlen);
! 166: if(mechbit && mechlen == len)
! 167: sasl->prefmech |= mechbit;
! 168: else
! 169: result = CURLE_URL_MALFORMAT;
! 170: }
! 171:
! 172: return result;
! 173: }
! 174:
! 175: /*
! 176: * Curl_sasl_init()
! 177: *
! 178: * Initializes the SASL structure.
! 179: */
! 180: void Curl_sasl_init(struct SASL *sasl, const struct SASLproto *params)
! 181: {
! 182: sasl->params = params; /* Set protocol dependent parameters */
! 183: sasl->state = SASL_STOP; /* Not yet running */
! 184: sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */
! 185: sasl->prefmech = SASL_AUTH_DEFAULT; /* Prefer all mechanisms */
! 186: sasl->authused = SASL_AUTH_NONE; /* No the authentication mechanism used */
! 187: sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */
! 188: sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */
! 189: sasl->force_ir = FALSE; /* Respect external option */
! 190: }
! 191:
! 192: /*
! 193: * state()
! 194: *
! 195: * This is the ONLY way to change SASL state!
! 196: */
! 197: static void state(struct SASL *sasl, struct connectdata *conn,
! 198: saslstate newstate)
! 199: {
! 200: #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
! 201: /* for debug purposes */
! 202: static const char * const names[]={
! 203: "STOP",
! 204: "PLAIN",
! 205: "LOGIN",
! 206: "LOGIN_PASSWD",
! 207: "EXTERNAL",
! 208: "CRAMMD5",
! 209: "DIGESTMD5",
! 210: "DIGESTMD5_RESP",
! 211: "NTLM",
! 212: "NTLM_TYPE2MSG",
! 213: "GSSAPI",
! 214: "GSSAPI_TOKEN",
! 215: "GSSAPI_NO_DATA",
! 216: "OAUTH2",
! 217: "OAUTH2_RESP",
! 218: "CANCEL",
! 219: "FINAL",
! 220: /* LAST */
! 221: };
! 222:
! 223: if(sasl->state != newstate)
! 224: infof(conn->data, "SASL %p state change from %s to %s\n",
! 225: (void *)sasl, names[sasl->state], names[newstate]);
! 226: #else
! 227: (void) conn;
! 228: #endif
! 229:
! 230: sasl->state = newstate;
! 231: }
! 232:
! 233: /*
! 234: * Curl_sasl_can_authenticate()
! 235: *
! 236: * Check if we have enough auth data and capabilities to authenticate.
! 237: */
! 238: bool Curl_sasl_can_authenticate(struct SASL *sasl, struct connectdata *conn)
! 239: {
! 240: /* Have credentials been provided? */
! 241: if(conn->bits.user_passwd)
! 242: return TRUE;
! 243:
! 244: /* EXTERNAL can authenticate without a user name and/or password */
! 245: if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL)
! 246: return TRUE;
! 247:
! 248: return FALSE;
! 249: }
! 250:
! 251: /*
! 252: * Curl_sasl_start()
! 253: *
! 254: * Calculate the required login details for SASL authentication.
! 255: */
! 256: CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
! 257: bool force_ir, saslprogress *progress)
! 258: {
! 259: CURLcode result = CURLE_OK;
! 260: struct Curl_easy *data = conn->data;
! 261: unsigned int enabledmechs;
! 262: const char *mech = NULL;
! 263: char *resp = NULL;
! 264: size_t len = 0;
! 265: saslstate state1 = SASL_STOP;
! 266: saslstate state2 = SASL_FINAL;
! 267: const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
! 268: conn->host.name;
! 269: const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
! 270: #if defined(USE_KERBEROS5) || defined(USE_NTLM)
! 271: const char *service = data->set.str[STRING_SERVICE_NAME] ?
! 272: data->set.str[STRING_SERVICE_NAME] :
! 273: sasl->params->service;
! 274: #endif
! 275: const char *oauth_bearer = data->set.str[STRING_BEARER];
! 276:
! 277: sasl->force_ir = force_ir; /* Latch for future use */
! 278: sasl->authused = 0; /* No mechanism used yet */
! 279: enabledmechs = sasl->authmechs & sasl->prefmech;
! 280: *progress = SASL_IDLE;
! 281:
! 282: /* Calculate the supported authentication mechanism, by decreasing order of
! 283: security, as well as the initial response where appropriate */
! 284: if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) {
! 285: mech = SASL_MECH_STRING_EXTERNAL;
! 286: state1 = SASL_EXTERNAL;
! 287: sasl->authused = SASL_MECH_EXTERNAL;
! 288:
! 289: if(force_ir || data->set.sasl_ir)
! 290: result = Curl_auth_create_external_message(data, conn->user, &resp,
! 291: &len);
! 292: }
! 293: else if(conn->bits.user_passwd) {
! 294: #if defined(USE_KERBEROS5)
! 295: if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() &&
! 296: Curl_auth_user_contains_domain(conn->user)) {
! 297: sasl->mutual_auth = FALSE;
! 298: mech = SASL_MECH_STRING_GSSAPI;
! 299: state1 = SASL_GSSAPI;
! 300: state2 = SASL_GSSAPI_TOKEN;
! 301: sasl->authused = SASL_MECH_GSSAPI;
! 302:
! 303: if(force_ir || data->set.sasl_ir)
! 304: result = Curl_auth_create_gssapi_user_message(data, conn->user,
! 305: conn->passwd,
! 306: service,
! 307: data->conn->host.name,
! 308: sasl->mutual_auth,
! 309: NULL, &conn->krb5,
! 310: &resp, &len);
! 311: }
! 312: else
! 313: #endif
! 314: #ifndef CURL_DISABLE_CRYPTO_AUTH
! 315: if((enabledmechs & SASL_MECH_DIGEST_MD5) &&
! 316: Curl_auth_is_digest_supported()) {
! 317: mech = SASL_MECH_STRING_DIGEST_MD5;
! 318: state1 = SASL_DIGESTMD5;
! 319: sasl->authused = SASL_MECH_DIGEST_MD5;
! 320: }
! 321: else if(enabledmechs & SASL_MECH_CRAM_MD5) {
! 322: mech = SASL_MECH_STRING_CRAM_MD5;
! 323: state1 = SASL_CRAMMD5;
! 324: sasl->authused = SASL_MECH_CRAM_MD5;
! 325: }
! 326: else
! 327: #endif
! 328: #ifdef USE_NTLM
! 329: if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) {
! 330: mech = SASL_MECH_STRING_NTLM;
! 331: state1 = SASL_NTLM;
! 332: state2 = SASL_NTLM_TYPE2MSG;
! 333: sasl->authused = SASL_MECH_NTLM;
! 334:
! 335: if(force_ir || data->set.sasl_ir)
! 336: result = Curl_auth_create_ntlm_type1_message(data,
! 337: conn->user, conn->passwd,
! 338: service,
! 339: hostname,
! 340: &conn->ntlm, &resp,
! 341: &len);
! 342: }
! 343: else
! 344: #endif
! 345: if((enabledmechs & SASL_MECH_OAUTHBEARER) && oauth_bearer) {
! 346: mech = SASL_MECH_STRING_OAUTHBEARER;
! 347: state1 = SASL_OAUTH2;
! 348: state2 = SASL_OAUTH2_RESP;
! 349: sasl->authused = SASL_MECH_OAUTHBEARER;
! 350:
! 351: if(force_ir || data->set.sasl_ir)
! 352: result = Curl_auth_create_oauth_bearer_message(data, conn->user,
! 353: hostname,
! 354: port,
! 355: oauth_bearer,
! 356: &resp, &len);
! 357: }
! 358: else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) {
! 359: mech = SASL_MECH_STRING_XOAUTH2;
! 360: state1 = SASL_OAUTH2;
! 361: sasl->authused = SASL_MECH_XOAUTH2;
! 362:
! 363: if(force_ir || data->set.sasl_ir)
! 364: result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
! 365: oauth_bearer,
! 366: &resp, &len);
! 367: }
! 368: else if(enabledmechs & SASL_MECH_PLAIN) {
! 369: mech = SASL_MECH_STRING_PLAIN;
! 370: state1 = SASL_PLAIN;
! 371: sasl->authused = SASL_MECH_PLAIN;
! 372:
! 373: if(force_ir || data->set.sasl_ir)
! 374: result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
! 375: conn->user, conn->passwd,
! 376: &resp, &len);
! 377: }
! 378: else if(enabledmechs & SASL_MECH_LOGIN) {
! 379: mech = SASL_MECH_STRING_LOGIN;
! 380: state1 = SASL_LOGIN;
! 381: state2 = SASL_LOGIN_PASSWD;
! 382: sasl->authused = SASL_MECH_LOGIN;
! 383:
! 384: if(force_ir || data->set.sasl_ir)
! 385: result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
! 386: }
! 387: }
! 388:
! 389: if(!result && mech) {
! 390: if(resp && sasl->params->maxirlen &&
! 391: strlen(mech) + len > sasl->params->maxirlen) {
! 392: free(resp);
! 393: resp = NULL;
! 394: }
! 395:
! 396: result = sasl->params->sendauth(conn, mech, resp);
! 397: if(!result) {
! 398: *progress = SASL_INPROGRESS;
! 399: state(sasl, conn, resp ? state2 : state1);
! 400: }
! 401: }
! 402:
! 403: free(resp);
! 404:
! 405: return result;
! 406: }
! 407:
! 408: /*
! 409: * Curl_sasl_continue()
! 410: *
! 411: * Continue the authentication.
! 412: */
! 413: CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
! 414: int code, saslprogress *progress)
! 415: {
! 416: CURLcode result = CURLE_OK;
! 417: struct Curl_easy *data = conn->data;
! 418: saslstate newstate = SASL_FINAL;
! 419: char *resp = NULL;
! 420: const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
! 421: conn->host.name;
! 422: const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
! 423: #if !defined(CURL_DISABLE_CRYPTO_AUTH)
! 424: char *chlg = NULL;
! 425: size_t chlglen = 0;
! 426: #endif
! 427: #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
! 428: defined(USE_NTLM)
! 429: const char *service = data->set.str[STRING_SERVICE_NAME] ?
! 430: data->set.str[STRING_SERVICE_NAME] :
! 431: sasl->params->service;
! 432: char *serverdata;
! 433: #endif
! 434: size_t len = 0;
! 435: const char *oauth_bearer = data->set.str[STRING_BEARER];
! 436:
! 437: *progress = SASL_INPROGRESS;
! 438:
! 439: if(sasl->state == SASL_FINAL) {
! 440: if(code != sasl->params->finalcode)
! 441: result = CURLE_LOGIN_DENIED;
! 442: *progress = SASL_DONE;
! 443: state(sasl, conn, SASL_STOP);
! 444: return result;
! 445: }
! 446:
! 447: if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP &&
! 448: code != sasl->params->contcode) {
! 449: *progress = SASL_DONE;
! 450: state(sasl, conn, SASL_STOP);
! 451: return CURLE_LOGIN_DENIED;
! 452: }
! 453:
! 454: switch(sasl->state) {
! 455: case SASL_STOP:
! 456: *progress = SASL_DONE;
! 457: return result;
! 458: case SASL_PLAIN:
! 459: result = Curl_auth_create_plain_message(data, conn->sasl_authzid,
! 460: conn->user, conn->passwd,
! 461: &resp, &len);
! 462: break;
! 463: case SASL_LOGIN:
! 464: result = Curl_auth_create_login_message(data, conn->user, &resp, &len);
! 465: newstate = SASL_LOGIN_PASSWD;
! 466: break;
! 467: case SASL_LOGIN_PASSWD:
! 468: result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len);
! 469: break;
! 470: case SASL_EXTERNAL:
! 471: result = Curl_auth_create_external_message(data, conn->user, &resp, &len);
! 472: break;
! 473:
! 474: #ifndef CURL_DISABLE_CRYPTO_AUTH
! 475: case SASL_CRAMMD5:
! 476: sasl->params->getmessage(data->state.buffer, &serverdata);
! 477: result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen);
! 478: if(!result)
! 479: result = Curl_auth_create_cram_md5_message(data, chlg, conn->user,
! 480: conn->passwd, &resp, &len);
! 481: free(chlg);
! 482: break;
! 483: case SASL_DIGESTMD5:
! 484: sasl->params->getmessage(data->state.buffer, &serverdata);
! 485: result = Curl_auth_create_digest_md5_message(data, serverdata,
! 486: conn->user, conn->passwd,
! 487: service,
! 488: &resp, &len);
! 489: newstate = SASL_DIGESTMD5_RESP;
! 490: break;
! 491: case SASL_DIGESTMD5_RESP:
! 492: resp = strdup("");
! 493: if(!resp)
! 494: result = CURLE_OUT_OF_MEMORY;
! 495: break;
! 496: #endif
! 497:
! 498: #ifdef USE_NTLM
! 499: case SASL_NTLM:
! 500: /* Create the type-1 message */
! 501: result = Curl_auth_create_ntlm_type1_message(data,
! 502: conn->user, conn->passwd,
! 503: service, hostname,
! 504: &conn->ntlm, &resp, &len);
! 505: newstate = SASL_NTLM_TYPE2MSG;
! 506: break;
! 507: case SASL_NTLM_TYPE2MSG:
! 508: /* Decode the type-2 message */
! 509: sasl->params->getmessage(data->state.buffer, &serverdata);
! 510: result = Curl_auth_decode_ntlm_type2_message(data, serverdata,
! 511: &conn->ntlm);
! 512: if(!result)
! 513: result = Curl_auth_create_ntlm_type3_message(data, conn->user,
! 514: conn->passwd, &conn->ntlm,
! 515: &resp, &len);
! 516: break;
! 517: #endif
! 518:
! 519: #if defined(USE_KERBEROS5)
! 520: case SASL_GSSAPI:
! 521: result = Curl_auth_create_gssapi_user_message(data, conn->user,
! 522: conn->passwd,
! 523: service,
! 524: data->conn->host.name,
! 525: sasl->mutual_auth, NULL,
! 526: &conn->krb5,
! 527: &resp, &len);
! 528: newstate = SASL_GSSAPI_TOKEN;
! 529: break;
! 530: case SASL_GSSAPI_TOKEN:
! 531: sasl->params->getmessage(data->state.buffer, &serverdata);
! 532: if(sasl->mutual_auth) {
! 533: /* Decode the user token challenge and create the optional response
! 534: message */
! 535: result = Curl_auth_create_gssapi_user_message(data, NULL, NULL,
! 536: NULL, NULL,
! 537: sasl->mutual_auth,
! 538: serverdata, &conn->krb5,
! 539: &resp, &len);
! 540: newstate = SASL_GSSAPI_NO_DATA;
! 541: }
! 542: else
! 543: /* Decode the security challenge and create the response message */
! 544: result = Curl_auth_create_gssapi_security_message(data, serverdata,
! 545: &conn->krb5,
! 546: &resp, &len);
! 547: break;
! 548: case SASL_GSSAPI_NO_DATA:
! 549: sasl->params->getmessage(data->state.buffer, &serverdata);
! 550: /* Decode the security challenge and create the response message */
! 551: result = Curl_auth_create_gssapi_security_message(data, serverdata,
! 552: &conn->krb5,
! 553: &resp, &len);
! 554: break;
! 555: #endif
! 556:
! 557: case SASL_OAUTH2:
! 558: /* Create the authorisation message */
! 559: if(sasl->authused == SASL_MECH_OAUTHBEARER) {
! 560: result = Curl_auth_create_oauth_bearer_message(data, conn->user,
! 561: hostname,
! 562: port,
! 563: oauth_bearer,
! 564: &resp, &len);
! 565:
! 566: /* Failures maybe sent by the server as continuations for OAUTHBEARER */
! 567: newstate = SASL_OAUTH2_RESP;
! 568: }
! 569: else
! 570: result = Curl_auth_create_xoauth_bearer_message(data, conn->user,
! 571: oauth_bearer,
! 572: &resp, &len);
! 573: break;
! 574:
! 575: case SASL_OAUTH2_RESP:
! 576: /* The continuation is optional so check the response code */
! 577: if(code == sasl->params->finalcode) {
! 578: /* Final response was received so we are done */
! 579: *progress = SASL_DONE;
! 580: state(sasl, conn, SASL_STOP);
! 581: return result;
! 582: }
! 583: else if(code == sasl->params->contcode) {
! 584: /* Acknowledge the continuation by sending a 0x01 response base64
! 585: encoded */
! 586: resp = strdup("AQ==");
! 587: if(!resp)
! 588: result = CURLE_OUT_OF_MEMORY;
! 589: break;
! 590: }
! 591: else {
! 592: *progress = SASL_DONE;
! 593: state(sasl, conn, SASL_STOP);
! 594: return CURLE_LOGIN_DENIED;
! 595: }
! 596:
! 597: case SASL_CANCEL:
! 598: /* Remove the offending mechanism from the supported list */
! 599: sasl->authmechs ^= sasl->authused;
! 600:
! 601: /* Start an alternative SASL authentication */
! 602: result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress);
! 603: newstate = sasl->state; /* Use state from Curl_sasl_start() */
! 604: break;
! 605: default:
! 606: failf(data, "Unsupported SASL authentication mechanism");
! 607: result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */
! 608: break;
! 609: }
! 610:
! 611: switch(result) {
! 612: case CURLE_BAD_CONTENT_ENCODING:
! 613: /* Cancel dialog */
! 614: result = sasl->params->sendcont(conn, "*");
! 615: newstate = SASL_CANCEL;
! 616: break;
! 617: case CURLE_OK:
! 618: if(resp)
! 619: result = sasl->params->sendcont(conn, resp);
! 620: break;
! 621: default:
! 622: newstate = SASL_STOP; /* Stop on error */
! 623: *progress = SASL_DONE;
! 624: break;
! 625: }
! 626:
! 627: free(resp);
! 628:
! 629: state(sasl, conn, newstate);
! 630:
! 631: return result;
! 632: }
! 633: #endif /* protocols are enabled that use SASL */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>