r11661: Store the INFO3 in the PAC data into the netsamlogon_cache.
[samba.git] / source / smbd / sesssetup.c
1 /* 
2    Unix SMB/CIFS implementation.
3    handle SMBsessionsetup
4    Copyright (C) Andrew Tridgell 1998-2001
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7    Copyright (C) Luke Howard          2003
8
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.
13    
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.
18    
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.
22 */
23
24 #include "includes.h"
25
26 uint32 global_client_caps = 0;
27
28 /*
29   on a logon error possibly map the error to success if "map to guest"
30   is set approriately
31 */
32 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
33                                 const char *user, const char *domain)
34 {
35         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
36                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || 
37                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
38                         DEBUG(3,("No such user %s [%s] - using guest account\n",
39                                  user, domain));
40                         status = make_server_info_guest(server_info);
41                 }
42         }
43
44         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
45                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
46                         DEBUG(3,("Registered username %s for guest access\n",user));
47                         status = make_server_info_guest(server_info);
48                 }
49         }
50
51         return status;
52 }
53
54 /****************************************************************************
55  Add the standard 'Samba' signature to the end of the session setup.
56 ****************************************************************************/
57
58 static int add_signature(char *outbuf, char *p)
59 {
60         char *start = p;
61         fstring lanman;
62
63         fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
64
65         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
66         p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
67         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
68
69         return PTR_DIFF(p, start);
70 }
71
72 /****************************************************************************
73  Send a security blob via a session setup reply.
74 ****************************************************************************/
75
76 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
77                                  DATA_BLOB blob, NTSTATUS nt_status)
78 {
79         char *p;
80
81         set_message(outbuf,4,0,True);
82
83         nt_status = nt_status_squash(nt_status);
84         SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
85         SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
86         SSVAL(outbuf, smb_vwv3, blob.length);
87         p = smb_buf(outbuf);
88
89         /* should we cap this? */
90         memcpy(p, blob.data, blob.length);
91         p += blob.length;
92
93         p += add_signature( outbuf, p );
94
95         set_message_end(outbuf,p);
96
97         show_msg(outbuf);
98         return send_smb(smbd_server_fd(),outbuf);
99 }
100
101 /****************************************************************************
102  Do a 'guest' logon, getting back the 
103 ****************************************************************************/
104
105 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) 
106 {
107         struct auth_context *auth_context;
108         auth_usersupplied_info *user_info = NULL;
109         
110         NTSTATUS nt_status;
111         unsigned char chal[8];
112
113         ZERO_STRUCT(chal);
114
115         DEBUG(3,("Got anonymous request\n"));
116
117         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
118                 return nt_status;
119         }
120
121         if (!make_user_info_guest(&user_info)) {
122                 (auth_context->free)(&auth_context);
123                 return NT_STATUS_NO_MEMORY;
124         }
125         
126         nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
127         (auth_context->free)(&auth_context);
128         free_user_info(&user_info);
129         return nt_status;
130 }
131
132
133 #ifdef HAVE_KRB5
134 /****************************************************************************
135 reply to a session setup spnego negotiate packet for kerberos
136 ****************************************************************************/
137 static int reply_spnego_kerberos(connection_struct *conn, 
138                                  char *inbuf, char *outbuf,
139                                  int length, int bufsize,
140                                  DATA_BLOB *secblob)
141 {
142         TALLOC_CTX *mem_ctx;
143         DATA_BLOB ticket;
144         char *client, *p, *domain;
145         fstring netbios_domain_name;
146         struct passwd *pw;
147         fstring user;
148         int sess_vuid;
149         NTSTATUS ret;
150         PAC_DATA *pac_data;
151         DATA_BLOB ap_rep, ap_rep_wrapped, response;
152         auth_serversupplied_info *server_info = NULL;
153         DATA_BLOB session_key = data_blob(NULL, 0);
154         uint8 tok_id[2];
155         DATA_BLOB nullblob = data_blob(NULL, 0);
156         fstring real_username;
157         BOOL map_domainuser_to_guest = False;
158         PAC_LOGON_INFO *logon_info = NULL;
159
160         ZERO_STRUCT(ticket);
161         ZERO_STRUCT(pac_data);
162         ZERO_STRUCT(ap_rep);
163         ZERO_STRUCT(ap_rep_wrapped);
164         ZERO_STRUCT(response);
165
166         mem_ctx = talloc_init("reply_spnego_kerberos");
167         if (mem_ctx == NULL)
168                 return ERROR_NT(NT_STATUS_NO_MEMORY);
169
170         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
171                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
172         }
173
174         ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
175
176         data_blob_free(&ticket);
177
178         if (!NT_STATUS_IS_OK(ret)) {
179                 DEBUG(1,("Failed to verify incoming ticket!\n"));       
180                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
181         }
182
183         DEBUG(3,("Ticket name is [%s]\n", client));
184
185         p = strchr_m(client, '@');
186         if (!p) {
187                 DEBUG(3,("Doesn't look like a valid principal\n"));
188                 data_blob_free(&ap_rep);
189                 data_blob_free(&session_key);
190                 SAFE_FREE(client);
191                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
192         }
193
194         *p = 0;
195
196         /* save the PAC data if we have it */
197
198         if (pac_data) {
199                 logon_info = get_logon_info_from_pac(pac_data);
200                 netsamlogon_cache_store( client, &logon_info->info3 );
201         }
202
203         if (!strequal(p+1, lp_realm())) {
204                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
205                 if (!lp_allow_trusted_domains()) {
206                         data_blob_free(&ap_rep);
207                         data_blob_free(&session_key);
208                         SAFE_FREE(client);
209                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
210                 }
211         }
212
213         /* this gives a fully qualified user name (ie. with full realm).
214            that leads to very long usernames, but what else can we do? */
215
216         domain = p+1;
217
218         if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
219
220                 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
221                 domain = netbios_domain_name;
222                 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
223
224         } else {
225
226                 /* If we have winbind running, we can (and must) shorten the
227                    username by using the short netbios name. Otherwise we will
228                    have inconsistent user names. With Kerberos, we get the
229                    fully qualified realm, with ntlmssp we get the short
230                    name. And even w2k3 does use ntlmssp if you for example
231                    connect to an ip address. */
232
233                 struct winbindd_request wb_request;
234                 struct winbindd_response wb_response;
235                 NSS_STATUS wb_result;
236
237                 ZERO_STRUCT(wb_request);
238                 ZERO_STRUCT(wb_response);
239
240                 DEBUG(10, ("Mapping [%s] to short name\n", domain));
241
242                 fstrcpy(wb_request.domain_name, domain);
243
244                 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
245                                              &wb_request, &wb_response);
246
247                 if (wb_result == NSS_STATUS_SUCCESS) {
248
249                         fstrcpy(netbios_domain_name,
250                                 wb_response.data.domain_info.name);
251                         domain = netbios_domain_name;
252
253                         DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
254                 } else {
255                         DEBUG(3, ("Could not find short name -- winbind "
256                                   "not running?\n"));
257                 }
258         }
259
260         fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
261         
262         /* lookup the passwd struct, create a new user if necessary */
263
264         map_username( user );
265
266         pw = smb_getpwnam( user, real_username, True );
267         if (!pw) {
268
269                 /* this was originally the behavior of Samba 2.2, if a user
270                    did not have a local uid but has been authenticated, then 
271                    map them to a guest account */
272
273                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ 
274                         map_domainuser_to_guest = True;
275                         fstrcpy(user,lp_guestaccount());
276                         pw = smb_getpwnam( user, real_username, True );
277                 } 
278
279                 /* extra sanity check that the guest account is valid */
280
281                 if ( !pw ) {
282                         DEBUG(1,("Username %s is invalid on this system\n", user));
283                         SAFE_FREE(client);
284                         data_blob_free(&ap_rep);
285                         data_blob_free(&session_key);
286                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
287                 }
288         }
289
290         /* setup the string used by %U */
291         
292         sub_set_smb_name( real_username );
293         reload_services(True);
294         if ( map_domainuser_to_guest ) {
295                 make_server_info_guest(&server_info);
296         } else if (logon_info) {
297                 ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
298
299                 if ( !NT_STATUS_IS_OK(ret) ) {
300                         DEBUG(1,("make_server_info_pac failed!\n"));
301                         SAFE_FREE(client);
302                         data_blob_free(&ap_rep);
303                         data_blob_free(&session_key);
304                         passwd_free(&pw);
305                         return ERROR_NT(ret);
306                 }
307
308         } else {
309                 ret = make_server_info_pw(&server_info, real_username, pw);
310
311                 if ( !NT_STATUS_IS_OK(ret) ) {
312                         DEBUG(1,("make_server_info_from_pw failed!\n"));
313                         SAFE_FREE(client);
314                         data_blob_free(&ap_rep);
315                         data_blob_free(&session_key);
316                         passwd_free(&pw);
317                         return ERROR_NT(ret);
318                 }
319
320                 /* make_server_info_pw does not set the domain. Without this we end up
321                  * with the local netbios name in substitutions for %D. */
322
323                 if (server_info->sam_account != NULL) {
324                         pdb_set_domain(server_info->sam_account, domain, PDB_SET);
325                 }
326         }
327
328
329         passwd_free(&pw);
330
331         /* register_vuid keeps the server info */
332         /* register_vuid takes ownership of session_key, no need to free after this.
333            A better interface would copy it.... */
334         sess_vuid = register_vuid(server_info, session_key, nullblob, client);
335
336         SAFE_FREE(client);
337
338         if (sess_vuid == -1) {
339                 ret = NT_STATUS_LOGON_FAILURE;
340         } else {
341                 /* current_user_info is changed on new vuid */
342                 reload_services( True );
343
344                 set_message(outbuf,4,0,True);
345                 SSVAL(outbuf, smb_vwv3, 0);
346                         
347                 if (server_info->guest) {
348                         SSVAL(outbuf,smb_vwv2,1);
349                 }
350                 
351                 SSVAL(outbuf, smb_uid, sess_vuid);
352
353                 if (!server_info->guest && !srv_signing_started()) {
354                         /* We need to start the signing engine
355                          * here but a W2K client sends the old
356                          * "BSRSPYL " signature instead of the
357                          * correct one. Subsequent packets will
358                          * be correct.
359                          */
360                         srv_check_sign_mac(inbuf, False);
361                 }
362         }
363
364         /* wrap that up in a nice GSS-API wrapping */
365         if (NT_STATUS_IS_OK(ret)) {
366                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
367         } else {
368                 ap_rep_wrapped = data_blob(NULL, 0);
369         }
370         response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
371         reply_sesssetup_blob(conn, outbuf, response, ret);
372
373         data_blob_free(&ap_rep);
374         data_blob_free(&ap_rep_wrapped);
375         data_blob_free(&response);
376         talloc_destroy(mem_ctx);
377
378         return -1; /* already replied */
379 }
380 #endif
381
382 /****************************************************************************
383  Send a session setup reply, wrapped in SPNEGO.
384  Get vuid and check first.
385  End the NTLMSSP exchange context if we are OK/complete fail
386  This should be split into two functions, one to handle each
387  leg of the NTLM auth steps.
388 ***************************************************************************/
389
390 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
391                                  uint16 vuid,
392                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
393                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, 
394                                  BOOL wrap) 
395 {
396         BOOL ret;
397         DATA_BLOB response;
398         struct auth_serversupplied_info *server_info = NULL;
399
400         if (NT_STATUS_IS_OK(nt_status)) {
401                 server_info = (*auth_ntlmssp_state)->server_info;
402         } else {
403                 nt_status = do_map_to_guest(nt_status, 
404                                             &server_info, 
405                                             (*auth_ntlmssp_state)->ntlmssp_state->user, 
406                                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
407         }
408
409         if (NT_STATUS_IS_OK(nt_status)) {
410                 int sess_vuid;
411                 DATA_BLOB nullblob = data_blob(NULL, 0);
412                 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
413
414                 /* register_vuid keeps the server info */
415                 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
416                 (*auth_ntlmssp_state)->server_info = NULL;
417
418                 if (sess_vuid == -1) {
419                         nt_status = NT_STATUS_LOGON_FAILURE;
420                 } else {
421                         
422                         /* current_user_info is changed on new vuid */
423                         reload_services( True );
424
425                         set_message(outbuf,4,0,True);
426                         SSVAL(outbuf, smb_vwv3, 0);
427                         
428                         if (server_info->guest) {
429                                 SSVAL(outbuf,smb_vwv2,1);
430                         }
431                         
432                         SSVAL(outbuf,smb_uid,sess_vuid);
433
434                         if (!server_info->guest && !srv_signing_started()) {
435                                 /* We need to start the signing engine
436                                  * here but a W2K client sends the old
437                                  * "BSRSPYL " signature instead of the
438                                  * correct one. Subsequent packets will
439                                  * be correct.
440                                  */
441
442                                 srv_check_sign_mac(inbuf, False);
443                         }
444                 }
445         }
446
447         if (wrap) {
448                 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
449         } else {
450                 response = *ntlmssp_blob;
451         }
452
453         ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
454         if (wrap) {
455                 data_blob_free(&response);
456         }
457
458         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
459            and the other end, that we are not finished yet. */
460
461         if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
462                 /* NB. This is *NOT* an error case. JRA */
463                 auth_ntlmssp_end(auth_ntlmssp_state);
464                 /* Kill the intermediate vuid */
465                 invalidate_vuid(vuid);
466         }
467
468         return ret;
469 }
470
471 /****************************************************************************
472  Reply to a session setup spnego negotiate packet.
473 ****************************************************************************/
474
475 static int reply_spnego_negotiate(connection_struct *conn, 
476                                   char *inbuf,
477                                   char *outbuf,
478                                   uint16 vuid,
479                                   int length, int bufsize,
480                                   DATA_BLOB blob1,
481                                   AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
482 {
483         char *OIDs[ASN1_MAX_OIDS];
484         DATA_BLOB secblob;
485         int i;
486         DATA_BLOB chal;
487 #ifdef HAVE_KRB5
488         BOOL got_kerberos_mechanism = False;
489 #endif
490         NTSTATUS nt_status;
491
492         /* parse out the OIDs and the first sec blob */
493         if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
494                 /* Kill the intermediate vuid */
495                 invalidate_vuid(vuid);
496
497                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
498         }
499
500         /* only look at the first OID for determining the mechToken --
501            accoirding to RFC2478, we should choose the one we want 
502            and renegotiate, but i smell a client bug here..  
503            
504            Problem observed when connecting to a member (samba box) 
505            of an AD domain as a user in a Samba domain.  Samba member 
506            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the 
507            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an 
508            NTLMSSP mechtoken.                 --jerry              */
509
510 #ifdef HAVE_KRB5        
511         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
512             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
513                 got_kerberos_mechanism = True;
514         }
515 #endif
516                 
517         for (i=0;OIDs[i];i++) {
518                 DEBUG(3,("Got OID %s\n", OIDs[i]));
519                 free(OIDs[i]);
520         }
521         DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
522
523 #ifdef HAVE_KRB5
524         if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
525                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
526                                                 length, bufsize, &secblob);
527                 data_blob_free(&secblob);
528                 /* Kill the intermediate vuid */
529                 invalidate_vuid(vuid);
530
531                 return ret;
532         }
533 #endif
534
535         if (*auth_ntlmssp_state) {
536                 auth_ntlmssp_end(auth_ntlmssp_state);
537         }
538
539         nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
540         if (!NT_STATUS_IS_OK(nt_status)) {
541                 /* Kill the intermediate vuid */
542                 invalidate_vuid(vuid);
543
544                 return ERROR_NT(nt_status);
545         }
546
547         nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 
548                                         secblob, &chal);
549
550         data_blob_free(&secblob);
551
552         reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
553                              &chal, nt_status, True);
554
555         data_blob_free(&chal);
556
557         /* already replied */
558         return -1;
559 }
560         
561 /****************************************************************************
562  Reply to a session setup spnego auth packet.
563 ****************************************************************************/
564
565 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
566                              uint16 vuid,
567                              int length, int bufsize,
568                              DATA_BLOB blob1,
569                              AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
570 {
571         DATA_BLOB auth, auth_reply;
572         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
573
574         if (!spnego_parse_auth(blob1, &auth)) {
575 #if 0
576                 file_save("auth.dat", blob1.data, blob1.length);
577 #endif
578                 /* Kill the intermediate vuid */
579                 invalidate_vuid(vuid);
580
581                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
582         }
583         
584         if (!*auth_ntlmssp_state) {
585                 /* Kill the intermediate vuid */
586                 invalidate_vuid(vuid);
587
588                 /* auth before negotiatiate? */
589                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
590         }
591         
592         nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, 
593                                         auth, &auth_reply);
594
595         data_blob_free(&auth);
596
597         reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
598                              auth_ntlmssp_state,
599                              &auth_reply, nt_status, True);
600                 
601         data_blob_free(&auth_reply);
602
603         /* and tell smbd that we have already replied to this packet */
604         return -1;
605 }
606
607 /****************************************************************************
608  Reply to a session setup command.
609 ****************************************************************************/
610
611 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
612                                         char *outbuf,
613                                         int length,int bufsize)
614 {
615         uint8 *p;
616         DATA_BLOB blob1;
617         int ret;
618         size_t bufrem;
619         fstring native_os, native_lanman, primary_domain;
620         char *p2;
621         uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
622         enum remote_arch_types ra_type = get_remote_arch();
623         int vuid = SVAL(inbuf,smb_uid);
624         user_struct *vuser = NULL;
625
626         DEBUG(3,("Doing spnego session setup\n"));
627
628         if (global_client_caps == 0) {
629                 global_client_caps = IVAL(inbuf,smb_vwv10);
630
631                 if (!(global_client_caps & CAP_STATUS32)) {
632                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
633                 }
634
635         }
636                 
637         p = (uint8 *)smb_buf(inbuf);
638
639         if (data_blob_len == 0) {
640                 /* an invalid request */
641                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
642         }
643
644         bufrem = smb_bufrem(inbuf, p);
645         /* pull the spnego blob */
646         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
647
648 #if 0
649         file_save("negotiate.dat", blob1.data, blob1.length);
650 #endif
651
652         p2 = inbuf + smb_vwv13 + data_blob_len;
653         p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
654         p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
655         p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
656         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
657                 native_os, native_lanman, primary_domain));
658
659         if ( ra_type == RA_WIN2K ) {
660                 /* Windows 2003 doesn't set the native lanman string, 
661                    but does set primary domain which is a bug I think */
662                            
663                 if ( !strlen(native_lanman) )
664                         ra_lanman_string( primary_domain );
665                 else
666                         ra_lanman_string( native_lanman );
667         }
668                 
669         vuser = get_partial_auth_user_struct(vuid);
670         if (!vuser) {
671                 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
672                 if (vuid == -1) {
673                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
674                 }
675         
676                 vuser = get_partial_auth_user_struct(vuid);
677         }
678
679         if (!vuser) {
680                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
681         }
682         
683         SSVAL(outbuf,smb_uid,vuid);
684         
685         if (blob1.data[0] == ASN1_APPLICATION(0)) {
686                 /* its a negTokenTarg packet */
687                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
688                                              &vuser->auth_ntlmssp_state);
689                 data_blob_free(&blob1);
690                 return ret;
691         }
692
693         if (blob1.data[0] == ASN1_CONTEXT(1)) {
694                 /* its a auth packet */
695                 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
696                                         &vuser->auth_ntlmssp_state);
697                 data_blob_free(&blob1);
698                 return ret;
699         }
700
701         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
702                 DATA_BLOB chal;
703                 NTSTATUS nt_status;
704                 if (!vuser->auth_ntlmssp_state) {
705                         nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
706                         if (!NT_STATUS_IS_OK(nt_status)) {
707                                 /* Kill the intermediate vuid */
708                                 invalidate_vuid(vuid);
709                                 
710                                 return ERROR_NT(nt_status);
711                         }
712                 }
713
714                 nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
715                                                 blob1, &chal);
716                 
717                 data_blob_free(&blob1);
718                 
719                 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
720                                            &vuser->auth_ntlmssp_state,
721                                            &chal, nt_status, False);
722                 data_blob_free(&chal);
723                 return -1;
724         }
725
726         /* what sort of packet is this? */
727         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
728
729         data_blob_free(&blob1);
730
731         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
732 }
733
734 /****************************************************************************
735  On new VC == 0, shutdown *all* old connections and users.
736  It seems that only NT4.x does this. At W2K and above (XP etc.).
737  a new session setup with VC==0 is ignored.
738 ****************************************************************************/
739
740 static void setup_new_vc_session(void)
741 {
742         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
743 #if 0
744         conn_close_all();
745         invalidate_all_vuids();
746 #endif
747 }
748
749 /****************************************************************************
750  Reply to a session setup command.
751 ****************************************************************************/
752
753 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
754                           int length,int bufsize)
755 {
756         int sess_vuid;
757         int   smb_bufsize;    
758         DATA_BLOB lm_resp;
759         DATA_BLOB nt_resp;
760         DATA_BLOB plaintext_password;
761         fstring user;
762         fstring sub_user; /* Sainitised username for substituion */
763         fstring domain;
764         fstring native_os;
765         fstring native_lanman;
766         fstring primary_domain;
767         static BOOL done_sesssetup = False;
768         extern BOOL global_encrypted_passwords_negotiated;
769         extern BOOL global_spnego_negotiated;
770         extern enum protocol_types Protocol;
771         extern int max_send;
772
773         auth_usersupplied_info *user_info = NULL;
774         extern struct auth_context *negprot_global_auth_context;
775         auth_serversupplied_info *server_info = NULL;
776
777         NTSTATUS nt_status;
778
779         BOOL doencrypt = global_encrypted_passwords_negotiated;
780
781         DATA_BLOB session_key;
782         
783         START_PROFILE(SMBsesssetupX);
784
785         ZERO_STRUCT(lm_resp);
786         ZERO_STRUCT(nt_resp);
787         ZERO_STRUCT(plaintext_password);
788
789         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
790
791         /* a SPNEGO session setup has 12 command words, whereas a normal
792            NT1 session setup has 13. See the cifs spec. */
793         if (CVAL(inbuf, smb_wct) == 12 &&
794             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
795                 if (!global_spnego_negotiated) {
796                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
797                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
798                 }
799
800                 if (SVAL(inbuf,smb_vwv4) == 0) {
801                         setup_new_vc_session();
802                 }
803                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
804         }
805
806         smb_bufsize = SVAL(inbuf,smb_vwv2);
807
808         if (Protocol < PROTOCOL_NT1) {
809                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
810
811                 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
812                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
813
814                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
815                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
816                 }
817
818                 if (doencrypt) {
819                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
820                 } else {
821                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
822                         /* Ensure null termination */
823                         plaintext_password.data[passlen1] = 0;
824                 }
825
826                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
827                 *domain = 0;
828
829         } else {
830                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
831                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
832                 enum remote_arch_types ra_type = get_remote_arch();
833                 char *p = smb_buf(inbuf);    
834                 char *save_p = smb_buf(inbuf);
835                 uint16 byte_count;
836                         
837
838                 if(global_client_caps == 0) {
839                         global_client_caps = IVAL(inbuf,smb_vwv11);
840                 
841                         if (!(global_client_caps & CAP_STATUS32)) {
842                                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
843                         }
844
845                         /* client_caps is used as final determination if client is NT or Win95. 
846                            This is needed to return the correct error codes in some
847                            circumstances.
848                         */
849                 
850                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
851                                 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
852                                         set_remote_arch( RA_WIN95);
853                                 }
854                         }
855                 }
856
857                 if (!doencrypt) {
858                         /* both Win95 and WinNT stuff up the password lengths for
859                            non-encrypting systems. Uggh. 
860                            
861                            if passlen1==24 its a win95 system, and its setting the
862                            password length incorrectly. Luckily it still works with the
863                            default code because Win95 will null terminate the password
864                            anyway 
865                            
866                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
867                            setting passlen2 to some random value which really stuffs
868                            things up. we need to fix that one.  */
869                         
870                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
871                                 passlen2 = 0;
872                 }
873                 
874                 /* check for nasty tricks */
875                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
876                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
877                 }
878
879                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
880                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
881                 }
882
883                 /* Save the lanman2 password and the NT md4 password. */
884                 
885                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
886                         doencrypt = False;
887                 }
888
889                 if (doencrypt) {
890                         lm_resp = data_blob(p, passlen1);
891                         nt_resp = data_blob(p+passlen1, passlen2);
892                 } else {
893                         pstring pass;
894                         BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
895
896 #if 0
897                         /* This was the previous fix. Not sure if it's still valid. JRA. */
898                         if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
899                                 /* NT4.0 stuffs up plaintext unicode password lengths... */
900                                 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
901                                         sizeof(pass), passlen1, STR_TERMINATE);
902 #endif
903
904                         if (unic && (passlen2 == 0) && passlen1) {
905                                 /* Only a ascii plaintext password was sent. */
906                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
907                                         passlen1, STR_TERMINATE|STR_ASCII);
908                         } else {
909                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), 
910                                         sizeof(pass),  unic ? passlen2 : passlen1, 
911                                         STR_TERMINATE);
912                         }
913                         plaintext_password = data_blob(pass, strlen(pass)+1);
914                 }
915                 
916                 p += passlen1 + passlen2;
917                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
918                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
919                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
920                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
921
922                 /* not documented or decoded by Ethereal but there is one more string 
923                    in the extra bytes which is the same as the PrimaryDomain when using 
924                    extended security.  Windows NT 4 and 2003 use this string to store 
925                    the native lanman string. Windows 9x does not include a string here 
926                    at all so we have to check if we have any extra bytes left */
927                 
928                 byte_count = SVAL(inbuf, smb_vwv13);
929                 if ( PTR_DIFF(p, save_p) < byte_count)
930                         p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
931                 else 
932                         fstrcpy( primary_domain, "null" );
933
934                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
935                          domain, native_os, native_lanman, primary_domain));
936
937                 if ( ra_type == RA_WIN2K ) {
938                         if ( strlen(native_lanman) == 0 )
939                                 ra_lanman_string( primary_domain );
940                         else
941                                 ra_lanman_string( native_lanman );
942                 }
943
944         }
945
946         if (SVAL(inbuf,smb_vwv4) == 0) {
947                 setup_new_vc_session();
948         }
949
950         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
951
952         if (*user) {
953                 if (global_spnego_negotiated) {
954                         
955                         /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
956                         
957                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
958                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
959                 }
960                 fstrcpy(sub_user, user);
961         } else {
962                 fstrcpy(sub_user, lp_guestaccount());
963         }
964
965         sub_set_smb_name(sub_user);
966
967         reload_services(True);
968         
969         if (lp_security() == SEC_SHARE) {
970                 /* in share level we should ignore any passwords */
971
972                 data_blob_free(&lm_resp);
973                 data_blob_free(&nt_resp);
974                 data_blob_clear_free(&plaintext_password);
975
976                 map_username(sub_user);
977                 add_session_user(sub_user);
978                 /* Then force it to null for the benfit of the code below */
979                 *user = 0;
980         }
981         
982         if (!*user) {
983
984                 nt_status = check_guest_password(&server_info);
985
986         } else if (doencrypt) {
987                 if (!negprot_global_auth_context) {
988                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
989                         return ERROR_NT(NT_STATUS_LOGON_FAILURE);
990                 }
991                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
992                                                          lm_resp, nt_resp);
993                 if (NT_STATUS_IS_OK(nt_status)) {
994                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
995                                                                                      user_info, 
996                                                                                      &server_info);
997                 }
998         } else {
999                 struct auth_context *plaintext_auth_context = NULL;
1000                 const uint8 *chal;
1001                 if (NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&plaintext_auth_context))) {
1002                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1003                         
1004                         if (!make_user_info_for_reply(&user_info, 
1005                                                       user, domain, chal,
1006                                                       plaintext_password)) {
1007                                 nt_status = NT_STATUS_NO_MEMORY;
1008                         }
1009                 
1010                         if (NT_STATUS_IS_OK(nt_status)) {
1011                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
1012                                                                                         user_info, 
1013                                                                                         &server_info); 
1014                                 
1015                                 (plaintext_auth_context->free)(&plaintext_auth_context);
1016                         }
1017                 }
1018         }
1019
1020         free_user_info(&user_info);
1021         
1022         if (!NT_STATUS_IS_OK(nt_status)) {
1023                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1024         }
1025         
1026         if (!NT_STATUS_IS_OK(nt_status)) {
1027                 data_blob_free(&nt_resp);
1028                 data_blob_free(&lm_resp);
1029                 data_blob_clear_free(&plaintext_password);
1030                 return ERROR_NT(nt_status_squash(nt_status));
1031         }
1032
1033         if (server_info->user_session_key.data) {
1034                 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1035         } else {
1036                 session_key = data_blob(NULL, 0);
1037         }
1038
1039         data_blob_clear_free(&plaintext_password);
1040         
1041         /* it's ok - setup a reply */
1042         set_message(outbuf,3,0,True);
1043         if (Protocol >= PROTOCOL_NT1) {
1044                 char *p = smb_buf( outbuf );
1045                 p += add_signature( outbuf, p );
1046                 set_message_end( outbuf, p );
1047                 /* perhaps grab OS version here?? */
1048         }
1049         
1050         if (server_info->guest) {
1051                 SSVAL(outbuf,smb_vwv2,1);
1052         }
1053
1054         /* register the name and uid as being validated, so further connections
1055            to a uid can get through without a password, on the same VC */
1056
1057         /* register_vuid keeps the server info */
1058         sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user);
1059         data_blob_free(&nt_resp);
1060         data_blob_free(&lm_resp);
1061
1062         if (sess_vuid == -1) {
1063                 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
1064         }
1065
1066         /* current_user_info is changed on new vuid */
1067         reload_services( True );
1068
1069         if (!server_info->guest && !srv_signing_started() && !srv_check_sign_mac(inbuf, True)) {
1070                 exit_server("reply_sesssetup_and_X: bad smb signature");
1071         }
1072
1073         SSVAL(outbuf,smb_uid,sess_vuid);
1074         SSVAL(inbuf,smb_uid,sess_vuid);
1075         
1076         if (!done_sesssetup)
1077                 max_send = MIN(max_send,smb_bufsize);
1078         
1079         done_sesssetup = True;
1080         
1081         END_PROFILE(SMBsesssetupX);
1082         return chain_reply(inbuf,outbuf,length,bufsize);
1083 }