iPXE
Functions | Variables
httpntlm.c File Reference

Hyper Text Transfer Protocol (HTTP) NTLM authentication. More...

#include <string.h>
#include <errno.h>
#include <ipxe/uri.h>
#include <ipxe/base64.h>
#include <ipxe/ntlm.h>
#include <ipxe/netbios.h>
#include <ipxe/http.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int http_parse_ntlm_auth (struct http_transaction *http, char *line)
 Parse HTTP "WWW-Authenticate" header for NTLM authentication.
static int http_ntlm_authenticate (struct http_transaction *http)
 Perform HTTP NTLM authentication.
static int http_format_ntlm_auth (struct http_transaction *http, char *buf, size_t len)
 Construct HTTP "Authorization" header for NTLM authentication.
 REQUIRING_SYMBOL (http_ntlm_auth)
 REQUIRE_OBJECT (httpauth)

Variables

struct http_authentication
http_ntlm_auth 
__http_authentication
 HTTP NTLM authentication scheme.
static const char http_ntlm_workstation [] = "iPXE"
 Workstation name used for NTLM authentication.

Detailed Description

Hyper Text Transfer Protocol (HTTP) NTLM authentication.

Definition in file httpntlm.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int http_parse_ntlm_auth ( struct http_transaction http,
char *  line 
) [static]

Parse HTTP "WWW-Authenticate" header for NTLM authentication.

Parameters:
httpHTTP transaction
lineRemaining header line
Return values:
rcReturn status code

Definition at line 53 of file httpntlm.c.

References http_request_auth::auth, http_request::auth, http_response::auth, base64_decode(), http_response_auth_ntlm::challenge, DBGC, ENOMEM, http_response::flags, free, HTTP_RESPONSE_RETRY, http_response_auth_ntlm::info, http_request_auth_ntlm::len, len, http_request_auth::ntlm, http_response_auth::ntlm, NULL, rc, http_transaction::request, http_transaction::response, rsp, strdup(), strerror(), and strlen().

                                                                              {
        struct http_response_auth_ntlm *rsp = &http->response.auth.ntlm;
        char *copy;
        int len;
        int rc;

        /* Create temporary copy of Base64-encoded challenge message */
        copy = strdup ( line );
        if ( ! copy ) {
                rc = -ENOMEM;
                goto err_alloc;
        }

        /* Decode challenge message, overwriting the original */
        len = base64_decode ( copy, line, strlen ( line ) );
        if ( len < 0 ) {
                rc = len;
                DBGC ( http, "HTTP %p could not decode NTLM challenge "
                       "\"%s\": %s\n", http, copy, strerror ( rc ) );
                goto err_decode;
        }

        /* Parse challenge, if present */
        if ( len ) {
                rsp->challenge = ( ( void * ) line );
                if ( ( rc = ntlm_challenge ( rsp->challenge, len,
                                             &rsp->info ) ) != 0 ) {
                        DBGC ( http, "HTTP %p could not parse NTLM challenge: "
                               "%s\n", http, strerror ( rc ) );
                        goto err_challenge;
                }
        }

        /* Allow HTTP request to be retried if the request had not
         * already tried authentication.  Note that NTLM requires an
         * additional round trip to obtain the challenge message,
         * which is not present in the initial WWW-Authenticate.
         */
        if ( ( http->request.auth.auth == NULL ) ||
             ( ( http->request.auth.auth == &http_ntlm_auth ) &&
               ( http->request.auth.ntlm.len == 0 ) && len ) ) {
                http->response.flags |= HTTP_RESPONSE_RETRY;
        }

        /* Success */
        rc = 0;

 err_challenge:
 err_decode:
        free ( copy );
 err_alloc:
        return rc;
}
static int http_ntlm_authenticate ( struct http_transaction http) [static]

Perform HTTP NTLM authentication.

Parameters:
httpHTTP transaction
Return values:
rcReturn status code

Definition at line 113 of file httpntlm.c.

