~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/auth/ntlmssp/ntlmssp_server.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/Netbios implementation.
 
3
   Version 3.0
 
4
   handle NLTMSSP, client server side parsing
 
5
 
 
6
   Copyright (C) Andrew Tridgell      2001
 
7
   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
 
8
   Copyright (C) Stefan Metzmacher 2005
 
9
 
 
10
   This program is free software; you can redistribute it and/or modify
 
11
   it under the terms of the GNU General Public License as published by
 
12
   the Free Software Foundation; either version 3 of the License, or
 
13
   (at your option) any later version.
 
14
   
 
15
   This program is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
   GNU General Public License for more details.
 
19
   
 
20
   You should have received a copy of the GNU General Public License
 
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
22
*/
 
23
 
 
24
#include "includes.h"
 
25
#include "system/network.h"
 
26
#include "auth/ntlmssp/ntlmssp.h"
 
27
#include "auth/ntlmssp/msrpc_parse.h"
 
28
#include "../lib/crypto/crypto.h"
 
29
#include "libcli/auth/libcli_auth.h"
 
30
#include "auth/credentials/credentials.h"
 
31
#include "auth/gensec/gensec.h"
 
32
#include "auth/auth.h"
 
33
#include "auth/ntlm/auth_proto.h"
 
34
#include "param/param.h"
 
35
#include "auth/session_proto.h"
 
36
 
 
37
/** 
 
38
 * Set a username on an NTLMSSP context - ensures it is talloc()ed 
 
39
 *
 
40
 */
 
41
 
 
42
static NTSTATUS ntlmssp_set_username(struct gensec_ntlmssp_state *gensec_ntlmssp_state, const char *user) 
 
43
{
 
44
        if (!user) {
 
45
                /* it should be at least "" */
 
46
                DEBUG(1, ("NTLMSSP failed to set username - cannot accept NULL username\n"));
 
47
                return NT_STATUS_INVALID_PARAMETER;
 
48
        }
 
49
        gensec_ntlmssp_state->user = talloc_strdup(gensec_ntlmssp_state, user);
 
50
        if (!gensec_ntlmssp_state->user) {
 
51
                return NT_STATUS_NO_MEMORY;
 
52
        }
 
53
        return NT_STATUS_OK;
 
54
}
 
55
 
 
56
/** 
 
57
 * Set a domain on an NTLMSSP context - ensures it is talloc()ed 
 
58
 *
 
59
 */
 
60
static NTSTATUS ntlmssp_set_domain(struct gensec_ntlmssp_state *gensec_ntlmssp_state, const char *domain) 
 
61
{
 
62
        gensec_ntlmssp_state->domain = talloc_strdup(gensec_ntlmssp_state, domain);
 
63
        if (!gensec_ntlmssp_state->domain) {
 
64
                return NT_STATUS_NO_MEMORY;
 
65
        }
 
66
        return NT_STATUS_OK;
 
67
}
 
68
 
 
69
/** 
 
70
 * Set a workstation on an NTLMSSP context - ensures it is talloc()ed 
 
71
 *
 
72
 */
 
73
static NTSTATUS ntlmssp_set_workstation(struct gensec_ntlmssp_state *gensec_ntlmssp_state, const char *workstation) 
 
74
{
 
75
        gensec_ntlmssp_state->workstation = talloc_strdup(gensec_ntlmssp_state, workstation);
 
76
        if (!gensec_ntlmssp_state->workstation) {
 
77
                return NT_STATUS_NO_MEMORY;
 
78
        }
 
79
        return NT_STATUS_OK;
 
80
}
 
81
 
 
82
/**
 
83
 * Determine correct target name flags for reply, given server role 
 
84
 * and negotiated flags
 
85
 * 
 
86
 * @param gensec_ntlmssp_state NTLMSSP State
 
87
 * @param neg_flags The flags from the packet
 
88
 * @param chal_flags The flags to be set in the reply packet
 
89
 * @return The 'target name' string.
 
90
 */
 
91
 
 
92
static const char *ntlmssp_target_name(struct gensec_ntlmssp_state *gensec_ntlmssp_state,
 
93
                                       uint32_t neg_flags, uint32_t *chal_flags) 
 
94
{
 
95
        if (neg_flags & NTLMSSP_REQUEST_TARGET) {
 
96
                *chal_flags |= NTLMSSP_CHAL_TARGET_INFO;
 
97
                *chal_flags |= NTLMSSP_REQUEST_TARGET;
 
98
                if (gensec_ntlmssp_state->server_role == ROLE_STANDALONE) {
 
99
                        *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER;
 
100
                        return gensec_ntlmssp_state->server_name;
 
101
                } else {
 
102
                        *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN;
 
103
                        return gensec_ntlmssp_state->domain;
 
104
                };
 
105
        } else {
 
106
                return "";
 
107
        }
 
108
}
 
