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>