iPXE
httpauth.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) authentication
00030  *
00031  */
00032 
00033 #include <stdio.h>
00034 #include <strings.h>
00035 #include <errno.h>
00036 #include <ipxe/http.h>
00037 
00038 /**
00039  * Identify authentication scheme
00040  *
00041  * @v http              HTTP transaction
00042  * @v name              Scheme name
00043  * @ret auth            Authentication scheme, or NULL
00044  */
00045 static struct http_authentication * http_authentication ( const char *name ) {
00046         struct http_authentication *auth;
00047 
00048         /* Identify authentication scheme */
00049         for_each_table_entry ( auth, HTTP_AUTHENTICATIONS ) {
00050                 if ( strcasecmp ( name, auth->name ) == 0 )
00051                         return auth;
00052         }
00053 
00054         return NULL;
00055 }
00056 
00057 /**
00058  * Parse HTTP "WWW-Authenticate" header
00059  *
00060  * @v http              HTTP transaction
00061  * @v line              Remaining header line
00062  * @ret rc              Return status code
00063  */
00064 static int http_parse_www_authenticate ( struct http_transaction *http,
00065                                          char *line ) {
00066         struct http_authentication *auth;
00067         char *name;
00068         int rc;
00069 
00070         /* Get scheme name */
00071         name = http_token ( &line, NULL );
00072         if ( ! name ) {
00073                 DBGC ( http, "HTTP %p malformed WWW-Authenticate \"%s\"\n",
00074                        http, line );
00075                 return -EPROTO;
00076         }
00077 
00078         /* Identify scheme */
00079         auth = http_authentication ( name );
00080         if ( ! auth ) {
00081                 DBGC ( http, "HTTP %p unrecognised authentication scheme "
00082                        "\"%s\"\n", http, name );
00083                 /* Ignore; the server may offer other schemes */
00084                 return 0;
00085         }
00086 
00087         /* Use first supported scheme */
00088         if ( http->response.auth.auth )
00089                 return 0;
00090         http->response.auth.auth = auth;
00091 
00092         /* Parse remaining header line */
00093         if ( ( rc = auth->parse ( http, line ) ) != 0 ) {
00094                 DBGC ( http, "HTTP %p could not parse %s WWW-Authenticate "
00095                        "\"%s\": %s\n", http, name, line, strerror ( rc ) );
00096                 return rc;
00097         }
00098 
00099         return 0;
00100 }
00101 
00102 /** HTTP "WWW-Authenticate" header */
00103 struct http_response_header
00104 http_response_www_authenticate __http_response_header = {
00105         .name = "WWW-Authenticate",
00106         .parse = http_parse_www_authenticate,
00107 };
00108 
00109 /**
00110  * Construct HTTP "Authorization" header
00111  *
00112  * @v http              HTTP transaction
00113  * @v buf               Buffer
00114  * @v len               Length of buffer
00115  * @ret len             Length of header value, or negative error
00116  */
00117 static int http_format_authorization ( struct http_transaction *http,
00118                                        char *buf, size_t len ) {
00119         struct http_authentication *auth = http->request.auth.auth;
00120         size_t used;
00121         int auth_len;
00122         int rc;
00123 
00124         /* Do nothing unless we have an authentication scheme */
00125         if ( ! auth )
00126                 return 0;
00127 
00128         /* Construct header */
00129         used = snprintf ( buf, len, "%s ", auth->name );
00130         auth_len = auth->format ( http, ( buf + used ),
00131                                   ( ( used < len ) ? ( len - used ) : 0 ) );
00132         if ( auth_len < 0 ) {
00133                 rc = auth_len;
00134                 return rc;
00135         }
00136         used += auth_len;
00137 
00138         return used;
00139 }
00140 
00141 /** HTTP "Authorization" header */
00142 struct http_request_header http_request_authorization __http_request_header = {
00143         .name = "Authorization",
00144         .format = http_format_authorization,
00145 };