Re: PATCH: ftp: allow @ in username for Basic Auth

2014-07-05 Thread Philip Guenther
On Tue, Jul 1, 2014 at 7:09 AM, Sébastien Marie semarie-open...@latrappe.fr
 wrote:

 On Sun, Jun 29, 2014 at 09:52:28PM -0700, Philip Guenther wrote:
Here's a patch to do that.
  
   Just a comment in code (unused variables in urldecode).
   Else it seems ok. And my use-case works.
 
  Dang it, I just noticed that I had sent an earlier version of my diff,
  which had problems with some proxy setting, IIRC.  Here's the diff that I
  settled on after testing.

 It works also for my use-case. Please note I haven't tested proxy
 setting (by lake of server to test).


Just committed it.  Thank you for pointing out the problem and confirming
that it works for you!


Philip Guenther


Re: PATCH: ftp: allow @ in username for Basic Auth

2014-07-01 Thread Sébastien Marie
On Sun, Jun 29, 2014 at 09:52:28PM -0700, Philip Guenther wrote:
   Here's a patch to do that.
  
  Just a comment in code (unused variables in urldecode).
  Else it seems ok. And my use-case works.
 
 Dang it, I just noticed that I had sent an earlier version of my diff, 
 which had problems with some proxy setting, IIRC.  Here's the diff that I 
 settled on after testing.
 

It works also for my use-case. Please note I haven't tested proxy
setting (by lake of server to test).

Thanks for your help.
-- 
Sébastien Marie



Re: PATCH: ftp: allow @ in username for Basic Auth

2014-06-29 Thread Philip Guenther
On Thu, 26 Jun 2014, S?bastien Marie wrote:
 On Wed, Jun 25, 2014 at 07:07:30PM -0700, Philip Guenther wrote:
  On Wed, 25 Jun 2014, S?bastien Marie wrote:
   On Tue, Jun 24, 2014 at 10:55:44AM -0700, Philip Guenther wrote:
