Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/curl/lib/curl_sasl.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*************************************************************************** | |
| 2 * _ _ ____ _ | |
| 3 * Project ___| | | | _ \| | | |
| 4 * / __| | | | |_) | | | |
| 5 * | (__| |_| | _ <| |___ | |
| 6 * \___|\___/|_| \_\_____| | |
| 7 * | |
| 8 * Copyright (C) 2012 - 2019, 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 | |
| 276 sasl->force_ir = force_ir; /* Latch for future use */ | |
| 277 sasl->authused = 0; /* No mechanism used yet */ | |
| 278 enabledmechs = sasl->authmechs & sasl->prefmech; | |
| 279 *progress = SASL_IDLE; | |
| 280 | |
| 281 /* Calculate the supported authentication mechanism, by decreasing order of | |
| 282 security, as well as the initial response where appropriate */ | |
| 283 if((enabledmechs & SASL_MECH_EXTERNAL) && !conn->passwd[0]) { | |
| 284 mech = SASL_MECH_STRING_EXTERNAL; | |
| 285 state1 = SASL_EXTERNAL; | |
| 286 sasl->authused = SASL_MECH_EXTERNAL; | |
| 287 | |
| 288 if(force_ir || data->set.sasl_ir) | |
| 289 result = Curl_auth_create_external_message(data, conn->user, &resp, | |
| 290 &len); | |
| 291 } | |
| 292 else if(conn->bits.user_passwd) { | |
| 293 #if defined(USE_KERBEROS5) | |
| 294 if((enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() && | |
| 295 Curl_auth_user_contains_domain(conn->user)) { | |
| 296 sasl->mutual_auth = FALSE; | |
| 297 mech = SASL_MECH_STRING_GSSAPI; | |
| 298 state1 = SASL_GSSAPI; | |
| 299 state2 = SASL_GSSAPI_TOKEN; | |
| 300 sasl->authused = SASL_MECH_GSSAPI; | |
| 301 | |
| 302 if(force_ir || data->set.sasl_ir) | |
| 303 result = Curl_auth_create_gssapi_user_message(data, conn->user, | |
| 304 conn->passwd, | |
| 305 service, | |
| 306 data->conn->host.name, | |
| 307 sasl->mutual_auth, | |
| 308 NULL, &conn->krb5, | |
| 309 &resp, &len); | |
| 310 } | |
| 311 else | |
| 312 #endif | |
| 313 #ifndef CURL_DISABLE_CRYPTO_AUTH | |
| 314 if((enabledmechs & SASL_MECH_DIGEST_MD5) && | |
| 315 Curl_auth_is_digest_supported()) { | |
| 316 mech = SASL_MECH_STRING_DIGEST_MD5; | |
| 317 state1 = SASL_DIGESTMD5; | |
| 318 sasl->authused = SASL_MECH_DIGEST_MD5; | |
| 319 } | |
| 320 else if(enabledmechs & SASL_MECH_CRAM_MD5) { | |
| 321 mech = SASL_MECH_STRING_CRAM_MD5; | |
| 322 state1 = SASL_CRAMMD5; | |
| 323 sasl->authused = SASL_MECH_CRAM_MD5; | |
| 324 } | |
| 325 else | |
| 326 #endif | |
| 327 #ifdef USE_NTLM | |
| 328 if((enabledmechs & SASL_MECH_NTLM) && Curl_auth_is_ntlm_supported()) { | |
| 329 mech = SASL_MECH_STRING_NTLM; | |
| 330 state1 = SASL_NTLM; | |
| 331 state2 = SASL_NTLM_TYPE2MSG; | |
| 332 sasl->authused = SASL_MECH_NTLM; | |
| 333 | |
| 334 if(force_ir || data->set.sasl_ir) | |
| 335 result = Curl_auth_create_ntlm_type1_message(data, | |
| 336 conn->user, conn->passwd, | |
| 337 service, | |
| 338 hostname, | |
| 339 &conn->ntlm, &resp, | |
| 340 &len); | |
| 341 } | |
| 342 else | |
| 343 #endif | |
| 344 if((enabledmechs & SASL_MECH_OAUTHBEARER) && conn->oauth_bearer) { | |
| 345 mech = SASL_MECH_STRING_OAUTHBEARER; | |
| 346 state1 = SASL_OAUTH2; | |
| 347 state2 = SASL_OAUTH2_RESP; | |
| 348 sasl->authused = SASL_MECH_OAUTHBEARER; | |
| 349 | |
| 350 if(force_ir || data->set.sasl_ir) | |
| 351 result = Curl_auth_create_oauth_bearer_message(data, conn->user, | |
| 352 hostname, | |
| 353 port, | |
| 354 conn->oauth_bearer, | |
| 355 &resp, &len); | |
| 356 } | |
| 357 else if((enabledmechs & SASL_MECH_XOAUTH2) && conn->oauth_bearer) { | |
| 358 mech = SASL_MECH_STRING_XOAUTH2; | |
| 359 state1 = SASL_OAUTH2; | |
| 360 sasl->authused = SASL_MECH_XOAUTH2; | |
| 361 | |
| 362 if(force_ir || data->set.sasl_ir) | |
| 363 result = Curl_auth_create_xoauth_bearer_message(data, conn->user, | |
| 364 conn->oauth_bearer, | |
| 365 &resp, &len); | |
| 366 } | |
| 367 else if(enabledmechs & SASL_MECH_PLAIN) { | |
| 368 mech = SASL_MECH_STRING_PLAIN; | |
| 369 state1 = SASL_PLAIN; | |
| 370 sasl->authused = SASL_MECH_PLAIN; | |
| 371 | |
| 372 if(force_ir || data->set.sasl_ir) | |
| 373 result = Curl_auth_create_plain_message(data, conn->sasl_authzid, | |
| 374 conn->user, conn->passwd, | |
| 375 &resp, &len); | |
| 376 } | |
| 377 else if(enabledmechs & SASL_MECH_LOGIN) { | |
| 378 mech = SASL_MECH_STRING_LOGIN; | |
| 379 state1 = SASL_LOGIN; | |
| 380 state2 = SASL_LOGIN_PASSWD; | |
| 381 sasl->authused = SASL_MECH_LOGIN; | |
| 382 | |
| 383 if(force_ir || data->set.sasl_ir) | |
| 384 result = Curl_auth_create_login_message(data, conn->user, &resp, &len); | |
| 385 } | |
| 386 } | |
| 387 | |
| 388 if(!result && mech) { | |
| 389 if(resp && sasl->params->maxirlen && | |
| 390 strlen(mech) + len > sasl->params->maxirlen) { | |
| 391 free(resp); | |
| 392 resp = NULL; | |
| 393 } | |
| 394 | |
| 395 result = sasl->params->sendauth(conn, mech, resp); | |
| 396 if(!result) { | |
| 397 *progress = SASL_INPROGRESS; | |
| 398 state(sasl, conn, resp ? state2 : state1); | |
| 399 } | |
| 400 } | |
| 401 | |
| 402 free(resp); | |
| 403 | |
| 404 return result; | |
| 405 } | |
| 406 | |
| 407 /* | |
| 408 * Curl_sasl_continue() | |
| 409 * | |
| 410 * Continue the authentication. | |
| 411 */ | |
| 412 CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn, | |
| 413 int code, saslprogress *progress) | |
| 414 { | |
| 415 CURLcode result = CURLE_OK; | |
| 416 struct Curl_easy *data = conn->data; | |
| 417 saslstate newstate = SASL_FINAL; | |
| 418 char *resp = NULL; | |
| 419 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : | |
| 420 conn->host.name; | |
| 421 const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; | |
| 422 #if !defined(CURL_DISABLE_CRYPTO_AUTH) | |
| 423 char *chlg = NULL; | |
| 424 size_t chlglen = 0; | |
| 425 #endif | |
| 426 #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \ | |
| 427 defined(USE_NTLM) | |
| 428 const char *service = data->set.str[STRING_SERVICE_NAME] ? | |
| 429 data->set.str[STRING_SERVICE_NAME] : | |
| 430 sasl->params->service; | |
| 431 char *serverdata; | |
| 432 #endif | |
| 433 size_t len = 0; | |
| 434 | |
| 435 *progress = SASL_INPROGRESS; | |
| 436 | |
| 437 if(sasl->state == SASL_FINAL) { | |
| 438 if(code != sasl->params->finalcode) | |
| 439 result = CURLE_LOGIN_DENIED; | |
| 440 *progress = SASL_DONE; | |
| 441 state(sasl, conn, SASL_STOP); | |
| 442 return result; | |
| 443 } | |
| 444 | |
| 445 if(sasl->state != SASL_CANCEL && sasl->state != SASL_OAUTH2_RESP && | |
| 446 code != sasl->params->contcode) { | |
| 447 *progress = SASL_DONE; | |
| 448 state(sasl, conn, SASL_STOP); | |
| 449 return CURLE_LOGIN_DENIED; | |
| 450 } | |
| 451 | |
| 452 switch(sasl->state) { | |
| 453 case SASL_STOP: | |
| 454 *progress = SASL_DONE; | |
| 455 return result; | |
| 456 case SASL_PLAIN: | |
| 457 result = Curl_auth_create_plain_message(data, conn->sasl_authzid, | |
| 458 conn->user, conn->passwd, | |
| 459 &resp, &len); | |
| 460 break; | |
| 461 case SASL_LOGIN: | |
| 462 result = Curl_auth_create_login_message(data, conn->user, &resp, &len); | |
| 463 newstate = SASL_LOGIN_PASSWD; | |
| 464 break; | |
| 465 case SASL_LOGIN_PASSWD: | |
| 466 result = Curl_auth_create_login_message(data, conn->passwd, &resp, &len); | |
| 467 break; | |
| 468 case SASL_EXTERNAL: | |
| 469 result = Curl_auth_create_external_message(data, conn->user, &resp, &len); | |
| 470 break; | |
| 471 | |
| 472 #ifndef CURL_DISABLE_CRYPTO_AUTH | |
| 473 case SASL_CRAMMD5: | |
| 474 sasl->params->getmessage(data->state.buffer, &serverdata); | |
| 475 result = Curl_auth_decode_cram_md5_message(serverdata, &chlg, &chlglen); | |
| 476 if(!result) | |
| 477 result = Curl_auth_create_cram_md5_message(data, chlg, conn->user, | |
| 478 conn->passwd, &resp, &len); | |
| 479 free(chlg); | |
| 480 break; | |
| 481 case SASL_DIGESTMD5: | |
| 482 sasl->params->getmessage(data->state.buffer, &serverdata); | |
| 483 result = Curl_auth_create_digest_md5_message(data, serverdata, | |
| 484 conn->user, conn->passwd, | |
| 485 service, | |
| 486 &resp, &len); | |
| 487 newstate = SASL_DIGESTMD5_RESP; | |
| 488 break; | |
| 489 case SASL_DIGESTMD5_RESP: | |
| 490 resp = strdup(""); | |
| 491 if(!resp) | |
| 492 result = CURLE_OUT_OF_MEMORY; | |
| 493 break; | |
| 494 #endif | |
| 495 | |
| 496 #ifdef USE_NTLM | |
| 497 case SASL_NTLM: | |
| 498 /* Create the type-1 message */ | |
| 499 result = Curl_auth_create_ntlm_type1_message(data, | |
| 500 conn->user, conn->passwd, | |
| 501 service, hostname, | |
| 502 &conn->ntlm, &resp, &len); | |
| 503 newstate = SASL_NTLM_TYPE2MSG; | |
| 504 break; | |
| 505 case SASL_NTLM_TYPE2MSG: | |
| 506 /* Decode the type-2 message */ | |
| 507 sasl->params->getmessage(data->state.buffer, &serverdata); | |
| 508 result = Curl_auth_decode_ntlm_type2_message(data, serverdata, | |
| 509 &conn->ntlm); | |
| 510 if(!result) | |
| 511 result = Curl_auth_create_ntlm_type3_message(data, conn->user, | |
| 512 conn->passwd, &conn->ntlm, | |
| 513 &resp, &len); | |
| 514 break; | |
| 515 #endif | |
| 516 | |
| 517 #if defined(USE_KERBEROS5) | |
| 518 case SASL_GSSAPI: | |
| 519 result = Curl_auth_create_gssapi_user_message(data, conn->user, | |
| 520 conn->passwd, | |
| 521 service, | |
| 522 data->conn->host.name, | |
| 523 sasl->mutual_auth, NULL, | |
| 524 &conn->krb5, | |
| 525 &resp, &len); | |
| 526 newstate = SASL_GSSAPI_TOKEN; | |
| 527 break; | |
| 528 case SASL_GSSAPI_TOKEN: | |
| 529 sasl->params->getmessage(data->state.buffer, &serverdata); | |
| 530 if(sasl->mutual_auth) { | |
| 531 /* Decode the user token challenge and create the optional response | |
| 532 message */ | |
| 533 result = Curl_auth_create_gssapi_user_message(data, NULL, NULL, | |
| 534 NULL, NULL, | |
| 535 sasl->mutual_auth, | |
| 536 serverdata, &conn->krb5, | |
| 537 &resp, &len); | |
| 538 newstate = SASL_GSSAPI_NO_DATA; | |
| 539 } | |
| 540 else | |
| 541 /* Decode the security challenge and create the response message */ | |
| 542 result = Curl_auth_create_gssapi_security_message(data, serverdata, | |
| 543 &conn->krb5, | |
| 544 &resp, &len); | |
| 545 break; | |
| 546 case SASL_GSSAPI_NO_DATA: | |
| 547 sasl->params->getmessage(data->state.buffer, &serverdata); | |
| 548 /* Decode the security challenge and create the response message */ | |
| 549 result = Curl_auth_create_gssapi_security_message(data, serverdata, | |
| 550 &conn->krb5, | |
| 551 &resp, &len); | |
| 552 break; | |
| 553 #endif | |
| 554 | |
| 555 case SASL_OAUTH2: | |
| 556 /* Create the authorisation message */ | |
| 557 if(sasl->authused == SASL_MECH_OAUTHBEARER) { | |
| 558 result = Curl_auth_create_oauth_bearer_message(data, conn->user, | |
| 559 hostname, | |
| 560 port, | |
| 561 conn->oauth_bearer, | |
| 562 &resp, &len); | |
| 563 | |
| 564 /* Failures maybe sent by the server as continuations for OAUTHBEARER */ | |
| 565 newstate = SASL_OAUTH2_RESP; | |
| 566 } | |
| 567 else | |
| 568 result = Curl_auth_create_xoauth_bearer_message(data, conn->user, | |
| 569 conn->oauth_bearer, | |
| 570 &resp, &len); | |
| 571 break; | |
| 572 | |
| 573 case SASL_OAUTH2_RESP: | |
| 574 /* The continuation is optional so check the response code */ | |
| 575 if(code == sasl->params->finalcode) { | |
| 576 /* Final response was received so we are done */ | |
| 577 *progress = SASL_DONE; | |
| 578 state(sasl, conn, SASL_STOP); | |
| 579 return result; | |
| 580 } | |
| 581 else if(code == sasl->params->contcode) { | |
| 582 /* Acknowledge the continuation by sending a 0x01 response base64 | |
| 583 encoded */ | |
| 584 resp = strdup("AQ=="); | |
| 585 if(!resp) | |
| 586 result = CURLE_OUT_OF_MEMORY; | |
| 587 break; | |
| 588 } | |
| 589 else { | |
| 590 *progress = SASL_DONE; | |
| 591 state(sasl, conn, SASL_STOP); | |
| 592 return CURLE_LOGIN_DENIED; | |
| 593 } | |
| 594 | |
| 595 case SASL_CANCEL: | |
| 596 /* Remove the offending mechanism from the supported list */ | |
| 597 sasl->authmechs ^= sasl->authused; | |
| 598 | |
| 599 /* Start an alternative SASL authentication */ | |
| 600 result = Curl_sasl_start(sasl, conn, sasl->force_ir, progress); | |
| 601 newstate = sasl->state; /* Use state from Curl_sasl_start() */ | |
| 602 break; | |
| 603 default: | |
| 604 failf(data, "Unsupported SASL authentication mechanism"); | |
| 605 result = CURLE_UNSUPPORTED_PROTOCOL; /* Should not happen */ | |
| 606 break; | |
| 607 } | |
| 608 | |
| 609 switch(result) { | |
| 610 case CURLE_BAD_CONTENT_ENCODING: | |
| 611 /* Cancel dialog */ | |
| 612 result = sasl->params->sendcont(conn, "*"); | |
| 613 newstate = SASL_CANCEL; | |
| 614 break; | |
| 615 case CURLE_OK: | |
| 616 if(resp) | |
| 617 result = sasl->params->sendcont(conn, resp); | |
| 618 break; | |
| 619 default: | |
| 620 newstate = SASL_STOP; /* Stop on error */ | |
| 621 *progress = SASL_DONE; | |
| 622 break; | |
| 623 } | |
| 624 | |
| 625 free(resp); | |
| 626 | |
| 627 state(sasl, conn, newstate); | |
| 628 | |
| 629 return result; | |
| 630 } | |
| 631 #endif /* protocols are enabled that use SASL */ |
