2 Unix SMB/Netbios implementation.
4 handle NLTMSSP, server side
6 Copyright (C) Andrew Tridgell 2001
7 Copyright (C) Andrew Bartlett 2001-2003
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
31 mem_ctx = talloc_init("NTLMSSP context");
33 *ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state));
34 if (!*ntlmssp_state) {
35 DEBUG(0,("ntlmssp_start: talloc failed!\n"));
36 talloc_destroy(mem_ctx);
37 return NT_STATUS_NO_MEMORY;
40 ZERO_STRUCTP(*ntlmssp_state);
42 (*ntlmssp_state)->mem_ctx = mem_ctx;
44 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&(*ntlmssp_state)->auth_context))) {
50 NTSTATUS ntlmssp_server_end(NTLMSSP_STATE **ntlmssp_state)
52 TALLOC_CTX *mem_ctx = (*ntlmssp_state)->mem_ctx;
53 if ((*ntlmssp_state)->auth_context) {
54 ((*ntlmssp_state)->auth_context->free)(&(*ntlmssp_state)->auth_context);
56 if ((*ntlmssp_state)->server_info) {
57 free_server_info(&(*ntlmssp_state)->server_info);
60 talloc_destroy(mem_ctx);
64 NTSTATUS ntlmssp_server_update(NTLMSSP_STATE *ntlmssp_state,
65 DATA_BLOB request, DATA_BLOB *reply)
67 uint32 ntlmssp_command;
69 if (!msrpc_parse(&request, "Cd",
72 return NT_STATUS_LOGON_FAILURE;
75 if (ntlmssp_command == NTLMSSP_NEGOTIATE) {
76 return ntlmssp_negotiate(ntlmssp_state, request, reply);
77 } else if (ntlmssp_command == NTLMSSP_AUTH) {
78 return ntlmssp_auth(ntlmssp_state, request, reply);
80 return NT_STATUS_LOGON_FAILURE;
84 static const char *ntlmssp_target_name(uint32 neg_flags, uint32 *chal_flags)
86 if (neg_flags & NTLMSSP_REQUEST_TARGET) {
87 if (lp_server_role() == ROLE_STANDALONE) {
88 *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
89 return global_myname();
91 *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
92 return lp_workgroup();
99 NTSTATUS ntlmssp_negotiate(NTLMSSP_STATE *ntlmssp_state,
100 DATA_BLOB request, DATA_BLOB *reply)
102 DATA_BLOB struct_blob;
103 fstring dnsname, dnsdomname;
104 uint32 ntlmssp_command, neg_flags, chal_flags;
105 char *cliname=NULL, *domname=NULL;
106 const uint8 *cryptkey;
107 const char *target_name;
109 /* parse the NTLMSSP packet */
111 file_save("ntlmssp_negotiate.dat", request.data, request.length);
114 if (!msrpc_parse(&request, "CddAA",
120 return NT_STATUS_LOGON_FAILURE;
126 debug_ntlmssp_flags(neg_flags);
128 cryptkey = ntlmssp_state->auth_context->get_ntlm_challenge(ntlmssp_state->auth_context);
130 /* Give them the challenge. For now, ignore neg_flags and just
131 return the flags we want. Obviously this is not correct */
134 NTLMSSP_NEGOTIATE_128 |
135 NTLMSSP_NEGOTIATE_NTLM |
136 NTLMSSP_CHAL_TARGET_INFO;
138 if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
139 chal_flags |= NTLMSSP_NEGOTIATE_UNICODE;
140 ntlmssp_state->unicode = True;
142 chal_flags |= NTLMSSP_NEGOTIATE_OEM;
145 target_name = ntlmssp_target_name(neg_flags, &chal_flags);
147 dnsdomname[0] = '\0';
148 get_mydomname(dnsdomname);
149 strlower(dnsdomname);
152 get_myfullname(dnsname);
155 /* the numbers here are the string type flags */
156 msrpc_gen(&struct_blob, "aaaaa",
157 ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN, lp_workgroup(),
158 ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER, global_myname(),
159 ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsname,
160 ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER_DNS, dnsdomname,
161 ntlmssp_state->unicode, 0, "");
164 const char *gen_string;
165 if (ntlmssp_state->unicode) {
166 gen_string = "CdUdbddB";
168 gen_string = "CdAdbddB";
171 msrpc_gen(reply, gen_string,
178 struct_blob.data, struct_blob.length);
181 data_blob_free(&struct_blob);
183 return NT_STATUS_MORE_PROCESSING_REQUIRED;
186 NTSTATUS ntlmssp_auth(NTLMSSP_STATE *ntlmssp_state,
187 DATA_BLOB request, DATA_BLOB *reply)
189 char *workgroup = NULL, *user = NULL, *machine = NULL;
190 DATA_BLOB lmhash, nthash, sess_key;
191 DATA_BLOB plaintext_password = data_blob(NULL, 0);
192 uint32 ntlmssp_command, neg_flags;
194 uint32 auth_flags = AUTH_FLAG_NONE;
195 auth_usersupplied_info *user_info = NULL;
197 const char *parse_string;
199 /* parse the NTLMSSP packet */
201 file_save("ntlmssp_auth.dat", request.data, request.length);
204 if (ntlmssp_state->unicode) {
205 parse_string = "CdBBUUUBd";
207 parse_string = "CdBBAAABd";
210 /* now the NTLMSSP encoded auth hashes */
211 if (!msrpc_parse(&request, parse_string,
221 return NT_STATUS_LOGON_FAILURE;
224 data_blob_free(&sess_key);
226 DEBUG(3,("Got user=[%s] workgroup=[%s] machine=[%s] len1=%d len2=%d\n",
227 user, workgroup, machine, lmhash.length, nthash.length));
229 /* the client has given us its machine name (which we otherwise would not get on port 445).
230 we need to possibly reload smb.conf if smb.conf includes depend on the machine name */
232 set_remote_machine_name(machine);
234 /* setup the string used by %U */
235 sub_set_smb_name(user);
237 reload_services(True);
240 file_save("nthash1.dat", nthash.data, nthash.length);
241 file_save("lmhash1.dat", lmhash.data, lmhash.length);
245 auth_flags |= AUTH_FLAG_LM_RESP;
248 if (nthash.length == 24) {
249 auth_flags |= AUTH_FLAG_NTLM_RESP;
250 } else if (nthash.length > 24) {
251 auth_flags |= AUTH_FLAG_NTLMv2_RESP;
256 nt_status = make_user_info_map(&user_info, user, workgroup, machine,
257 lmhash, nthash, plaintext_password,
260 ntlmssp_state->orig_user = talloc_strdup(ntlmssp_state->mem_ctx, user);
261 ntlmssp_state->orig_domain = talloc_strdup(ntlmssp_state->mem_ctx, workgroup);
264 SAFE_FREE(workgroup);
267 if (!NT_STATUS_IS_OK(nt_status)) {
271 nt_status = ntlmssp_state->auth_context->check_ntlm_password(ntlmssp_state->auth_context, user_info, &ntlmssp_state->server_info);
273 (ntlmssp_state->auth_context->free)(&ntlmssp_state->auth_context);
275 free_user_info(&user_info);
277 data_blob_free(&lmhash);
279 data_blob_free(&nthash);
281 *reply = data_blob(NULL, 0);