On Tue, Jun 24, 2014 at 9:01 AM, S?bastien Marie 
semarie-open...@latrappe.fr wrote:
  ...
   So, I think ftp(1) should urldecode userinfo before base64.
  
  I agree.
  
   I propose another patch that implement urldecoding of userinfo (as it 
   come from URI).
  
  It also needs to be fixed for proxy authentication.  I think the code to 
  urldecode and reencode in base64 should be factored out.
 
 If urldecode is refactored, it may return the length of decoded string
 (as size_t* parameter: NULL for no result, output variable else).
 
 The purpose is to properly managed the case where %00 is include in the
 userinfo. Else it results truncation (as string are \0 terminate).
 
 But it would need more work: if in recode_credentials there is no
 problem (just need to pass ulen to urldecode, and don't need strlen),
 urldecode is used also for FTP URL parsing.
 
 But note that I don't sure that manage %00 in userinfo make sense.
 
  Here's a patch to do that.
 
 Just a comment in code (unused variables in urldecode).
 Else it seems ok. And my use-case works.

Dang it, I just noticed that I had sent an earlier version of my diff, 
which had problems with some proxy setting, IIRC.  Here's the diff that I 
settled on after testing.

sigh

Philip Guenther


Index: fetch.c
===
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.122
diff -u -p -r1.122 fetch.c
--- fetch.c 20 May 2014 01:25:23 -  1.122
+++ fetch.c 30 Jun 2014 04:47:25 -
@@ -76,6 +76,7 @@ void  aborthttp(int);
 void   abortfile(int);
 char   hextochar(const char *);
 char   *urldecode(const char *);
+char   *recode_credentials(const char *_userinfo);
 intftp_printf(FILE *, SSL *, const char *, ...) 
__attribute__((format(printf, 3, 4)));
 char   *ftp_readline(FILE *, SSL *, size_t *);
 size_t ftp_read(FILE *, SSL *, char *, size_t);
@@ -97,8 +98,6 @@ SSL_CTX   *ssl_get_ssl_ctx(void);
 #define FTP_PROXY  ftp_proxy /* env var with ftp proxy location */
 #define HTTP_PROXY http_proxy/* env var with http proxy location */
 
-#define COOKIE_MAX_LEN 42
-
 #define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0'))
 
 static const char at_encoding_warning[] =
@@ -393,7 +392,7 @@ url_get(const char *origline, const char
struct addrinfo hints, *res0, *res, *ares = NULL;
const char * volatile savefile;
char * volatile proxyurl = NULL;
-   char *cookie = NULL;
+   char *credentials = NULL;
volatile int s = -1, out;
volatile sig_t oldintr, oldinti;
FILE *fin = NULL;
@@ -402,9 +401,9 @@ url_get(const char *origline, const char
ssize_t len, wlen;
 #ifndef SMALL
char *sslpath = NULL, *sslhost = NULL;
-   char *locbase, *full_host = NULL, *auth = NULL;
+   char *locbase, *full_host = NULL;
const char *scheme;
-   int ishttpsurl = 0;
+   int ishttpurl = 0, ishttpsurl = 0;
SSL_CTX *ssl_ctx = NULL;
 #endif /* !SMALL */
SSL *ssl = NULL;
@@ -420,6 +419,7 @@ url_get(const char *origline, const char
if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
host = newline + sizeof(HTTP_URL) - 1;
 #ifndef SMALL
+   ishttpurl = 1;
scheme = HTTP_URL;
 #endif /* !SMALL */
} else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
@@ -472,17 +472,10 @@ noslash:
 * contain the path. Basic auth from RFC 2617, valid
 * characters for path are in RFC 3986 section 3.3.
 */
-   if (proxyenv == NULL 
-   (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) {
+   if (proxyenv == NULL  (ishttpurl || ishttpsurl)) {
if ((p = strchr(host, '@')) != NULL) {
-   size_t authlen = (strlen(host) + 5) * 4 / 3;
-   *p = 0; /* Kill @ */
-   if ((auth = malloc(authlen)) == NULL)
-   err(1, Can't allocate memory for 
-   authorization);
-   if (b64_ntop(host, strlen(host),
-   auth, authlen) == -1)
-   errx(1, error in base64 encoding);
+   *p = '\0';
+   credentials = recode_credentials(host);
host = p + 1;
}
}
@@ -544,17 +537,13 @@ noslash:
path = strchr(host, '@');   /* look for credentials in 
proxy */
if (!EMPTYSTRING(path)) {
*path = '\0';
-   cookie = strchr(host, ':');
- 

Re: PATCH: ftp: allow @ in username for Basic Auth

2014-06-25 Thread Sébastien Marie
On Tue, Jun 24, 2014 at 10:55:44AM -0700, Philip Guenther wrote:
 On Tue, Jun 24, 2014 at 9:01 AM, Sébastien Marie 
 semarie-open...@latrappe.fr wrote:
 
  As I see not activity or feedback for this one line patch, I think it
  need more explain ?
 
 
 Sorry, the patch is incorrect; per RFC 3986, the parser is correct to split
 the authority on the first '@'.  The correct method to include an '@' in
 the userinfo part is to percent-encode it as %40.
 

Thanks for pointing me the good RFC for the format of userinfo in URI.

But, I am not sure to understand *where* is located my problem: if it is
a problem in ftp(1), or a problem in specific service I try to used with
ftp (dyndns server, the http reply come from ngnix server).

Currently ftp(1) manage http, https with url_get function. The basic
auth implemented here do *not* try to decode any urlencoded information.

So pass user%40example.com:password as userinfo in URI will result to
base64 user%40example.com:password (and not
u...@example.com:password).

The dyndns service reply with 401 Unauthorized.


Comparing with curl(1) (in ports), a user:password information passed as
argument is passed to base64 as it, but a user:password passed in the
URI is firstly urldecoded before base64.

$ curl -v -u 'n...@example.com:password' 'http://localhost/'
Authorization: Basic bmFtZUBleGFtcGxlLmNvbTpwYXNzd29yZA==

$ curl -v 'http://name%40example.com:password@localhost/'
Authorization: Basic bmFtZUBleGFtcGxlLmNvbTpwYXNzd29yZA==

bmFtZUBleGFtcGxlLmNvbTpwYXNzd29yZA== is n...@example.com:password


So, I think ftp(1) should urldecode userinfo before base64. I propose
another patch that implement urldecoding of userinfo (as it come from
URI).

Some comments about the patch:
 - I stop use p variable for userinfo parse: I declare and use two new
   variables, userinfo and userinfoend. I hope the code is more
   readable.

 - for urldecoding, I use an already defined function. Memory is
   allocated and checked by this function.

 - I didn't try to parse userinfo as user:password. The userinfo
   string is passed as it to urldecode.

Thanks.
-- 
Sébastien Marie



Index: fetch.c
===
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.122
diff -u -p -r1.122 fetch.c
--- fetch.c 20 May 2014 01:25:23 -  1.122
+++ fetch.c 25 Jun 2014 06:49:11 -
@@ -474,16 +474,30 @@ noslash:
 */
if (proxyenv == NULL 
(!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) {
-   if ((p = strchr(host, '@')) != NULL) {
-   size_t authlen = (strlen(host) + 5) * 4 / 3;
-   *p = 0; /* Kill @ */
+   char *userinfo, *userinfoend;
+
+   /* extract userinfo part */
+   if ((userinfoend = strchr(host, '@')) != NULL) {
+   size_t authlen;
+
+   /* separate userinfo and host components */
+   userinfo = host;
+   host = userinfoend + 1;
+   *userinfoend = '\0';
+
+   /* urldecode userinfo */
+   userinfo = urldecode(userinfo);
+
+   /* build Basic auth */
+   authlen = (strlen(userinfo) + 5) * 4 / 3;
if ((auth = malloc(authlen)) == NULL)
err(1, Can't allocate memory for 
authorization);
-   if (b64_ntop(host, strlen(host),
+   if (b64_ntop(userinfo, strlen(userinfo),
auth, authlen) == -1)
errx(1, error in base64 encoding);
-   host = p + 1;
+
+   free(userinfo);
}
}
 #endif /* SMALL */



Re: PATCH: ftp: allow @ in username for Basic Auth

2014-06-25 Thread Philip Guenther
On Wed, 25 Jun 2014, S?bastien Marie wrote:
 On Tue, Jun 24, 2014 at 10:55:44AM -0700, Philip Guenther wrote:
  On Tue, Jun 24, 2014 at 9:01 AM, S?bastien Marie 
  semarie-open...@latrappe.fr wrote:
...
  Sorry, the patch is incorrect; per RFC 3986, the parser is correct to 
  split the authority on the first '@'.  The correct method to include 
  an '@' in the userinfo part is to percent-encode it as %40.
 
 Thanks for pointing me the good RFC for the format of userinfo in URI.
 
 But, I am not sure to understand *where* is located my problem: if it is 
 a problem in ftp(1), or a problem in specific service I try to used with 
 ftp (dyndns server, the http reply come from ngnix server).
 
 Currently ftp(1) manage http, https with url_get function. The basic
 auth implemented here do *not* try to decode any urlencoded information.
 
 So pass user%40example.com:password as userinfo in URI will result to
 base64 user%40example.com:password (and not
 u...@example.com:password).
...
 So, I think ftp(1) should urldecode userinfo before base64.

I agree.


 I propose another patch that implement urldecoding of userinfo (as it 
 come from URI).

It also needs to be fixed for proxy authentication.  I think the code to 
urldecode and reencode in base64 should be factored out.

Here's a patch to do that.

Also:
 - eliminates the COOKIE_MAX_LEN constant (if they can fit it on the 
   command line or in their environment, surely we can malloc the base64 
   version)
 - renames the variable with user:pass from cookie to credentials
 - empty password isn't an error
 - add a boolean ishttpurl so that we don't have to do strcmps on the schema
   that we just set
 - when looping across multiple ftp:// urls on the command line, don't
   leak the username/password memory


Index: fetch.c
===
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.122
diff -u -p -r1.122 fetch.c
--- fetch.c 20 May 2014 01:25:23 -  1.122
+++ fetch.c 26 Jun 2014 01:40:28 -
@@ -75,7 +75,8 @@ static inturl_get(const char *, const c
 void   aborthttp(int);
 void   abortfile(int);
 char   hextochar(const char *);
-char   *urldecode(const char *);
+void   urldecode(char *);
+char   *recode_credentials(char *_userinfo);
 intftp_printf(FILE *, SSL *, const char *, ...) 
__attribute__((format(printf, 3, 4)));
 char   *ftp_readline(FILE *, SSL *, size_t *);
 size_t ftp_read(FILE *, SSL *, char *, size_t);
@@ -97,8 +98,6 @@ SSL_CTX   *ssl_get_ssl_ctx(void);
 #define FTP_PROXY  ftp_proxy /* env var with ftp proxy location */
 #define HTTP_PROXY http_proxy/* env var with http proxy location */
 
-#define COOKIE_MAX_LEN 42
-
 #define EMPTYSTRING(x) ((x) == NULL || (*(x) == '\0'))
 
 static const char at_encoding_warning[] =
@@ -393,7 +392,7 @@ url_get(const char *origline, const char
struct addrinfo hints, *res0, *res, *ares = NULL;
const char * volatile savefile;
char * volatile proxyurl = NULL;
-   char *cookie = NULL;
+   char *credentials = NULL;
volatile int s = -1, out;
volatile sig_t oldintr, oldinti;
FILE *fin = NULL;
@@ -402,9 +401,9 @@ url_get(const char *origline, const char
ssize_t len, wlen;
 #ifndef SMALL
char *sslpath = NULL, *sslhost = NULL;
-   char *locbase, *full_host = NULL, *auth = NULL;
+   char *locbase, *full_host = NULL;
const char *scheme;
-   int ishttpsurl = 0;
+   int ishttpurl = 0, ishttpsurl = 0;
SSL_CTX *ssl_ctx = NULL;
 #endif /* !SMALL */
SSL *ssl = NULL;
@@ -420,6 +419,7 @@ url_get(const char *origline, const char
if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
host = newline + sizeof(HTTP_URL) - 1;
 #ifndef SMALL
+   ishttpurl = 1;
scheme = HTTP_URL;
 #endif /* !SMALL */
} else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
@@ -472,17 +472,10 @@ noslash:
 * contain the path. Basic auth from RFC 2617, valid
 * characters for path are in RFC 3986 section 3.3.
 */
-   if (proxyenv == NULL 
-   (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) {
+   if (proxyenv == NULL  (ishttpurl || ishttpsurl)) {
if ((p = strchr(host, '@')) != NULL) {
-   size_t authlen = (strlen(host) + 5) * 4 / 3;
-   *p = 0; /* Kill @ */
-   if ((auth = malloc(authlen)) == NULL)
-   err(1, Can't allocate memory for 
-   authorization);
-   if (b64_ntop(host, strlen(host),
-   auth, authlen) == -1)
-   errx(1, error in base64 encoding);
+   *p = '\0';
+   credentials 

Re: PATCH: ftp: allow @ in username for Basic Auth

2014-06-25 Thread Sébastien Marie
On Wed, Jun 25, 2014 at 07:07:30PM -0700, Philip Guenther wrote:
 On Wed, 25 Jun 2014, S?bastien Marie wrote:
  On Tue, Jun 24, 2014 at 10:55:44AM -0700, Philip Guenther wrote:
   On Tue, Jun 24, 2014 at 9:01 AM, S?bastien Marie 
   semarie-open...@latrappe.fr wrote:
 ...
  So, I think ftp(1) should urldecode userinfo before base64.
 
 I agree.
 
  I propose another patch that implement urldecoding of userinfo (as it 
  come from URI).
 
 It also needs to be fixed for proxy authentication.  I think the code to 
 urldecode and reencode in base64 should be factored out.

If urldecode is refactored, it may return the length of decoded string
(as size_t* parameter: NULL for no result, output variable else).

The purpose is to properly managed the case where %00 is include in the
userinfo. Else it results truncation (as string are \0 terminate).

But it would need more work: if in recode_credentials there is no
problem (just need to pass ulen to urldecode, and don't need strlen),
urldecode is used also for FTP URL parsing.

But note that I don't sure that manage %00 in userinfo make sense.

 Here's a patch to do that.

Just a comment in code (unused variables in urldecode).
Else it seems ok. And my use-case works.

 ...
 
 Index: fetch.c
 ===
 RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
 retrieving revision 1.122
 diff -u -p -r1.122 fetch.c
 --- fetch.c   20 May 2014 01:25:23 -  1.122
 +++ fetch.c   26 Jun 2014 01:40:28 -
 @@ -75,7 +75,8 @@ static int  url_get(const char *, const c
  void aborthttp(int);
  void abortfile(int);
  char hextochar(const char *);
 -char *urldecode(const char *);
 +void urldecode(char *);
 +char *recode_credentials(char *_userinfo);
  int  ftp_printf(FILE *, SSL *, const char *, ...) 
 __attribute__((format(printf, 3, 4)));
  char *ftp_readline(FILE *, SSL *, size_t *);
  size_t   ftp_read(FILE *, SSL *, char *, size_t);
 @@ -97,8 +98,6 @@ SSL_CTX *ssl_get_ssl_ctx(void);
  #define FTP_PROXYftp_proxy /* env var with ftp proxy location */
  #define HTTP_PROXY   http_proxy/* env var with http proxy location */
  
 -#define COOKIE_MAX_LEN   42
 -
  #define EMPTYSTRING(x)   ((x) == NULL || (*(x) == '\0'))
  
  static const char at_encoding_warning[] =
 @@ -393,7 +392,7 @@ url_get(const char *origline, const char
   struct addrinfo hints, *res0, *res, *ares = NULL;
   const char * volatile savefile;
   char * volatile proxyurl = NULL;
 - char *cookie = NULL;
 + char *credentials = NULL;
   volatile int s = -1, out;
   volatile sig_t oldintr, oldinti;
   FILE *fin = NULL;
 @@ -402,9 +401,9 @@ url_get(const char *origline, const char
   ssize_t len, wlen;
  #ifndef SMALL
   char *sslpath = NULL, *sslhost = NULL;
 - char *locbase, *full_host = NULL, *auth = NULL;
 + char *locbase, *full_host = NULL;
   const char *scheme;
 - int ishttpsurl = 0;
 + int ishttpurl = 0, ishttpsurl = 0;
   SSL_CTX *ssl_ctx = NULL;
  #endif /* !SMALL */
   SSL *ssl = NULL;
 @@ -420,6 +419,7 @@ url_get(const char *origline, const char
   if (strncasecmp(newline, HTTP_URL, sizeof(HTTP_URL) - 1) == 0) {
   host = newline + sizeof(HTTP_URL) - 1;
  #ifndef SMALL
 + ishttpurl = 1;
   scheme = HTTP_URL;
  #endif /* !SMALL */
   } else if (strncasecmp(newline, FTP_URL, sizeof(FTP_URL) - 1) == 0) {
 @@ -472,17 +472,10 @@ noslash:
* contain the path. Basic auth from RFC 2617, valid
* characters for path are in RFC 3986 section 3.3.
*/
 - if (proxyenv == NULL 
 - (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) {
 + if (proxyenv == NULL  (ishttpurl || ishttpsurl)) {
   if ((p = strchr(host, '@')) != NULL) {
 - size_t authlen = (strlen(host) + 5) * 4 / 3;
 - *p = 0; /* Kill @ */
 - if ((auth = malloc(authlen)) == NULL)
 - err(1, Can't allocate memory for 
 - authorization);
 - if (b64_ntop(host, strlen(host),
 - auth, authlen) == -1)
 - errx(1, error in base64 encoding);
 + *p = '\0';
 + credentials = recode_credentials(host);
   host = p + 1;
   }
   }
 @@ -544,27 +537,14 @@ noslash:
   path = strchr(host, '@');   /* look for credentials in 
 proxy */
   if (!EMPTYSTRING(path)) {
   *path = '\0';
 - cookie = strchr(host, ':');
 - if (EMPTYSTRING(cookie)) {
 + if (strchr(host, ':') == NULL) {
   warnx(Malformed proxy URL: %s, proxyenv);
   goto 

Re: PATCH: ftp: allow @ in username for Basic Auth

2014-06-24 Thread Sébastien Marie
Hi,

As I see not activity or feedback for this one line patch, I think it
need more explain ?

Currently, when you pass an URL with user/pass embed, the code parse it
badly.

For example:
https://mym...@example.com:my-passw...@another-domain.example.com/blabla

Just before the code search if the supplied URL contains a user/pass,
the variables are:

scheme = https://;
host = mym...@example.com:my-passw...@another-domain.example.com

The code use strchr(3) on host in order to find '@' in host variable,
and separate the user/pass component and the host component.

But, with strchr the result is:
p = mymail
host = example.com:my-passw...@another-domain.example.com

The patch replace strchr(3) by strrchr(3) to obtain:
p = mym...@example.com:my-password
host = another-domain.example.com

As the hostname should not contains '@' char, and user/pass may contains
it, (as defined by rfc1738), this patch make ftp(1) to more respect
standard.

Thanks.
-- 
Sébastien Marie

On Mon, Jun 23, 2014 at 10:15:25AM +0200, Sébastien Marie wrote:
 Hi,
 
 Using ftp(1) with HTTP(S) scheme and Basic auth, it is currently not
 possible to have username (or password) with a '@' inner.
 
 For example, this URI is badly parsed:
 ftp https://mym...@example.com:my-passw...@another-domain.example.com/blabla
 
 According to RFC2617, '@' is a valid character in user-id or password:
   user-pass   = userid : password
   userid  = *TEXT excluding :
   password= *TEXT
 
 Here a patch to search the last '@' in the string (which don't contains
 the path at this time).
 
 -- 
 Sébastien Marie
 
 Index: fetch.c
 ===
 RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
 retrieving revision 1.122
 diff -u -p -r1.122 fetch.c
 --- fetch.c   20 May 2014 01:25:23 -  1.122
 +++ fetch.c   23 Jun 2014 07:46:33 -
 @@ -474,7 +474,7 @@ noslash:
*/
   if (proxyenv == NULL 
   (!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) {
 - if ((p = strchr(host, '@')) != NULL) {
 + if ((p = strrchr(host, '@')) != NULL) {
   size_t authlen = (strlen(host) + 5) * 4 / 3;
   *p = 0; /* Kill @ */
   if ((auth = malloc(authlen)) == NULL)
 



Re: PATCH: ftp: allow @ in username for Basic Auth

2014-06-24 Thread Philip Guenther
On Tue, Jun 24, 2014 at 9:01 AM, Sébastien Marie 
semarie-open...@latrappe.fr wrote:

 As I see not activity or feedback for this one line patch, I think it
 need more explain ?


Sorry, the patch is incorrect; per RFC 3986, the parser is correct to split
the authority on the first '@'.  The correct method to include an '@' in
the userinfo part is to percent-encode it as %40.


Philip Guenther


PATCH: ftp: allow @ in username for Basic Auth

2014-06-23 Thread Sébastien Marie
Hi,

Using ftp(1) with HTTP(S) scheme and Basic auth, it is currently not
possible to have username (or password) with a '@' inner.

For example, this URI is badly parsed:
ftp https://mym...@example.com:my-passw...@another-domain.example.com/blabla

According to RFC2617, '@' is a valid character in user-id or password:
  user-pass   = userid : password
  userid  = *TEXT excluding :
  password= *TEXT

Here a patch to search the last '@' in the string (which don't contains
the path at this time).

-- 
Sébastien Marie

Index: fetch.c
===
RCS file: /cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.122
diff -u -p -r1.122 fetch.c
--- fetch.c 20 May 2014 01:25:23 -  1.122
+++ fetch.c 23 Jun 2014 07:46:33 -
@@ -474,7 +474,7 @@ noslash:
 */
if (proxyenv == NULL 
(!strcmp(scheme, HTTP_URL) || !strcmp(scheme, HTTPS_URL))) {
-   if ((p = strchr(host, '@')) != NULL) {
+   if ((p = strrchr(host, '@')) != NULL) {
size_t authlen = (strlen(host) + 5) * 4 / 3;
*p = 0; /* Kill @ */
if ((auth = malloc(authlen)) == NULL)