Remove a pointles call to smb_bufrem
[ira/wip.git] / source3 / smbd / sesssetup.c
index aee8e498e9d258d906aae384a36d8e49bc41be84..b2583861217f93ead7d082233283f4280132d5c0 100644 (file)
@@ -45,7 +45,7 @@ static NTSTATUS do_map_to_guest(NTSTATUS status,
                    (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
                        DEBUG(3,("No such user %s [%s] - using guest account\n",
                                 user, domain));
-                       status = make_server_info_guest(server_info);
+                       status = make_server_info_guest(NULL, server_info);
                }
        }
 
@@ -53,7 +53,7 @@ static NTSTATUS do_map_to_guest(NTSTATUS status,
                if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
                        DEBUG(3,("Registered username %s for guest access\n",
                                user));
-                       status = make_server_info_guest(server_info);
+                       status = make_server_info_guest(NULL, server_info);
                }
        }
 
@@ -125,21 +125,18 @@ static void reply_sesssetup_blob(struct smb_request *req,
        if (!NT_STATUS_IS_OK(nt_status) &&
            !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                reply_nterror(req, nt_status_squash(nt_status));
-       } else {
-               nt_status = nt_status_squash(nt_status);
-               SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
-               SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
-               SSVAL(req->outbuf, smb_vwv3, blob.length);
-
-               if ((message_push_blob(&req->outbuf, blob) == -1)
-                   || (push_signature(&req->outbuf) == -1)) {
-                       reply_nterror(req, NT_STATUS_NO_MEMORY);
-               }
+               return;
        }
 
-       show_msg((char *)req->outbuf);
-       srv_send_smb(smbd_server_fd(),(char *)req->outbuf,req->encrypted);
-       TALLOC_FREE(req->outbuf);
+       nt_status = nt_status_squash(nt_status);
+       SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
+       SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
+       SSVAL(req->outbuf, smb_vwv3, blob.length);
+
+       if ((message_push_blob(&req->outbuf, blob) == -1)
+           || (push_signature(&req->outbuf) == -1)) {
+               reply_nterror(req, NT_STATUS_NO_MEMORY);
+       }
 }
 
 /****************************************************************************
@@ -248,6 +245,7 @@ static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
 
 static void reply_spnego_kerberos(struct smb_request *req,
                                  DATA_BLOB *secblob,
+                                 const char *mechOID,
                                  uint16 vuid,
                                  bool *p_invalidate_vuid)
 {
@@ -259,7 +257,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
        fstring user;
        int sess_vuid = req->vuid;
        NTSTATUS ret = NT_STATUS_OK;
-       PAC_DATA *pac_data = NULL;
+       struct PAC_DATA *pac_data = NULL;
        DATA_BLOB ap_rep, ap_rep_wrapped, response;
        auth_serversupplied_info *server_info = NULL;
        DATA_BLOB session_key = data_blob_null;
@@ -268,7 +266,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
        fstring real_username;
        bool map_domainuser_to_guest = False;
        bool username_was_mapped;
-       PAC_LOGON_INFO *logon_info = NULL;
+       struct PAC_LOGON_INFO *logon_info = NULL;
 
        ZERO_STRUCT(ticket);
        ZERO_STRUCT(ap_rep);
@@ -394,10 +392,9 @@ static void reply_spnego_kerberos(struct smb_request *req,
 
        domain = p+1;
 
-       if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
-               unistr2_to_ascii(netbios_domain_name,
-                               &logon_info->info3.uni_logon_dom,
-                               sizeof(netbios_domain_name));
+       if (logon_info && logon_info->info3.base.domain.string) {
+               fstrcpy(netbios_domain_name,
+                       logon_info->info3.base.domain.string);
                domain = netbios_domain_name;
                DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
 
@@ -410,30 +407,24 @@ static void reply_spnego_kerberos(struct smb_request *req,
                   name. And even w2k3 does use ntlmssp if you for example
                   connect to an ip address. */
 
