| /* | |
| * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. | |
| * | |
| * This program is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU General Public License as | |
| * published by the Free Software Foundation; either version 2 of the | |
| * License, or any later version. | |
| * | |
| * This program is distributed in the hope that it will be useful, but | |
| * WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with this program; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| * 02110-1301, USA. | |
| * | |
| * You can also choose to distribute this program under the terms of | |
| * the Unmodified Binary Distribution Licence (as given in the file | |
| * COPYING.UBDL), provided that you have satisfied its requirements. | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| FILE_SECBOOT ( PERMITTED ); | |
| /** | |
| * @file | |
| * | |
| * Hyper Text Transfer Protocol (HTTP) Basic authentication | |
| * | |
| */ | |
| #include <stdio.h> | |
| #include <errno.h> | |
| #include <ipxe/uri.h> | |
| #include <ipxe/base64.h> | |
| #include <ipxe/http.h> | |
| /* Disambiguate the various error causes */ | |
| #define EACCES_USERNAME __einfo_error ( EINFO_EACCES_USERNAME ) | |
| #define EINFO_EACCES_USERNAME \ | |
| __einfo_uniqify ( EINFO_EACCES, 0x01, \ | |
| "No username available for Basic authentication" ) | |
| /** | |
| * Parse HTTP "WWW-Authenticate" header for Basic authentication | |
| * | |
| * @v http HTTP transaction | |
| * @v line Remaining header line | |
| * @ret rc Return status code | |
| */ | |
| static int http_parse_basic_auth ( struct http_transaction *http, | |
| char *line __unused ) { | |
| /* Allow HTTP request to be retried if the request had not | |
| * already tried authentication. | |
| */ | |
| if ( ! http->request.auth.auth ) | |
| http->response.flags |= HTTP_RESPONSE_RETRY; | |
| return 0; | |
| } | |
| /** | |
| * Perform HTTP Basic authentication | |
| * | |
| * @v http HTTP transaction | |
| * @ret rc Return status code | |
| */ | |
| static int http_basic_authenticate ( struct http_transaction *http ) { | |
| struct http_request_auth_basic *req = &http->request.auth.basic; | |
| /* Record username and password */ | |
| if ( ! http->uri->user ) { | |
| DBGC ( http, "HTTP %p has no username for Basic " | |
| "authentication\n", http ); | |
| return -EACCES_USERNAME; | |
| } | |
| req->username = http->uri->user; | |
| req->password = ( http->uri->password ? http->uri->password : "" ); | |
| return 0; | |
| } | |
| /** | |
| * Construct HTTP "Authorization" header for Basic authentication | |
| * | |
| * @v http HTTP transaction | |
| * @v buf Buffer | |
| * @v len Length of buffer | |
| * @ret len Length of header value, or negative error | |
| */ | |
| static int http_format_basic_auth ( struct http_transaction *http, | |
| char *buf, size_t len ) { | |
| struct http_request_auth_basic *req = &http->request.auth.basic; | |
| size_t user_pw_len = ( strlen ( req->username ) + 1 /* ":" */ + | |
| strlen ( req->password ) ); | |
| char user_pw[ user_pw_len + 1 /* NUL */ ]; | |
| /* Sanity checks */ | |
| assert ( req->username != NULL ); | |
| assert ( req->password != NULL ); | |
| /* Construct "user:password" string */ | |
| snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", | |
| req->username, req->password ); | |
| /* Construct response */ | |
| return base64_encode ( user_pw, user_pw_len, buf, len ); | |
| } | |
| /** HTTP Basic authentication scheme */ | |
| struct http_authentication http_basic_auth __http_authentication = { | |
| .name = "Basic", | |
| .parse = http_parse_basic_auth, | |
| .authenticate = http_basic_authenticate, | |
| .format = http_format_basic_auth, | |
| }; | |
| /* Drag in HTTP authentication support */ | |
| REQUIRING_SYMBOL ( http_basic_auth ); | |
| REQUIRE_OBJECT ( httpauth ); |