109
 
 
110
 
 
111
 
 
112
/**
 
113
 * Next state function for the Negotiate packet
 
114
 * 
 
115
 * @param gensec_security GENSEC state
 
116
 * @param out_mem_ctx Memory context for *out
 
117
 * @param in The request, as a DATA_BLOB.  reply.data must be NULL
 
118
 * @param out The reply, as an allocated DATA_BLOB, caller to free.
 
119
 * @return Errors or MORE_PROCESSING_REQUIRED if (normal) a reply is required. 
 
120
 */
 
121
 
 
122
NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security, 
 
123
                                  TALLOC_CTX *out_mem_ctx, 
 
124
                                  const DATA_BLOB in, DATA_BLOB *out) 
 
125
{
 
126
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
 
127
        DATA_BLOB struct_blob;
 
128
        uint32_t neg_flags = 0;
 
129
        uint32_t ntlmssp_command, chal_flags;
 
130
        const uint8_t *cryptkey;
 
131
        const char *target_name;
 
132
 
 
133
        /* parse the NTLMSSP packet */
 
134
#if 0
 
135
        file_save("ntlmssp_negotiate.dat", request.data, request.length);
 
136
#endif
 
137
 
 
138
        if (in.length) {
 
139
                if ((in.length < 16) || !msrpc_parse(out_mem_ctx, 
 
140
                                                         &in, "Cdd",
 
141
                                                         "NTLMSSP",
 
142
                                                         &ntlmssp_command,
 
143
                                                         &neg_flags)) {
 
144
                        DEBUG(1, ("ntlmssp_server_negotiate: failed to parse "
 
145
                                "NTLMSSP Negotiate of length %u:\n",
 
146
                                (unsigned int)in.length ));
 
147
                        dump_data(2, in.data, in.length);
 
148
                        return NT_STATUS_INVALID_PARAMETER;
 
149
                }
 
150
                debug_ntlmssp_flags(neg_flags);
 
151
        }
 
152
        
 
153
        ntlmssp_handle_neg_flags(gensec_ntlmssp_state, neg_flags, gensec_ntlmssp_state->allow_lm_key);
 
154
 
 
155
        /* Ask our caller what challenge they would like in the packet */
 
156
        cryptkey = gensec_ntlmssp_state->get_challenge(gensec_ntlmssp_state);
 
157
        if (!cryptkey) {
 
158
                DEBUG(1, ("ntlmssp_server_negotiate: backend doesn't give a challenge\n"));
 
159
                return NT_STATUS_INTERNAL_ERROR;
 
160
        }
 
161
 
 
162
        /* Check if we may set the challenge */
 
163
        if (!gensec_ntlmssp_state->may_set_challenge(gensec_ntlmssp_state)) {
 
164
                gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
 
165
        }
 
166
 
 
167
        /* The flags we send back are not just the negotiated flags,
 
168
         * they are also 'what is in this packet'.  Therfore, we
 
169
         * operate on 'chal_flags' from here on 
 
170
         */
 
171
 
 
172
        chal_flags = gensec_ntlmssp_state->neg_flags;
 
173
 
 
174
        /* get the right name to fill in as 'target' */
 
175
        target_name = ntlmssp_target_name(gensec_ntlmssp_state, 
 
176
                                          neg_flags, &chal_flags); 
 
177
        if (target_name == NULL) 
 
178
                return NT_STATUS_INVALID_PARAMETER;
 
179
 
 
180
        gensec_ntlmssp_state->chal = data_blob_talloc(gensec_ntlmssp_state, cryptkey, 8);
 
181
        gensec_ntlmssp_state->internal_chal = data_blob_talloc(gensec_ntlmssp_state, cryptkey, 8);
 
182
 
 
183
        /* This creates the 'blob' of names that appears at the end of the packet */
 
184
        if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
 
185
                char dnsdomname[MAXHOSTNAMELEN], dnsname[MAXHOSTNAMELEN];
 
186
                const char *target_name_dns = "";
 
187
 
 
188
                /* Find out the DNS domain name */
 
189
                dnsdomname[0] = '\0';
 
190
                safe_strcpy(dnsdomname, lp_realm(gensec_security->settings->lp_ctx), sizeof(dnsdomname) - 1);
 
191
                strlower_m(dnsdomname);
 
192
 
 
193
                /* Find out the DNS host name */
 
194
                safe_strcpy(dnsname, gensec_ntlmssp_state->server_name, sizeof(dnsname) - 1);
 
195
                if (dnsdomname[0] != '\0') {
 
196
                        safe_strcat(dnsname, ".", sizeof(dnsname) - 1);
 
197
                        safe_strcat(dnsname, dnsdomname, sizeof(dnsname) - 1);
 
198
                }
 
199
                strlower_m(dnsname);
 
200
 
 
201
                if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) {
 
202
                        target_name_dns = dnsdomname;
 
203
                } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) {
 
204
                        target_name_dns = dnsname;
 
205
                }
 
