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