2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
29 * Hyper Text Transfer Protocol (HTTP) authentication
36 #include <ipxe/http.h>
39 * Identify authentication scheme
41 * @v http HTTP transaction
43 * @ret auth Authentication scheme, or NULL
45 static struct http_authentication * http_authentication ( const char *name ) {
46 struct http_authentication *auth;
48 /* Identify authentication scheme */
49 for_each_table_entry ( auth, HTTP_AUTHENTICATIONS ) {
50 if ( strcasecmp ( name, auth->name ) == 0 )
57 /** An HTTP "WWW-Authenticate" response field */
58 struct http_www_authenticate_field {
65 /** Define an HTTP "WWW-Authenticate" response field */
66 #define HTTP_WWW_AUTHENTICATE_FIELD( _name ) { \
68 .offset = offsetof ( struct http_transaction, \
69 response.auth._name ), \
73 * Set HTTP "WWW-Authenticate" response field value
75 * @v http HTTP transaction
76 * @v field Response field
77 * @v value Field value
80 http_www_auth_field ( struct http_transaction *http,
81 struct http_www_authenticate_field *field, char *value ) {
84 ptr = ( ( ( void * ) http ) + field->offset );
88 /** HTTP "WWW-Authenticate" fields */
89 static struct http_www_authenticate_field http_www_auth_fields[] = {
90 HTTP_WWW_AUTHENTICATE_FIELD ( realm ),
91 HTTP_WWW_AUTHENTICATE_FIELD ( qop ),
92 HTTP_WWW_AUTHENTICATE_FIELD ( algorithm ),
93 HTTP_WWW_AUTHENTICATE_FIELD ( nonce ),
94 HTTP_WWW_AUTHENTICATE_FIELD ( opaque ),
98 * Parse HTTP "WWW-Authenticate" header
100 * @v http HTTP transaction
101 * @v line Remaining header line
102 * @ret rc Return status code
104 static int http_parse_www_authenticate ( struct http_transaction *http,
106 struct http_www_authenticate_field *field;
112 /* Get scheme name */
113 name = http_token ( &line, NULL );
115 DBGC ( http, "HTTP %p malformed WWW-Authenticate \"%s\"\n",
120 /* Identify scheme */
121 http->response.auth.auth = http_authentication ( name );
122 if ( ! http->response.auth.auth ) {
123 DBGC ( http, "HTTP %p unrecognised authentication scheme "
124 "\"%s\"\n", http, name );
129 while ( ( key = http_token ( &line, &value ) ) ) {
130 for ( i = 0 ; i < ( sizeof ( http_www_auth_fields ) /
131 sizeof ( http_www_auth_fields[0] ) ) ; i++){
132 field = &http_www_auth_fields[i];
133 if ( strcasecmp ( key, field->name ) == 0 )
134 http_www_auth_field ( http, field, value );
138 /* Allow HTTP request to be retried if the request had not
139 * already tried authentication.
141 if ( ! http->request.auth.auth )
142 http->response.flags |= HTTP_RESPONSE_RETRY;
147 /** HTTP "WWW-Authenticate" header */
148 struct http_response_header
149 http_response_www_authenticate __http_response_header = {
150 .name = "WWW-Authenticate",
151 .parse = http_parse_www_authenticate,
155 * Construct HTTP "Authorization" header
157 * @v http HTTP transaction
159 * @v len Length of buffer
160 * @ret len Length of header value, or negative error
162 static int http_format_authorization ( struct http_transaction *http,
163 char *buf, size_t len ) {
164 struct http_authentication *auth = http->request.auth.auth;
169 /* Do nothing unless we have an authentication scheme */
173 /* Construct header */
174 used = snprintf ( buf, len, "%s ", auth->name );
175 auth_len = auth->format ( http, ( buf + used ),
176 ( ( used < len ) ? ( len - used ) : 0 ) );
177 if ( auth_len < 0 ) {
186 /** HTTP "Authorization" header */
187 struct http_request_header http_request_authorization __http_request_header = {
188 .name = "Authorization",
189 .format = http_format_authorization,