aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/url.c218
1 files changed, 158 insertions, 60 deletions
diff --git a/lib/url.c b/lib/url.c
index d0f664d2b..afd8f1e6c 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -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,80 +4382,169 @@ 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);
+ /* 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 */
+ conn->bits.userpwd_in_url = TRUE;
+ conn->bits.user_passwd = TRUE; /* enable user+password */
+
+ /* Decode the user */
+ 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);
+
+ free(newname);
}
- }
- 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]) {
- char *newname;
+ if(passwdp) {
+ /* We have a password in the URL so decode it */
+ char *newpasswd = curl_easy_unescape(data, passwdp, 0, NULL);
+ if(!newpasswd)
+ return CURLE_OUT_OF_MEMORY;
+
+ if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
+ strcpy(passwd, newpasswd);
- /* We have a user in the URL */
- conn->bits.userpwd_in_url = TRUE;
- conn->bits.user_passwd = TRUE; /* enable user+password */
+ free(newpasswd);
+ }
- /* Decode the user */
- newname = curl_easy_unescape(data, user, 0, NULL);
- if(!newname)
- return CURLE_OUT_OF_MEMORY;
+ if(optionsp) {
+ /* We have an options list in the URL so decode it */
+ char *newoptions = curl_easy_unescape(data, optionsp, 0, NULL);
+ if(!newoptions)
+ return CURLE_OUT_OF_MEMORY;
- if(strlen(newname) < MAX_CURL_USER_LENGTH)
- strcpy(user, newname);
+ if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH)
+ strcpy(options, newoptions);
- /* if the new name is longer than accepted, then just use
- the unconverted name, it'll be wrong but what the heck */
- free(newname);
+ free(newoptions);
+ }
}
- if(passwd[0]) {
- /* We have a password in the URL so decode it */
- char *newpasswd = curl_easy_unescape(data, passwd, 0, NULL);
- if(!newpasswd)
- return CURLE_OUT_OF_MEMORY;
+ Curl_safefree(userp);
+ Curl_safefree(passwdp);
+ Curl_safefree(optionsp);
+ }
+ }
- if(strlen(newpasswd) < MAX_CURL_PASSWORD_LENGTH)
- strcpy(passwd, newpasswd);
+ return result;
+}
- free(newpasswd);
- }
+/*
+ * 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(options[0]) {
- /* We have an options list in the URL so decode it */
- char *newoptions = curl_easy_unescape(data, options, 0, NULL);
- if(!newoptions)
- return 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;
+ }
- if(strlen(newoptions) < MAX_CURL_OPTIONS_LENGTH)
- strcpy(options, newoptions);
+ /* Copy the password portion if necessary */
+ if(ptemp) {
+ memcpy(ptemp, psep + 1, plen);
+ ptemp[plen] = '\0';
+ Curl_safefree(*passwdp);
+ *passwdp = ptemp;
+ }
- free(newoptions);
- }
+ /* Copy the password portion if necessary */
+ if(otemp) {
+ memcpy(otemp, osep + 1, olen);
+ otemp[olen] = '\0';
+ Curl_safefree(*optionsp);
+ *optionsp = otemp;
}
}
- return CURLE_OK;
+ return result;
}
/*************************************************************