Commit bb20989a authored by Steve Holme's avatar Steve Holme
Browse files

url: Moved parsing of login details out of parse_url_login()

Separated the parsing of login details from the processing of them in
parse_url_login() ready for use by setstropt_userpwd().
parent 0d49e408
Loading
Loading
Loading
Loading
+158 −60
Original line number Diff line number Diff line
@@ -144,6 +144,9 @@ static CURLcode do_init(struct connectdata *conn);
static CURLcode parse_url_login(struct SessionHandle *data,
                                struct connectdata *conn,
                                char *user, char *passwd, char *options);
static CURLcode parse_login_details(const char *login, const size_t len,
                                    char **userptr, char **passwdptr,
                                    char **optionsptr);
/*
 * Protocol table.
 */
@@ -4326,6 +4329,7 @@ static CURLcode parse_proxy_auth(struct SessionHandle *data,
#endif /* CURL_DISABLE_PROXY */

/*
 * parse_url_login()
 *
 * Parse the login details (user name, password and options) from the URL and
 * strip them out of the host name
@@ -4344,6 +4348,11 @@ static CURLcode parse_url_login(struct SessionHandle *data,
                                struct connectdata *conn,
                                char *user, char *passwd, char *options)
{
  CURLcode result = CURLE_OK;
  char *userp = NULL;
  char *passwdp = NULL;
  char *optionsp = NULL;

  /* At this point, we're hoping all the other special cases have
   * been taken care of, so conn->host.name is at most
   *    [user[:password][;options]]@]hostname
@@ -4352,7 +4361,7 @@ static CURLcode parse_url_login(struct SessionHandle *data,
   */

  char *ptr = strchr(conn->host.name, '@');
  char *userpass = conn->host.name;
  char *login = conn->host.name;

  user[0] = 0;   /* to make everything well-defined */
  passwd[0] = 0;
@@ -4361,7 +4370,7 @@ static CURLcode parse_url_login(struct SessionHandle *data,
  /* We will now try to extract the
   * possible login information in a string like:
   * ftp://user:password@ftp.my.site:8021/README */
  if(ptr != NULL) {
  if(ptr) {
    /* There's login information to the left of the @ */

    conn->host.name = ++ptr;
@@ -4373,34 +4382,11 @@ static CURLcode parse_url_login(struct SessionHandle *data,
     */

    if(data->set.use_netrc != CURL_NETRC_REQUIRED) {
      /* We could use the information in the URL so extract it */
      if(*userpass != ':') {
        if(*userpass != ';') {
          /* The user is given so extract the user, password and options */
          int result = sscanf(userpass,
                              "%" MAX_CURL_USER_LENGTH_TXT "[^:;@]:"
                              "%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];"
                              "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]",
                              user, passwd, options);

          /* The extract failed so extract the user and options instead */
          if(result == 1)
            sscanf(userpass, "%" MAX_CURL_USER_LENGTH_TXT "[^:;@];"
                             "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]",
                              user, options);
        }
        else {
          /* No name or password are given so extract the options only */
        sscanf(userpass, ";%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]", options);
        }
      }
      else
        /* No name is given so extract the password and options */
        sscanf(userpass, ":%" MAX_CURL_PASSWORD_LENGTH_TXT "[^;@];"
               "%" MAX_CURL_OPTIONS_LENGTH_TXT "[^@]",
               passwd, options);

      if(user[0]) {
      /* We could use the login information in the URL so extract it */
      result = parse_login_details(login, ptr - login - 1,
                                   &userp, &passwdp, &optionsp);
      if(!result) {
        if(userp) {
          char *newname;

          /* We have a user in the URL */
@@ -4408,21 +4394,19 @@ static CURLcode parse_url_login(struct SessionHandle *data,
          conn->bits.user_passwd = TRUE; /* enable user+password */

          /* Decode the user */
        newname = curl_easy_unescape(data, user, 0, NULL);
          newname = curl_easy_unescape(data, userp, 0, NULL);
          if(!newname)
            return CURLE_OUT_OF_MEMORY;

          if(strlen(newname) < MAX_CURL_USER_LENGTH)
            strcpy(user, newname);

        /* if the new name is longer than accepted, then just use
           the unconverted name, it'll be wrong but what the heck */
          free(newname);
        }

      if(passwd[0]) {
        if(passwdp) {
          /* We have a password in the URL so decode it */
        char *newpasswd = curl_easy_unescape(data, passwd, 0, NULL);
          char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
          if(!newpasswd)
            return CURLE_OUT_OF_MEMORY;

@@ -4432,9 +4416,9 @@ static CURLcode parse_url_login(struct SessionHandle *data,
          free(newpasswd);
        }

      if(options[0]) {
        if(optionsp) {
          /* We have an options list in the URL so decode it */
        char *newoptions = curl_easy_unescape(data, options, 0, NULL);
          char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
          if(!newoptions)
            return CURLE_OUT_OF_MEMORY;

@@ -4444,9 +4428,123 @@ static CURLcode parse_url_login(struct SessionHandle *data,
          free(newoptions);
        }
      }

      Curl_safefree(userp);
      Curl_safefree(passwdp);
      Curl_safefree(optionsp);
    }
  }

  return CURLE_OK;
  return result;
}

/*
 * parse_login_details()
 *
 * This is used to parse a login string for user name, password and options in
 * the following formats:
 *
 *   user
 *   user:password
 *   user:password;options
 *   user;options
 *   user;options:password
 *   :password
 *   :password;options
 *   ;options
 *   ;options:password
 *
 * Parameters:
 *
 * login    [in]     - The login string.
 * len      [in]     - The length of the login string.
 * userp    [in/out] - The address where a pointer to newly allocated memory
 *                     holding the user will be stored upon completion.
 * passdwp  [in/out] - The address where a pointer to newly allocated memory
 *                     holding the password will be stored upon completion.
 * optionsp [in/out] - The address where a pointer to newly allocated memory
 *                     holding the options will be stored upon completion.
 *
 * Returns CURLE_OK on success.
 */
static CURLcode parse_login_details(const char *login, const size_t len,
                                    char **userp, char **passwdp, char **optionsp)
{
  int result = CURLE_OK;
  char *utemp = NULL;
  char *ptemp = NULL;
  char *otemp = NULL;
  const char *psep = NULL;
  const char *osep = NULL;
  size_t ulen;
  size_t plen;
  size_t olen;

  /* Attempt to find the password separator */
  if(passwdp)
    psep = strchr(login, ':');

  /* Attempt to find the options separator */
  if(optionsp)
    osep = strchr(login, ';');

  /* Calculate the portion lengths */
  ulen = (psep ?
          (osep && psep > osep ? osep - login : psep - login) :
          (osep ? osep - login : len));
  plen = (psep ?
          (osep && osep > psep ? osep - psep : login + len - psep) - 1 : 0);
  olen = (osep ?
          (psep && psep > osep ? psep - osep : login + len - osep) - 1 : 0);

  /* Allocate the user portion temporary buffer */
  if(userp && ulen) {
    utemp = malloc(ulen + 1);
    if(!utemp)
      result = CURLE_OUT_OF_MEMORY;
  }

  /* Allocate the password portion temporary buffer */
  if(!result && passwdp && plen) {
    ptemp = malloc(plen + 1);
    if(!ptemp)
      result = CURLE_OUT_OF_MEMORY;
  }

  /* Allocate the options  portion temporary buffer */
  if(!result && optionsp && olen) {
    otemp = malloc(olen + 1);
    if(!otemp)
      result = CURLE_OUT_OF_MEMORY;
  }

  if(!result) {
    /* Copy the user portion if necessary */
    if(utemp) {
      memcpy(utemp, login, ulen);
      utemp[ulen] = '\0';
      Curl_safefree(*userp);
      *userp = utemp;
    }

    /* Copy the password portion if necessary */
    if(ptemp) {
      memcpy(ptemp, psep + 1, plen);
      ptemp[plen] = '\0';
      Curl_safefree(*passwdp);
      *passwdp = ptemp;
    }

    /* Copy the password portion if necessary */
    if(otemp) {
      memcpy(otemp, osep + 1, olen);
      otemp[olen] = '\0';
      Curl_safefree(*optionsp);
      *optionsp = otemp;
    }
  }

  return result;
}

/*************************************************************