iPXE
httpbasic.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /**
00027  * @file
00028  *
00029  * Hyper Text Transfer Protocol (HTTP) Basic authentication
00030  *
00031  */
00032 
00033 #include <stdio.h>
00034 #include <errno.h>
00035 #include <ipxe/uri.h>
00036 #include <ipxe/base64.h>
00037 #include <ipxe/http.h>
00038 
00039 /* Disambiguate the various error causes */
00040 #define EACCES_USERNAME __einfo_error ( EINFO_EACCES_USERNAME )
00041 #define EINFO_EACCES_USERNAME                                           \
00042         __einfo_uniqify ( EINFO_EACCES, 0x01,                           \
00043                           "No username available for Basic authentication" )
00044 
00045 /**
00046  * Parse HTTP "WWW-Authenticate" header for Basic authentication
00047  *
00048  * @v http              HTTP transaction
00049  * @v line              Remaining header line
00050  * @ret rc              Return status code
00051  */
00052 static int http_parse_basic_auth ( struct http_transaction *http,
00053                                    char *line __unused ) {
00054 
00055         /* Allow HTTP request to be retried if the request had not
00056          * already tried authentication.
00057          */
00058         if ( ! http->request.auth.auth )
00059                 http->response.flags |= HTTP_RESPONSE_RETRY;
00060 
00061         return 0;
00062 }
00063 
00064 /**
00065  * Perform HTTP Basic authentication
00066  *
00067  * @v http              HTTP transaction
00068  * @ret rc              Return status code
00069  */
00070 static int http_basic_authenticate ( struct http_transaction *http ) {
00071         struct http_request_auth_basic *req = &http->request.auth.basic;
00072 
00073         /* Record username and password */
00074         if ( ! http->uri->user ) {
00075                 DBGC ( http, "HTTP %p has no username for Basic "
00076                        "authentication\n", http );
00077                 return -EACCES_USERNAME;
00078         }
00079         req->username = http->uri->user;
00080         req->password = ( http->uri->password ? http->uri->password : "" );
00081 
00082         return 0;
00083 }
00084 
00085 /**
00086  * Construct HTTP "Authorization" header for Basic authentication
00087  *
00088  * @v http              HTTP transaction
00089  * @v buf               Buffer
00090  * @v len               Length of buffer
00091  * @ret len             Length of header value, or negative error
00092  */
00093 static int http_format_basic_auth ( struct http_transaction *http,
00094                                     char *buf, size_t len ) {
00095         struct http_request_auth_basic *req = &http->request.auth.basic;
00096         size_t user_pw_len = ( strlen ( req->username ) + 1 /* ":" */ +
00097                                strlen ( req->password ) );
00098         char user_pw[ user_pw_len + 1 /* NUL */ ];
00099 
00100         /* Sanity checks */
00101         assert ( req->username != NULL );
00102         assert ( req->password != NULL );
00103 
00104         /* Construct "user:password" string */
00105         snprintf ( user_pw, sizeof ( user_pw ), "%s:%s",
00106                    req->username, req->password );
00107 
00108         /* Construct response */
00109         return base64_encode ( user_pw, user_pw_len, buf, len );
00110 }
00111 
00112 /** HTTP Basic authentication scheme */
00113 struct http_authentication http_basic_auth __http_authentication = {
00114         .name = "Basic",
00115         .parse = http_parse_basic_auth,
00116         .authenticate = http_basic_authenticate,
00117         .format = http_format_basic_auth,
00118 };
00119 
00120 /* Drag in HTTP authentication support */
00121 REQUIRING_SYMBOL ( http_basic_auth );
00122 REQUIRE_OBJECT ( httpauth );