diff options
author | Andrew Bartlett <abartlet@samba.org> | 2003-01-15 12:52:38 +0000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2003-01-15 12:52:38 +0000 |
commit | 58fe4d9c20203f6f55c8e995402e156becb91b3e (patch) | |
tree | d357827fbbc9caed4796b498498f7667f0368e91 /source3/libsmb | |
parent | 3095cbd63526ae474482e45175695b9fdf41cd3e (diff) | |
download | samba-58fe4d9c20203f6f55c8e995402e156becb91b3e.tar.gz samba-58fe4d9c20203f6f55c8e995402e156becb91b3e.tar.bz2 samba-58fe4d9c20203f6f55c8e995402e156becb91b3e.zip |
Refactor the NTLMSSP code again - this time we use function pointers to
eliminate the dependency on the auth subsystem. The next step is to add
the required code to 'ntlm_auth', for export to Squid etc.
Andrew Bartlett
(This used to be commit 9e48ab86da40e4c1cafa70c04fb9ebdcce23dfab)
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/cliconnect.c | 3 | ||||
-rw-r--r-- | source3/libsmb/ntlmssp.c | 278 |
2 files changed, 280 insertions, 1 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index cc3aaf92be..389b7a1733 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -465,7 +465,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, neg_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_128 | - NTLMSSP_NEGOTIATE_NTLM; + NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_REQUEST_TARGET; memset(sess_key, 0, 16); diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c new file mode 100644 index 0000000000..4183f3e77a --- /dev/null +++ b/source3/libsmb/ntlmssp.c @@ -0,0 +1,278 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + handle NLTMSSP, server side + + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Andrew Bartlett 2001-2003 + + 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 + (at your option) 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/** + * Default challange generation code. + * + */ + + +static const uint8 *get_challenge(void *cookie) +{ + static uchar chal[8]; + generate_random_buffer(chal, sizeof(chal), False); + + return chal; +} + +NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init("NTLMSSP context"); + + *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state)); + if (!*ntlmssp_state) { + DEBUG(0,("ntlmssp_start: talloc failed!\n")); + talloc_destroy(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCTP(*ntlmssp_state); + + (*ntlmssp_state)->mem_ctx = mem_ctx; + (*ntlmssp_state)->get_challenge = get_challenge; + + (*ntlmssp_state)->get_global_myname = global_myname; + (*ntlmssp_state)->get_domain = lp_workgroup; + + return NT_STATUS_OK; +} + +NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state) +{ + TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx; + + data_blob_free(&(*ntlmssp_state)->lm_resp); + data_blob_free(&(*ntlmssp_state)->nt_resp); + + SAFE_FREE((*ntlmssp_state)->user); + SAFE_FREE((*ntlmssp_state)->domain); + SAFE_FREE((*ntlmssp_state)->workstation); + + talloc_destroy(mem_ctx); + *ntlmssp_state = NULL; + return NT_STATUS_OK; +} + +NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state, + DATA_BLOB request, DATA_BLOB *reply) +{ + uint32 ntlmssp_command; + + if (!msrpc_parse(&request, "Cd", + "NTLMSSP", + &ntlmssp_command)) { + return NT_STATUS_LOGON_FAILURE; + } + + if (ntlmssp_command == NTLMSSP_NEGOTIATE) { + return ntlmssp_negotiate(ntlmssp_state, request, reply); + } else if (ntlmssp_command == NTLMSSP_AUTH) { + return ntlmssp_auth(ntlmssp_state, request, reply); + } else { + return NT_STATUS_LOGON_FAILURE; + } +} + +static const char *ntlmssp_target_name(NTLMSSP_STATE *ntlmssp_state, + uint32 neg_flags, uint32 *chal_flags) +{ + if (neg_flags & NTLMSSP_REQUEST_TARGET) { + *chal_flags |= NTLMSSP_CHAL_TARGET_INFO; + *chal_flags |= NTLMSSP_REQUEST_TARGET; + if (lp_server_role() == ROLE_STANDALONE) { + *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER; + return ntlmssp_state->get_global_myname(); + } else { + *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN; + return ntlmssp_state->get_domain(); + }; + } else { + return ""; + } +} + +NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state, + DATA_BLOB request, DATA_BLOB *reply) +{ + DATA_BLOB struct_blob; + fstring dnsname, dnsdomname; + uint32 ntlmssp_command, neg_flags, chal_flags; + char *cliname=NULL, *domname=NULL; + const uint8 *cryptkey; + const char *target_name; + + /* parse the NTLMSSP packet */ +#if 0 + file_save("ntlmssp_negotiate.dat", request.data, request.length); +#endif + + if (!msrpc_parse(&request, "CddAA", + "NTLMSSP", + &ntlmssp_command, + &neg_flags, + &cliname, + &domname)) { + return NT_STATUS_LOGON_FAILURE; + } + + SAFE_FREE(cliname); + SAFE_FREE(domname); + + debug_ntlmssp_flags(neg_flags); + + cryptkey = ntlmssp_state->get_challenge(ntlmssp_state->auth_context); + + /* Give them the challenge. For now, ignore neg_flags and just + return the flags we want. Obviously this is not correct */ + + chal_flags = + NTLMSSP_NEGOTIATE_128 | + NTLMSSP_NEGOTIATE_NTLM; + + if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { + chal_flags |= NTLMSSP_NEGOTIATE_UNICODE; + ntlmssp_state->unicode = True; + } else { + chal_flags |= NTLMSSP_NEGOTIATE_OEM; + } + + target_name = ntlmssp_target_name(ntlmssp_state, + neg_flags, &chal_flags); + + /* This should be a 'netbios domain -> DNS domain' mapping */ + dnsdomname[0] = '\0'; + get_mydomname(dnsdomname); + strlower(dnsdomname); + + dnsname[0] = '\0'; + get_myfullname(dnsname); + strlower(dnsname); + + if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) + { + const char *target_name_dns = ""; + if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) { + target_name_dns = dnsdomname; + } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) { + target_name_dns = dnsname; + } + + /* the numbers here are the string type flags */ + msrpc_gen(&struct_blob, "aaaaa", + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN, target_name, + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN_DNS, target_name_dns, + ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER_DNS, dnsdomname, + ntlmssp_state->unicode, 0, ""); + } else { + struct_blob = data_blob(NULL, 0); + } + + { + const char *gen_string; + if (ntlmssp_state->unicode) { + gen_string = "CdUdbddB"; + } else { + gen_string = "CdAdbddB"; + } + + msrpc_gen(reply, gen_string, + "NTLMSSP", + NTLMSSP_CHALLENGE, + target_name, + chal_flags, + cryptkey, 8, + 0, 0, + struct_blob.data, struct_blob.length); + } + + data_blob_free(&struct_blob); + + return NT_STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state, + DATA_BLOB request, DATA_BLOB *reply) +{ + DATA_BLOB sess_key; + uint32 ntlmssp_command, neg_flags; + NTSTATUS nt_status; + + const char *parse_string; + + /* parse the NTLMSSP packet */ +#if 0 + file_save("ntlmssp_auth.dat", request.data, request.length); +#endif + + if (ntlmssp_state->unicode) { + parse_string = "CdBBUUUBd"; + } else { + parse_string = "CdBBAAABd"; + } + + data_blob_free(&ntlmssp_state->lm_resp); + data_blob_free(&ntlmssp_state->nt_resp); + + SAFE_FREE(ntlmssp_state->user); + SAFE_FREE(ntlmssp_state->domain); + SAFE_FREE(ntlmssp_state->workstation); + + /* now the NTLMSSP encoded auth hashes */ + if (!msrpc_parse(&request, parse_string, + "NTLMSSP", + &ntlmssp_command, + &ntlmssp_state->lm_resp, + &ntlmssp_state->nt_resp, + &ntlmssp_state->domain, + &ntlmssp_state->user, + &ntlmssp_state->workstation, + &sess_key, + &neg_flags)) { + return NT_STATUS_LOGON_FAILURE; + } + + data_blob_free(&sess_key); + + DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%d len2=%d\n", + ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, ntlmssp_state->lm_resp.length, ntlmssp_state->nt_resp.length)); + +#if 0 + file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length); + file_save("lmhash1.dat", &ntlmssp_state->lm_resp.data, &ntlmssp_state->lm_resp.length); +#endif + + nt_status = ntlmssp_state->check_password(ntlmssp_state->auth_context); + + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + + *reply = data_blob(NULL, 0); + + return nt_status; +} |