diff options
author | Heikki Korpela <heko@cvs.openbsd.org> | 2001-11-14 07:59:29 +0000 |
---|---|---|
committer | Heikki Korpela <heko@cvs.openbsd.org> | 2001-11-14 07:59:29 +0000 |
commit | 3835e63e6f014d6a5a40042cf2a72ab80fc9dda7 (patch) | |
tree | 7230e478c6aa488bc0dc15bd67ba59756082ca2c /usr.bin/ftp | |
parent | 9cd9561cf44f3461a4e3b7550aed27ebaed4cc87 (diff) |
o Don't accept URLs with user:pass@ and an extra unencoded @.
@ should be encoded as %40 for passwords and usernames. @ in
the pathname portion of the URL is ok.
o decode usernames and passwords as per FTP URL specification.
spotted by krw@, input from krw@ and fgs@
millert@ ok
Diffstat (limited to 'usr.bin/ftp')
-rw-r--r-- | usr.bin/ftp/fetch.c | 77 |
1 files changed, 72 insertions, 5 deletions
diff --git a/usr.bin/ftp/fetch.c b/usr.bin/ftp/fetch.c index 8bf028b56a8..8c7f8ce8e1d 100644 --- a/usr.bin/ftp/fetch.c +++ b/usr.bin/ftp/fetch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fetch.c,v 1.36 2001/10/27 10:31:27 heko Exp $ */ +/* $OpenBSD: fetch.c,v 1.37 2001/11/14 07:59:28 heko Exp $ */ /* $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */ /*- @@ -38,7 +38,7 @@ */ #ifndef lint -static char rcsid[] = "$OpenBSD: fetch.c,v 1.36 2001/10/27 10:31:27 heko Exp $"; +static char rcsid[] = "$OpenBSD: fetch.c,v 1.37 2001/11/14 07:59:28 heko Exp $"; #endif /* not lint */ /* @@ -72,7 +72,8 @@ static char rcsid[] = "$OpenBSD: fetch.c,v 1.36 2001/10/27 10:31:27 heko Exp $"; static int url_get __P((const char *, const char *, const char *)); void aborthttp __P((int)); void abortfile __P((int)); - +char hextochar __P((const char *)); +char *urldecode __P((const char *)); #define FTP_URL "ftp://" /* ftp URL prefix */ #define HTTP_URL "http://" /* http URL prefix */ @@ -83,6 +84,9 @@ void abortfile __P((int)); #define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0')) +static const char *at_encoding_warning = + "Extra `@' characters in usernames and passwords should be encoded as %%40"; + jmp_buf httpabort; /* @@ -644,7 +648,7 @@ auto_fetch(argc, argv, outfile) */ host = line; if (strncasecmp(line, FTP_URL, sizeof(FTP_URL) - 1) == 0) { - char *passend, *userend; + char *passend, *passagain, *userend; if (ftpproxy) { if (url_get(line, ftpproxy, outfile) == -1) @@ -657,14 +661,20 @@ auto_fetch(argc, argv, outfile) /* Look for [user:pass@]host[:port] */ /* check if we have "user:pass@" */ - passend = strchr(host, '@'); userend = strchr(host, ':'); + passend = strchr(host, '@'); if (passend && userend && userend < passend && (!dir || passend < dir)) { user = host; pass = userend + 1; host = passend + 1; *userend = *passend = '\0'; + passagain = strchr(host, '@'); + if (strchr(pass, '@') != NULL || + (passagain != NULL && passagain < dir)) { + warnx(at_encoding_warning); + goto bad_ftp_url; + } if (EMPTYSTRING(user) || EMPTYSTRING(pass)) { bad_ftp_url: @@ -672,6 +682,8 @@ bad_ftp_url: rval = argpos + 1; continue; } + user = urldecode(user); + pass = urldecode(pass); } #ifdef INET6 @@ -854,6 +866,61 @@ bad_ftp_url: return (rval); } +char * +urldecode(str) + const char *str; +{ + char *ret; + char c; + int i, reallen; + + if (str == NULL) + return NULL; + if ((ret = malloc(strlen(str)+1)) == NULL) + err(1, "Can't allocate memory for URL decoding"); + for (i = 0, reallen = 0; str[i] != '\0'; i++, reallen++, ret++) { + c = str[i]; + if (c == '+') { + *ret = ' '; + continue; + } + /* Can't use strtol here because next char after %xx may be + * a digit. */ + if (c == '%' && isxdigit(str[i+1]) && isxdigit(str[i+2])) { + *ret = hextochar(&str[i+1]); + i+=2; + continue; + } + *ret = c; + } + *ret = '\0'; + + return ret-reallen; +} + +char +hextochar(str) + const char *str; +{ + char c, ret; + + c = str[0]; + ret = c; + if (isalpha(c)) + ret -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + ret -= '0'; + ret *= 16; + + c = str[1]; + ret += c; + if (isalpha(c)) + ret -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + ret -= '0'; + return ret; +} + int isurl(p) const char *p; |