r22751: Next step for the cluster merge: sessionid.tdb should contain a 'struct
[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 extern struct auth_context *negprot_global_auth_context;
27 extern BOOL global_encrypted_passwords_negotiated;
28 extern BOOL global_spnego_negotiated;
29 extern enum protocol_types Protocol;
30 extern int max_send;
31
32 uint32 global_client_caps = 0;
33
34 /*
35   on a logon error possibly map the error to success if "map to guest"
36   is set approriately
37 */
38 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
39                                 const char *user, const char *domain)
40 {
41         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
42                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || 
43                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
44                         DEBUG(3,("No such user %s [%s] - using guest account\n",
45                                  user, domain));
46                         status = make_server_info_guest(server_info);
47                 }
48         }
49
50         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
51                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
52                         DEBUG(3,("Registered username %s for guest access\n",user));
53                         status = make_server_info_guest(server_info);
54                 }
55         }
56
57         return status;
58 }
59
60 /****************************************************************************
61  Add the standard 'Samba' signature to the end of the session setup.
62 ****************************************************************************/
63
64 static int add_signature(char *outbuf, char *p)
65 {
66         char *start = p;
67         fstring lanman;
68
69         fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
70
71         p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
72         p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
73         p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
74
75         return PTR_DIFF(p, start);
76 }
77
78 /****************************************************************************
79  Start the signing engine if needed. Don't fail signing here.
80 ****************************************************************************/
81
82 static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
83 {
84         if (!server_info->guest && !srv_signing_started()) {
85                 /* We need to start the signing engine
86                  * here but a W2K client sends the old
87                  * "BSRSPYL " signature instead of the
88                  * correct one. Subsequent packets will
89                  * be correct.
90                  */
91                 srv_check_sign_mac(inbuf, False);
92         }
93 }
94
95 /****************************************************************************
96  Send a security blob via a session setup reply.
97 ****************************************************************************/
98
99 static BOOL reply_sesssetup_blob(connection_struct *conn,
100                                 const char *inbuf,
101                                 char *outbuf,
102                                 DATA_BLOB blob,
103                                 NTSTATUS nt_status)
104 {
105         char *p;
106
107         if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
108                 ERROR_NT(nt_status_squash(nt_status));
109         } else {
110                 set_message(inbuf,outbuf,4,0,True);
111
112                 nt_status = nt_status_squash(nt_status);
113                 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
114                 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
115                 SSVAL(outbuf, smb_vwv3, blob.length);
116                 p = smb_buf(outbuf);
117
118                 /* should we cap this? */
119                 memcpy(p, blob.data, blob.length);
120                 p += blob.length;
121
122                 p += add_signature( outbuf, p );
123
124                 set_message_end(inbuf,outbuf,p);
125         }
126
127         show_msg(outbuf);
128         return send_smb(smbd_server_fd(),outbuf);
129 }
130
131 /****************************************************************************
132  Do a 'guest' logon, getting back the 
133 ****************************************************************************/
134
135 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) 
136 {
137         struct auth_context *auth_context;
138         auth_usersupplied_info *user_info = NULL;
139         
140         NTSTATUS nt_status;
141         unsigned char chal[8];
142
143         ZERO_STRUCT(chal);
144
145         DEBUG(3,("Got anonymous request\n"));
146
147         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
148                 return nt_status;
149         }
150
151         if (!make_user_info_guest(&user_info)) {
152                 (auth_context->free)(&auth_context);
153                 return NT_STATUS_NO_MEMORY;
154         }
155         
156         nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
157         (auth_context->free)(&auth_context);
158         free_user_info(&user_info);
159         return nt_status;
160 }
161
162
163 #ifdef HAVE_KRB5
164
165 #if 0
166 /* Experiment that failed. See "only happens with a KDC" comment below. */
167 /****************************************************************************
168  Cerate a clock skew error blob for a Windows client.
169 ****************************************************************************/
170
171 static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
172 {
173         krb5_context context = NULL;
174         krb5_error_code kerr = 0;
175         krb5_data reply;
176         krb5_principal host_princ = NULL;
177         char *host_princ_s = NULL;
178         BOOL ret = False;
179
180         *pblob_out = data_blob(NULL,0);
181
182         initialize_krb5_error_table();
183         kerr = krb5_init_context(&context);
184         if (kerr) {
185                 return False;
186         }
187         /* Create server principal. */
188         asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
189         if (!host_princ_s) {
190                 goto out;
191         }
192         strlower_m(host_princ_s);
193
194         kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
195         if (kerr) {
196                 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
197                         host_princ_s, error_message(kerr) ));
198                 goto out;
199         }
200         
201         kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
202         if (kerr) {
203                 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
204                         error_message(kerr) ));
205                 goto out;
206         }
207
208         *pblob_out = data_blob(reply.data, reply.length);
209         kerberos_free_data_contents(context,&reply);
210         ret = True;
211
212   out:
213
214         if (host_princ_s) {
215                 SAFE_FREE(host_princ_s);
216         }
217         if (host_princ) {
218                 krb5_free_principal(context, host_princ);
219         }
220         krb5_free_context(context);
221         return ret;
222 }
223 #endif
224
225 /****************************************************************************
226  Reply to a session setup spnego negotiate packet for kerberos.
227 ****************************************************************************/
228
229 static int reply_spnego_kerberos(connection_struct *conn, 
230                                  char *inbuf, char *outbuf,
231                                  int length, int bufsize,
232                                  DATA_BLOB *secblob,
233                                  BOOL *p_invalidate_vuid)
234 {
235         TALLOC_CTX *mem_ctx;
236         DATA_BLOB ticket;
237         char *client, *p, *domain;
238         fstring netbios_domain_name;
239         struct passwd *pw;
240         fstring user;
241         int sess_vuid;
242         NTSTATUS ret;
243         PAC_DATA *pac_data;
244         DATA_BLOB ap_rep, ap_rep_wrapped, response;
245         auth_serversupplied_info *server_info = NULL;
246         DATA_BLOB session_key = data_blob(NULL, 0);
247         uint8 tok_id[2];
248         DATA_BLOB nullblob = data_blob(NULL, 0);
249         fstring real_username;
250         BOOL map_domainuser_to_guest = False;
251         BOOL username_was_mapped;
252         PAC_LOGON_INFO *logon_info = NULL;
253
254         ZERO_STRUCT(ticket);
255         ZERO_STRUCT(pac_data);
256         ZERO_STRUCT(ap_rep);
257         ZERO_STRUCT(ap_rep_wrapped);
258         ZERO_STRUCT(response);
259
260         /* Normally we will always invalidate the intermediate vuid. */
261         *p_invalidate_vuid = True;
262
263         mem_ctx = talloc_init("reply_spnego_kerberos");
264         if (mem_ctx == NULL) {
265                 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
266         }
267
268         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
269                 talloc_destroy(mem_ctx);
270                 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
271         }
272
273         ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
274
275         data_blob_free(&ticket);
276
277         if (!NT_STATUS_IS_OK(ret)) {
278 #if 0
279                 /* Experiment that failed. See "only happens with a KDC" comment below. */
280
281                 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
282
283                         /*
284                          * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
285                          * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
286                          * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
287                          * clock and continues rather than giving an error. JRA.
288                          * -- Looks like this only happens with a KDC. JRA.
289                          */
290
291                         BOOL ok = make_krb5_skew_error(&ap_rep);
292                         if (!ok) {
293                                 talloc_destroy(mem_ctx);
294                                 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
295                         }
296                         ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
297                         response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
298                         reply_sesssetup_blob(conn, inbuf, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
299
300                         /*
301                          * In this one case we don't invalidate the intermediate vuid.
302                          * as we're expecting the client to re-use it for the next
303                          * sessionsetupX packet. JRA.
304                          */
305
306                         *p_invalidate_vuid = False;
307
308                         data_blob_free(&ap_rep);
309                         data_blob_free(&ap_rep_wrapped);
310                         data_blob_free(&response);
311                         talloc_destroy(mem_ctx);
312                         return -1; /* already replied */
313                 }
314 #else
315                 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
316                         ret = NT_STATUS_LOGON_FAILURE;
317                 }
318 #endif
319                 DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret))); 
320                 talloc_destroy(mem_ctx);
321                 return ERROR_NT(nt_status_squash(ret));
322         }
323
324         DEBUG(3,("Ticket name is [%s]\n", client));
325
326         p = strchr_m(client, '@');
327         if (!p) {
328                 DEBUG(3,("Doesn't look like a valid principal\n"));
329                 data_blob_free(&ap_rep);
330                 data_blob_free(&session_key);
331                 SAFE_FREE(client);
332                 talloc_destroy(mem_ctx);
333                 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
334         }
335
336         *p = 0;
337
338         /* save the PAC data if we have it */
339
340         if (pac_data) {
341                 logon_info = get_logon_info_from_pac(pac_data);
342                 if (logon_info) {
343                         netsamlogon_cache_store( client, &logon_info->info3 );
344                 }
345         }
346
347         if (!strequal(p+1, lp_realm())) {
348                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
349                 if (!lp_allow_trusted_domains()) {
350                         data_blob_free(&ap_rep);
351                         data_blob_free(&session_key);
352                         SAFE_FREE(client);
353                         talloc_destroy(mem_ctx);
354                         return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
355                 }
356         }
357
358         /* this gives a fully qualified user name (ie. with full realm).
359            that leads to very long usernames, but what else can we do? */
360
361         domain = p+1;
362
363         if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
364
365                 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
366                 domain = netbios_domain_name;
367                 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
368
369         } else {
370
371                 /* If we have winbind running, we can (and must) shorten the
372                    username by using the short netbios name. Otherwise we will
373                    have inconsistent user names. With Kerberos, we get the
374                    fully qualified realm, with ntlmssp we get the short
375                    name. And even w2k3 does use ntlmssp if you for example
376                    connect to an ip address. */
377
378                 struct winbindd_request wb_request;
379                 struct winbindd_response wb_response;
380                 NSS_STATUS wb_result;
381
382                 ZERO_STRUCT(wb_request);
383                 ZERO_STRUCT(wb_response);
384
385                 DEBUG(10, ("Mapping [%s] to short name\n", domain));
386
387                 fstrcpy(wb_request.domain_name, domain);
388
389                 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
390                                              &wb_request, &wb_response);
391
392                 if (wb_result == NSS_STATUS_SUCCESS) {
393
394                         fstrcpy(netbios_domain_name,
395                                 wb_response.data.domain_info.name);
396                         domain = netbios_domain_name;
397
398                         DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
399                 } else {
400                         DEBUG(3, ("Could not find short name -- winbind "
401                                   "not running?\n"));
402                 }
403         }
404
405         fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
406         
407         /* lookup the passwd struct, create a new user if necessary */
408
409         username_was_mapped = map_username( user );
410
411         pw = smb_getpwnam( mem_ctx, user, real_username, True );
412
413         if (pw) {
414                 /* if a real user check pam account restrictions */
415                 /* only really perfomed if "obey pam restriction" is true */
416                 /* do this before an eventual mappign to guest occurs */
417                 ret = smb_pam_accountcheck(pw->pw_name);
418                 if (  !NT_STATUS_IS_OK(ret)) {
419                         DEBUG(1, ("PAM account restriction prevents user login\n"));
420                         data_blob_free(&ap_rep);
421                         data_blob_free(&session_key);
422                         TALLOC_FREE(mem_ctx);
423                         return ERROR_NT(nt_status_squash(ret));
424                 }
425         }
426
427         if (!pw) {
428
429                 /* this was originally the behavior of Samba 2.2, if a user
430                    did not have a local uid but has been authenticated, then 
431                    map them to a guest account */
432
433                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ 
434                         map_domainuser_to_guest = True;
435                         fstrcpy(user,lp_guestaccount());
436                         pw = smb_getpwnam( mem_ctx, user, real_username, True );
437                 } 
438
439                 /* extra sanity check that the guest account is valid */
440
441                 if ( !pw ) {
442                         DEBUG(1,("Username %s is invalid on this system\n", user));
443                         SAFE_FREE(client);
444                         data_blob_free(&ap_rep);
445                         data_blob_free(&session_key);
446                         TALLOC_FREE(mem_ctx);
447                         return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
448                 }
449         }
450
451         /* setup the string used by %U */
452         
453         sub_set_smb_name( real_username );
454         reload_services(True);
455
456         if ( map_domainuser_to_guest ) {
457                 make_server_info_guest(&server_info);
458         } else if (logon_info) {
459                 /* pass the unmapped username here since map_username() 
460                    will be called again from inside make_server_info_info3() */
461                 
462                 ret = make_server_info_info3(mem_ctx, client, domain, 
463                                              &server_info, &logon_info->info3);
464                 if ( !NT_STATUS_IS_OK(ret) ) {
465                         DEBUG(1,("make_server_info_info3 failed: %s!\n",
466                                  nt_errstr(ret)));
467                         SAFE_FREE(client);
468                         data_blob_free(&ap_rep);
469                         data_blob_free(&session_key);
470                         TALLOC_FREE(mem_ctx);
471                         return ERROR_NT(nt_status_squash(ret));
472                 }
473
474         } else {
475                 ret = make_server_info_pw(&server_info, real_username, pw);
476
477                 if ( !NT_STATUS_IS_OK(ret) ) {
478                         DEBUG(1,("make_server_info_pw failed: %s!\n",
479                                  nt_errstr(ret)));
480                         SAFE_FREE(client);
481                         data_blob_free(&ap_rep);
482                         data_blob_free(&session_key);
483                         TALLOC_FREE(mem_ctx);
484                         return ERROR_NT(nt_status_squash(ret));
485                 }
486
487                 /* make_server_info_pw does not set the domain. Without this
488                  * we end up with the local netbios name in substitutions for
489                  * %D. */
490
491                 if (server_info->sam_account != NULL) {
492                         pdb_set_domain(server_info->sam_account, domain, PDB_SET);
493                 }
494         }
495
496         server_info->was_mapped |= username_was_mapped;
497         
498         /* we need to build the token for the user. make_server_info_guest()
499            already does this */
500         
501         if ( !server_info->ptok ) {
502                 ret = create_local_token( server_info );
503                 if ( !NT_STATUS_IS_OK(ret) ) {
504                         SAFE_FREE(client);
505                         data_blob_free(&ap_rep);
506                         data_blob_free(&session_key);
507                         TALLOC_FREE( mem_ctx );
508                         TALLOC_FREE( server_info );
509                         return ERROR_NT(nt_status_squash(ret));
510                 }
511         }
512
513         /* register_vuid keeps the server info */
514         /* register_vuid takes ownership of session_key, no need to free after this.
515            A better interface would copy it.... */
516         sess_vuid = register_vuid(server_info, session_key, nullblob, client);
517
518         SAFE_FREE(client);
519
520         if (sess_vuid == UID_FIELD_INVALID ) {
521                 ret = NT_STATUS_LOGON_FAILURE;
522         } else {
523                 /* current_user_info is changed on new vuid */
524                 reload_services( True );
525
526                 set_message(inbuf,outbuf,4,0,True);
527                 SSVAL(outbuf, smb_vwv3, 0);
528                         
529                 if (server_info->guest) {
530                         SSVAL(outbuf,smb_vwv2,1);
531                 }
532                 
533                 SSVAL(outbuf, smb_uid, sess_vuid);
534
535                 sessionsetup_start_signing_engine(server_info, inbuf);
536         }
537
538         /* wrap that up in a nice GSS-API wrapping */
539         if (NT_STATUS_IS_OK(ret)) {
540                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
541         } else {
542                 ap_rep_wrapped = data_blob(NULL, 0);
543         }
544         response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
545         reply_sesssetup_blob(conn, inbuf, outbuf, response, ret);
546
547         data_blob_free(&ap_rep);
548         data_blob_free(&ap_rep_wrapped);
549         data_blob_free(&response);
550         TALLOC_FREE(mem_ctx);
551
552         return -1; /* already replied */
553 }
554 #endif
555
556 /****************************************************************************
557  Send a session setup reply, wrapped in SPNEGO.
558  Get vuid and check first.
559  End the NTLMSSP exchange context if we are OK/complete fail
560  This should be split into two functions, one to handle each
561  leg of the NTLM auth steps.
562 ***************************************************************************/
563
564 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
565                                  uint16 vuid,
566                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
567                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status, 
568                                  BOOL wrap) 
569 {
570         BOOL ret;
571         DATA_BLOB response;
572         struct auth_serversupplied_info *server_info = NULL;
573
574         if (NT_STATUS_IS_OK(nt_status)) {
575                 server_info = (*auth_ntlmssp_state)->server_info;
576         } else {
577                 nt_status = do_map_to_guest(nt_status, 
578                                             &server_info, 
579                                             (*auth_ntlmssp_state)->ntlmssp_state->user, 
580                                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
581         }
582
583         if (NT_STATUS_IS_OK(nt_status)) {
584                 int sess_vuid;
585                 DATA_BLOB nullblob = data_blob(NULL, 0);
586                 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
587
588                 /* register_vuid keeps the server info */
589                 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
590                 (*auth_ntlmssp_state)->server_info = NULL;
591
592                 if (sess_vuid == UID_FIELD_INVALID ) {
593                         nt_status = NT_STATUS_LOGON_FAILURE;
594                 } else {
595                         
596                         /* current_user_info is changed on new vuid */
597                         reload_services( True );
598
599                         set_message(inbuf,outbuf,4,0,True);
600                         SSVAL(outbuf, smb_vwv3, 0);
601                         
602                         if (server_info->guest) {
603                                 SSVAL(outbuf,smb_vwv2,1);
604                         }
605                         
606                         SSVAL(outbuf,smb_uid,sess_vuid);
607
608                         sessionsetup_start_signing_engine(server_info, inbuf);
609                 }
610         }
611
612         if (wrap) {
613                 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
614         } else {
615                 response = *ntlmssp_blob;
616         }
617
618         ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status);
619         if (wrap) {
620                 data_blob_free(&response);
621         }
622
623         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
624            and the other end, that we are not finished yet. */
625
626         if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
627                 /* NB. This is *NOT* an error case. JRA */
628                 auth_ntlmssp_end(auth_ntlmssp_state);
629                 /* Kill the intermediate vuid */
630                 invalidate_vuid(vuid);
631         }
632
633         return ret;
634 }
635
636 /****************************************************************************
637  Is this a krb5 mechanism ?
638 ****************************************************************************/
639
640 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
641 {
642         char *OIDs[ASN1_MAX_OIDS];
643         int i;
644
645         *p_is_krb5 = False;
646
647         /* parse out the OIDs and the first sec blob */
648         if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
649                 return NT_STATUS_LOGON_FAILURE;
650         }
651
652         /* only look at the first OID for determining the mechToken --
653            accoirding to RFC2478, we should choose the one we want 
654            and renegotiate, but i smell a client bug here..  
655            
656            Problem observed when connecting to a member (samba box) 
657            of an AD domain as a user in a Samba domain.  Samba member 
658            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the 
659            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an 
660            NTLMSSP mechtoken.                 --jerry              */
661
662 #ifdef HAVE_KRB5        
663         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
664             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
665                 *p_is_krb5 = True;
666         }
667 #endif
668                 
669         for (i=0;OIDs[i];i++) {
670                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
671                 free(OIDs[i]);
672         }
673         return NT_STATUS_OK;
674 }
675
676 /****************************************************************************
677  Reply to a session setup spnego negotiate packet.
678 ****************************************************************************/
679
680 static int reply_spnego_negotiate(connection_struct *conn, 
681                                   char *inbuf,
682                                   char *outbuf,
683                                   uint16 vuid,
684                                   int length, int bufsize,
685                                   DATA_BLOB blob1,
686                                   AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
687 {
688         DATA_BLOB secblob;
689         DATA_BLOB chal;
690         BOOL got_kerberos_mechanism = False;
691         NTSTATUS status;
692
693         status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
694         if (!NT_STATUS_IS_OK(status)) {
695                 /* Kill the intermediate vuid */
696                 invalidate_vuid(vuid);
697                 return ERROR_NT(nt_status_squash(status));
698         }
699
700         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
701
702 #ifdef HAVE_KRB5
703         if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
704                 BOOL destroy_vuid = True;
705                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
706                                                 length, bufsize, &secblob, &destroy_vuid);
707                 data_blob_free(&secblob);
708                 if (destroy_vuid) {
709                         /* Kill the intermediate vuid */
710                         invalidate_vuid(vuid);
711                 }
712                 return ret;
713         }
714 #endif
715
716         if (*auth_ntlmssp_state) {
717                 auth_ntlmssp_end(auth_ntlmssp_state);
718         }
719
720         status = auth_ntlmssp_start(auth_ntlmssp_state);
721         if (!NT_STATUS_IS_OK(status)) {
722                 /* Kill the intermediate vuid */
723                 invalidate_vuid(vuid);
724                 return ERROR_NT(nt_status_squash(status));
725         }
726
727         status = auth_ntlmssp_update(*auth_ntlmssp_state, 
728                                         secblob, &chal);
729
730         data_blob_free(&secblob);
731
732         reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
733                              &chal, status, True);
734
735         data_blob_free(&chal);
736
737         /* already replied */
738         return -1;
739 }
740
741 /****************************************************************************
742  Reply to a session setup spnego auth packet.
743 ****************************************************************************/
744
745 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
746                              uint16 vuid,
747                              int length, int bufsize,
748                              DATA_BLOB blob1,
749                              AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
750 {
751         DATA_BLOB auth = data_blob(NULL,0);
752         DATA_BLOB auth_reply = data_blob(NULL,0);
753         DATA_BLOB secblob = data_blob(NULL,0);
754         NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
755
756         if (!spnego_parse_auth(blob1, &auth)) {
757 #if 0
758                 file_save("auth.dat", blob1.data, blob1.length);
759 #endif
760                 /* Kill the intermediate vuid */
761                 invalidate_vuid(vuid);
762
763                 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
764         }
765
766         if (auth.data[0] == ASN1_APPLICATION(0)) {
767                 /* Might be a second negTokenTarg packet */
768
769                 BOOL got_krb5_mechanism = False;
770                 status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
771                 if (NT_STATUS_IS_OK(status)) {
772                         DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
773 #ifdef HAVE_KRB5
774                         if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
775                                 BOOL destroy_vuid = True;
776                                 int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
777                                                                 length, bufsize, &secblob, &destroy_vuid);
778                                 data_blob_free(&secblob);
779                                 data_blob_free(&auth);
780                                 if (destroy_vuid) {
781                                         /* Kill the intermediate vuid */
782                                         invalidate_vuid(vuid);
783                                 }
784                                 return ret;
785                         }
786 #endif
787                 }
788         }
789
790         /* If we get here it wasn't a negTokenTarg auth packet. */
791         data_blob_free(&secblob);
792         
793         if (!*auth_ntlmssp_state) {
794                 /* Kill the intermediate vuid */
795                 invalidate_vuid(vuid);
796
797                 /* auth before negotiatiate? */
798                 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
799         }
800         
801         status = auth_ntlmssp_update(*auth_ntlmssp_state, 
802                                         auth, &auth_reply);
803
804         data_blob_free(&auth);
805
806         reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
807                              auth_ntlmssp_state,
808                              &auth_reply, status, True);
809                 
810         data_blob_free(&auth_reply);
811
812         /* and tell smbd that we have already replied to this packet */
813         return -1;
814 }
815
816 /****************************************************************************
817  List to store partial SPNEGO auth fragments.
818 ****************************************************************************/
819
820 static struct pending_auth_data *pd_list;
821
822 /****************************************************************************
823  Delete an entry on the list.
824 ****************************************************************************/
825
826 static void delete_partial_auth(struct pending_auth_data *pad)
827 {
828         if (!pad) {
829                 return;
830         }
831         DLIST_REMOVE(pd_list, pad);
832         data_blob_free(&pad->partial_data);
833         SAFE_FREE(pad);
834 }
835
836 /****************************************************************************
837  Search for a partial SPNEGO auth fragment matching an smbpid.
838 ****************************************************************************/
839
840 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
841 {
842         struct pending_auth_data *pad;
843
844         for (pad = pd_list; pad; pad = pad->next) {
845                 if (pad->smbpid == smbpid) {
846                         break;
847                 }
848         }
849         return pad;
850 }
851
852 /****************************************************************************
853  Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
854  else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
855 ****************************************************************************/
856
857 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
858 {
859         struct pending_auth_data *pad = NULL;
860         ASN1_DATA data;
861         size_t needed_len = 0;
862
863         pad = get_pending_auth_data(smbpid);
864
865         /* Ensure we have some data. */
866         if (pblob->length == 0) {
867                 /* Caller can cope. */
868                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
869                 delete_partial_auth(pad);
870                 return NT_STATUS_OK;
871         }
872
873         /* Were we waiting for more data ? */
874         if (pad) {
875                 DATA_BLOB tmp_blob;
876                 size_t copy_len = MIN(65536, pblob->length);
877
878                 /* Integer wrap paranoia.... */
879
880                 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
881                     pad->partial_data.length + copy_len < copy_len) {
882
883                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
884                                 "pad->partial_data.length = %u, "
885                                 "copy_len = %u\n",
886                                 (unsigned int)pad->partial_data.length,
887                                 (unsigned int)copy_len ));
888
889                         delete_partial_auth(pad);
890                         return NT_STATUS_INVALID_PARAMETER;
891                 }
892
893                 DEBUG(10,("check_spnego_blob_complete: "
894                         "pad->partial_data.length = %u, "
895                         "pad->needed_len = %u, "
896                         "copy_len = %u, "
897                         "pblob->length = %u,\n",
898                         (unsigned int)pad->partial_data.length,
899                         (unsigned int)pad->needed_len,
900                         (unsigned int)copy_len,
901                         (unsigned int)pblob->length ));
902
903                 tmp_blob = data_blob(NULL,
904                                 pad->partial_data.length + copy_len);
905
906                 /* Concatenate the two (up to copy_len) bytes. */
907                 memcpy(tmp_blob.data,
908                         pad->partial_data.data,
909                         pad->partial_data.length);
910                 memcpy(tmp_blob.data + pad->partial_data.length,
911                         pblob->data,
912                         copy_len);
913
914                 /* Replace the partial data. */
915                 data_blob_free(&pad->partial_data);
916                 pad->partial_data = tmp_blob;
917                 ZERO_STRUCT(tmp_blob);
918
919                 /* Are we done ? */
920                 if (pblob->length >= pad->needed_len) {
921                         /* Yes, replace pblob. */
922                         data_blob_free(pblob);
923                         *pblob = pad->partial_data;
924                         ZERO_STRUCT(pad->partial_data);
925                         delete_partial_auth(pad);
926                         return NT_STATUS_OK;
927                 }
928
929                 /* Still need more data. */
930                 pad->needed_len -= copy_len;
931                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
932         }
933
934         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
935             (pblob->data[0] != ASN1_CONTEXT(1))) {
936                 /* Not something we can determine the
937                  * length of.
938                  */
939                 return NT_STATUS_OK;
940         }
941
942         /* This is a new SPNEGO sessionsetup - see if
943          * the data given in this blob is enough.
944          */
945
946         asn1_load(&data, *pblob);
947         asn1_start_tag(&data, pblob->data[0]);
948         if (data.has_error || data.nesting == NULL) {
949                 asn1_free(&data);
950                 /* Let caller catch. */
951                 return NT_STATUS_OK;
952         }
953
954         /* Integer wrap paranoia.... */
955
956         if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
957             data.nesting->taglen + data.nesting->start < data.nesting->start) {
958
959                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
960                         "data.nesting->taglen = %u, "
961                         "data.nesting->start = %u\n",
962                         (unsigned int)data.nesting->taglen,
963                         (unsigned int)data.nesting->start ));
964
965                 asn1_free(&data);
966                 return NT_STATUS_INVALID_PARAMETER;
967         }
968
969         /* Total length of the needed asn1 is the tag length
970          * plus the current offset. */
971
972         needed_len = data.nesting->taglen + data.nesting->start;
973         asn1_free(&data);
974
975         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
976                 "pblob->length = %u\n",
977                 (unsigned int)needed_len,
978                 (unsigned int)pblob->length ));
979
980         if (needed_len <= pblob->length) {
981                 /* Nothing to do - blob is complete. */
982                 return NT_STATUS_OK;
983         }
984
985         /* Refuse the blob if it's bigger than 64k. */
986         if (needed_len > 65536) {
987                 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
988                         (unsigned int)needed_len ));
989                 return NT_STATUS_INVALID_PARAMETER;
990         }
991
992         /* We must store this blob until complete. */
993         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
994                 return NT_STATUS_NO_MEMORY;
995         }
996         pad->needed_len = needed_len - pblob->length;
997         pad->partial_data = data_blob(pblob->data, pblob->length);
998         if (pad->partial_data.data == NULL) {
999                 SAFE_FREE(pad);
1000                 return NT_STATUS_NO_MEMORY;
1001         }
1002         pad->smbpid = smbpid;
1003         pad->vuid = vuid;
1004         DLIST_ADD(pd_list, pad);
1005
1006         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1007 }
1008
1009 /****************************************************************************
1010  Reply to a session setup command.
1011  conn POINTER CAN BE NULL HERE !
1012 ****************************************************************************/
1013
1014 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
1015                                         char *outbuf,
1016                                         int length,int bufsize)
1017 {
1018         uint8 *p;
1019         DATA_BLOB blob1;
1020         int ret;
1021         size_t bufrem;
1022         fstring native_os, native_lanman, primary_domain;
1023         char *p2;
1024         uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
1025         enum remote_arch_types ra_type = get_remote_arch();
1026         int vuid = SVAL(inbuf,smb_uid);
1027         user_struct *vuser = NULL;
1028         NTSTATUS status = NT_STATUS_OK;
1029         uint16 smbpid = SVAL(inbuf,smb_pid);
1030
1031         DEBUG(3,("Doing spnego session setup\n"));
1032
1033         if (global_client_caps == 0) {
1034                 global_client_caps = IVAL(inbuf,smb_vwv10);
1035
1036                 if (!(global_client_caps & CAP_STATUS32)) {
1037                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1038                 }
1039
1040         }
1041                 
1042         p = (uint8 *)smb_buf(inbuf);
1043
1044         if (data_blob_len == 0) {
1045                 /* an invalid request */
1046                 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1047         }
1048
1049         bufrem = smb_bufrem(inbuf, p);
1050         /* pull the spnego blob */
1051         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1052
1053 #if 0
1054         file_save("negotiate.dat", blob1.data, blob1.length);
1055 #endif
1056
1057         p2 = inbuf + smb_vwv13 + data_blob_len;
1058         p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
1059         p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
1060         p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
1061         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
1062                 native_os, native_lanman, primary_domain));
1063
1064         if ( ra_type == RA_WIN2K ) {
1065                 /* Vista sets neither the OS or lanman strings */
1066
1067                 if ( !strlen(native_os) && !strlen(native_lanman) )
1068                         set_remote_arch(RA_VISTA);
1069                 
1070                 /* Windows 2003 doesn't set the native lanman string, 
1071                    but does set primary domain which is a bug I think */
1072                            
1073                 if ( !strlen(native_lanman) ) {
1074                         ra_lanman_string( primary_domain );
1075                 } else {
1076                         ra_lanman_string( native_lanman );
1077                 }
1078         }
1079                 
1080         vuser = get_partial_auth_user_struct(vuid);
1081         if (!vuser) {
1082                 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1083                 if (pad) {
1084                         DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1085                                 (unsigned int)pad->vuid ));
1086                         vuid = pad->vuid;
1087                         vuser = get_partial_auth_user_struct(vuid);
1088                 }
1089         }
1090
1091         if (!vuser) {
1092                 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
1093                 if (vuid == UID_FIELD_INVALID ) {
1094                         data_blob_free(&blob1);
1095                         return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1096                 }
1097         
1098                 vuser = get_partial_auth_user_struct(vuid);
1099         }
1100
1101         if (!vuser) {
1102                 data_blob_free(&blob1);
1103                 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1104         }
1105         
1106         SSVAL(outbuf,smb_uid,vuid);
1107
1108         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1109          * sessionsetup requests as the Windows limit on the security blob
1110          * field is 4k. Bug #4400. JRA.
1111          */
1112
1113         status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1114         if (!NT_STATUS_IS_OK(status)) {
1115                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1116                         /* Real error - kill the intermediate vuid */
1117                         invalidate_vuid(vuid);
1118                 }
1119                 data_blob_free(&blob1);
1120                 return ERROR_NT(nt_status_squash(status));
1121         }
1122
1123         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1124                 /* its a negTokenTarg packet */
1125                 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1126                                              &vuser->auth_ntlmssp_state);
1127                 data_blob_free(&blob1);
1128                 return ret;
1129         }
1130
1131         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1132                 /* its a auth packet */
1133                 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1134                                         &vuser->auth_ntlmssp_state);
1135                 data_blob_free(&blob1);
1136                 return ret;
1137         }
1138
1139         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1140                 DATA_BLOB chal;
1141                 if (!vuser->auth_ntlmssp_state) {
1142                         status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1143                         if (!NT_STATUS_IS_OK(status)) {
1144                                 /* Kill the intermediate vuid */
1145                                 invalidate_vuid(vuid);
1146                                 data_blob_free(&blob1);
1147                                 return ERROR_NT(nt_status_squash(status));
1148                         }
1149                 }
1150
1151                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1152                                                 blob1, &chal);
1153                 
1154                 data_blob_free(&blob1);
1155                 
1156                 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
1157                                            &vuser->auth_ntlmssp_state,
1158                                            &chal, status, False);
1159                 data_blob_free(&chal);
1160                 return -1;
1161         }
1162
1163         /* what sort of packet is this? */
1164         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1165
1166         data_blob_free(&blob1);
1167
1168         return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1169 }
1170
1171 /****************************************************************************
1172  On new VC == 0, shutdown *all* old connections and users.
1173  It seems that only NT4.x does this. At W2K and above (XP etc.).
1174  a new session setup with VC==0 is ignored.
1175 ****************************************************************************/
1176
1177 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1178                                 void *p)
1179 {
1180         struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
1181         const char *ip = (const char *)p;
1182
1183         if (!process_exists(sessionid->pid)) {
1184                 return 0;
1185         }
1186
1187         if (procid_is_me(&sessionid->pid)) {
1188                 return 0;
1189         }
1190
1191         if (strcmp(ip, sessionid->ip_addr) != 0) {
1192                 return 0;
1193         }
1194
1195         message_send_pid(sessionid->pid, MSG_SHUTDOWN,
1196                          NULL, 0, True);
1197         return 0;
1198 }
1199
1200 static void setup_new_vc_session(void)
1201 {
1202         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1203 #if 0
1204         conn_close_all();
1205         invalidate_all_vuids();
1206 #endif
1207         if (lp_reset_on_zero_vc()) {
1208                 session_traverse(shutdown_other_smbds, client_addr());
1209         }
1210 }
1211
1212 /****************************************************************************
1213  Reply to a session setup command.
1214 ****************************************************************************/
1215
1216 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1217                           int length,int bufsize)
1218 {
1219         int sess_vuid;
1220         int   smb_bufsize;    
1221         DATA_BLOB lm_resp;
1222         DATA_BLOB nt_resp;
1223         DATA_BLOB plaintext_password;
1224         fstring user;
1225         fstring sub_user; /* Sainitised username for substituion */
1226         fstring domain;
1227         fstring native_os;
1228         fstring native_lanman;
1229         fstring primary_domain;
1230         static BOOL done_sesssetup = False;
1231         auth_usersupplied_info *user_info = NULL;
1232         auth_serversupplied_info *server_info = NULL;
1233
1234         NTSTATUS nt_status;
1235
1236         BOOL doencrypt = global_encrypted_passwords_negotiated;
1237
1238         DATA_BLOB session_key;
1239         
1240         START_PROFILE(SMBsesssetupX);
1241
1242         ZERO_STRUCT(lm_resp);
1243         ZERO_STRUCT(nt_resp);
1244         ZERO_STRUCT(plaintext_password);
1245
1246         DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1247
1248         /* a SPNEGO session setup has 12 command words, whereas a normal
1249            NT1 session setup has 13. See the cifs spec. */
1250         if (CVAL(inbuf, smb_wct) == 12 &&
1251             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1252                 if (!global_spnego_negotiated) {
1253                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1254                         return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1255                 }
1256
1257                 if (SVAL(inbuf,smb_vwv4) == 0) {
1258                         setup_new_vc_session();
1259                 }
1260                 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1261         }
1262
1263         smb_bufsize = SVAL(inbuf,smb_vwv2);
1264
1265         if (Protocol < PROTOCOL_NT1) {
1266                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1267
1268                 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1269                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1270
1271                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1272                         return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1273                 }
1274
1275                 if (doencrypt) {
1276                         lm_resp = data_blob(smb_buf(inbuf), passlen1);
1277                 } else {
1278                         plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1279                         /* Ensure null termination */
1280                         plaintext_password.data[passlen1] = 0;
1281                 }
1282
1283                 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1284                 *domain = 0;
1285
1286         } else {
1287                 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1288                 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1289                 enum remote_arch_types ra_type = get_remote_arch();
1290                 char *p = smb_buf(inbuf);    
1291                 char *save_p = smb_buf(inbuf);
1292                 uint16 byte_count;
1293                         
1294
1295                 if(global_client_caps == 0) {
1296                         global_client_caps = IVAL(inbuf,smb_vwv11);
1297                 
1298                         if (!(global_client_caps & CAP_STATUS32)) {
1299                                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1300                         }
1301
1302                         /* client_caps is used as final determination if client is NT or Win95. 
1303                            This is needed to return the correct error codes in some
1304                            circumstances.
1305                         */
1306                 
1307                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1308                                 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1309                                         set_remote_arch( RA_WIN95);
1310                                 }
1311                         }
1312                 }
1313
1314                 if (!doencrypt) {
1315                         /* both Win95 and WinNT stuff up the password lengths for
1316                            non-encrypting systems. Uggh. 
1317                            
1318                            if passlen1==24 its a win95 system, and its setting the
1319                            password length incorrectly. Luckily it still works with the
1320                            default code because Win95 will null terminate the password
1321                            anyway 
1322                            
1323                            if passlen1>0 and passlen2>0 then maybe its a NT box and its
1324                            setting passlen2 to some random value which really stuffs
1325                            things up. we need to fix that one.  */
1326                         
1327                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1328                                 passlen2 = 0;
1329                 }
1330                 
1331                 /* check for nasty tricks */
1332                 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1333                         return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1334                 }
1335
1336                 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1337                         return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1338                 }
1339
1340                 /* Save the lanman2 password and the NT md4 password. */
1341                 
1342                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1343                         doencrypt = False;
1344                 }
1345
1346                 if (doencrypt) {
1347                         lm_resp = data_blob(p, passlen1);
1348                         nt_resp = data_blob(p+passlen1, passlen2);
1349                 } else {
1350                         pstring pass;
1351                         BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1352
1353 #if 0
1354                         /* This was the previous fix. Not sure if it's still valid. JRA. */
1355                         if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1356                                 /* NT4.0 stuffs up plaintext unicode password lengths... */
1357                                 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1358                                         sizeof(pass), passlen1, STR_TERMINATE);
1359 #endif
1360
1361                         if (unic && (passlen2 == 0) && passlen1) {
1362                                 /* Only a ascii plaintext password was sent. */
1363                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1364                                         passlen1, STR_TERMINATE|STR_ASCII);
1365                         } else {
1366                                 srvstr_pull(inbuf, pass, smb_buf(inbuf), 
1367                                         sizeof(pass),  unic ? passlen2 : passlen1, 
1368                                         STR_TERMINATE);
1369                         }
1370                         plaintext_password = data_blob(pass, strlen(pass)+1);
1371                 }
1372                 
1373                 p += passlen1 + passlen2;
1374                 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1375                 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1376                 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1377                 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1378
1379                 /* not documented or decoded by Ethereal but there is one more string 
1380                    in the extra bytes which is the same as the PrimaryDomain when using 
1381                    extended security.  Windows NT 4 and 2003 use this string to store 
1382                    the native lanman string. Windows 9x does not include a string here 
1383                    at all so we have to check if we have any extra bytes left */
1384                 
1385                 byte_count = SVAL(inbuf, smb_vwv13);
1386                 if ( PTR_DIFF(p, save_p) < byte_count)
1387                         p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1388                 else 
1389                         fstrcpy( primary_domain, "null" );
1390
1391                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1392                          domain, native_os, native_lanman, primary_domain));
1393
1394                 if ( ra_type == RA_WIN2K ) {
1395                         if ( strlen(native_lanman) == 0 )
1396                                 ra_lanman_string( primary_domain );
1397                         else
1398                                 ra_lanman_string( native_lanman );
1399                 }
1400
1401         }
1402
1403         if (SVAL(inbuf,smb_vwv4) == 0) {
1404                 setup_new_vc_session();
1405         }
1406
1407         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1408
1409         if (*user) {
1410                 if (global_spnego_negotiated) {
1411                         
1412                         /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1413                         
1414                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1415                         return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1416                 }
1417                 fstrcpy(sub_user, user);
1418         } else {
1419                 fstrcpy(sub_user, lp_guestaccount());
1420         }
1421
1422         sub_set_smb_name(sub_user);
1423
1424         reload_services(True);
1425         
1426         if (lp_security() == SEC_SHARE) {
1427                 /* in share level we should ignore any passwords */
1428
1429                 data_blob_free(&lm_resp);
1430                 data_blob_free(&nt_resp);
1431                 data_blob_clear_free(&plaintext_password);
1432
1433                 map_username(sub_user);
1434                 add_session_user(sub_user);
1435                 add_session_workgroup(domain);
1436                 /* Then force it to null for the benfit of the code below */
1437                 *user = 0;
1438         }
1439         
1440         if (!*user) {
1441
1442                 nt_status = check_guest_password(&server_info);
1443
1444         } else if (doencrypt) {
1445                 if (!negprot_global_auth_context) {
1446                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted session setup without negprot denied!\n"));
1447                         return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1448                 }
1449                 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1450                                                          lm_resp, nt_resp);
1451                 if (NT_STATUS_IS_OK(nt_status)) {
1452                         nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
1453                                                                                      user_info, 
1454                                                                                      &server_info);
1455                 }
1456         } else {
1457                 struct auth_context *plaintext_auth_context = NULL;
1458                 const uint8 *chal;
1459
1460                 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1461
1462                 if (NT_STATUS_IS_OK(nt_status)) {
1463                         chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1464                         
1465                         if (!make_user_info_for_reply(&user_info, 
1466                                                       user, domain, chal,
1467                                                       plaintext_password)) {
1468                                 nt_status = NT_STATUS_NO_MEMORY;
1469                         }
1470                 
1471                         if (NT_STATUS_IS_OK(nt_status)) {
1472                                 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, 
1473                                                                                         user_info, 
1474                                                                                         &server_info); 
1475                                 
1476                                 (plaintext_auth_context->free)(&plaintext_auth_context);
1477                         }
1478                 }
1479         }
1480
1481         free_user_info(&user_info);
1482         
1483         if (!NT_STATUS_IS_OK(nt_status)) {
1484                 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1485         }
1486         
1487         if (!NT_STATUS_IS_OK(nt_status)) {
1488                 data_blob_free(&nt_resp);
1489                 data_blob_free(&lm_resp);
1490                 data_blob_clear_free(&plaintext_password);
1491                 return ERROR_NT(nt_status_squash(nt_status));
1492         }
1493
1494         /* Ensure we can't possible take a code path leading to a null defref. */
1495         if (!server_info) {
1496                 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1497         }
1498
1499         nt_status = create_local_token(server_info);
1500         if (!NT_STATUS_IS_OK(nt_status)) {
1501                 DEBUG(10, ("create_local_token failed: %s\n",
1502                            nt_errstr(nt_status)));
1503                 data_blob_free(&nt_resp);
1504                 data_blob_free(&lm_resp);
1505                 data_blob_clear_free(&plaintext_password);
1506                 return ERROR_NT(nt_status_squash(nt_status));
1507         }
1508
1509         if (server_info->user_session_key.data) {
1510                 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1511         } else {
1512                 session_key = data_blob(NULL, 0);
1513         }
1514
1515         data_blob_clear_free(&plaintext_password);
1516         
1517         /* it's ok - setup a reply */
1518         set_message(inbuf,outbuf,3,0,True);
1519         if (Protocol >= PROTOCOL_NT1) {
1520                 char *p = smb_buf( outbuf );
1521                 p += add_signature( outbuf, p );
1522                 set_message_end(inbuf, outbuf, p );
1523                 /* perhaps grab OS version here?? */
1524         }
1525         
1526         if (server_info->guest) {
1527                 SSVAL(outbuf,smb_vwv2,1);
1528         }
1529
1530         /* register the name and uid as being validated, so further connections
1531            to a uid can get through without a password, on the same VC */
1532
1533         if (lp_security() == SEC_SHARE) {
1534                 sess_vuid = UID_FIELD_INVALID;
1535                 data_blob_free(&session_key);
1536                 TALLOC_FREE(server_info);
1537         } else {
1538                 /* register_vuid keeps the server info */
1539                 sess_vuid = register_vuid(server_info, session_key,
1540                                           nt_resp.data ? nt_resp : lm_resp,
1541                                           sub_user);
1542                 if (sess_vuid == UID_FIELD_INVALID) {
1543                         data_blob_free(&nt_resp);
1544                         data_blob_free(&lm_resp);
1545                         return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1546                 }
1547
1548                 /* current_user_info is changed on new vuid */
1549                 reload_services( True );
1550
1551                 sessionsetup_start_signing_engine(server_info, inbuf);
1552         }
1553
1554         data_blob_free(&nt_resp);
1555         data_blob_free(&lm_resp);
1556         
1557         SSVAL(outbuf,smb_uid,sess_vuid);
1558         SSVAL(inbuf,smb_uid,sess_vuid);
1559         
1560         if (!done_sesssetup)
1561                 max_send = MIN(max_send,smb_bufsize);
1562         
1563         done_sesssetup = True;
1564         
1565         END_PROFILE(SMBsesssetupX);
1566         return chain_reply(inbuf,outbuf,length,bufsize);
1567 }