206
 
 
207
                msrpc_gen(out_mem_ctx, 
 
208
                          &struct_blob, "aaaaa",
 
209
                          NTLMSSP_NAME_TYPE_DOMAIN, target_name,
 
210
                          NTLMSSP_NAME_TYPE_SERVER, gensec_ntlmssp_state->server_name,
 
211
                          NTLMSSP_NAME_TYPE_DOMAIN_DNS, dnsdomname,
 
212
                          NTLMSSP_NAME_TYPE_SERVER_DNS, dnsname,
 
213
                          0, "");
 
214
        } else {
 
215
                struct_blob = data_blob(NULL, 0);
 
216
        }
 
217
 
 
218
        {
 
219
                /* Marshal the packet in the right format, be it unicode or ASCII */
 
220
                const char *gen_string;
 
221
                if (gensec_ntlmssp_state->unicode) {
 
222
                        gen_string = "CdUdbddB";
 
223
                } else {
 
224
                        gen_string = "CdAdbddB";
 
225
                }
 
226
                
 
227
                msrpc_gen(out_mem_ctx, 
 
228
                          out, gen_string,
 
229
                          "NTLMSSP", 
 
230
                          NTLMSSP_CHALLENGE,
 
231
                          target_name,
 
232
                          chal_flags,
 
233
                          cryptkey, 8,
 
234
                          0, 0,
 
235
                          struct_blob.data, struct_blob.length);
 
236
        }
 
237
                
 
238
        gensec_ntlmssp_state->expected_state = NTLMSSP_AUTH;
 
239
 
 
240
        return NT_STATUS_MORE_PROCESSING_REQUIRED;
 
241
}
 
242
 
 
243
/**
 
244
 * Next state function for the Authenticate packet
 
245
 * 
 
246
 * @param gensec_ntlmssp_state NTLMSSP State
 
247
 * @param request The request, as a DATA_BLOB
 
248
 * @return Errors or NT_STATUS_OK. 
 
249
 */
 
250
 
 
251
static NTSTATUS ntlmssp_server_preauth(struct gensec_ntlmssp_state *gensec_ntlmssp_state,
 
252
                                       const DATA_BLOB request) 
 
253
{
 
254
        uint32_t ntlmssp_command, auth_flags;
 
255
        NTSTATUS nt_status;
 
256
 
 
257
        uint8_t session_nonce_hash[16];
 
258
 
 
259
        const char *parse_string;
 
260
        char *domain = NULL;
 
261
        char *user = NULL;
 
262
        char *workstation = NULL;
 
263
 
 
264
#if 0
 
265
        file_save("ntlmssp_auth.dat", request.data, request.length);
 
266
#endif
 
267
 
 
268
        if (gensec_ntlmssp_state->unicode) {
 
269
                parse_string = "CdBBUUUBd";
 
270
        } else {
 
271
                parse_string = "CdBBAAABd";
 
272
        }
 
273
 
 
274
        /* zero these out */
 
275
        data_blob_free(&gensec_ntlmssp_state->lm_resp);
 
276
        data_blob_free(&gensec_ntlmssp_state->nt_resp);
 
277
        data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
278
 
 
279
        gensec_ntlmssp_state->user = NULL;
 
280
        gensec_ntlmssp_state->domain = NULL;
 
281
        gensec_ntlmssp_state->workstation = NULL;
 
282
 
 
283
        /* now the NTLMSSP encoded auth hashes */
 
284
        if (!msrpc_parse(gensec_ntlmssp_state, 
 
285
                         &request, parse_string,
 
286
                         "NTLMSSP", 
 
287
                         &ntlmssp_command, 
 
288
                         &gensec_ntlmssp_state->lm_resp,
 
289
                         &gensec_ntlmssp_state->nt_resp,
 
290
                         &domain, 
 
291
                         &user, 
 
292
                         &workstation,
 
293
                         &gensec_ntlmssp_state->encrypted_session_key,
 
294
                         &auth_flags)) {
 
295
                DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n"));
 
296
                dump_data(10, request.data, request.length);
 
297
 
 
298
                /* zero this out */
 
299
                data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
300
                auth_flags = 0;
 
301
                
 
302
                /* Try again with a shorter string (Win9X truncates this packet) */
 
303
                if (gensec_ntlmssp_state->unicode) {
 
304
                        parse_string = "CdBBUUU";
 
305
                } else {
 
306
                        parse_string = "CdBBAAA";
 
307
                }
 
308
 
 
309
                /* now the NTLMSSP encoded auth hashes */
 
310
                if (!msrpc_parse(gensec_ntlmssp_state, 
 
311
                                 &request, parse_string,
 
312
                                 "NTLMSSP", 
 
313
                                 &ntlmssp_command, 
 
314
                                 &gensec_ntlmssp_state->lm_resp,
 
315
                                 &gensec_ntlmssp_state->nt_resp,
 
316
                                 &domain, 
 
317
                                 &user, 
 
318
                                 &workstation)) {
 
319
                        DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n"));
 
320
                        dump_data(2, request.data, request.length);
 
321
 
 
322
                        return NT_STATUS_INVALID_PARAMETER;
 
323
                }
 
324
        }
 
325
 
 
326
        if (auth_flags)
 
327
                ntlmssp_handle_neg_flags(gensec_ntlmssp_state, auth_flags, gensec_ntlmssp_state->allow_lm_key);
 
328
 
 
329
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(gensec_ntlmssp_state, domain))) {
 
330
                /* zero this out */
 
331
                data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
332
                return nt_status;
 
333
        }
 
