struct uri_parser *parser = &url_parser->parser;
struct http_url *url = url_parser->url;
struct uri_authority auth;
+ const char *user = NULL, *password = NULL;
int ret;
if ((ret = uri_parse_authority(parser, &auth)) < 0)
return FALSE;
if (ret > 0) {
if (auth.enc_userinfo != NULL) {
- /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-20
+ const char *p;
- Section 2.8.1:
+ if ((url_parser->flags & HTTP_URL_ALLOW_USERINFO_PART) == 0) {
+ /* http://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-20
- {...} Senders MUST NOT include a userinfo subcomponent (and its "@"
- delimiter) when transmitting an "http" URI in a message. Recipients
- of HTTP messages that contain a URI reference SHOULD parse for the
- existence of userinfo and treat its presence as an error, likely
- indicating that the deprecated subcomponent is being used to
- obscure the authority for the sake of phishing attacks.
- */
- parser->error = "HTTP URL does not allow `userinfo@' part";
- return FALSE;
+ Section 2.8.1:
+
+ {...} Senders MUST NOT include a userinfo subcomponent (and its "@"
+ delimiter) when transmitting an "http" URI in a message. Recipients
+ of HTTP messages that contain a URI reference SHOULD parse for the
+ existence of userinfo and treat its presence as an error, likely
+ indicating that the deprecated subcomponent is being used to
+ obscure the authority for the sake of phishing attacks.
+ */
+ parser->error = "HTTP URL does not allow `userinfo@' part";
+ return FALSE;
+ }
+
+ p = strchr(auth.enc_userinfo, ':');
+ if (p == NULL) {
+ if (!uri_data_decode(parser, auth.enc_userinfo, NULL, &user))
+ return FALSE;
+ } else {
+ if (!uri_data_decode(parser, auth.enc_userinfo, p, &user))
+ return FALSE;
+ if (!uri_data_decode(parser, p+1, NULL, &password))
+ return FALSE;
+ }
}
}
if (url != NULL) {
url->have_host_ip = auth.have_host_ip;
url->port = auth.port;
url->have_port = auth.have_port;
+ url->user = p_strdup(parser->pool, user);
+ url->password = p_strdup(parser->pool, password);
}
return TRUE;
}
parser->error = "Relative HTTP URL not allowed";
return FALSE;
} else if (!have_authority && url != NULL) {
- url->host_name = p_strdup(parser->pool, base->host_name);
+ url->host_name = p_strdup_empty(parser->pool, base->host_name);
url->host_ip = base->host_ip;
url->have_host_ip = base->have_host_ip;
url->port = base->port;
url->have_port = base->have_port;
url->have_ssl = base->have_ssl;
+ url->user = p_strdup_empty(parser->pool, base->user);
+ url->password = p_strdup_empty(parser->pool, base->password);
}
url_parser->relative = TRUE;
struct ip_addr host_ip;
in_port_t port;
+ /* userinfo (not parsed by default) */
+ const char *user;
+ const char *password;
+
/* path */
const char *path;
/* Scheme part 'http:' is already parsed externally. This implies that
this is an absolute HTTP URL. */
HTTP_URL_PARSE_SCHEME_EXTERNAL = 0x01,
- /* Allow '#fragment' part in URL */
- HTTP_URL_ALLOW_FRAGMENT_PART = 0x02
+ /* Allow '#fragment' part in HTTP URL */
+ HTTP_URL_ALLOW_FRAGMENT_PART = 0x02,
+ /* Allow 'user:password@' part in HTTP URL */
+ HTTP_URL_ALLOW_USERINFO_PART = 0x04
};
int http_url_parse(const char *url, struct http_url *base,
.have_host_ip = TRUE,
.port = 8080, .have_port = TRUE }
#endif
+ },{
+ .url = "http://user@api.dovecot.org",
+ .flags = HTTP_URL_ALLOW_USERINFO_PART,
+ .url_parsed = {
+ .host_name = "api.dovecot.org", .user = "user" }
+ },{
+ .url = "http://userid:secret@api.dovecot.org",
+ .flags = HTTP_URL_ALLOW_USERINFO_PART,
+ .url_parsed = {
+ .host_name = "api.dovecot.org",
+ .user = "userid", .password = "secret" }
+ },{
+ .url = "http://su%3auserid:secret@api.dovecot.org",
+ .flags = HTTP_URL_ALLOW_USERINFO_PART,
+ .url_parsed = {
+ .host_name = "api.dovecot.org",
+ .user = "su:userid", .password = "secret" }
},{
.url = "http://www.example.com/"
"?question=What%20are%20you%20doing%3f&answer=Nothing.",
test_out("url->host_ip = (valid)",
urlp->have_host_ip == urlt->have_host_ip);
}
+ if (urlp->user == NULL || urlt->user == NULL) {
+ test_out(t_strdup_printf("url->user = %s", urlp->user),
+ urlp->user == urlt->user);
+ } else {
+ test_out(t_strdup_printf("url->user = %s", urlp->user),
+ strcmp(urlp->user, urlt->user) == 0);
+ }
+ if (urlp->password == NULL || urlt->password == NULL) {
+ test_out(t_strdup_printf("url->password = %s", urlp->password),
+ urlp->password == urlt->password);
+ } else {
+ test_out(t_strdup_printf("url->password = %s", urlp->password),
+ strcmp(urlp->password, urlt->password) == 0);
+ }
if (urlp->path == NULL || urlt->path == NULL) {
test_out(t_strdup_printf("url->path = %s", urlp->path),
urlp->path == urlt->path);