Annotation of embedaddon/curl/lib/curl_sasl.c, revision 1.1.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>