334
 
 
335
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(gensec_ntlmssp_state, user))) {
 
336
                /* zero this out */
 
337
                data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
338
                return nt_status;
 
339
        }
 
340
 
 
341
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(gensec_ntlmssp_state, workstation))) {
 
342
                /* zero this out */
 
343
                data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
344
                return nt_status;
 
345
        }
 
346
 
 
347
        DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
 
348
                 gensec_ntlmssp_state->user, gensec_ntlmssp_state->domain, gensec_ntlmssp_state->workstation, (unsigned long)gensec_ntlmssp_state->lm_resp.length, (unsigned long)gensec_ntlmssp_state->nt_resp.length));
 
349
 
 
350
#if 0
 
351
        file_save("nthash1.dat",  &gensec_ntlmssp_state->nt_resp.data,  &gensec_ntlmssp_state->nt_resp.length);
 
352
        file_save("lmhash1.dat",  &gensec_ntlmssp_state->lm_resp.data,  &gensec_ntlmssp_state->lm_resp.length);
 
353
#endif
 
354
 
 
355
        /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a 
 
356
           client challenge 
 
357
        
 
358
           However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
 
359
        */
 
360
        if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
 
361
                if (gensec_ntlmssp_state->nt_resp.length == 24 && gensec_ntlmssp_state->lm_resp.length == 24) {
 
362
                        struct MD5Context md5_session_nonce_ctx;
 
363
                        SMB_ASSERT(gensec_ntlmssp_state->internal_chal.data 
 
364
                                   && gensec_ntlmssp_state->internal_chal.length == 8);
 
365
                        
 
366
                        gensec_ntlmssp_state->doing_ntlm2 = true;
 
367
 
 
368
                        memcpy(gensec_ntlmssp_state->crypt.ntlm2.session_nonce, gensec_ntlmssp_state->internal_chal.data, 8);
 
369
                        memcpy(&gensec_ntlmssp_state->crypt.ntlm2.session_nonce[8], gensec_ntlmssp_state->lm_resp.data, 8);
 
370
                        
 
371
                        MD5Init(&md5_session_nonce_ctx);
 
372
                        MD5Update(&md5_session_nonce_ctx, gensec_ntlmssp_state->crypt.ntlm2.session_nonce, 16);
 
373
                        MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
 
374
                        
 
375
                        gensec_ntlmssp_state->chal = data_blob_talloc(gensec_ntlmssp_state, 
 
376
                                                               session_nonce_hash, 8);
 
377
 
 
378
                        /* LM response is no longer useful, zero it out */
 
379
                        data_blob_free(&gensec_ntlmssp_state->lm_resp);
 
380
 
 
381
                        /* We changed the effective challenge - set it */
 
382
                        if (!NT_STATUS_IS_OK(nt_status = 
 
383
                                             gensec_ntlmssp_state->set_challenge(gensec_ntlmssp_state, 
 
384
                                                                                 &gensec_ntlmssp_state->chal))) {
 
385
                                /* zero this out */
 
386
                                data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
387
                                return nt_status;
 
388
                        }
 
389
 
 
390
                        /* LM Key is incompatible... */
 
391
                        gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
 
392
                }
 
393
        }
 
394
        return NT_STATUS_OK;
 
395
}
 
