s3:smbd: make use of smbXsrv_session for smb1
[metze/samba/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 "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
39 #include "lib/conn_tdb.h"
40
41 /****************************************************************************
42  Add the standard 'Samba' signature to the end of the session setup.
43 ****************************************************************************/
44
45 static int push_signature(uint8 **outbuf)
46 {
47         char *lanman;
48         int result, tmp;
49
50         result = 0;
51
52         tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
53
54         if (tmp == -1) return -1;
55         result += tmp;
56
57         if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
58                 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
59                 SAFE_FREE(lanman);
60         }
61         else {
62                 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
63         }
64
65         if (tmp == -1) return -1;
66         result += tmp;
67
68         tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
69
70         if (tmp == -1) return -1;
71         result += tmp;
72
73         return result;
74 }
75
76 /****************************************************************************
77  Do a 'guest' logon, getting back the
78 ****************************************************************************/
79
80 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
81                                      TALLOC_CTX *mem_ctx, 
82                                      struct auth_session_info **session_info)
83 {
84         struct auth4_context *auth_context;
85         struct auth_usersupplied_info *user_info = NULL;
86         uint8_t chal[8];
87         NTSTATUS nt_status;
88
89         DEBUG(3,("Got anonymous request\n"));
90
91         nt_status = make_auth4_context(talloc_tos(), &auth_context);
92         if (!NT_STATUS_IS_OK(nt_status)) {
93                 return nt_status;
94         }
95
96         auth_context->get_ntlm_challenge(auth_context,
97                                          chal);
98
99         if (!make_user_info_guest(remote_address, &user_info)) {
100                 TALLOC_FREE(auth_context);
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         nt_status = auth_check_password_session_info(auth_context, 
105                                                      mem_ctx, user_info, session_info);
106         free_user_info(&user_info);
107         TALLOC_FREE(auth_context);
108         return nt_status;
109 }
110
111 /****************************************************************************
112  Reply to a session setup command.
113  conn POINTER CAN BE NULL HERE !
114 ****************************************************************************/
115
116 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
117 {
118         const uint8 *p;
119         DATA_BLOB in_blob;
120         DATA_BLOB out_blob = data_blob_null;
121         size_t bufrem;
122         char *tmp;
123         const char *native_os;
124         const char *native_lanman;
125         const char *primary_domain;
126         const char *p2;
127         uint16 data_blob_len = SVAL(req->vwv+7, 0);
128         enum remote_arch_types ra_type = get_remote_arch();
129         uint64_t vuid = req->vuid;
130         NTSTATUS status = NT_STATUS_OK;
131         struct smbd_server_connection *sconn = req->sconn;
132         uint16_t action = 0;
133         NTTIME now = timeval_to_nttime(&req->request_time);
134         struct smbXsrv_session *session = NULL;
135
136         DEBUG(3,("Doing spnego session setup\n"));
137
138         if (global_client_caps == 0) {
139                 global_client_caps = IVAL(req->vwv+10, 0);
140
141                 if (!(global_client_caps & CAP_STATUS32)) {
142                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
143                 }
144         }
145
146         p = req->buf;
147
148         if (data_blob_len == 0) {
149                 /* an invalid request */
150                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
151                 return;
152         }
153
154         bufrem = smbreq_bufrem(req, p);
155         /* pull the spnego blob */
156         in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
157
158 #if 0
159         file_save("negotiate.dat", in_blob.data, in_blob.length);
160 #endif
161
162         p2 = (const char *)req->buf + in_blob.length;
163
164         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
165                                      STR_TERMINATE);
166         native_os = tmp ? tmp : "";
167
168         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
169                                      STR_TERMINATE);
170         native_lanman = tmp ? tmp : "";
171
172         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
173                                      STR_TERMINATE);
174         primary_domain = tmp ? tmp : "";
175
176         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
177                 native_os, native_lanman, primary_domain));
178
179         if ( ra_type == RA_WIN2K ) {
180                 /* Vista sets neither the OS or lanman strings */
181
182                 if ( !strlen(native_os) && !strlen(native_lanman) )
183                         set_remote_arch(RA_VISTA);
184
185                 /* Windows 2003 doesn't set the native lanman string,
186                    but does set primary domain which is a bug I think */
187
188                 if ( !strlen(native_lanman) ) {
189                         ra_lanman_string( primary_domain );
190                 } else {
191                         ra_lanman_string( native_lanman );
192                 }
193         } else if ( ra_type == RA_VISTA ) {
194                 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
195                         set_remote_arch(RA_OSX);
196                 }
197         }
198
199         if (vuid != 0) {
200                 status = smb1srv_session_lookup(sconn->conn,
201                                                 vuid, now,
202                                                 &session);
203                 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
204                         reply_force_doserror(req, ERRSRV, ERRbaduid);
205                         return;
206                 }
207                 if (NT_STATUS_IS_OK(status)) {
208                         reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
209                         return;
210                 }
211                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
212                         reply_nterror(req, nt_status_squash(status));
213                         return;
214                 }
215         }
216
217         if (session == NULL) {
218                 /* create a new session */
219                 status = smbXsrv_session_create(sconn->conn,
220                                                 now, &session);
221                 if (!NT_STATUS_IS_OK(status)) {
222                         reply_nterror(req, nt_status_squash(status));
223                         return;
224                 }
225         }
226
227         if (!session->gensec) {
228                 status = auth_generic_prepare(session, sconn->remote_address,
229                                               &session->gensec);
230                 if (!NT_STATUS_IS_OK(status)) {
231                         TALLOC_FREE(session);
232                         reply_nterror(req, nt_status_squash(status));
233                         return;
234                 }
235
236                 gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
237                 gensec_want_feature(session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
238
239                 status = gensec_start_mech_by_oid(session->gensec,
240                                                   GENSEC_OID_SPNEGO);
241                 if (!NT_STATUS_IS_OK(status)) {
242                         DEBUG(0, ("Failed to start SPNEGO handler!\n"));
243                         TALLOC_FREE(session);;
244                         reply_nterror(req, nt_status_squash(status));
245                         return;
246                 }
247         }
248
249         become_root();
250         status = gensec_update(session->gensec,
251                                talloc_tos(), NULL,
252                                in_blob, &out_blob);
253         unbecome_root();
254         if (!NT_STATUS_IS_OK(status) &&
255             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
256                 TALLOC_FREE(session);
257                 reply_nterror(req, nt_status_squash(status));
258                 return;
259         }
260
261         if (NT_STATUS_IS_OK(status)) {
262                 struct auth_session_info *session_info = NULL;
263
264                 status = gensec_session_info(session->gensec,
265                                              session,
266                                              &session_info);
267                 if (!NT_STATUS_IS_OK(status)) {
268                         DEBUG(1,("Failed to generate session_info "
269                                  "(user and group token) for session setup: %s\n",
270                                  nt_errstr(status)));
271                         data_blob_free(&out_blob);
272                         TALLOC_FREE(session);
273                         reply_nterror(req, nt_status_squash(status));
274                         return;
275                 }
276
277                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
278                         action = 1;
279                 }
280
281                 session->compat = talloc_zero(session, struct user_struct);
282                 if (session->compat == NULL) {
283                         data_blob_free(&out_blob);
284                         TALLOC_FREE(session);
285                         reply_nterror(req, NT_STATUS_NO_MEMORY);
286                         return;
287                 }
288                 session->compat->session = session;
289                 session->compat->homes_snum = -1;
290                 session->compat->session_info = session_info;
291                 session->compat->session_keystr = NULL;
292                 session->compat->vuid = session->global->session_wire_id;
293                 DLIST_ADD(sconn->users, session->compat);
294                 sconn->num_users++;
295
296                 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
297                         session->compat->homes_snum =
298                                 register_homes_share(session_info->unix_info->unix_name);
299                 }
300
301                 if (!session_claim(sconn, session->compat)) {
302                         DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
303                                   (unsigned long long)session->compat->vuid));
304                         data_blob_free(&out_blob);
305                         TALLOC_FREE(session);
306                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
307                         return;
308                 }
309
310                 if (srv_is_signing_negotiated(sconn) && action == 0) {
311                         /*
312                          * Try and turn on server signing on the first non-guest
313                          * sessionsetup.
314                          */
315                         srv_set_signing(sconn,
316                                 session_info->session_key,
317                                 data_blob_null);
318                 }
319
320                 set_current_user_info(session_info->unix_info->sanitized_username,
321                                       session_info->unix_info->unix_name,
322                                       session_info->info->domain_name);
323
324                 session->status = NT_STATUS_OK;
325                 session->global->auth_session_info = talloc_move(session->global,
326                                                                  &session_info);
327                 session->global->auth_session_info_seqnum += 1;
328                 session->global->channels[0].auth_session_info_seqnum =
329                         session->global->auth_session_info_seqnum;
330
331                 status = smbXsrv_session_update(session);
332                 if (!NT_STATUS_IS_OK(status)) {
333                         DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
334                                   (unsigned long long)session->compat->vuid,
335                                   nt_errstr(status)));
336                         data_blob_free(&out_blob);
337                         TALLOC_FREE(session);
338                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
339                         return;
340                 }
341
342                 /* current_user_info is changed on new vuid */
343                 reload_services(sconn, conn_snum_used, true);
344         }
345
346         vuid = session->global->session_wire_id;
347
348         reply_outbuf(req, 4, 0);
349
350         SSVAL(req->outbuf, smb_uid, vuid);
351         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
352         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
353         SSVAL(req->outbuf, smb_vwv2, action);
354         SSVAL(req->outbuf, smb_vwv3, out_blob.length);
355
356         if (message_push_blob(&req->outbuf, out_blob) == -1) {
357                 data_blob_free(&out_blob);
358                 TALLOC_FREE(session);
359                 reply_nterror(req, NT_STATUS_NO_MEMORY);
360                 return;
361         }
362         data_blob_free(&out_blob);
363
364         if (push_signature(&req->outbuf) == -1) {
365                 TALLOC_FREE(session);
366                 reply_nterror(req, NT_STATUS_NO_MEMORY);
367                 return;
368         }
369 }
370
371 /****************************************************************************
372  On new VC == 0, shutdown *all* old connections and users.
373  It seems that only NT4.x does this. At W2K and above (XP etc.).
374  a new session setup with VC==0 is ignored.
375 ****************************************************************************/
376
377 struct shutdown_state {
378         const char *ip;
379         struct messaging_context *msg_ctx;
380 };
381
382 static int shutdown_other_smbds(const struct connections_key *key,
383                                 const struct connections_data *crec,
384                                 void *private_data)
385 {
386         struct shutdown_state *state = (struct shutdown_state *)private_data;
387         struct server_id self_pid = messaging_server_id(state->msg_ctx);
388
389         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
390                    server_id_str(talloc_tos(), &crec->pid), crec->addr));
391
392         if (!process_exists(crec->pid)) {
393                 DEBUG(10, ("process does not exist\n"));
394                 return 0;
395         }
396
397         if (serverid_equal(&crec->pid, &self_pid)) {
398                 DEBUG(10, ("It's me\n"));
399                 return 0;
400         }
401
402         if (strcmp(state->ip, crec->addr) != 0) {
403                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
404                 return 0;
405         }
406
407         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
408                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
409                   state->ip));
410
411         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
412                        &data_blob_null);
413         return 0;
414 }
415
416 static void setup_new_vc_session(struct smbd_server_connection *sconn)
417 {
418         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
419                 "compatible we would close all old resources.\n"));
420 #if 0
421         conn_close_all();
422         invalidate_all_vuids();
423 #endif
424         if (lp_reset_on_zero_vc()) {
425                 char *addr;
426                 struct shutdown_state state;
427
428                 addr = tsocket_address_inet_addr_string(
429                         sconn->remote_address, talloc_tos());
430                 if (addr == NULL) {
431                         return;
432                 }
433                 state.ip = addr;
434                 state.msg_ctx = sconn->msg_ctx;
435                 connections_forall_read(shutdown_other_smbds, &state);
436                 TALLOC_FREE(addr);
437         }
438 }
439
440 /****************************************************************************
441  Reply to a session setup command.
442 ****************************************************************************/
443
444 void reply_sesssetup_and_X(struct smb_request *req)
445 {
446         uint64_t sess_vuid;
447         int smb_bufsize;
448         DATA_BLOB lm_resp;
449         DATA_BLOB nt_resp;
450         DATA_BLOB plaintext_password;
451         char *tmp;
452         const char *user;
453         fstring sub_user; /* Sanitised username for substituion */
454         const char *domain;
455         const char *native_os;
456         const char *native_lanman;
457         const char *primary_domain;
458         struct auth_usersupplied_info *user_info = NULL;
459         struct auth_session_info *session_info = NULL;
460         uint16 smb_flag2 = req->flags2;
461         uint16_t action = 0;
462         NTTIME now = timeval_to_nttime(&req->request_time);
463         struct smbXsrv_session *session = NULL;
464
465         NTSTATUS nt_status;
466         struct smbd_server_connection *sconn = req->sconn;
467
468         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
469         bool signing_allowed = false;
470         bool signing_mandatory = false;
471
472         START_PROFILE(SMBsesssetupX);
473
474         ZERO_STRUCT(lm_resp);
475         ZERO_STRUCT(nt_resp);
476         ZERO_STRUCT(plaintext_password);
477
478         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
479
480         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
481                 signing_allowed = true;
482         }
483         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
484                 signing_mandatory = true;
485         }
486
487         /*
488          * We can call srv_set_signing_negotiated() each time.
489          * It finds out when it needs to turn into a noop
490          * itself.
491          */
492         srv_set_signing_negotiated(req->sconn,
493                                    signing_allowed,
494                                    signing_mandatory);
495
496         /* a SPNEGO session setup has 12 command words, whereas a normal
497            NT1 session setup has 13. See the cifs spec. */
498         if (req->wct == 12 &&
499             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
500
501                 if (!sconn->smb1.negprot.spnego) {
502                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
503                                  "at SPNEGO session setup when it was not "
504                                  "negotiated.\n"));
505                         reply_nterror(req, nt_status_squash(
506                                               NT_STATUS_LOGON_FAILURE));
507                         END_PROFILE(SMBsesssetupX);
508                         return;
509                 }
510
511                 if (SVAL(req->vwv+4, 0) == 0) {
512                         setup_new_vc_session(req->sconn);
513                 }
514
515                 reply_sesssetup_and_X_spnego(req);
516                 END_PROFILE(SMBsesssetupX);
517                 return;
518         }
519
520         smb_bufsize = SVAL(req->vwv+2, 0);
521
522         if (get_Protocol() < PROTOCOL_NT1) {
523                 uint16 passlen1 = SVAL(req->vwv+7, 0);
524
525                 /* Never do NT status codes with protocols before NT1 as we
526                  * don't get client caps. */
527                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
528
529                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
530                         reply_nterror(req, nt_status_squash(
531                                               NT_STATUS_INVALID_PARAMETER));
532                         END_PROFILE(SMBsesssetupX);
533                         return;
534                 }
535
536                 if (doencrypt) {
537                         lm_resp = data_blob(req->buf, passlen1);
538                 } else {
539                         plaintext_password = data_blob(req->buf, passlen1+1);
540                         /* Ensure null termination */
541                         plaintext_password.data[passlen1] = 0;
542                 }
543
544                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
545                                        req->buf + passlen1, STR_TERMINATE);
546                 user = tmp ? tmp : "";
547
548                 domain = "";
549
550         } else {
551                 uint16 passlen1 = SVAL(req->vwv+7, 0);
552                 uint16 passlen2 = SVAL(req->vwv+8, 0);
553                 enum remote_arch_types ra_type = get_remote_arch();
554                 const uint8_t *p = req->buf;
555                 const uint8_t *save_p = req->buf;
556                 uint16 byte_count;
557
558
559                 if(global_client_caps == 0) {
560                         global_client_caps = IVAL(req->vwv+11, 0);
561
562                         if (!(global_client_caps & CAP_STATUS32)) {
563                                 remove_from_common_flags2(
564                                                 FLAGS2_32_BIT_ERROR_CODES);
565                         }
566
567                         /* client_caps is used as final determination if
568                          * client is NT or Win95. This is needed to return
569                          * the correct error codes in some circumstances.
570                         */
571
572                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
573                                         ra_type == RA_WIN95) {
574                                 if(!(global_client_caps & (CAP_NT_SMBS|
575                                                         CAP_STATUS32))) {
576                                         set_remote_arch( RA_WIN95);
577                                 }
578                         }
579                 }
580
581                 if (!doencrypt) {
582                         /* both Win95 and WinNT stuff up the password
583                          * lengths for non-encrypting systems. Uggh.
584
585                            if passlen1==24 its a win95 system, and its setting
586                            the password length incorrectly. Luckily it still
587                            works with the default code because Win95 will null
588                            terminate the password anyway
589
590                            if passlen1>0 and passlen2>0 then maybe its a NT box
591                            and its setting passlen2 to some random value which
592                            really stuffs things up. we need to fix that one.  */
593
594                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
595                                         passlen2 != 1) {
596                                 passlen2 = 0;
597                         }
598                 }
599
600                 /* check for nasty tricks */
601                 if (passlen1 > MAX_PASS_LEN
602                     || passlen1 > smbreq_bufrem(req, p)) {
603                         reply_nterror(req, nt_status_squash(
604                                               NT_STATUS_INVALID_PARAMETER));
605                         END_PROFILE(SMBsesssetupX);
606                         return;
607                 }
608
609                 if (passlen2 > MAX_PASS_LEN
610                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
611                         reply_nterror(req, nt_status_squash(
612                                               NT_STATUS_INVALID_PARAMETER));
613                         END_PROFILE(SMBsesssetupX);
614                         return;
615                 }
616
617                 /* Save the lanman2 password and the NT md4 password. */
618
619                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
620                         doencrypt = False;
621                 }
622
623                 if (doencrypt) {
624                         lm_resp = data_blob(p, passlen1);
625                         nt_resp = data_blob(p+passlen1, passlen2);
626                 } else {
627                         char *pass = NULL;
628                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
629
630                         if (unic && (passlen2 == 0) && passlen1) {
631                                 /* Only a ascii plaintext password was sent. */
632                                 (void)srvstr_pull_talloc(talloc_tos(),
633                                                         req->inbuf,
634                                                         req->flags2,
635                                                         &pass,
636                                                         req->buf,
637                                                         passlen1,
638                                                         STR_TERMINATE|STR_ASCII);
639                         } else {
640                                 (void)srvstr_pull_talloc(talloc_tos(),
641                                                         req->inbuf,
642                                                         req->flags2,
643                                                         &pass,
644                                                         req->buf,
645                                                         unic ? passlen2 : passlen1,
646                                                         STR_TERMINATE);
647                         }
648                         if (!pass) {
649                                 reply_nterror(req, nt_status_squash(
650                                               NT_STATUS_INVALID_PARAMETER));
651                                 END_PROFILE(SMBsesssetupX);
652                                 return;
653                         }
654                         plaintext_password = data_blob(pass, strlen(pass)+1);
655                 }
656
657                 p += passlen1 + passlen2;
658
659                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
660                                             STR_TERMINATE);
661                 user = tmp ? tmp : "";
662
663                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
664                                             STR_TERMINATE);
665                 domain = tmp ? tmp : "";
666
667                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
668                                             STR_TERMINATE);
669                 native_os = tmp ? tmp : "";
670
671                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
672                                             STR_TERMINATE);
673                 native_lanman = tmp ? tmp : "";
674
675                 /* not documented or decoded by Ethereal but there is one more
676                  * string in the extra bytes which is the same as the
677                  * PrimaryDomain when using extended security.  Windows NT 4
678                  * and 2003 use this string to store the native lanman string.
679                  * Windows 9x does not include a string here at all so we have
680                  * to check if we have any extra bytes left */
681
682                 byte_count = SVAL(req->vwv+13, 0);
683                 if ( PTR_DIFF(p, save_p) < byte_count) {
684                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
685                                                     STR_TERMINATE);
686                         primary_domain = tmp ? tmp : "";
687                 } else {
688                         primary_domain = talloc_strdup(talloc_tos(), "null");
689                 }
690
691                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
692                         "PrimaryDomain=[%s]\n",
693                         domain, native_os, native_lanman, primary_domain));
694
695                 if ( ra_type == RA_WIN2K ) {
696                         if ( strlen(native_lanman) == 0 )
697                                 ra_lanman_string( primary_domain );
698                         else
699                                 ra_lanman_string( native_lanman );
700                 }
701
702         }
703
704         if (SVAL(req->vwv+4, 0) == 0) {
705                 setup_new_vc_session(req->sconn);
706         }
707
708         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
709                                 domain, user, get_remote_machine_name()));
710
711         if (*user) {
712                 if (sconn->smb1.negprot.spnego) {
713
714                         /* This has to be here, because this is a perfectly
715                          * valid behaviour for guest logons :-( */
716
717                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
718                                 "at 'normal' session setup after "
719                                 "negotiating spnego.\n"));
720                         reply_nterror(req, nt_status_squash(
721                                               NT_STATUS_LOGON_FAILURE));
722                         END_PROFILE(SMBsesssetupX);
723                         return;
724                 }
725                 fstrcpy(sub_user, user);
726         } else {
727                 fstrcpy(sub_user, "");
728         }
729
730         sub_set_smb_name(sub_user);
731
732         reload_services(sconn, conn_snum_used, true);
733
734         if (!*user) {
735
736                 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
737
738         } else if (doencrypt) {
739                 struct auth4_context *negprot_auth_context = NULL;
740                 negprot_auth_context = sconn->smb1.negprot.auth_context;
741                 if (!negprot_auth_context) {
742                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
743                                 "session setup without negprot denied!\n"));
744                         reply_nterror(req, nt_status_squash(
745                                               NT_STATUS_LOGON_FAILURE));
746                         END_PROFILE(SMBsesssetupX);
747                         return;
748                 }
749                 nt_status = make_user_info_for_reply_enc(&user_info, user,
750                                                 domain,
751                                                 sconn->remote_address,
752                                                 lm_resp, nt_resp);
753                 if (NT_STATUS_IS_OK(nt_status)) {
754                         nt_status = auth_check_password_session_info(negprot_auth_context, 
755                                                                      req, user_info, &session_info);
756                 }
757         } else {
758                 struct auth4_context *plaintext_auth_context = NULL;
759
760                 nt_status = make_auth4_context(
761                         talloc_tos(), &plaintext_auth_context);
762
763                 if (NT_STATUS_IS_OK(nt_status)) {
764                         uint8_t chal[8];
765
766                         plaintext_auth_context->get_ntlm_challenge(
767                                         plaintext_auth_context, chal);
768
769                         if (!make_user_info_for_reply(&user_info,
770                                                       user, domain,
771                                                       sconn->remote_address,
772                                                       chal,
773                                                       plaintext_password)) {
774                                 nt_status = NT_STATUS_NO_MEMORY;
775                         }
776
777                         if (NT_STATUS_IS_OK(nt_status)) {
778                                 nt_status = auth_check_password_session_info(plaintext_auth_context, 
779                                                                              req, user_info, &session_info);
780                         }
781                         TALLOC_FREE(plaintext_auth_context);
782                 }
783         }
784
785         free_user_info(&user_info);
786
787         if (!NT_STATUS_IS_OK(nt_status)) {
788                 data_blob_free(&nt_resp);
789                 data_blob_free(&lm_resp);
790                 data_blob_clear_free(&plaintext_password);
791                 reply_nterror(req, nt_status_squash(nt_status));
792                 END_PROFILE(SMBsesssetupX);
793                 return;
794         }
795
796         data_blob_clear_free(&plaintext_password);
797
798         /* it's ok - setup a reply */
799         reply_outbuf(req, 3, 0);
800         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
801         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
802
803         if (get_Protocol() >= PROTOCOL_NT1) {
804                 push_signature(&req->outbuf);
805                 /* perhaps grab OS version here?? */
806         }
807
808         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
809                 action = 1;
810         }
811
812         /* register the name and uid as being validated, so further connections
813            to a uid can get through without a password, on the same VC */
814
815         nt_status = smbXsrv_session_create(sconn->conn,
816                                            now, &session);
817         if (!NT_STATUS_IS_OK(nt_status)) {
818                 data_blob_free(&nt_resp);
819                 data_blob_free(&lm_resp);
820                 reply_nterror(req, nt_status_squash(nt_status));
821                 END_PROFILE(SMBsesssetupX);
822                 return;
823         }
824
825         session->compat = talloc_zero(session, struct user_struct);
826         if (session->compat == NULL) {
827                 data_blob_free(&nt_resp);
828                 data_blob_free(&lm_resp);
829                 TALLOC_FREE(session);
830                 reply_nterror(req, NT_STATUS_NO_MEMORY);
831                 END_PROFILE(SMBsesssetupX);
832                 return;
833         }
834         session->compat->session = session;
835         session->compat->homes_snum = -1;
836         session->compat->session_info = session_info;
837         session->compat->session_keystr = NULL;
838         session->compat->vuid = session->global->session_wire_id;
839         DLIST_ADD(sconn->users, session->compat);
840         sconn->num_users++;
841
842         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
843                 session->compat->homes_snum =
844                         register_homes_share(session_info->unix_info->unix_name);
845         }
846
847         if (!session_claim(sconn, session->compat)) {
848                 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
849                           (unsigned long long)session->compat->vuid));
850                 data_blob_free(&nt_resp);
851                 data_blob_free(&lm_resp);
852                 TALLOC_FREE(session);
853                 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
854                 END_PROFILE(SMBsesssetupX);
855                 return;
856         }
857
858         if (srv_is_signing_negotiated(sconn) && action == 0) {
859                 /*
860                  * Try and turn on server signing on the first non-guest
861                  * sessionsetup.
862                  */
863                 srv_set_signing(sconn,
864                         session_info->session_key,
865                         nt_resp.data ? nt_resp : lm_resp);
866         }
867
868         set_current_user_info(session_info->unix_info->sanitized_username,
869                               session_info->unix_info->unix_name,
870                               session_info->info->domain_name);
871
872         session->status = NT_STATUS_OK;
873         session->global->auth_session_info = talloc_move(session->global,
874                                                          &session_info);
875         session->global->auth_session_info_seqnum += 1;
876         session->global->channels[0].auth_session_info_seqnum =
877                 session->global->auth_session_info_seqnum;
878
879         nt_status = smbXsrv_session_update(session);
880         if (!NT_STATUS_IS_OK(nt_status)) {
881                 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
882                           (unsigned long long)session->compat->vuid,
883                           nt_errstr(nt_status)));
884                 data_blob_free(&nt_resp);
885                 data_blob_free(&lm_resp);
886                 TALLOC_FREE(session);
887                 reply_nterror(req, nt_status_squash(nt_status));
888                 END_PROFILE(SMBsesssetupX);
889                 return;
890         }
891
892         /* current_user_info is changed on new vuid */
893         reload_services(sconn, conn_snum_used, true);
894
895         sess_vuid = session->global->session_wire_id;
896
897         data_blob_free(&nt_resp);
898         data_blob_free(&lm_resp);
899
900         SSVAL(req->outbuf,smb_vwv2,action);
901         SSVAL(req->outbuf,smb_uid,sess_vuid);
902         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
903         req->vuid = sess_vuid;
904
905         if (!sconn->smb1.sessions.done_sesssetup) {
906                 sconn->smb1.sessions.max_send =
907                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
908         }
909         sconn->smb1.sessions.done_sesssetup = true;
910
911         END_PROFILE(SMBsesssetupX);
912 }