113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci * RFC2195 CRAM-MD5 authentication 2413498266Sopenharmony_ci * RFC2617 Basic and Digest Access Authentication 2513498266Sopenharmony_ci * RFC2831 DIGEST-MD5 authentication 2613498266Sopenharmony_ci * RFC4422 Simple Authentication and Security Layer (SASL) 2713498266Sopenharmony_ci * RFC4616 PLAIN authentication 2813498266Sopenharmony_ci * RFC5802 SCRAM-SHA-1 authentication 2913498266Sopenharmony_ci * RFC7677 SCRAM-SHA-256 authentication 3013498266Sopenharmony_ci * RFC6749 OAuth 2.0 Authorization Framework 3113498266Sopenharmony_ci * RFC7628 A Set of SASL Mechanisms for OAuth 3213498266Sopenharmony_ci * Draft LOGIN SASL Mechanism <draft-murchison-sasl-login-00.txt> 3313498266Sopenharmony_ci * 3413498266Sopenharmony_ci ***************************************************************************/ 3513498266Sopenharmony_ci 3613498266Sopenharmony_ci#include "curl_setup.h" 3713498266Sopenharmony_ci 3813498266Sopenharmony_ci#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ 3913498266Sopenharmony_ci !defined(CURL_DISABLE_POP3) || \ 4013498266Sopenharmony_ci (!defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)) 4113498266Sopenharmony_ci 4213498266Sopenharmony_ci#include <curl/curl.h> 4313498266Sopenharmony_ci#include "urldata.h" 4413498266Sopenharmony_ci 4513498266Sopenharmony_ci#include "curl_base64.h" 4613498266Sopenharmony_ci#include "curl_md5.h" 4713498266Sopenharmony_ci#include "vauth/vauth.h" 4813498266Sopenharmony_ci#include "cfilters.h" 4913498266Sopenharmony_ci#include "vtls/vtls.h" 5013498266Sopenharmony_ci#include "curl_hmac.h" 5113498266Sopenharmony_ci#include "curl_sasl.h" 5213498266Sopenharmony_ci#include "warnless.h" 5313498266Sopenharmony_ci#include "strtok.h" 5413498266Sopenharmony_ci#include "sendf.h" 5513498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 5613498266Sopenharmony_ci#include "curl_printf.h" 5713498266Sopenharmony_ci#include "curl_memory.h" 5813498266Sopenharmony_ci#include "memdebug.h" 5913498266Sopenharmony_ci 6013498266Sopenharmony_ci/* Supported mechanisms */ 6113498266Sopenharmony_cistatic const struct { 6213498266Sopenharmony_ci const char *name; /* Name */ 6313498266Sopenharmony_ci size_t len; /* Name length */ 6413498266Sopenharmony_ci unsigned short bit; /* Flag bit */ 6513498266Sopenharmony_ci} mechtable[] = { 6613498266Sopenharmony_ci { "LOGIN", 5, SASL_MECH_LOGIN }, 6713498266Sopenharmony_ci { "PLAIN", 5, SASL_MECH_PLAIN }, 6813498266Sopenharmony_ci { "CRAM-MD5", 8, SASL_MECH_CRAM_MD5 }, 6913498266Sopenharmony_ci { "DIGEST-MD5", 10, SASL_MECH_DIGEST_MD5 }, 7013498266Sopenharmony_ci { "GSSAPI", 6, SASL_MECH_GSSAPI }, 7113498266Sopenharmony_ci { "EXTERNAL", 8, SASL_MECH_EXTERNAL }, 7213498266Sopenharmony_ci { "NTLM", 4, SASL_MECH_NTLM }, 7313498266Sopenharmony_ci { "XOAUTH2", 7, SASL_MECH_XOAUTH2 }, 7413498266Sopenharmony_ci { "OAUTHBEARER", 11, SASL_MECH_OAUTHBEARER }, 7513498266Sopenharmony_ci { "SCRAM-SHA-1", 11, SASL_MECH_SCRAM_SHA_1 }, 7613498266Sopenharmony_ci { "SCRAM-SHA-256",13, SASL_MECH_SCRAM_SHA_256 }, 7713498266Sopenharmony_ci { ZERO_NULL, 0, 0 } 7813498266Sopenharmony_ci}; 7913498266Sopenharmony_ci 8013498266Sopenharmony_ci/* 8113498266Sopenharmony_ci * Curl_sasl_cleanup() 8213498266Sopenharmony_ci * 8313498266Sopenharmony_ci * This is used to cleanup any libraries or curl modules used by the sasl 8413498266Sopenharmony_ci * functions. 8513498266Sopenharmony_ci * 8613498266Sopenharmony_ci * Parameters: 8713498266Sopenharmony_ci * 8813498266Sopenharmony_ci * conn [in] - The connection data. 8913498266Sopenharmony_ci * authused [in] - The authentication mechanism used. 9013498266Sopenharmony_ci */ 9113498266Sopenharmony_civoid Curl_sasl_cleanup(struct connectdata *conn, unsigned short authused) 9213498266Sopenharmony_ci{ 9313498266Sopenharmony_ci (void)conn; 9413498266Sopenharmony_ci (void)authused; 9513498266Sopenharmony_ci 9613498266Sopenharmony_ci#if defined(USE_KERBEROS5) 9713498266Sopenharmony_ci /* Cleanup the gssapi structure */ 9813498266Sopenharmony_ci if(authused == SASL_MECH_GSSAPI) { 9913498266Sopenharmony_ci Curl_auth_cleanup_gssapi(&conn->krb5); 10013498266Sopenharmony_ci } 10113498266Sopenharmony_ci#endif 10213498266Sopenharmony_ci 10313498266Sopenharmony_ci#if defined(USE_GSASL) 10413498266Sopenharmony_ci /* Cleanup the GSASL structure */ 10513498266Sopenharmony_ci if(authused & (SASL_MECH_SCRAM_SHA_1 | SASL_MECH_SCRAM_SHA_256)) { 10613498266Sopenharmony_ci Curl_auth_gsasl_cleanup(&conn->gsasl); 10713498266Sopenharmony_ci } 10813498266Sopenharmony_ci#endif 10913498266Sopenharmony_ci 11013498266Sopenharmony_ci#if defined(USE_NTLM) 11113498266Sopenharmony_ci /* Cleanup the NTLM structure */ 11213498266Sopenharmony_ci if(authused == SASL_MECH_NTLM) { 11313498266Sopenharmony_ci Curl_auth_cleanup_ntlm(&conn->ntlm); 11413498266Sopenharmony_ci } 11513498266Sopenharmony_ci#endif 11613498266Sopenharmony_ci} 11713498266Sopenharmony_ci 11813498266Sopenharmony_ci/* 11913498266Sopenharmony_ci * Curl_sasl_decode_mech() 12013498266Sopenharmony_ci * 12113498266Sopenharmony_ci * Convert a SASL mechanism name into a token. 12213498266Sopenharmony_ci * 12313498266Sopenharmony_ci * Parameters: 12413498266Sopenharmony_ci * 12513498266Sopenharmony_ci * ptr [in] - The mechanism string. 12613498266Sopenharmony_ci * maxlen [in] - Maximum mechanism string length. 12713498266Sopenharmony_ci * len [out] - If not NULL, effective name length. 12813498266Sopenharmony_ci * 12913498266Sopenharmony_ci * Returns the SASL mechanism token or 0 if no match. 13013498266Sopenharmony_ci */ 13113498266Sopenharmony_ciunsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen, 13213498266Sopenharmony_ci size_t *len) 13313498266Sopenharmony_ci{ 13413498266Sopenharmony_ci unsigned int i; 13513498266Sopenharmony_ci char c; 13613498266Sopenharmony_ci 13713498266Sopenharmony_ci for(i = 0; mechtable[i].name; i++) { 13813498266Sopenharmony_ci if(maxlen >= mechtable[i].len && 13913498266Sopenharmony_ci !memcmp(ptr, mechtable[i].name, mechtable[i].len)) { 14013498266Sopenharmony_ci if(len) 14113498266Sopenharmony_ci *len = mechtable[i].len; 14213498266Sopenharmony_ci 14313498266Sopenharmony_ci if(maxlen == mechtable[i].len) 14413498266Sopenharmony_ci return mechtable[i].bit; 14513498266Sopenharmony_ci 14613498266Sopenharmony_ci c = ptr[mechtable[i].len]; 14713498266Sopenharmony_ci if(!ISUPPER(c) && !ISDIGIT(c) && c != '-' && c != '_') 14813498266Sopenharmony_ci return mechtable[i].bit; 14913498266Sopenharmony_ci } 15013498266Sopenharmony_ci } 15113498266Sopenharmony_ci 15213498266Sopenharmony_ci return 0; 15313498266Sopenharmony_ci} 15413498266Sopenharmony_ci 15513498266Sopenharmony_ci/* 15613498266Sopenharmony_ci * Curl_sasl_parse_url_auth_option() 15713498266Sopenharmony_ci * 15813498266Sopenharmony_ci * Parse the URL login options. 15913498266Sopenharmony_ci */ 16013498266Sopenharmony_ciCURLcode Curl_sasl_parse_url_auth_option(struct SASL *sasl, 16113498266Sopenharmony_ci const char *value, size_t len) 16213498266Sopenharmony_ci{ 16313498266Sopenharmony_ci CURLcode result = CURLE_OK; 16413498266Sopenharmony_ci size_t mechlen; 16513498266Sopenharmony_ci 16613498266Sopenharmony_ci if(!len) 16713498266Sopenharmony_ci return CURLE_URL_MALFORMAT; 16813498266Sopenharmony_ci 16913498266Sopenharmony_ci if(sasl->resetprefs) { 17013498266Sopenharmony_ci sasl->resetprefs = FALSE; 17113498266Sopenharmony_ci sasl->prefmech = SASL_AUTH_NONE; 17213498266Sopenharmony_ci } 17313498266Sopenharmony_ci 17413498266Sopenharmony_ci if(!strncmp(value, "*", len)) 17513498266Sopenharmony_ci sasl->prefmech = SASL_AUTH_DEFAULT; 17613498266Sopenharmony_ci else { 17713498266Sopenharmony_ci unsigned short mechbit = Curl_sasl_decode_mech(value, len, &mechlen); 17813498266Sopenharmony_ci if(mechbit && mechlen == len) 17913498266Sopenharmony_ci sasl->prefmech |= mechbit; 18013498266Sopenharmony_ci else 18113498266Sopenharmony_ci result = CURLE_URL_MALFORMAT; 18213498266Sopenharmony_ci } 18313498266Sopenharmony_ci 18413498266Sopenharmony_ci return result; 18513498266Sopenharmony_ci} 18613498266Sopenharmony_ci 18713498266Sopenharmony_ci/* 18813498266Sopenharmony_ci * Curl_sasl_init() 18913498266Sopenharmony_ci * 19013498266Sopenharmony_ci * Initializes the SASL structure. 19113498266Sopenharmony_ci */ 19213498266Sopenharmony_civoid Curl_sasl_init(struct SASL *sasl, struct Curl_easy *data, 19313498266Sopenharmony_ci const struct SASLproto *params) 19413498266Sopenharmony_ci{ 19513498266Sopenharmony_ci unsigned long auth = data->set.httpauth; 19613498266Sopenharmony_ci 19713498266Sopenharmony_ci sasl->params = params; /* Set protocol dependent parameters */ 19813498266Sopenharmony_ci sasl->state = SASL_STOP; /* Not yet running */ 19913498266Sopenharmony_ci sasl->curmech = NULL; /* No mechanism yet. */ 20013498266Sopenharmony_ci sasl->authmechs = SASL_AUTH_NONE; /* No known authentication mechanism yet */ 20113498266Sopenharmony_ci sasl->prefmech = params->defmechs; /* Default preferred mechanisms */ 20213498266Sopenharmony_ci sasl->authused = SASL_AUTH_NONE; /* The authentication mechanism used */ 20313498266Sopenharmony_ci sasl->resetprefs = TRUE; /* Reset prefmech upon AUTH parsing. */ 20413498266Sopenharmony_ci sasl->mutual_auth = FALSE; /* No mutual authentication (GSSAPI only) */ 20513498266Sopenharmony_ci sasl->force_ir = FALSE; /* Respect external option */ 20613498266Sopenharmony_ci 20713498266Sopenharmony_ci if(auth != CURLAUTH_BASIC) { 20813498266Sopenharmony_ci unsigned short mechs = SASL_AUTH_NONE; 20913498266Sopenharmony_ci 21013498266Sopenharmony_ci /* If some usable http authentication options have been set, determine 21113498266Sopenharmony_ci new defaults from them. */ 21213498266Sopenharmony_ci if(auth & CURLAUTH_BASIC) 21313498266Sopenharmony_ci mechs |= SASL_MECH_PLAIN | SASL_MECH_LOGIN; 21413498266Sopenharmony_ci if(auth & CURLAUTH_DIGEST) 21513498266Sopenharmony_ci mechs |= SASL_MECH_DIGEST_MD5; 21613498266Sopenharmony_ci if(auth & CURLAUTH_NTLM) 21713498266Sopenharmony_ci mechs |= SASL_MECH_NTLM; 21813498266Sopenharmony_ci if(auth & CURLAUTH_BEARER) 21913498266Sopenharmony_ci mechs |= SASL_MECH_OAUTHBEARER | SASL_MECH_XOAUTH2; 22013498266Sopenharmony_ci if(auth & CURLAUTH_GSSAPI) 22113498266Sopenharmony_ci mechs |= SASL_MECH_GSSAPI; 22213498266Sopenharmony_ci 22313498266Sopenharmony_ci if(mechs != SASL_AUTH_NONE) 22413498266Sopenharmony_ci sasl->prefmech = mechs; 22513498266Sopenharmony_ci } 22613498266Sopenharmony_ci} 22713498266Sopenharmony_ci 22813498266Sopenharmony_ci/* 22913498266Sopenharmony_ci * sasl_state() 23013498266Sopenharmony_ci * 23113498266Sopenharmony_ci * This is the ONLY way to change SASL state! 23213498266Sopenharmony_ci */ 23313498266Sopenharmony_cistatic void sasl_state(struct SASL *sasl, struct Curl_easy *data, 23413498266Sopenharmony_ci saslstate newstate) 23513498266Sopenharmony_ci{ 23613498266Sopenharmony_ci#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 23713498266Sopenharmony_ci /* for debug purposes */ 23813498266Sopenharmony_ci static const char * const names[]={ 23913498266Sopenharmony_ci "STOP", 24013498266Sopenharmony_ci "PLAIN", 24113498266Sopenharmony_ci "LOGIN", 24213498266Sopenharmony_ci "LOGIN_PASSWD", 24313498266Sopenharmony_ci "EXTERNAL", 24413498266Sopenharmony_ci "CRAMMD5", 24513498266Sopenharmony_ci "DIGESTMD5", 24613498266Sopenharmony_ci "DIGESTMD5_RESP", 24713498266Sopenharmony_ci "NTLM", 24813498266Sopenharmony_ci "NTLM_TYPE2MSG", 24913498266Sopenharmony_ci "GSSAPI", 25013498266Sopenharmony_ci "GSSAPI_TOKEN", 25113498266Sopenharmony_ci "GSSAPI_NO_DATA", 25213498266Sopenharmony_ci "OAUTH2", 25313498266Sopenharmony_ci "OAUTH2_RESP", 25413498266Sopenharmony_ci "GSASL", 25513498266Sopenharmony_ci "CANCEL", 25613498266Sopenharmony_ci "FINAL", 25713498266Sopenharmony_ci /* LAST */ 25813498266Sopenharmony_ci }; 25913498266Sopenharmony_ci 26013498266Sopenharmony_ci if(sasl->state != newstate) 26113498266Sopenharmony_ci infof(data, "SASL %p state change from %s to %s", 26213498266Sopenharmony_ci (void *)sasl, names[sasl->state], names[newstate]); 26313498266Sopenharmony_ci#else 26413498266Sopenharmony_ci (void) data; 26513498266Sopenharmony_ci#endif 26613498266Sopenharmony_ci 26713498266Sopenharmony_ci sasl->state = newstate; 26813498266Sopenharmony_ci} 26913498266Sopenharmony_ci 27013498266Sopenharmony_ci#if defined(USE_NTLM) || defined(USE_GSASL) || defined(USE_KERBEROS5) || \ 27113498266Sopenharmony_ci !defined(CURL_DISABLE_DIGEST_AUTH) 27213498266Sopenharmony_ci/* Get the SASL server message and convert it to binary. */ 27313498266Sopenharmony_cistatic CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, 27413498266Sopenharmony_ci struct bufref *out) 27513498266Sopenharmony_ci{ 27613498266Sopenharmony_ci CURLcode result = CURLE_OK; 27713498266Sopenharmony_ci 27813498266Sopenharmony_ci result = sasl->params->getmessage(data, out); 27913498266Sopenharmony_ci if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) { 28013498266Sopenharmony_ci unsigned char *msg; 28113498266Sopenharmony_ci size_t msglen; 28213498266Sopenharmony_ci const char *serverdata = (const char *) Curl_bufref_ptr(out); 28313498266Sopenharmony_ci 28413498266Sopenharmony_ci if(!*serverdata || *serverdata == '=') 28513498266Sopenharmony_ci Curl_bufref_set(out, NULL, 0, NULL); 28613498266Sopenharmony_ci else { 28713498266Sopenharmony_ci result = Curl_base64_decode(serverdata, &msg, &msglen); 28813498266Sopenharmony_ci if(!result) 28913498266Sopenharmony_ci Curl_bufref_set(out, msg, msglen, curl_free); 29013498266Sopenharmony_ci } 29113498266Sopenharmony_ci } 29213498266Sopenharmony_ci return result; 29313498266Sopenharmony_ci} 29413498266Sopenharmony_ci#endif 29513498266Sopenharmony_ci 29613498266Sopenharmony_ci/* Encode the outgoing SASL message. */ 29713498266Sopenharmony_cistatic CURLcode build_message(struct SASL *sasl, struct bufref *msg) 29813498266Sopenharmony_ci{ 29913498266Sopenharmony_ci CURLcode result = CURLE_OK; 30013498266Sopenharmony_ci 30113498266Sopenharmony_ci if(sasl->params->flags & SASL_FLAG_BASE64) { 30213498266Sopenharmony_ci if(!Curl_bufref_ptr(msg)) /* Empty message. */ 30313498266Sopenharmony_ci Curl_bufref_set(msg, "", 0, NULL); 30413498266Sopenharmony_ci else if(!Curl_bufref_len(msg)) /* Explicit empty response. */ 30513498266Sopenharmony_ci Curl_bufref_set(msg, "=", 1, NULL); 30613498266Sopenharmony_ci else { 30713498266Sopenharmony_ci char *base64; 30813498266Sopenharmony_ci size_t base64len; 30913498266Sopenharmony_ci 31013498266Sopenharmony_ci result = Curl_base64_encode((const char *) Curl_bufref_ptr(msg), 31113498266Sopenharmony_ci Curl_bufref_len(msg), &base64, &base64len); 31213498266Sopenharmony_ci if(!result) 31313498266Sopenharmony_ci Curl_bufref_set(msg, base64, base64len, curl_free); 31413498266Sopenharmony_ci } 31513498266Sopenharmony_ci } 31613498266Sopenharmony_ci 31713498266Sopenharmony_ci return result; 31813498266Sopenharmony_ci} 31913498266Sopenharmony_ci 32013498266Sopenharmony_ci/* 32113498266Sopenharmony_ci * Curl_sasl_can_authenticate() 32213498266Sopenharmony_ci * 32313498266Sopenharmony_ci * Check if we have enough auth data and capabilities to authenticate. 32413498266Sopenharmony_ci */ 32513498266Sopenharmony_cibool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data) 32613498266Sopenharmony_ci{ 32713498266Sopenharmony_ci /* Have credentials been provided? */ 32813498266Sopenharmony_ci if(data->state.aptr.user) 32913498266Sopenharmony_ci return TRUE; 33013498266Sopenharmony_ci 33113498266Sopenharmony_ci /* EXTERNAL can authenticate without a user name and/or password */ 33213498266Sopenharmony_ci if(sasl->authmechs & sasl->prefmech & SASL_MECH_EXTERNAL) 33313498266Sopenharmony_ci return TRUE; 33413498266Sopenharmony_ci 33513498266Sopenharmony_ci return FALSE; 33613498266Sopenharmony_ci} 33713498266Sopenharmony_ci 33813498266Sopenharmony_ci/* 33913498266Sopenharmony_ci * Curl_sasl_start() 34013498266Sopenharmony_ci * 34113498266Sopenharmony_ci * Calculate the required login details for SASL authentication. 34213498266Sopenharmony_ci */ 34313498266Sopenharmony_ciCURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, 34413498266Sopenharmony_ci bool force_ir, saslprogress *progress) 34513498266Sopenharmony_ci{ 34613498266Sopenharmony_ci CURLcode result = CURLE_OK; 34713498266Sopenharmony_ci struct connectdata *conn = data->conn; 34813498266Sopenharmony_ci unsigned short enabledmechs; 34913498266Sopenharmony_ci const char *mech = NULL; 35013498266Sopenharmony_ci struct bufref resp; 35113498266Sopenharmony_ci saslstate state1 = SASL_STOP; 35213498266Sopenharmony_ci saslstate state2 = SASL_FINAL; 35313498266Sopenharmony_ci const char *hostname, *disp_hostname; 35413498266Sopenharmony_ci int port; 35513498266Sopenharmony_ci#if defined(USE_KERBEROS5) || defined(USE_NTLM) 35613498266Sopenharmony_ci const char *service = data->set.str[STRING_SERVICE_NAME] ? 35713498266Sopenharmony_ci data->set.str[STRING_SERVICE_NAME] : 35813498266Sopenharmony_ci sasl->params->service; 35913498266Sopenharmony_ci#endif 36013498266Sopenharmony_ci const char *oauth_bearer = data->set.str[STRING_BEARER]; 36113498266Sopenharmony_ci struct bufref nullmsg; 36213498266Sopenharmony_ci 36313498266Sopenharmony_ci Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port); 36413498266Sopenharmony_ci Curl_bufref_init(&nullmsg); 36513498266Sopenharmony_ci Curl_bufref_init(&resp); 36613498266Sopenharmony_ci sasl->force_ir = force_ir; /* Latch for future use */ 36713498266Sopenharmony_ci sasl->authused = 0; /* No mechanism used yet */ 36813498266Sopenharmony_ci enabledmechs = sasl->authmechs & sasl->prefmech; 36913498266Sopenharmony_ci *progress = SASL_IDLE; 37013498266Sopenharmony_ci 37113498266Sopenharmony_ci /* Calculate the supported authentication mechanism, by decreasing order of 37213498266Sopenharmony_ci security, as well as the initial response where appropriate */ 37313498266Sopenharmony_ci if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) { 37413498266Sopenharmony_ci mech = SASL_MECH_STRING_EXTERNAL; 37513498266Sopenharmony_ci state1 = SASL_EXTERNAL; 37613498266Sopenharmony_ci sasl->authused = SASL_MECH_EXTERNAL; 37713498266Sopenharmony_ci 37813498266Sopenharmony_ci if(force_ir || data->set.sasl_ir) 37913498266Sopenharmony_ci result = Curl_auth_create_external_message(conn->user, &resp); 38013498266Sopenharmony_ci } 38113498266Sopenharmony_ci else if(data->state.aptr.user) { 38213498266Sopenharmony_ci#if defined(USE_KERBEROS5) 38313498266Sopenharmony_ci if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() && 38413498266Sopenharmony_ci Curl_auth_user_contains_domain(conn->user)) { 38513498266Sopenharmony_ci sasl->mutual_auth = FALSE; 38613498266Sopenharmony_ci mech = SASL_MECH_STRING_GSSAPI; 38713498266Sopenharmony_ci state1 = SASL_GSSAPI; 38813498266Sopenharmony_ci state2 = SASL_GSSAPI_TOKEN; 38913498266Sopenharmony_ci sasl->authused = SASL_MECH_GSSAPI; 39013498266Sopenharmony_ci 39113498266Sopenharmony_ci if(force_ir || data->set.sasl_ir) 39213498266Sopenharmony_ci result = Curl_auth_create_gssapi_user_message(data, conn->user, 39313498266Sopenharmony_ci conn->passwd, 39413498266Sopenharmony_ci service, 39513498266Sopenharmony_ci conn->host.name, 39613498266Sopenharmony_ci sasl->mutual_auth, 39713498266Sopenharmony_ci NULL, &conn->krb5, 39813498266Sopenharmony_ci &resp); 39913498266Sopenharmony_ci } 40013498266Sopenharmony_ci else 40113498266Sopenharmony_ci#endif 40213498266Sopenharmony_ci#ifdef USE_GSASL 40313498266Sopenharmony_ci if((enabledmechs & SASL_MECH_SCRAM_SHA_256) && 40413498266Sopenharmony_ci Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256, 40513498266Sopenharmony_ci &conn->gsasl)) { 40613498266Sopenharmony_ci mech = SASL_MECH_STRING_SCRAM_SHA_256; 40713498266Sopenharmony_ci sasl->authused = SASL_MECH_SCRAM_SHA_256; 40813498266Sopenharmony_ci state1 = SASL_GSASL; 40913498266Sopenharmony_ci state2 = SASL_GSASL; 41013498266Sopenharmony_ci 41113498266Sopenharmony_ci result = Curl_auth_gsasl_start(data, conn->user, 41213498266Sopenharmony_ci conn->passwd, &conn->gsasl); 41313498266Sopenharmony_ci if(result == CURLE_OK && (force_ir || data->set.sasl_ir)) 41413498266Sopenharmony_ci result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp); 41513498266Sopenharmony_ci } 41613498266Sopenharmony_ci else if((enabledmechs & SASL_MECH_SCRAM_SHA_1) && 41713498266Sopenharmony_ci Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1, 41813498266Sopenharmony_ci &conn->gsasl)) { 41913498266Sopenharmony_ci mech = SASL_MECH_STRING_SCRAM_SHA_1; 42013498266Sopenharmony_ci sasl->authused = SASL_MECH_SCRAM_SHA_1; 42113498266Sopenharmony_ci state1 = SASL_GSASL; 42213498266Sopenharmony_ci state2 = SASL_GSASL; 42313498266Sopenharmony_ci 42413498266Sopenharmony_ci result = Curl_auth_gsasl_start(data, conn->user, 42513498266Sopenharmony_ci conn->passwd, &conn->gsasl); 42613498266Sopenharmony_ci if(result == CURLE_OK && (force_ir || data->set.sasl_ir)) 42713498266Sopenharmony_ci result = Curl_auth_gsasl_token(data, &nullmsg, &conn->gsasl, &resp); 42813498266Sopenharmony_ci } 42913498266Sopenharmony_ci else 43013498266Sopenharmony_ci#endif 43113498266Sopenharmony_ci#ifndef CURL_DISABLE_DIGEST_AUTH 43213498266Sopenharmony_ci if((enabledmechs & SASL_MECH_DIGEST_MD5) && 43313498266Sopenharmony_ci Curl_auth_is_digest_supported()) { 43413498266Sopenharmony_ci mech = SASL_MECH_STRING_DIGEST_MD5; 43513498266Sopenharmony_ci state1 = SASL_DIGESTMD5; 43613498266Sopenharmony_ci sasl->authused = SASL_MECH_DIGEST_MD5; 43713498266Sopenharmony_ci } 43813498266Sopenharmony_ci else if(enabledmechs & SASL_MECH_CRAM_MD5) { 43913498266Sopenharmony_ci mech = SASL_MECH_STRING_CRAM_MD5; 44013498266Sopenharmony_ci state1 = SASL_CRAMMD5; 44113498266Sopenharmony_ci sasl->authused = SASL_MECH_CRAM_MD5; 44213498266Sopenharmony_ci } 44313498266Sopenharmony_ci else 44413498266Sopenharmony_ci#endif 44513498266Sopenharmony_ci#ifdef USE_NTLM 44613498266Sopenharmony_ci if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) { 44713498266Sopenharmony_ci mech = SASL_MECH_STRING_NTLM; 44813498266Sopenharmony_ci state1 = SASL_NTLM; 44913498266Sopenharmony_ci state2 = SASL_NTLM_TYPE2MSG; 45013498266Sopenharmony_ci sasl->authused = SASL_MECH_NTLM; 45113498266Sopenharmony_ci 45213498266Sopenharmony_ci if(force_ir || data->set.sasl_ir) 45313498266Sopenharmony_ci result = Curl_auth_create_ntlm_type1_message(data, 45413498266Sopenharmony_ci conn->user, conn->passwd, 45513498266Sopenharmony_ci service, 45613498266Sopenharmony_ci hostname, 45713498266Sopenharmony_ci &conn->ntlm, &resp); 45813498266Sopenharmony_ci } 45913498266Sopenharmony_ci else 46013498266Sopenharmony_ci#endif 46113498266Sopenharmony_ci if((enabledmechs & SASL_MECH_OAUTHBEARER) && oauth_bearer) { 46213498266Sopenharmony_ci mech = SASL_MECH_STRING_OAUTHBEARER; 46313498266Sopenharmony_ci state1 = SASL_OAUTH2; 46413498266Sopenharmony_ci state2 = SASL_OAUTH2_RESP; 46513498266Sopenharmony_ci sasl->authused = SASL_MECH_OAUTHBEARER; 46613498266Sopenharmony_ci 46713498266Sopenharmony_ci if(force_ir || data->set.sasl_ir) 46813498266Sopenharmony_ci result = Curl_auth_create_oauth_bearer_message(conn->user, 46913498266Sopenharmony_ci hostname, 47013498266Sopenharmony_ci port, 47113498266Sopenharmony_ci oauth_bearer, 47213498266Sopenharmony_ci &resp); 47313498266Sopenharmony_ci } 47413498266Sopenharmony_ci else if((enabledmechs & SASL_MECH_XOAUTH2) && oauth_bearer) { 47513498266Sopenharmony_ci mech = SASL_MECH_STRING_XOAUTH2; 47613498266Sopenharmony_ci state1 = SASL_OAUTH2; 47713498266Sopenharmony_ci sasl->authused = SASL_MECH_XOAUTH2; 47813498266Sopenharmony_ci 47913498266Sopenharmony_ci if(force_ir || data->set.sasl_ir) 48013498266Sopenharmony_ci result = Curl_auth_create_xoauth_bearer_message(conn->user, 48113498266Sopenharmony_ci oauth_bearer, 48213498266Sopenharmony_ci &resp); 48313498266Sopenharmony_ci } 48413498266Sopenharmony_ci else if(enabledmechs & SASL_MECH_PLAIN) { 48513498266Sopenharmony_ci mech = SASL_MECH_STRING_PLAIN; 48613498266Sopenharmony_ci state1 = SASL_PLAIN; 48713498266Sopenharmony_ci sasl->authused = SASL_MECH_PLAIN; 48813498266Sopenharmony_ci 48913498266Sopenharmony_ci if(force_ir || data->set.sasl_ir) 49013498266Sopenharmony_ci result = Curl_auth_create_plain_message(conn->sasl_authzid, 49113498266Sopenharmony_ci conn->user, conn->passwd, 49213498266Sopenharmony_ci &resp); 49313498266Sopenharmony_ci } 49413498266Sopenharmony_ci else if(enabledmechs & SASL_MECH_LOGIN) { 49513498266Sopenharmony_ci mech = SASL_MECH_STRING_LOGIN; 49613498266Sopenharmony_ci state1 = SASL_LOGIN; 49713498266Sopenharmony_ci state2 = SASL_LOGIN_PASSWD; 49813498266Sopenharmony_ci sasl->authused = SASL_MECH_LOGIN; 49913498266Sopenharmony_ci 50013498266Sopenharmony_ci if(force_ir || data->set.sasl_ir) 50113498266Sopenharmony_ci result = Curl_auth_create_login_message(conn->user, &resp); 50213498266Sopenharmony_ci } 50313498266Sopenharmony_ci } 50413498266Sopenharmony_ci 50513498266Sopenharmony_ci if(!result && mech) { 50613498266Sopenharmony_ci sasl->curmech = mech; 50713498266Sopenharmony_ci if(Curl_bufref_ptr(&resp)) 50813498266Sopenharmony_ci result = build_message(sasl, &resp); 50913498266Sopenharmony_ci 51013498266Sopenharmony_ci if(sasl->params->maxirlen && 51113498266Sopenharmony_ci strlen(mech) + Curl_bufref_len(&resp) > sasl->params->maxirlen) 51213498266Sopenharmony_ci Curl_bufref_free(&resp); 51313498266Sopenharmony_ci 51413498266Sopenharmony_ci if(!result) 51513498266Sopenharmony_ci result = sasl->params->sendauth(data, mech, &resp); 51613498266Sopenharmony_ci 51713498266Sopenharmony_ci if(!result) { 51813498266Sopenharmony_ci *progress = SASL_INPROGRESS; 51913498266Sopenharmony_ci sasl_state(sasl, data, Curl_bufref_ptr(&resp) ? state2 : state1); 52013498266Sopenharmony_ci } 52113498266Sopenharmony_ci } 52213498266Sopenharmony_ci 52313498266Sopenharmony_ci Curl_bufref_free(&resp); 52413498266Sopenharmony_ci return result; 52513498266Sopenharmony_ci} 52613498266Sopenharmony_ci 52713498266Sopenharmony_ci/* 52813498266Sopenharmony_ci * Curl_sasl_continue() 52913498266Sopenharmony_ci * 53013498266Sopenharmony_ci * Continue the authentication. 53113498266Sopenharmony_ci */ 53213498266Sopenharmony_ciCURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, 53313498266Sopenharmony_ci int code, saslprogress *progress) 53413498266Sopenharmony_ci{ 53513498266Sopenharmony_ci CURLcode result = CURLE_OK; 53613498266Sopenharmony_ci struct connectdata *conn = data->conn; 53713498266Sopenharmony_ci saslstate newstate = SASL_FINAL; 53813498266Sopenharmony_ci struct bufref resp; 53913498266Sopenharmony_ci const char *hostname, *disp_hostname; 54013498266Sopenharmony_ci int port; 54113498266Sopenharmony_ci#if defined(USE_KERBEROS5) || defined(USE_NTLM) \ 54213498266Sopenharmony_ci || !defined(CURL_DISABLE_DIGEST_AUTH) 54313498266Sopenharmony_ci const char *service = data->set.str[STRING_SERVICE_NAME] ? 54413498266Sopenharmony_ci data->set.str[STRING_SERVICE_NAME] : 54513498266Sopenharmony_ci sasl->params->service; 54613498266Sopenharmony_ci#endif 54713498266Sopenharmony_ci const char *oauth_bearer = data->set.str[STRING_BEARER]; 54813498266Sopenharmony_ci struct bufref serverdata; 54913498266Sopenharmony_ci 55013498266Sopenharmony_ci Curl_conn_get_host(data, FIRSTSOCKET, &hostname, &disp_hostname, &port); 55113498266Sopenharmony_ci Curl_bufref_init(&serverdata); 55213498266Sopenharmony_ci Curl_bufref_init(&resp); 55313498266Sopenharmony_ci *progress = SASL_INPROGRESS; 55413498266Sopenharmony_ci 55513498266Sopenharmony_ci if(sasl->state == SASL_FINAL) { 55613498266Sopenharmony_ci if(code != sasl->params->finalcode) 55713498266Sopenharmony_ci result = CURLE_LOGIN_DENIED; 55813498266Sopenharmony_ci *progress = SASL_DONE; 55913498266Sopenharmony_ci sasl_state(sasl, data, SASL_STOP); 56013498266Sopenharmony_ci return result; 56113498266Sopenharmony_ci } 56213498266Sopenharmony_ci 56313498266Sopenharmony_ci if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP && 56413498266Sopenharmony_ci code != sasl->params->contcode) { 56513498266Sopenharmony_ci *progress = SASL_DONE; 56613498266Sopenharmony_ci sasl_state(sasl, data, SASL_STOP); 56713498266Sopenharmony_ci return CURLE_LOGIN_DENIED; 56813498266Sopenharmony_ci } 56913498266Sopenharmony_ci 57013498266Sopenharmony_ci switch(sasl->state) { 57113498266Sopenharmony_ci case SASL_STOP: 57213498266Sopenharmony_ci *progress = SASL_DONE; 57313498266Sopenharmony_ci return result; 57413498266Sopenharmony_ci case SASL_PLAIN: 57513498266Sopenharmony_ci result = Curl_auth_create_plain_message(conn->sasl_authzid, 57613498266Sopenharmony_ci conn->user, conn->passwd, &resp); 57713498266Sopenharmony_ci break; 57813498266Sopenharmony_ci case SASL_LOGIN: 57913498266Sopenharmony_ci result = Curl_auth_create_login_message(conn->user, &resp); 58013498266Sopenharmony_ci newstate = SASL_LOGIN_PASSWD; 58113498266Sopenharmony_ci break; 58213498266Sopenharmony_ci case SASL_LOGIN_PASSWD: 58313498266Sopenharmony_ci result = Curl_auth_create_login_message(conn->passwd, &resp); 58413498266Sopenharmony_ci break; 58513498266Sopenharmony_ci case SASL_EXTERNAL: 58613498266Sopenharmony_ci result = Curl_auth_create_external_message(conn->user, &resp); 58713498266Sopenharmony_ci break; 58813498266Sopenharmony_ci#ifdef USE_GSASL 58913498266Sopenharmony_ci case SASL_GSASL: 59013498266Sopenharmony_ci result = get_server_message(sasl, data, &serverdata); 59113498266Sopenharmony_ci if(!result) 59213498266Sopenharmony_ci result = Curl_auth_gsasl_token(data, &serverdata, &conn->gsasl, &resp); 59313498266Sopenharmony_ci if(!result && Curl_bufref_len(&resp) > 0) 59413498266Sopenharmony_ci newstate = SASL_GSASL; 59513498266Sopenharmony_ci break; 59613498266Sopenharmony_ci#endif 59713498266Sopenharmony_ci#ifndef CURL_DISABLE_DIGEST_AUTH 59813498266Sopenharmony_ci case SASL_CRAMMD5: 59913498266Sopenharmony_ci result = get_server_message(sasl, data, &serverdata); 60013498266Sopenharmony_ci if(!result) 60113498266Sopenharmony_ci result = Curl_auth_create_cram_md5_message(&serverdata, conn->user, 60213498266Sopenharmony_ci conn->passwd, &resp); 60313498266Sopenharmony_ci break; 60413498266Sopenharmony_ci case SASL_DIGESTMD5: 60513498266Sopenharmony_ci result = get_server_message(sasl, data, &serverdata); 60613498266Sopenharmony_ci if(!result) 60713498266Sopenharmony_ci result = Curl_auth_create_digest_md5_message(data, &serverdata, 60813498266Sopenharmony_ci conn->user, conn->passwd, 60913498266Sopenharmony_ci service, &resp); 61013498266Sopenharmony_ci if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) 61113498266Sopenharmony_ci newstate = SASL_DIGESTMD5_RESP; 61213498266Sopenharmony_ci break; 61313498266Sopenharmony_ci case SASL_DIGESTMD5_RESP: 61413498266Sopenharmony_ci /* Keep response NULL to output an empty line. */ 61513498266Sopenharmony_ci break; 61613498266Sopenharmony_ci#endif 61713498266Sopenharmony_ci 61813498266Sopenharmony_ci#ifdef USE_NTLM 61913498266Sopenharmony_ci case SASL_NTLM: 62013498266Sopenharmony_ci /* Create the type-1 message */ 62113498266Sopenharmony_ci result = Curl_auth_create_ntlm_type1_message(data, 62213498266Sopenharmony_ci conn->user, conn->passwd, 62313498266Sopenharmony_ci service, hostname, 62413498266Sopenharmony_ci &conn->ntlm, &resp); 62513498266Sopenharmony_ci newstate = SASL_NTLM_TYPE2MSG; 62613498266Sopenharmony_ci break; 62713498266Sopenharmony_ci case SASL_NTLM_TYPE2MSG: 62813498266Sopenharmony_ci /* Decode the type-2 message */ 62913498266Sopenharmony_ci result = get_server_message(sasl, data, &serverdata); 63013498266Sopenharmony_ci if(!result) 63113498266Sopenharmony_ci result = Curl_auth_decode_ntlm_type2_message(data, &serverdata, 63213498266Sopenharmony_ci &conn->ntlm); 63313498266Sopenharmony_ci if(!result) 63413498266Sopenharmony_ci result = Curl_auth_create_ntlm_type3_message(data, conn->user, 63513498266Sopenharmony_ci conn->passwd, &conn->ntlm, 63613498266Sopenharmony_ci &resp); 63713498266Sopenharmony_ci break; 63813498266Sopenharmony_ci#endif 63913498266Sopenharmony_ci 64013498266Sopenharmony_ci#if defined(USE_KERBEROS5) 64113498266Sopenharmony_ci case SASL_GSSAPI: 64213498266Sopenharmony_ci result = Curl_auth_create_gssapi_user_message(data, conn->user, 64313498266Sopenharmony_ci conn->passwd, 64413498266Sopenharmony_ci service, 64513498266Sopenharmony_ci conn->host.name, 64613498266Sopenharmony_ci sasl->mutual_auth, NULL, 64713498266Sopenharmony_ci &conn->krb5, 64813498266Sopenharmony_ci &resp); 64913498266Sopenharmony_ci newstate = SASL_GSSAPI_TOKEN; 65013498266Sopenharmony_ci break; 65113498266Sopenharmony_ci case SASL_GSSAPI_TOKEN: 65213498266Sopenharmony_ci result = get_server_message(sasl, data, &serverdata); 65313498266Sopenharmony_ci if(!result) { 65413498266Sopenharmony_ci if(sasl->mutual_auth) { 65513498266Sopenharmony_ci /* Decode the user token challenge and create the optional response 65613498266Sopenharmony_ci message */ 65713498266Sopenharmony_ci result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, 65813498266Sopenharmony_ci NULL, NULL, 65913498266Sopenharmony_ci sasl->mutual_auth, 66013498266Sopenharmony_ci &serverdata, 66113498266Sopenharmony_ci &conn->krb5, 66213498266Sopenharmony_ci &resp); 66313498266Sopenharmony_ci newstate = SASL_GSSAPI_NO_DATA; 66413498266Sopenharmony_ci } 66513498266Sopenharmony_ci else 66613498266Sopenharmony_ci /* Decode the security challenge and create the response message */ 66713498266Sopenharmony_ci result = Curl_auth_create_gssapi_security_message(data, 66813498266Sopenharmony_ci conn->sasl_authzid, 66913498266Sopenharmony_ci &serverdata, 67013498266Sopenharmony_ci &conn->krb5, 67113498266Sopenharmony_ci &resp); 67213498266Sopenharmony_ci } 67313498266Sopenharmony_ci break; 67413498266Sopenharmony_ci case SASL_GSSAPI_NO_DATA: 67513498266Sopenharmony_ci /* Decode the security challenge and create the response message */ 67613498266Sopenharmony_ci result = get_server_message(sasl, data, &serverdata); 67713498266Sopenharmony_ci if(!result) 67813498266Sopenharmony_ci result = Curl_auth_create_gssapi_security_message(data, 67913498266Sopenharmony_ci conn->sasl_authzid, 68013498266Sopenharmony_ci &serverdata, 68113498266Sopenharmony_ci &conn->krb5, 68213498266Sopenharmony_ci &resp); 68313498266Sopenharmony_ci break; 68413498266Sopenharmony_ci#endif 68513498266Sopenharmony_ci 68613498266Sopenharmony_ci case SASL_OAUTH2: 68713498266Sopenharmony_ci /* Create the authorization message */ 68813498266Sopenharmony_ci if(sasl->authused == SASL_MECH_OAUTHBEARER) { 68913498266Sopenharmony_ci result = Curl_auth_create_oauth_bearer_message(conn->user, 69013498266Sopenharmony_ci hostname, 69113498266Sopenharmony_ci port, 69213498266Sopenharmony_ci oauth_bearer, 69313498266Sopenharmony_ci &resp); 69413498266Sopenharmony_ci 69513498266Sopenharmony_ci /* Failures maybe sent by the server as continuations for OAUTHBEARER */ 69613498266Sopenharmony_ci newstate = SASL_OAUTH2_RESP; 69713498266Sopenharmony_ci } 69813498266Sopenharmony_ci else 69913498266Sopenharmony_ci result = Curl_auth_create_xoauth_bearer_message(conn->user, 70013498266Sopenharmony_ci oauth_bearer, 70113498266Sopenharmony_ci &resp); 70213498266Sopenharmony_ci break; 70313498266Sopenharmony_ci 70413498266Sopenharmony_ci case SASL_OAUTH2_RESP: 70513498266Sopenharmony_ci /* The continuation is optional so check the response code */ 70613498266Sopenharmony_ci if(code == sasl->params->finalcode) { 70713498266Sopenharmony_ci /* Final response was received so we are done */ 70813498266Sopenharmony_ci *progress = SASL_DONE; 70913498266Sopenharmony_ci sasl_state(sasl, data, SASL_STOP); 71013498266Sopenharmony_ci return result; 71113498266Sopenharmony_ci } 71213498266Sopenharmony_ci else if(code == sasl->params->contcode) { 71313498266Sopenharmony_ci /* Acknowledge the continuation by sending a 0x01 response. */ 71413498266Sopenharmony_ci Curl_bufref_set(&resp, "\x01", 1, NULL); 71513498266Sopenharmony_ci break; 71613498266Sopenharmony_ci } 71713498266Sopenharmony_ci else { 71813498266Sopenharmony_ci *progress = SASL_DONE; 71913498266Sopenharmony_ci sasl_state(sasl, data, SASL_STOP); 72013498266Sopenharmony_ci return CURLE_LOGIN_DENIED; 72113498266Sopenharmony_ci } 72213498266Sopenharmony_ci 72313498266Sopenharmony_ci case SASL_CANCEL: 72413498266Sopenharmony_ci /* Remove the offending mechanism from the supported list */ 72513498266Sopenharmony_ci sasl->authmechs ^= sasl->authused; 72613498266Sopenharmony_ci 72713498266Sopenharmony_ci /* Start an alternative SASL authentication */ 72813498266Sopenharmony_ci return Curl_sasl_start(sasl, data, sasl->force_ir, progress); 72913498266Sopenharmony_ci default: 73013498266Sopenharmony_ci failf(data, "Unsupported SASL authentication mechanism"); 73113498266Sopenharmony_ci result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ 73213498266Sopenharmony_ci break; 73313498266Sopenharmony_ci } 73413498266Sopenharmony_ci 73513498266Sopenharmony_ci Curl_bufref_free(&serverdata); 73613498266Sopenharmony_ci 73713498266Sopenharmony_ci switch(result) { 73813498266Sopenharmony_ci case CURLE_BAD_CONTENT_ENCODING: 73913498266Sopenharmony_ci /* Cancel dialog */ 74013498266Sopenharmony_ci result = sasl->params->cancelauth(data, sasl->curmech); 74113498266Sopenharmony_ci newstate = SASL_CANCEL; 74213498266Sopenharmony_ci break; 74313498266Sopenharmony_ci case CURLE_OK: 74413498266Sopenharmony_ci result = build_message(sasl, &resp); 74513498266Sopenharmony_ci if(!result) 74613498266Sopenharmony_ci result = sasl->params->contauth(data, sasl->curmech, &resp); 74713498266Sopenharmony_ci break; 74813498266Sopenharmony_ci default: 74913498266Sopenharmony_ci newstate = SASL_STOP; /* Stop on error */ 75013498266Sopenharmony_ci *progress = SASL_DONE; 75113498266Sopenharmony_ci break; 75213498266Sopenharmony_ci } 75313498266Sopenharmony_ci 75413498266Sopenharmony_ci Curl_bufref_free(&resp); 75513498266Sopenharmony_ci 75613498266Sopenharmony_ci sasl_state(sasl, data, newstate); 75713498266Sopenharmony_ci 75813498266Sopenharmony_ci return result; 75913498266Sopenharmony_ci} 76013498266Sopenharmony_ci#endif /* protocols are enabled that use SASL */ 761