dovecot-2.2: lib-http: Added (non-default) support for parsing u...

dovecot at dovecot.org dovecot at dovecot.org
Tue Sep 17 21:58:06 EEST 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/ec9eab188dd8
changeset: 16761:ec9eab188dd8
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Tue Sep 17 21:57:48 2013 +0300
description:
lib-http: Added (non-default) support for parsing user:pasword from HTTP URL.

diffstat:

 src/lib-http/http-url.c      |  44 ++++++++++++++++++++++++++++++++------------
 src/lib-http/http-url.h      |  10 ++++++++--
 src/lib-http/test-http-url.c |  31 +++++++++++++++++++++++++++++++
 3 files changed, 71 insertions(+), 14 deletions(-)

diffs (156 lines):

diff -r 6be5d8d8af2d -r ec9eab188dd8 src/lib-http/http-url.c
--- a/src/lib-http/http-url.c	Tue Sep 17 21:57:14 2013 +0300
+++ b/src/lib-http/http-url.c	Tue Sep 17 21:57:48 2013 +0300
@@ -32,25 +32,41 @@
 	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) {
@@ -59,6 +75,8 @@
 		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;
 }
@@ -210,12 +228,14 @@
 			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;
diff -r 6be5d8d8af2d -r ec9eab188dd8 src/lib-http/http-url.h
--- a/src/lib-http/http-url.h	Tue Sep 17 21:57:14 2013 +0300
+++ b/src/lib-http/http-url.h	Tue Sep 17 21:57:48 2013 +0300
@@ -11,6 +11,10 @@
 	struct ip_addr host_ip;
 	in_port_t port;
 
+	/* userinfo (not parsed by default) */
+	const char *user;
+	const char *password;
+
 	/* path */
 	const char *path;
 
@@ -33,8 +37,10 @@
 	/* 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,
diff -r 6be5d8d8af2d -r ec9eab188dd8 src/lib-http/test-http-url.c
--- a/src/lib-http/test-http-url.c	Tue Sep 17 21:57:14 2013 +0300
+++ b/src/lib-http/test-http-url.c	Tue Sep 17 21:57:48 2013 +0300
@@ -48,6 +48,23 @@
 			.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.",
 		.url_parsed = {
@@ -296,6 +313,20 @@
 				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);


More information about the dovecot-cvs mailing list