396
 
 
397
/**
 
398
 * Next state function for the Authenticate packet 
 
399
 * (after authentication - figures out the session keys etc)
 
400
 * 
 
401
 * @param gensec_ntlmssp_state NTLMSSP State
 
402
 * @return Errors or NT_STATUS_OK. 
 
403
 */
 
404
 
 
405
static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security, 
 
406
                                        DATA_BLOB *user_session_key, 
 
407
                                        DATA_BLOB *lm_session_key) 
 
408
{
 
409
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
 
410
        NTSTATUS nt_status;
 
411
        DATA_BLOB session_key = data_blob(NULL, 0);
 
412
 
 
413
        if (user_session_key)
 
414
                dump_data_pw("USER session key:\n", user_session_key->data, user_session_key->length);
 
415
 
 
416
        if (lm_session_key) 
 
417
                dump_data_pw("LM first-8:\n", lm_session_key->data, lm_session_key->length);
 
418
 
 
419
        /* Handle the different session key derivation for NTLM2 */
 
420
        if (gensec_ntlmssp_state->doing_ntlm2) {
 
421
                if (user_session_key && user_session_key->data && user_session_key->length == 16) {
 
422
                        session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
 
423
                        hmac_md5(user_session_key->data, gensec_ntlmssp_state->crypt.ntlm2.session_nonce, 
 
424
                                 sizeof(gensec_ntlmssp_state->crypt.ntlm2.session_nonce), session_key.data);
 
425
                        DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
 
426
                        dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
 
427
                        
 
428
                } else {
 
429
                        DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
 
430
                        session_key = data_blob(NULL, 0);
 
431
                }
 
432
        } else if ((gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
 
433
                /* Ensure we can never get here on NTLMv2 */
 
434
                && (gensec_ntlmssp_state->nt_resp.length == 0 || gensec_ntlmssp_state->nt_resp.length == 24)) {
 
435
 
 
436
                if (lm_session_key && lm_session_key->data && lm_session_key->length >= 8) {
 
437
                        if (gensec_ntlmssp_state->lm_resp.data && gensec_ntlmssp_state->lm_resp.length == 24) {
 
438
                                session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
 
439
                                SMBsesskeygen_lm_sess_key(lm_session_key->data, gensec_ntlmssp_state->lm_resp.data, 
 
440
                                                          session_key.data);
 
441
                                DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
 
442
                                dump_data_pw("LM session key:\n", session_key.data, session_key.length);
 
443
                        } else {
 
444
                                
 
445
                                /* When there is no LM response, just use zeros */
 
446
                                static const uint8_t zeros[24];
 
447
                                session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);
 
448
                                SMBsesskeygen_lm_sess_key(zeros, zeros, 
 
449
                                                          session_key.data);
 
450
                                DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
 
451
                                dump_data_pw("LM session key:\n", session_key.data, session_key.length);
 
452
                        }
 
453
                } else {
 
454
                        /* LM Key not selected */
 
455
                        gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
 
456
 
 
457
                        DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
 
458
                        session_key = data_blob(NULL, 0);
 
459
                }
 
460
 
 
461
        } else if (user_session_key && user_session_key->data) {
 
462
                session_key = *user_session_key;
 
463
                DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
 
464
                dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
 
465
 
 
466
                /* LM Key not selected */
 
467
                gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
 
468
 
 
469
        } else if (lm_session_key && lm_session_key->data) {
 
470
                /* Very weird to have LM key, but no user session key, but anyway.. */
 
471
                session_key = *lm_session_key;
 
472
                DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
 
473
                dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
 
474
 
 
475
                /* LM Key not selected */
 
476
                gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
 
477
 
 
478
        } else {
 
479
                DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
 
480
                session_key = data_blob(NULL, 0);
 
481
 
 
482
                /* LM Key not selected */
 
483
                gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
 
484
        }
 
485
 
 
486
        /* With KEY_EXCH, the client supplies the proposed session key, 
 
487
           but encrypts it with the long-term key */
 
488
        if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
 
489
                if (!gensec_ntlmssp_state->encrypted_session_key.data 
 
490
                    || gensec_ntlmssp_state->encrypted_session_key.length != 16) {
 
491
                        data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
492
                        DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", 
 
493
                                  (unsigned)gensec_ntlmssp_state->encrypted_session_key.length));
 
494
                        return NT_STATUS_INVALID_PARAMETER;
 
495
                } else if (!session_key.data || session_key.length != 16) {
 
496
                        DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", 
 
497
                                  (unsigned)session_key.length));
 
498
                        gensec_ntlmssp_state->session_key = session_key;
 