-               struct winbindd_request wb_request;
-               struct winbindd_response wb_response;
-               NSS_STATUS wb_result;
-
-               ZERO_STRUCT(wb_request);
-               ZERO_STRUCT(wb_response);
+               wbcErr wbc_status;
+               struct wbcDomainInfo *info = NULL;
 
                DEBUG(10, ("Mapping [%s] to short name\n", domain));
 
-               fstrcpy(wb_request.domain_name, domain);
+               wbc_status = wbcDomainInfo(domain, &info);
 
-               wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
-                                            &wb_request, &wb_response);
-
-               if (wb_result == NSS_STATUS_SUCCESS) {
+               if (WBC_ERROR_IS_OK(wbc_status)) {
 
                        fstrcpy(netbios_domain_name,
-                               wb_response.data.domain_info.name);
-                       domain = netbios_domain_name;
+                               info->short_name);
 
+                       wbcFreeMemory(info);
+                       domain = netbios_domain_name;
                        DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
                } else {
-                       DEBUG(3, ("Could not find short name -- winbind "
-                                 "not running?\n"));
+                       DEBUG(3, ("Could not find short name: %s\n",
+                               wbcErrorString(wbc_status)));
                }
        }
 
@@ -448,7 +439,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
        if (pw) {
                /* if a real user check pam account restrictions */
                /* only really perfomed if "obey pam restriction" is true */
-               /* do this before an eventual mappign to guest occurs */
+               /* do this before an eventual mapping to guest occurs */
                ret = smb_pam_accountcheck(pw->pw_name);
                if (  !NT_STATUS_IS_OK(ret)) {
                        DEBUG(1,("PAM account restriction "
@@ -494,7 +485,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
        reload_services(True);
 
        if ( map_domainuser_to_guest ) {
-               make_server_info_guest(&server_info);
+               make_server_info_guest(NULL, &server_info);
        } else if (logon_info) {
                /* pass the unmapped username here since map_username()
                   will be called again from inside make_server_info_info3() */
@@ -536,9 +527,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
                }
        }
 
-       if (username_was_mapped) {
-               server_info->was_mapped = username_was_mapped;
-       }
+       server_info->nss_token |= username_was_mapped;
 
        /* we need to build the token for the user. make_server_info_guest()
           already does this */
@@ -546,6 +535,8 @@ static void reply_spnego_kerberos(struct smb_request *req,
        if ( !server_info->ptok ) {
                ret = create_local_token( server_info );
                if ( !NT_STATUS_IS_OK(ret) ) {
+                       DEBUG(10,("failed to create local token: %s\n",
+                               nt_errstr(ret)));
                        SAFE_FREE(client);
                        data_blob_free(&ap_rep);
                        data_blob_free(&session_key);
@@ -564,9 +555,13 @@ static void reply_spnego_kerberos(struct smb_request *req,
        if (!is_partial_auth_vuid(sess_vuid)) {
                sess_vuid = register_initial_vuid();
        }
+
+       data_blob_free(&server_info->user_session_key);
+       server_info->user_session_key = session_key;
+       session_key = data_blob_null;
+
        sess_vuid = register_existing_vuid(sess_vuid,
                                        server_info,
-                                       session_key,
                                        nullblob,
                                        client);
 
@@ -577,7 +572,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
 
        if (sess_vuid == UID_FIELD_INVALID ) {
                ret = NT_STATUS_LOGON_FAILURE;
-               data_blob_free(&session_key);
        } else {
                /* current_user_info is changed on new vuid */
                reload_services( True );
@@ -603,7 +597,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
                ap_rep_wrapped = data_blob_null;
        }
        response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
-                       OID_KERBEROS5_OLD);
+                       mechOID);
        reply_sesssetup_blob(req, response, ret);
 
        data_blob_free(&ap_rep);
@@ -626,6 +620,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
                                 uint16 vuid,
                                 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
                                 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
+                                const char *OID,
                                 bool wrap)
 {
        DATA_BLOB response;
@@ -646,23 +641,24 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
 
        if (NT_STATUS_IS_OK(nt_status)) {
                DATA_BLOB nullblob = data_blob_null;
-               DATA_BLOB session_key =
-                       data_blob(
-                       (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
-                       (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
 
                if (!is_partial_auth_vuid(vuid)) {
-                       data_blob_free(&session_key);
                        nt_status = NT_STATUS_LOGON_FAILURE;
                        goto out;
                }
+
+               data_blob_free(&server_info->user_session_key);
+               server_info->user_session_key =
+                       data_blob_talloc(
+                       server_info,
+                       (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
+                       (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
+
                /* register_existing_vuid keeps the server info */
                if (register_existing_vuid(vuid,
-                               server_info,
-                               session_key, nullblob,
+                               server_info, nullblob,
                                (*auth_ntlmssp_state)->ntlmssp_state->user) !=
                                        vuid) {
-                       data_blob_free(&session_key);
                        nt_status = NT_STATUS_LOGON_FAILURE;
                        goto out;
                }
@@ -686,7 +682,7 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
 
        if (wrap) {
                response = spnego_gen_auth_response(ntlmssp_blob,
-                               nt_status, OID_NTLMSSP);
+                               nt_status, OID);
        } else {
                response = *ntlmssp_blob;
        }
@@ -713,13 +709,15 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
  Is this a krb5 mechanism ?
 ****************************************************************************/
 
-NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
-               bool *p_is_krb5)
+NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
+               DATA_BLOB *pblob_out,
+               char **kerb_mechOID)
 {
        char *OIDs[ASN1_MAX_OIDS];
        int i;
+       NTSTATUS ret = NT_STATUS_OK;
 
-       *p_is_krb5 = False;
+       *kerb_mechOID = NULL;
 
        /* parse out the OIDs and the first sec blob */
        if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
@@ -739,15 +737,40 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
 #ifdef HAVE_KRB5
        if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
            strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
-               *p_is_krb5 = True;
+               *kerb_mechOID = SMB_STRDUP(OIDs[0]);
+               if (*kerb_mechOID == NULL) {
+                       ret = NT_STATUS_NO_MEMORY;
+               }
        }
 #endif
 
        for (i=0;OIDs[i];i++) {
                DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
-               free(OIDs[i]);
+               talloc_free(OIDs[i]);
        }
-       return NT_STATUS_OK;
+       return ret;
+}
+
+/****************************************************************************
+ Fall back from krb5 to NTLMSSP.
+****************************************************************************/
+
+static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
+                                               uint16 vuid)
+{
+       DATA_BLOB response;
+
+       reply_outbuf(req, 4, 0);
+        SSVAL(req->outbuf,smb_uid,vuid);
+
+       DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
+               "but set to downgrade to NTLMSSP\n"));
+
+       response = spnego_gen_auth_response(NULL,
+                       NT_STATUS_MORE_PROCESSING_REQUIRED,
+                       OID_NTLMSSP);
+       reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
+       data_blob_free(&response);
 }
 
 /****************************************************************************
@@ -761,11 +784,10 @@ static void reply_spnego_negotiate(struct smb_request *req,
 {
        DATA_BLOB secblob;
        DATA_BLOB chal;
-       bool got_kerberos_mechanism = False;
+       char *kerb_mech = NULL;
        NTSTATUS status;
 
-       status = parse_spnego_mechanisms(blob1, &secblob,
-                       &got_kerberos_mechanism);
+       status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
        if (!NT_STATUS_IS_OK(status)) {
                /* Kill the intermediate vuid */
                invalidate_vuid(vuid);
@@ -777,16 +799,17 @@ static void reply_spnego_negotiate(struct smb_request *req,
                                (unsigned long)secblob.length));
 
 #ifdef HAVE_KRB5
-       if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
+       if (kerb_mech && ((lp_security()==SEC_ADS) ||
                                lp_use_kerberos_keytab()) ) {
                bool destroy_vuid = True;
-               reply_spnego_kerberos(req, &secblob, vuid,
-                                     &destroy_vuid);
+               reply_spnego_kerberos(req, &secblob, kerb_mech,
+                                     vuid, &destroy_vuid);
                data_blob_free(&secblob);
                if (destroy_vuid) {
                        /* Kill the intermediate vuid */
                        invalidate_vuid(vuid);
                }
+               SAFE_FREE(kerb_mech);
                return;
        }
 #endif
@@ -795,6 +818,15 @@ static void reply_spnego_negotiate(struct smb_request *req,
                auth_ntlmssp_end(auth_ntlmssp_state);
        }
 
+       if (kerb_mech) {
+               data_blob_free(&secblob);
+               /* The mechtoken is a krb5 ticket, but
+                * we need to fall back to NTLM. */
+               reply_spnego_downgrade_to_ntlmssp(req, vuid);
+               SAFE_FREE(kerb_mech);
+               return;
+       }
+
        status = auth_ntlmssp_start(auth_ntlmssp_state);
        if (!NT_STATUS_IS_OK(status)) {
                /* Kill the intermediate vuid */
@@ -809,7 +841,7 @@ static void reply_spnego_negotiate(struct smb_request *req,
        data_blob_free(&secblob);
 
        reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
-                            &chal, status, True);
+                            &chal, status, OID_NTLMSSP, true);
 
        data_blob_free(&chal);
 
@@ -829,7 +861,7 @@ static void reply_spnego_auth(struct smb_request *req,
        DATA_BLOB auth = data_blob_null;
        DATA_BLOB auth_reply = data_blob_null;
        DATA_BLOB secblob = data_blob_null;
-       NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
+       NTSTATUS status = NT_STATUS_LOGON_FAILURE;
 
        if (!spnego_parse_auth(blob1, &auth)) {
 #if 0
@@ -839,34 +871,54 @@ static void reply_spnego_auth(struct smb_request *req,
                invalidate_vuid(vuid);
 
                reply_nterror(req, nt_status_squash(
-                                     NT_STATUS_INVALID_PARAMETER));
+                                     NT_STATUS_LOGON_FAILURE));
                return;
        }
 
        if (auth.data[0] == ASN1_APPLICATION(0)) {
                /* Might be a second negTokenTarg packet */
+               char *kerb_mech = NULL;
+
+               status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       /* Kill the intermediate vuid */
+                       invalidate_vuid(vuid);
+                       reply_nterror(req, nt_status_squash(status));
+                       return;
+               }
 
-               bool got_krb5_mechanism = False;
-               status = parse_spnego_mechanisms(auth, &secblob,
-                               &got_krb5_mechanism);
-               if (NT_STATUS_IS_OK(status)) {
-                       DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
-                                       (unsigned long)secblob.length));
+               DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
+                               (unsigned long)secblob.length));
 #ifdef HAVE_KRB5
-                       if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
-                                               lp_use_kerberos_keytab()) ) {
-                               bool destroy_vuid = True;
-                               reply_spnego_kerberos(req, &secblob,
-                                                     vuid, &destroy_vuid);
-                               data_blob_free(&secblob);
-                               data_blob_free(&auth);
-                               if (destroy_vuid) {
-                                       /* Kill the intermediate vuid */
-                                       invalidate_vuid(vuid);
-                               }
-                               return;
+               if (kerb_mech && ((lp_security()==SEC_ADS) ||
+                                       lp_use_kerberos_keytab()) ) {
+                       bool destroy_vuid = True;
+                       reply_spnego_kerberos(req, &secblob, kerb_mech,
+                                             vuid, &destroy_vuid);
+                       data_blob_free(&secblob);
+                       data_blob_free(&auth);
+                       if (destroy_vuid) {
+                               /* Kill the intermediate vuid */
+                               invalidate_vuid(vuid);
                        }
+                       SAFE_FREE(kerb_mech);
+                       return;
+               }
 #endif
+               /* Can't blunder into NTLMSSP auth if we have
+                * a krb5 ticket. */
+
+               if (kerb_mech) {
+                       /* Kill the intermediate vuid */
+                       invalidate_vuid(vuid);
+                       DEBUG(3,("reply_spnego_auth: network "
+                               "misconfiguration, client sent us a "
+                               "krb5 ticket and kerberos security "
+                               "not enabled"));
+                       reply_nterror(req, nt_status_squash(
+                                       NT_STATUS_LOGON_FAILURE));
+                       SAFE_FREE(kerb_mech);
                }
        }
 