References http_request::auth, http_response::auth, http_response_auth_ntlm::challenge, DBGC, domain, EACCES, http_ntlm_workstation, http_response_auth_ntlm::info, http_request_auth_ntlm::len, http_request_auth_ntlm::lm, netbios_domain(), netbios_domain_undo(), http_request_auth_ntlm::nt, http_request_auth::ntlm, http_response_auth::ntlm, ntlm_authenticate_len(), ntlm_key(), ntlm_response(), NULL, uri::password, http_transaction::request, http_transaction::response, rsp, http_transaction::uri, uri::user, and http_request_auth_ntlm::username.

                                                                    {
        struct http_request_auth_ntlm *req = &http->request.auth.ntlm;
        struct http_response_auth_ntlm *rsp = &http->response.auth.ntlm;
        struct ntlm_key key;
        const char *domain;
        char *username;
        const char *password;

        /* If we have no challenge yet, then just send a Negotiate message */
        if ( ! rsp->challenge ) {
                DBGC ( http, "HTTP %p sending NTLM Negotiate\n", http );
                return 0;
        }

        /* Record username */
        if ( ! http->uri->user ) {
                DBGC ( http, "HTTP %p has no username for NTLM "
                       "authentication\n", http );
                return -EACCES;
        }
        req->username = http->uri->user;
        password = ( http->uri->password ? http->uri->password : "" );

        /* Split NetBIOS [domain\]username */
        username = ( ( char * ) req->username );
        domain = netbios_domain ( &username );

        /* Generate key */
        ntlm_key ( domain, username, password, &key );

        /* Generate responses */
        ntlm_response ( &rsp->info, &key, NULL, &req->lm, &req->nt );

        /* Calculate Authenticate message length */
        req->len = ntlm_authenticate_len ( &rsp->info, domain, username,
                                           http_ntlm_workstation );

        /* Restore NetBIOS [domain\]username */
        netbios_domain_undo ( domain, username );

        return 0;
}
static int http_format_ntlm_auth ( struct http_transaction http,
char *  buf,
size_t  len 
) [static]

Construct HTTP "Authorization" header for NTLM authentication.

Parameters:
httpHTTP transaction
bufBuffer
lenLength of buffer
Return values:
lenLength of header value, or negative error

Definition at line 164 of file httpntlm.c.

References assert, http_request::auth, http_response::auth, base64_encode(), base64_encoded_len(), http_response_auth_ntlm::challenge, domain, ENOMEM, free, http_ntlm_workstation, http_response_auth_ntlm::info, http_request_auth_ntlm::len, len, http_request_auth_ntlm::lm, malloc(), netbios_domain(), netbios_domain_undo(), http_request_auth_ntlm::nt, http_request_auth::ntlm, http_response_auth::ntlm, ntlm_authenticate(), http_transaction::request, http_transaction::response, rsp, and http_request_auth_ntlm::username.

                                                           {
        struct http_request_auth_ntlm *req = &http->request.auth.ntlm;
        struct http_response_auth_ntlm *rsp = &http->response.auth.ntlm;
        struct ntlm_authenticate *auth;
        const char *domain;
        char *username;
        size_t check;

        /* If we have no challenge yet, then just send a Negotiate message */
        if ( ! rsp->challenge ) {
                return base64_encode ( &ntlm_negotiate,
                                       sizeof ( ntlm_negotiate ), buf, len );
        }

        /* Skip allocation if just calculating length */
        if ( ! len )
                return base64_encoded_len ( req->len );

        /* Allocate temporary buffer for Authenticate message */
        auth = malloc ( req->len );
        if ( ! auth )
                return -ENOMEM;

        /* Split NetBIOS [domain\]username */
        username = ( ( char * ) req->username );
        domain = netbios_domain ( &username );

        /* Construct raw Authenticate message */
        check = ntlm_authenticate ( &rsp->info, domain, username,
                                    http_ntlm_workstation, &req->lm,
                                    &req->nt, auth );
        assert ( check == req->len );

        /* Restore NetBIOS [domain\]username */
        netbios_domain_undo ( domain, username );

        /* Base64-encode Authenticate message */
        len = base64_encode ( auth, req->len, buf, len );

        /* Free raw Authenticate message */
        free ( auth );

        return len;
}
REQUIRING_SYMBOL ( http_ntlm_auth  )
REQUIRE_OBJECT ( httpauth  )

Variable Documentation

Initial value:
 {
        .name = "NTLM",
        .parse = http_parse_ntlm_auth,
        .authenticate = http_ntlm_authenticate,
        .format = http_format_ntlm_auth,
}

HTTP NTLM authentication scheme.

Definition at line 41 of file httpntlm.c.

const char http_ntlm_workstation[] = "iPXE" [static]

Workstation name used for NTLM authentication.

Definition at line 44 of file httpntlm.c.

Referenced by http_format_ntlm_auth(), and http_ntlm_authenticate().