499
                } else {
 
500
                        dump_data_pw("KEY_EXCH session key (enc):\n", 
 
501
                                     gensec_ntlmssp_state->encrypted_session_key.data, 
 
502
                                     gensec_ntlmssp_state->encrypted_session_key.length);
 
503
                        arcfour_crypt(gensec_ntlmssp_state->encrypted_session_key.data, 
 
504
                                      session_key.data, 
 
505
                                      gensec_ntlmssp_state->encrypted_session_key.length);
 
506
                        gensec_ntlmssp_state->session_key = data_blob_talloc(gensec_ntlmssp_state, 
 
507
                                                                      gensec_ntlmssp_state->encrypted_session_key.data, 
 
508
                                                                      gensec_ntlmssp_state->encrypted_session_key.length);
 
509
                        dump_data_pw("KEY_EXCH session key:\n", gensec_ntlmssp_state->encrypted_session_key.data, 
 
510
                                     gensec_ntlmssp_state->encrypted_session_key.length);
 
511
                }
 
512
        } else {
 
513
                gensec_ntlmssp_state->session_key = session_key;
 
514
        }
 
515
 
 
516
        /* keep the session key around on the new context */
 
517
        talloc_steal(gensec_ntlmssp_state, session_key.data);
 
518
 
 
519
        if ((gensec_security->want_features & GENSEC_FEATURE_SIGN)
 
520
            || (gensec_security->want_features & GENSEC_FEATURE_SEAL)) {
 
521
                nt_status = ntlmssp_sign_init(gensec_ntlmssp_state);
 
522
        } else {
 
523
                nt_status = NT_STATUS_OK;
 
524
        }
 
525
 
 
526
        data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);
 
527
        
 
528
        /* allow arbitarily many authentications, but watch that this will cause a 
 
529
           memory leak, until the gensec_ntlmssp_state is shutdown 
 
530
        */
 
531
 
 
532
        if (gensec_ntlmssp_state->server_multiple_authentications) {
 
533
                gensec_ntlmssp_state->expected_state = NTLMSSP_AUTH;
 
534
        } else {
 
535
                gensec_ntlmssp_state->expected_state = NTLMSSP_DONE;
 
536
        }
 
537
 
 
538
        return nt_status;
 
539
}
 
540
 
 
541
 
 
542
/**
 
543
 * Next state function for the Authenticate packet
 
544
 * 
 
545
 * @param gensec_security GENSEC state
 
546
 * @param out_mem_ctx Memory context for *out
 
547
 * @param in The request, as a DATA_BLOB.  reply.data must be NULL
 
548
 * @param out The reply, as an allocated DATA_BLOB, caller to free.
 
549
 * @return Errors or NT_STATUS_OK if authentication sucessful
 
550
 */
 
551
 
 
552
NTSTATUS ntlmssp_server_auth(struct gensec_security *gensec_security, 
 
553
                             TALLOC_CTX *out_mem_ctx, 
 
554
                             const DATA_BLOB in, DATA_BLOB *out) 
 
555
{       
 
556
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
 
557
        DATA_BLOB user_session_key = data_blob(NULL, 0);
 
558
        DATA_BLOB lm_session_key = data_blob(NULL, 0);
 
559
        NTSTATUS nt_status;
 
560
 
 
561
        TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
 
562
        if (!mem_ctx) {
 
563
                return NT_STATUS_NO_MEMORY;
 
564
        }
 
565
 
 
566
        /* zero the outbound NTLMSSP packet */
 
567
        *out = data_blob_talloc(out_mem_ctx, NULL, 0);
 
568
 
 
569
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_preauth(gensec_ntlmssp_state, in))) {
 
570
                talloc_free(mem_ctx);
 
571
                return nt_status;
 
572
        }
 
573
 
 
574
        /*
 
575
         * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
 
576
         * is required (by "ntlm auth = no" and "lm auth = no" being set in the
 
577
         * smb.conf file) and no NTLMv2 response was sent then the password check
 
578
         * will fail here. JRA.
 
579
         */
 
580
 
 
581
        /* Finally, actually ask if the password is OK */
 
582
 
 
583
        if (!NT_STATUS_IS_OK(nt_status = gensec_ntlmssp_state->check_password(gensec_ntlmssp_state, mem_ctx,
 
584
                                                                              &user_session_key, &lm_session_key))) {
 
585
                talloc_free(mem_ctx);
 
586
                return nt_status;
 
587
        }
 
588
        
 
589
        if (gensec_security->want_features
 
590
            & (GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL|GENSEC_FEATURE_SESSION_KEY)) {
 
591
                nt_status = ntlmssp_server_postauth(gensec_security, &user_session_key, &lm_session_key);
 
592
                talloc_free(mem_ctx);
 
593
                return nt_status;
 
594
        } else {
 
595
                gensec_ntlmssp_state->session_key = data_blob(NULL, 0);
 
596
                talloc_free(mem_ctx);
 
597
                return NT_STATUS_OK;
 
598
        }
 