@@ -874,13 +926,13 @@ static void reply_spnego_auth(struct smb_request *req,
        data_blob_free(&secblob);
 
        if (!*auth_ntlmssp_state) {
-               /* Kill the intermediate vuid */
-               invalidate_vuid(vuid);
-
-               /* auth before negotiatiate? */
-               reply_nterror(req, nt_status_squash(
-                                     NT_STATUS_INVALID_PARAMETER));
-               return;
+               status = auth_ntlmssp_start(auth_ntlmssp_state);
+               if (!NT_STATUS_IS_OK(status)) {
+                       /* Kill the intermediate vuid */
+                       invalidate_vuid(vuid);
+                       reply_nterror(req, nt_status_squash(status));
+                       return;
+               }
        }
 
        status = auth_ntlmssp_update(*auth_ntlmssp_state,
@@ -888,9 +940,11 @@ static void reply_spnego_auth(struct smb_request *req,
 
        data_blob_free(&auth);
 
+       /* Don't send the mechid as we've already sent this (RFC4178). */
+
        reply_spnego_ntlmssp(req, vuid,
                             auth_ntlmssp_state,
-                            &auth_reply, status, True);
+                            &auth_reply, status, NULL, true);
 
        data_blob_free(&auth_reply);
 
@@ -944,7 +998,7 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
                DATA_BLOB *pblob)
 {
        struct pending_auth_data *pad = NULL;
-       ASN1_DATA data;
+       ASN1_DATA *data;
        size_t needed_len = 0;
 
        pad = get_pending_auth_data(smbpid);
@@ -1031,34 +1085,39 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
         * the data given in this blob is enough.
         */
 
-       asn1_load(&data, *pblob);
-       asn1_start_tag(&data, pblob->data[0]);
-       if (data.has_error || data.nesting == NULL) {
-               asn1_free(&data);
+       data = asn1_init(NULL);
+       if (data == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       asn1_load(data, *pblob);
+       asn1_start_tag(data, pblob->data[0]);
+       if (data->has_error || data->nesting == NULL) {
+               asn1_free(data);
                /* Let caller catch. */
                return NT_STATUS_OK;
        }
 
        /* Integer wrap paranoia.... */
 
-       if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
-           data.nesting->taglen + data.nesting->start < data.nesting->start) {
+       if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
+           data->nesting->taglen + data->nesting->start < data->nesting->start) {
 
                DEBUG(2,("check_spnego_blob_complete: integer wrap "
                        "data.nesting->taglen = %u, "
                        "data.nesting->start = %u\n",
-                       (unsigned int)data.nesting->taglen,
-                       (unsigned int)data.nesting->start ));
+                       (unsigned int)data->nesting->taglen,
+                       (unsigned int)data->nesting->start ));
 
-               asn1_free(&data);
+               asn1_free(data);
                return NT_STATUS_INVALID_PARAMETER;
        }
 
        /* Total length of the needed asn1 is the tag length
         * plus the current offset. */
 
-       needed_len = data.nesting->taglen + data.nesting->start;
-       asn1_free(&data);
+       needed_len = data->nesting->taglen + data->nesting->start;
+       asn1_free(data);
 
        DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
                "pblob->length = %u\n",
@@ -1257,7 +1316,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
                reply_spnego_ntlmssp(req, vuid,
                                     &vuser->auth_ntlmssp_state,
-                                    &chal, status, False);
+                                    &chal, status, OID_NTLMSSP, false);
                data_blob_free(&chal);
                return;
        }
