File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / curl_sasl.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    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>