599
}
 
600
 
 
601
/**
 
602
 * Return the challenge as determined by the authentication subsystem 
 
603
 * @return an 8 byte random challenge
 
604
 */
 
605
 
 
606
static const uint8_t *auth_ntlmssp_get_challenge(const struct gensec_ntlmssp_state *gensec_ntlmssp_state)
 
607
{
 
608
        NTSTATUS status;
 
609
        const uint8_t *chal;
 
610
 
 
611
        status = gensec_ntlmssp_state->auth_context->get_challenge(gensec_ntlmssp_state->auth_context, &chal);
 
612
        if (!NT_STATUS_IS_OK(status)) {
 
613
                DEBUG(1, ("auth_ntlmssp_get_challenge: failed to get challenge: %s\n",
 
614
                        nt_errstr(status)));
 
615
                return NULL;
 
616
        }
 
617
 
 
618
        return chal;
 
619
}
 
620
 
 
621
/**
 
622
 * Some authentication methods 'fix' the challenge, so we may not be able to set it
 
623
 *
 
624
 * @return If the effective challenge used by the auth subsystem may be modified
 
625
 */
 
626
static bool auth_ntlmssp_may_set_challenge(const struct gensec_ntlmssp_state *gensec_ntlmssp_state)
 
627
{
 
628
        return gensec_ntlmssp_state->auth_context->challenge_may_be_modified(gensec_ntlmssp_state->auth_context);
 
629
}
 
630
 
 
631
/**
 
632
 * NTLM2 authentication modifies the effective challenge, 
 
633
 * @param challenge The new challenge value
 
634
 */
 
635
static NTSTATUS auth_ntlmssp_set_challenge(struct gensec_ntlmssp_state *gensec_ntlmssp_state, DATA_BLOB *challenge)
 
636
{
 
637
        NTSTATUS nt_status;
 
638
        struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;
 
639
        const uint8_t *chal;
 
640
 
 
641
        if (challenge->length != 8) {
 
642
                return NT_STATUS_INVALID_PARAMETER;
 
643
        }
 
644
 
 
645
        chal = challenge->data;
 
646
 
 
647
        nt_status = gensec_ntlmssp_state->auth_context->set_challenge(auth_context, 
 
648
                                                                      chal, 
 
649
                                                                      "NTLMSSP callback (NTLM2)");
 
650
 
 
651
        return nt_status;
 
652
}
 
653
 
 
654
/**
 
655
 * Check the password on an NTLMSSP login.  
 
656
 *
 
657
 * Return the session keys used on the connection.
 
658
 */
 
659
 
 
660
static NTSTATUS auth_ntlmssp_check_password(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 
 
661
                                            TALLOC_CTX *mem_ctx, 
 
662
                                            DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 
 
663
{
 
664
        NTSTATUS nt_status;
 
665
        struct auth_usersupplied_info *user_info = talloc(mem_ctx, struct auth_usersupplied_info);
 
666
        if (!user_info) {
 
667
                return NT_STATUS_NO_MEMORY;
 
668
        }
 
669
 
 
670
        user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
 
671
        user_info->flags = 0;
 
672
        user_info->mapped_state = false;
 
673
        user_info->client.account_name = gensec_ntlmssp_state->user;
 
674
        user_info->client.domain_name = gensec_ntlmssp_state->domain;
 
675
        user_info->workstation_name = gensec_ntlmssp_state->workstation;
 
676
        user_info->remote_host = gensec_get_peer_addr(gensec_ntlmssp_state->gensec_security);
 
677
 
 
678
        user_info->password_state = AUTH_PASSWORD_RESPONSE;
 
679
        user_info->password.response.lanman = gensec_ntlmssp_state->lm_resp;
 
680
        user_info->password.response.lanman.data = talloc_steal(user_info, gensec_ntlmssp_state->lm_resp.data);
 
681
        user_info->password.response.nt = gensec_ntlmssp_state->nt_resp;
 
682
        user_info->password.response.nt.data = talloc_steal(user_info, gensec_ntlmssp_state->nt_resp.data);
 
683
 
 
684
        nt_status = gensec_ntlmssp_state->auth_context->check_password(gensec_ntlmssp_state->auth_context, 
 
685
                                                                       mem_ctx,
 
686
                                                                       user_info, 
 
687
                                                                       &gensec_ntlmssp_state->server_info);
 
688
        talloc_free(user_info);
 
689
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
690
 
 
691
        talloc_steal(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info);
 
692
 
 
693
        if (gensec_ntlmssp_state->server_info->user_session_key.length) {
 
694
                DEBUG(10, ("Got NT session key of length %u\n", 
 
695
                           (unsigned)gensec_ntlmssp_state->server_info->user_session_key.length));
 
696
                if (!talloc_reference(mem_ctx, gensec_ntlmssp_state->server_info->user_session_key.data)) {
 
697
                        return NT_STATUS_NO_MEMORY;
 
698
                }
 
699
 
 
700
                *user_session_key = gensec_ntlmssp_state->server_info->user_session_key;
 
701
        }
 
702
        if (gensec_ntlmssp_state->server_info->lm_session_key.length) {
 
703
                DEBUG(10, ("Got LM session key of length %u\n", 
 
704
                           (unsigned)gensec_ntlmssp_state->server_info->lm_session_key.length));
 
705
                if (!talloc_reference(mem_ctx, gensec_ntlmssp_state->server_info->lm_session_key.data)) {
 
706
                        return NT_STATUS_NO_MEMORY;
 
707
                }
 
708
 
 
709
                *lm_session_key = gensec_ntlmssp_state->server_info->lm_session_key;
 
710
        }
 
711
        return nt_status;
 
712
}
 
713
 
 
714
/** 
 
715
 * Return the credentials of a logged on user, including session keys
 
716
 * etc.
 
717
 *
 
718
 * Only valid after a successful authentication
 
719
 *
 
720
 * May only be called once per authentication.
 
721
 *
 
722
 */
 
723
 
 
724
NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,
 
725
                                     struct auth_session_info **session_info) 
 