@@ -1295,6 +1354,9 @@ static int shutdown_other_smbds(struct db_record *rec,
                return 0;
        }
 
+       DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
+                "(IP %s)\n", procid_to_pid(&crec->pid), ip));
+
        messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
                       &data_blob_null);
        return 0;
@@ -1343,8 +1405,6 @@ void reply_sesssetup_and_X(struct smb_request *req)
 
        bool doencrypt = global_encrypted_passwords_negotiated;
 
-       DATA_BLOB session_key;
-
        START_PROFILE(SMBsesssetupX);
 
        ZERO_STRUCT(lm_resp);
@@ -1387,8 +1447,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
                remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
 
                if ((passlen1 > MAX_PASS_LEN)
-                   || (passlen1 > smb_bufrem(req->inbuf,
-                                             smb_buf(req->inbuf)))) {
+                   || (passlen1 > smb_buflen(req->inbuf))) {
                        reply_nterror(req, nt_status_squash(
                                              NT_STATUS_INVALID_PARAMETER));
                        END_PROFILE(SMBsesssetupX);
@@ -1485,7 +1544,11 @@ void reply_sesssetup_and_X(struct smb_request *req)
                if (doencrypt) {
                        lm_resp = data_blob(p, passlen1);
                        nt_resp = data_blob(p+passlen1, passlen2);
-               } else {
+               } else if (lp_security() != SEC_SHARE) {
+                       /*
+                        * In share level we should ignore any passwords, so
+                        * only read them if we're not.
+                        */
                        char *pass = NULL;
                        bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
 
@@ -1588,7 +1651,7 @@ void reply_sesssetup_and_X(struct smb_request *req)
        reload_services(True);
 
        if (lp_security() == SEC_SHARE) {
-               /* in share level we should ignore any passwords */
+               /* In share level we should ignore any passwords */
 
                data_blob_free(&lm_resp);
                data_blob_free(&nt_resp);
@@ -1676,23 +1739,19 @@ void reply_sesssetup_and_X(struct smb_request *req)
                return;
        }
 
-       nt_status = create_local_token(server_info);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(10, ("create_local_token failed: %s\n",
-                          nt_errstr(nt_status)));
-               data_blob_free(&nt_resp);
-               data_blob_free(&lm_resp);
-               data_blob_clear_free(&plaintext_password);
-               reply_nterror(req, nt_status_squash(nt_status));
-               END_PROFILE(SMBsesssetupX);
-               return;
-       }
+       if (!server_info->ptok) {
+               nt_status = create_local_token(server_info);
 
-       if (server_info->user_session_key.data) {
-               session_key = data_blob(server_info->user_session_key.data,
-                               server_info->user_session_key.length);
-       } else {
-               session_key = data_blob_null;
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       DEBUG(10, ("create_local_token failed: %s\n",
+                                  nt_errstr(nt_status)));
+                       data_blob_free(&nt_resp);
+                       data_blob_free(&lm_resp);
+                       data_blob_clear_free(&plaintext_password);
+                       reply_nterror(req, nt_status_squash(nt_status));
+                       END_PROFILE(SMBsesssetupX);
+                       return;
+               }
        }
 
        data_blob_clear_free(&plaintext_password);
@@ -1713,7 +1772,6 @@ void reply_sesssetup_and_X(struct smb_request *req)
 
        if (lp_security() == SEC_SHARE) {
                sess_vuid = UID_FIELD_INVALID;
-               data_blob_free(&session_key);
                TALLOC_FREE(server_info);
        } else {
                /* Ignore the initial vuid. */
@@ -1721,7 +1779,6 @@ void reply_sesssetup_and_X(struct smb_request *req)
                if (sess_vuid == UID_FIELD_INVALID) {
                        data_blob_free(&nt_resp);
                        data_blob_free(&lm_resp);
-                       data_blob_free(&session_key);
                        reply_nterror(req, nt_status_squash(
                                              NT_STATUS_LOGON_FAILURE));
                        END_PROFILE(SMBsesssetupX);
@@ -1730,13 +1787,11 @@ void reply_sesssetup_and_X(struct smb_request *req)
                /* register_existing_vuid keeps the server info */
                sess_vuid = register_existing_vuid(sess_vuid,
                                        server_info,
-                                       session_key,
                                        nt_resp.data ? nt_resp : lm_resp,
                                        sub_user);
                if (sess_vuid == UID_FIELD_INVALID) {
                        data_blob_free(&nt_resp);
                        data_blob_free(&lm_resp);
-                       data_blob_free(&session_key);
                        reply_nterror(req, nt_status_squash(
                                              NT_STATUS_LOGON_FAILURE));
                        END_PROFILE(SMBsesssetupX);