From 6737a8795f20c21bb48d410c2d9266f8c9c11bbc Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 19 Feb 2018 11:58:28 +0000 Subject: [http] Allow for domain names within NTLM user names Allow a NetBIOS domain name to be specified within a URL using a syntax such as: http://domain%5Cusername:password@server/path Signed-off-by: Michael Brown --- src/core/netbios.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++ src/include/ipxe/netbios.h | 30 +++++++++++++++++++++++ src/net/tcp/httpntlm.c | 25 ++++++++++++++++--- 3 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 src/core/netbios.c create mode 100644 src/include/ipxe/netbios.h diff --git a/src/core/netbios.c b/src/core/netbios.c new file mode 100644 index 00000000..0d4e2086 --- /dev/null +++ b/src/core/netbios.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 Michael Brown . + * + * 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 + * + * NetBIOS user names + * + */ + +#include +#include +#include + +/** + * Split NetBIOS [domain\]username into separate domain and username fields + * + * @v username NetBIOS [domain\]username string + * @ret domain Domain portion of string, or NULL if no domain present + * + * This function modifies the original string by removing the + * separator. The caller may restore the string using + * netbios_domain_undo(). + */ +const char * netbios_domain ( char **username ) { + char *domain_username = *username; + char *sep; + + /* Find separator, if present */ + sep = strchr ( domain_username, '\\' ); + if ( ! sep ) + return NULL; + + /* Overwrite separator with NUL terminator and update username string */ + *sep = '\0'; + *username = ( sep + 1 ); + + return domain_username; +} diff --git a/src/include/ipxe/netbios.h b/src/include/ipxe/netbios.h new file mode 100644 index 00000000..c1155255 --- /dev/null +++ b/src/include/ipxe/netbios.h @@ -0,0 +1,30 @@ +#ifndef _IPXE_NETBIOS_H +#define _IPXE_NETBIOS_H + +/** @file + * + * NetBIOS user names + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +extern const char * netbios_domain ( char **username ); + +/** + * Restore NetBIOS [domain\]username + * + * @v domain NetBIOS domain name + * @v username NetBIOS user name + * + * Restore the separator in a NetBIOS [domain\]username as split by + * netbios_domain(). + */ +static inline void netbios_domain_undo ( const char *domain, char *username ) { + + /* Restore separator, if applicable */ + if ( domain ) + username[-1] = '\\'; +} + +#endif /* _IPXE_NETBIOS_H */ diff --git a/src/net/tcp/httpntlm.c b/src/net/tcp/httpntlm.c index 00238e96..25187bd1 100644 --- a/src/net/tcp/httpntlm.c +++ b/src/net/tcp/httpntlm.c @@ -35,6 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include struct http_authentication http_ntlm_auth __http_authentication; @@ -113,6 +114,8 @@ static int http_ntlm_authenticate ( struct http_transaction *http ) { 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 */ @@ -130,16 +133,23 @@ static int http_ntlm_authenticate ( struct http_transaction *http ) { 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 ( NULL, req->username, password, &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, NULL, req->username, + req->len = ntlm_authenticate_len ( &rsp->info, domain, username, http_ntlm_workstation ); + /* Restore NetBIOS [domain\]username */ + netbios_domain_undo ( domain, username ); + return 0; } @@ -156,6 +166,8 @@ static int http_format_ntlm_auth ( struct http_transaction *http, 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 */ @@ -173,12 +185,19 @@ static int http_format_ntlm_auth ( struct http_transaction *http, 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, NULL, req->username, + 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 ); -- cgit v1.2.3-55-g7522