726
{
 
727
        NTSTATUS nt_status;
 
728
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
 
729
 
 
730
        nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_security->event_ctx, gensec_security->settings->lp_ctx, gensec_ntlmssp_state->server_info, session_info);
 
731
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
732
 
 
733
        (*session_info)->session_key = data_blob_talloc(*session_info, 
 
734
                                                        gensec_ntlmssp_state->session_key.data,
 
735
                                                        gensec_ntlmssp_state->session_key.length);
 
736
 
 
737
        return NT_STATUS_OK;
 
738
}
 
739
 
 
740
/**
 
741
 * Start NTLMSSP on the server side 
 
742
 *
 
743
 */
 
744
NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)
 
745
{
 
746
        NTSTATUS nt_status;
 
747
        struct gensec_ntlmssp_state *gensec_ntlmssp_state;
 
748
 
 
749
        nt_status = gensec_ntlmssp_start(gensec_security);
 
750
        NT_STATUS_NOT_OK_RETURN(nt_status);
 
751
 
 
752
        gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;
 
753
 
 
754
        gensec_ntlmssp_state->role = NTLMSSP_SERVER;
 
755
 
 
756
        gensec_ntlmssp_state->workstation = NULL;
 
757
        gensec_ntlmssp_state->server_name = lp_netbios_name(gensec_security->settings->lp_ctx);
 
758
 
 
759
        gensec_ntlmssp_state->domain = lp_workgroup(gensec_security->settings->lp_ctx);
 
760
 
 
761
        gensec_ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;
 
762
 
 
763
        gensec_ntlmssp_state->allow_lm_key = (lp_lanman_auth(gensec_security->settings->lp_ctx) 
 
764
                                          && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false));
 
765
 
 
766
        gensec_ntlmssp_state->server_multiple_authentications = false;
 
767
        
 
768
        gensec_ntlmssp_state->neg_flags = 
 
769
                NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_UNKNOWN_02000000;
 
770
 
 
771
        gensec_ntlmssp_state->lm_resp = data_blob(NULL, 0);
 
772
        gensec_ntlmssp_state->nt_resp = data_blob(NULL, 0);
 
773
        gensec_ntlmssp_state->encrypted_session_key = data_blob(NULL, 0);
 
774
 
 
775
        if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) {
 
776
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;               
 
777
        }
 
778
 
 
779
        if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) {
 
780
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;                
 
781
        }
 
782
 
 
783
        if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) {
 
784
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;          
 
785
        }
 
786
 
 
787
        if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) {
 
788
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;               
 
789
        }
 
790
 
 
791
        if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) {
 
792
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;             
 
793
        }
 
794
 
 
795
        if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
 
796
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
 
797
        }
 
798
        if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
 
799
                gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
 
800
        }
 
801
 
 
802
        gensec_ntlmssp_state->auth_context = gensec_security->auth_context;
 
803
 
 
804
        gensec_ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;
 
805
        gensec_ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;
 
806
        gensec_ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;
 
807
        gensec_ntlmssp_state->check_password = auth_ntlmssp_check_password;
 
808
        gensec_ntlmssp_state->server_role = lp_server_role(gensec_security->settings->lp_ctx);
 
809
 
 
810
        return NT_STATUS_OK;
 
811
}
 
812