Browse Source

[http] Support MD5-sess Digest authentication

Microsoft IIS supports only MD5-sess for Digest authentication.

Requested-by: Andreas Hammarskjöld <junior@2PintSoftware.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
042a982c4d
1 changed files with 42 additions and 2 deletions
  1. 42
    2
      src/net/tcp/httpcore.c

+ 42
- 2
src/net/tcp/httpcore.c View File

@@ -120,8 +120,12 @@ enum http_flags {
120 120
 	HTTP_BASIC_AUTH = 0x0020,
121 121
 	/** Provide Digest authentication details */
122 122
 	HTTP_DIGEST_AUTH = 0x0040,
123
+	/** Include qop parameter in Digest authentication reponse */
124
+	HTTP_DIGEST_AUTH_QOP = 0x0080,
125
+	/** Use MD5-sess algorithm for Digest authentication */
126
+	HTTP_DIGEST_AUTH_MD5_SESS = 0x0100,
123 127
 	/** Socket must be reopened */
124
-	HTTP_REOPEN_SOCKET = 0x0080,
128
+	HTTP_REOPEN_SOCKET = 0x0200,
125 129
 };
126 130
 
127 131
 /** HTTP receive state */
@@ -615,6 +619,18 @@ static int http_rx_digest_auth ( struct http_request *http, char *params ) {
615 619
 			/* Not an error; "opaque" is optional */
616 620
 		}
617 621
 
622
+		/* Check for presence of qop */
623
+		if ( strstr ( params, "qop=\"" ) != NULL )
624
+			http->flags |= HTTP_DIGEST_AUTH_QOP;
625
+
626
+		/* Check for MD5-sess.  For some bizarre reason,
627
+		 * RFC2617 requires this to be unquoted, which means
628
+		 * that http_digest_param() cannot be used.
629
+		 */
630
+		if ( strstr ( params, "algorithm=MD5-sess" ) != NULL )
631
+			http->flags |= HTTP_DIGEST_AUTH_MD5_SESS;
632
+
633
+		/* Retry using digest authentication */
618 634
 		http->flags |= ( HTTP_TRY_AGAIN | HTTP_DIGEST_AUTH );
619 635
 	}
620 636
 
@@ -1133,10 +1149,13 @@ static char * http_digest_auth ( struct http_request *http,
1133 1149
 	const char *realm = http->auth_realm;
1134 1150
 	const char *nonce = http->auth_nonce;
1135 1151
 	const char *opaque = http->auth_opaque;
1152
+	char cnonce[ 9 /* "xxxxxxxx" + NUL */ ];
1136 1153
 	struct md5_context ctx;
1137 1154
 	char ha1[ base16_encoded_len ( MD5_DIGEST_SIZE ) + 1 /* NUL */ ];
1138 1155
 	char ha2[ base16_encoded_len ( MD5_DIGEST_SIZE ) + 1 /* NUL */ ];
1139 1156
 	char response[ base16_encoded_len ( MD5_DIGEST_SIZE ) + 1 /* NUL */ ];
1157
+	int qop = ( http->flags & HTTP_DIGEST_AUTH_QOP );
1158
+	int md5sess = ( qop && ( http->flags & HTTP_DIGEST_AUTH_MD5_SESS ) );
1140 1159
 	char *auth;
1141 1160
 	int len;
1142 1161
 
@@ -1145,12 +1164,22 @@ static char * http_digest_auth ( struct http_request *http,
1145 1164
 	assert ( realm != NULL );
1146 1165
 	assert ( nonce != NULL );
1147 1166
 
1167
+	/* Generate a client nonce */
1168
+	snprintf ( cnonce, sizeof ( cnonce ), "%08lx", random() );
1169
+
1148 1170
 	/* Generate HA1 */
1149 1171
 	http_digest_init ( &ctx );
1150 1172
 	http_digest_update ( &ctx, user );
1151 1173
 	http_digest_update ( &ctx, realm );
1152 1174
 	http_digest_update ( &ctx, password );
1153 1175
 	http_digest_final ( &ctx, ha1 );
1176
+	if ( md5sess ) {
1177
+		http_digest_init ( &ctx );
1178
+		http_digest_update ( &ctx, ha1 );
1179
+		http_digest_update ( &ctx, nonce );
1180
+		http_digest_update ( &ctx, cnonce );
1181
+		http_digest_final ( &ctx, ha1 );
1182
+	}
1154 1183
 
1155 1184
 	/* Generate HA2 */
1156 1185
 	http_digest_init ( &ctx );
@@ -1162,13 +1191,24 @@ static char * http_digest_auth ( struct http_request *http,
1162 1191
 	http_digest_init ( &ctx );
1163 1192
 	http_digest_update ( &ctx, ha1 );
1164 1193
 	http_digest_update ( &ctx, nonce );
1194
+	if ( qop ) {
1195
+		http_digest_update ( &ctx, "00000001" /* nc */ );
1196
+		http_digest_update ( &ctx, cnonce );
1197
+		http_digest_update ( &ctx, "auth" /* qop */ );
1198
+	}
1165 1199
 	http_digest_update ( &ctx, ha2 );
1166 1200
 	http_digest_final ( &ctx, response );
1167 1201
 
1168 1202
 	/* Generate the authorisation string */
1169 1203
 	len = asprintf ( &auth, "Authorization: Digest username=\"%s\", "
1170 1204
 			 "realm=\"%s\", nonce=\"%s\", uri=\"%s\", "
1171
-			 "%s%s%sresponse=\"%s\"\r\n", user, realm, nonce, uri,
1205
+			 "%s%s%s%s%s%s%s%sresponse=\"%s\"\r\n",
1206
+			 user, realm, nonce, uri,
1207
+			 ( qop ? "qop=\"auth\", algorithm=" : "" ),
1208
+			 ( qop ? ( md5sess ? "MD5-sess, " : "MD5, " ) : "" ),
1209
+			 ( qop ? "nc=00000001, cnonce=\"" : "" ),
1210
+			 ( qop ? cnonce : "" ),
1211
+			 ( qop ? "\", " : "" ),
1172 1212
 			 ( opaque ? "opaque=\"" : "" ),
1173 1213
 			 ( opaque ? opaque : "" ),
1174 1214
 			 ( opaque ? "\", " : "" ), response );

Loading…
Cancel
Save