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