Ignore:
Timestamp:
Nov 24, 2016, 1:14:11 PM (9 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to version 4.4.3

File:
1 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source3/smbd/sesssetup.c

    r860 r988  
    2727#include "smbd/smbd.h"
    2828#include "smbd/globals.h"
    29 #include "../libcli/auth/spnego.h"
    30 #include "../libcli/auth/ntlmssp.h"
    31 #include "ntlmssp_wrap.h"
    32 #include "../librpc/gen_ndr/krb5pac.h"
    33 #include "libads/kerberos_proto.h"
    34 #include "../lib/util/asn1.h"
    3529#include "auth.h"
    3630#include "messages.h"
    3731#include "smbprofile.h"
    38 
    39 /* For split krb5 SPNEGO blobs. */
    40 struct pending_auth_data {
    41         struct pending_auth_data *prev, *next;
    42         uint16 vuid; /* Tag for this entry. */
    43         uint16 smbpid; /* Alternate tag for this entry. */
    44         size_t needed_len;
    45         DATA_BLOB partial_data;
    46 };
    47 
    48 /*
    49   on a logon error possibly map the error to success if "map to guest"
    50   is set approriately
    51 */
    52 NTSTATUS do_map_to_guest(NTSTATUS status,
    53                         struct auth_serversupplied_info **server_info,
    54                         const char *user, const char *domain)
    55 {
    56         user = user ? user : "";
    57         domain = domain ? domain : "";
    58 
    59         if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
    60                 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
    61                     (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
    62                         DEBUG(3,("No such user %s [%s] - using guest account\n",
    63                                  user, domain));
    64                         status = make_server_info_guest(NULL, server_info);
    65                 }
    66         }
    67 
    68         if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
    69                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
    70                         DEBUG(3,("Registered username %s for guest access\n",
    71                                 user));
    72                         status = make_server_info_guest(NULL, server_info);
    73                 }
    74         }
    75 
    76         return status;
    77 }
     32#include "../libcli/security/security.h"
     33#include "auth/gensec/gensec.h"
     34#include "lib/conn_tdb.h"
     35#include "../libcli/smb/smb_signing.h"
    7836
    7937/****************************************************************************
     
    8139****************************************************************************/
    8240
    83 static int push_signature(uint8 **outbuf)
     41static int push_signature(uint8_t **outbuf)
    8442{
    8543        char *lanman;
    8644        int result, tmp;
     45        fstring native_os;
    8746
    8847        result = 0;
    8948
    90         tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
     49        fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
     50                SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
     51
     52        tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
    9153
    9254        if (tmp == -1) return -1;
     
    11375
    11476/****************************************************************************
    115  Send a security blob via a session setup reply.
    116 ****************************************************************************/
    117 
    118 static void reply_sesssetup_blob(struct smb_request *req,
    119                                  DATA_BLOB blob,
    120                                  NTSTATUS nt_status)
    121 {
    122         if (!NT_STATUS_IS_OK(nt_status) &&
    123             !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    124                 reply_nterror(req, nt_status_squash(nt_status));
    125                 return;
    126         }
    127 
    128         nt_status = nt_status_squash(nt_status);
    129         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
    130         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
    131         SSVAL(req->outbuf, smb_vwv3, blob.length);
    132 
    133         if ((message_push_blob(&req->outbuf, blob) == -1)
    134             || (push_signature(&req->outbuf) == -1)) {
    135                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    136         }
    137 }
    138 
    139 /****************************************************************************
    14077 Do a 'guest' logon, getting back the
    14178****************************************************************************/
    14279
    143 static NTSTATUS check_guest_password(struct auth_serversupplied_info **server_info)
     80static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
     81                                     TALLOC_CTX *mem_ctx,
     82                                     struct auth_session_info **session_info)
    14483{
    145         struct auth_context *auth_context;
     84        struct auth4_context *auth_context;
    14685        struct auth_usersupplied_info *user_info = NULL;
    147 
     86        uint8_t chal[8];
    14887        NTSTATUS nt_status;
    149         static unsigned char chal[8] = { 0, };
    15088
    15189        DEBUG(3,("Got anonymous request\n"));
    15290
    153         nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
     91        nt_status = make_auth4_context(talloc_tos(), &auth_context);
    15492        if (!NT_STATUS_IS_OK(nt_status)) {
    15593                return nt_status;
    15694        }
    15795
    158         if (!make_user_info_guest(&user_info)) {
     96        auth_context->get_ntlm_challenge(auth_context,
     97                                         chal);
     98
     99        if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
    159100                TALLOC_FREE(auth_context);
    160101                return NT_STATUS_NO_MEMORY;
    161102        }
    162103
    163         nt_status = auth_context->check_ntlm_password(auth_context,
    164                                                 user_info,
    165                                                 server_info);
     104        nt_status = auth_check_password_session_info(auth_context,
     105                                                     mem_ctx, user_info, session_info);
     106        TALLOC_FREE(user_info);
    166107        TALLOC_FREE(auth_context);
    167         free_user_info(&user_info);
    168108        return nt_status;
    169 }
    170 
    171 
    172 #ifdef HAVE_KRB5
    173 
    174 #if 0
    175 /* Experiment that failed. See "only happens with a KDC" comment below. */
    176 /****************************************************************************
    177  Cerate a clock skew error blob for a Windows client.
    178 ****************************************************************************/
    179 
    180 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
    181 {
    182         krb5_context context = NULL;
    183         krb5_error_code kerr = 0;
    184         krb5_data reply;
    185         krb5_principal host_princ = NULL;
    186         char *host_princ_s = NULL;
    187         bool ret = False;
    188 
    189         *pblob_out = data_blob_null;
    190 
    191         initialize_krb5_error_table();
    192         kerr = krb5_init_context(&context);
    193         if (kerr) {
    194                 return False;
    195         }
    196         /* Create server principal. */
    197         asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
    198         if (!host_princ_s) {
    199                 goto out;
    200         }
    201         strlower_m(host_princ_s);
    202 
    203         kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
    204         if (kerr) {
    205                 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
    206                         "for name %s: Error %s\n",
    207                         host_princ_s, error_message(kerr) ));
    208                 goto out;
    209         }
    210 
    211         kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
    212                         host_princ, &reply);
    213         if (kerr) {
    214                 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
    215                         "failed: Error %s\n",
    216                         error_message(kerr) ));
    217                 goto out;
    218         }
    219 
    220         *pblob_out = data_blob(reply.data, reply.length);
    221         kerberos_free_data_contents(context,&reply);
    222         ret = True;
    223 
    224   out:
    225 
    226         if (host_princ_s) {
    227                 SAFE_FREE(host_princ_s);
    228         }
    229         if (host_princ) {
    230                 krb5_free_principal(context, host_princ);
    231         }
    232         krb5_free_context(context);
    233         return ret;
    234 }
    235 #endif
    236 
    237 /****************************************************************************
    238  Reply to a session setup spnego negotiate packet for kerberos.
    239 ****************************************************************************/
    240 
    241 static void reply_spnego_kerberos(struct smb_request *req,
    242                                   DATA_BLOB *secblob,
    243                                   const char *mechOID,
    244                                   uint16 vuid,
    245                                   bool *p_invalidate_vuid)
    246 {
    247         TALLOC_CTX *mem_ctx;
    248         DATA_BLOB ticket;
    249         struct passwd *pw;
    250         int sess_vuid = req->vuid;
    251         NTSTATUS ret = NT_STATUS_OK;
    252         DATA_BLOB ap_rep, ap_rep_wrapped, response;
    253         struct auth_serversupplied_info *server_info = NULL;
    254         DATA_BLOB session_key = data_blob_null;
    255         uint8 tok_id[2];
    256         DATA_BLOB nullblob = data_blob_null;
    257         bool map_domainuser_to_guest = False;
    258         bool username_was_mapped;
    259         struct PAC_LOGON_INFO *logon_info = NULL;
    260         struct smbd_server_connection *sconn = req->sconn;
    261         char *principal;
    262         char *user;
    263         char *domain;
    264         char *real_username;
    265 
    266         ZERO_STRUCT(ticket);
    267         ZERO_STRUCT(ap_rep);
    268         ZERO_STRUCT(ap_rep_wrapped);
    269         ZERO_STRUCT(response);
    270 
    271         /* Normally we will always invalidate the intermediate vuid. */
    272         *p_invalidate_vuid = True;
    273 
    274         mem_ctx = talloc_init("reply_spnego_kerberos");
    275         if (mem_ctx == NULL) {
    276                 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
    277                 return;
    278         }
    279 
    280         if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
    281                 talloc_destroy(mem_ctx);
    282                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
    283                 return;
    284         }
    285 
    286         ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
    287                                 &principal, &logon_info, &ap_rep,
    288                                 &session_key, True);
    289 
    290         data_blob_free(&ticket);
    291 
    292         if (!NT_STATUS_IS_OK(ret)) {
    293 #if 0
    294                 /* Experiment that failed.
    295                  * See "only happens with a KDC" comment below. */
    296 
    297                 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
    298 
    299                         /*
    300                          * Windows in this case returns
    301                          * NT_STATUS_MORE_PROCESSING_REQUIRED
    302                          * with a negTokenTarg blob containing an krb5_error
    303                          * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
    304                          * The client then fixes its clock and continues rather
    305                          * than giving an error. JRA.
    306                          * -- Looks like this only happens with a KDC. JRA.
    307                          */
    308 
    309                         bool ok = make_krb5_skew_error(&ap_rep);
    310                         if (!ok) {
    311                                 talloc_destroy(mem_ctx);
    312                                 return ERROR_NT(nt_status_squash(
    313                                                 NT_STATUS_LOGON_FAILURE));
    314                         }
    315                         ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
    316                                         TOK_ID_KRB_ERROR);
    317                         response = spnego_gen_auth_response(&ap_rep_wrapped,
    318                                         ret, OID_KERBEROS5_OLD);
    319                         reply_sesssetup_blob(conn, inbuf, outbuf, response,
    320                                         NT_STATUS_MORE_PROCESSING_REQUIRED);
    321 
    322                         /*
    323                          * In this one case we don't invalidate the
    324                          * intermediate vuid as we're expecting the client
    325                          * to re-use it for the next sessionsetupX packet. JRA.
    326                          */
    327 
    328                         *p_invalidate_vuid = False;
    329 
    330                         data_blob_free(&ap_rep);
    331                         data_blob_free(&ap_rep_wrapped);
    332                         data_blob_free(&response);
    333                         talloc_destroy(mem_ctx);
    334                         return -1; /* already replied */
    335                 }
    336 #else
    337                 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
    338                         ret = NT_STATUS_LOGON_FAILURE;
    339                 }
    340 #endif
    341                 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
    342                                 nt_errstr(ret)));
    343                 talloc_destroy(mem_ctx);
    344                 reply_nterror(req, nt_status_squash(ret));
    345                 return;
    346         }
    347 
    348         ret = get_user_from_kerberos_info(talloc_tos(),
    349                                           sconn->client_id.name,
    350                                           principal, logon_info,
    351                                           &username_was_mapped,
    352                                           &map_domainuser_to_guest,
    353                                           &user, &domain,
    354                                           &real_username, &pw);
    355         if (!NT_STATUS_IS_OK(ret)) {
    356                 data_blob_free(&ap_rep);
    357                 data_blob_free(&session_key);
    358                 talloc_destroy(mem_ctx);
    359                 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
    360                 return;
    361         }
    362 
    363         /* save the PAC data if we have it */
    364         if (logon_info) {
    365                 netsamlogon_cache_store(user, &logon_info->info3);
    366         }
    367 
    368         /* setup the string used by %U */
    369         sub_set_smb_name(real_username);
    370 
    371         /* reload services so that the new %U is taken into account */
    372         reload_services(sconn->msg_ctx, sconn->sock, True);
    373 
    374         ret = make_server_info_krb5(mem_ctx,
    375                                     user, domain, real_username, pw,
    376                                     logon_info, map_domainuser_to_guest,
    377                                     &server_info);
    378         if (!NT_STATUS_IS_OK(ret)) {
    379                 DEBUG(1, ("make_server_info_krb5 failed!\n"));
    380                 data_blob_free(&ap_rep);
    381                 data_blob_free(&session_key);
    382                 TALLOC_FREE(mem_ctx);
    383                 reply_nterror(req, nt_status_squash(ret));
    384                 return;
    385         }
    386 
    387         server_info->nss_token |= username_was_mapped;
    388 
    389         /* we need to build the token for the user. make_server_info_guest()
    390            already does this */
    391 
    392         if ( !server_info->security_token ) {
    393                 ret = create_local_token( server_info );
    394                 if ( !NT_STATUS_IS_OK(ret) ) {
    395                         DEBUG(10,("failed to create local token: %s\n",
    396                                 nt_errstr(ret)));
    397                         data_blob_free(&ap_rep);
    398                         data_blob_free(&session_key);
    399                         TALLOC_FREE( mem_ctx );
    400                         TALLOC_FREE( server_info );
    401                         reply_nterror(req, nt_status_squash(ret));
    402                         return;
    403                 }
    404         }
    405 
    406         if (!is_partial_auth_vuid(sconn, sess_vuid)) {
    407                 sess_vuid = register_initial_vuid(sconn);
    408         }
    409 
    410         data_blob_free(&server_info->user_session_key);
    411         /* Set the kerberos-derived session key onto the server_info */
    412         server_info->user_session_key = session_key;
    413         talloc_steal(server_info, session_key.data);
    414 
    415         session_key = data_blob_null;
    416 
    417         /* register_existing_vuid keeps the server info */
    418         /* register_existing_vuid takes ownership of session_key on success,
    419          * no need to free after this on success. A better interface would copy
    420          * it.... */
    421 
    422         sess_vuid = register_existing_vuid(sconn, sess_vuid,
    423                                            server_info, nullblob, user);
    424 
    425         reply_outbuf(req, 4, 0);
    426         SSVAL(req->outbuf,smb_uid,sess_vuid);
    427 
    428         if (sess_vuid == UID_FIELD_INVALID ) {
    429                 ret = NT_STATUS_LOGON_FAILURE;
    430         } else {
    431                 /* current_user_info is changed on new vuid */
    432                 reload_services(sconn->msg_ctx, sconn->sock, True);
    433 
    434                 SSVAL(req->outbuf, smb_vwv3, 0);
    435 
    436                 if (server_info->guest) {
    437                         SSVAL(req->outbuf,smb_vwv2,1);
    438                 }
    439 
    440                 SSVAL(req->outbuf, smb_uid, sess_vuid);
    441 
    442                 /* Successful logon. Keep this vuid. */
    443                 *p_invalidate_vuid = False;
    444         }
    445 
    446         /* wrap that up in a nice GSS-API wrapping */
    447         if (NT_STATUS_IS_OK(ret)) {
    448                 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
    449                                 TOK_ID_KRB_AP_REP);
    450         } else {
    451                 ap_rep_wrapped = data_blob_null;
    452         }
    453         response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
    454                         mechOID);
    455         reply_sesssetup_blob(req, response, ret);
    456 
    457         data_blob_free(&ap_rep);
    458         data_blob_free(&ap_rep_wrapped);
    459         data_blob_free(&response);
    460         TALLOC_FREE(mem_ctx);
    461 }
    462 
    463 #endif
    464 
    465 /****************************************************************************
    466  Send a session setup reply, wrapped in SPNEGO.
    467  Get vuid and check first.
    468  End the NTLMSSP exchange context if we are OK/complete fail
    469  This should be split into two functions, one to handle each
    470  leg of the NTLM auth steps.
    471 ***************************************************************************/
    472 
    473 static void reply_spnego_ntlmssp(struct smb_request *req,
    474                                  uint16 vuid,
    475                                  struct auth_ntlmssp_state **auth_ntlmssp_state,
    476                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
    477                                  const char *OID,
    478                                  bool wrap)
    479 {
    480         bool do_invalidate = true;
    481         DATA_BLOB response;
    482         struct auth_serversupplied_info *session_info = NULL;
    483         struct smbd_server_connection *sconn = req->sconn;
    484 
    485         if (NT_STATUS_IS_OK(nt_status)) {
    486                 nt_status = auth_ntlmssp_steal_session_info(talloc_tos(),
    487                                         (*auth_ntlmssp_state), &session_info);
    488         } else {
    489                 /* Note that this session_info won't have a session
    490                  * key.  But for map to guest, that's exactly the right
    491                  * thing - we can't reasonably guess the key the
    492                  * client wants, as the password was wrong */
    493                 nt_status = do_map_to_guest(nt_status,
    494                                             &session_info,
    495                                             auth_ntlmssp_get_username(*auth_ntlmssp_state),
    496                                             auth_ntlmssp_get_domain(*auth_ntlmssp_state));
    497         }
    498 
    499         reply_outbuf(req, 4, 0);
    500 
    501         SSVAL(req->outbuf, smb_uid, vuid);
    502 
    503         if (NT_STATUS_IS_OK(nt_status)) {
    504                 DATA_BLOB nullblob = data_blob_null;
    505 
    506                 if (!is_partial_auth_vuid(sconn, vuid)) {
    507                         nt_status = NT_STATUS_LOGON_FAILURE;
    508                         goto out;
    509                 }
    510 
    511                 /* register_existing_vuid keeps the server info */
    512                 if (register_existing_vuid(sconn, vuid,
    513                                            session_info, nullblob,
    514                                            auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
    515                                            vuid) {
    516                         /* The problem is, *auth_ntlmssp_state points
    517                          * into the vuser this will have
    518                          * talloc_free()'ed in
    519                          * register_existing_vuid() */
    520                         do_invalidate = false;
    521                         nt_status = NT_STATUS_LOGON_FAILURE;
    522                         goto out;
    523                 }
    524 
    525                 /* current_user_info is changed on new vuid */
    526                 reload_services(sconn->msg_ctx, sconn->sock, True);
    527 
    528                 SSVAL(req->outbuf, smb_vwv3, 0);
    529 
    530                 if (session_info->guest) {
    531                         SSVAL(req->outbuf,smb_vwv2,1);
    532                 }
    533         }
    534 
    535   out:
    536 
    537         if (wrap) {
    538                 response = spnego_gen_auth_response(talloc_tos(),
    539                                 ntlmssp_blob,
    540                                 nt_status, OID);
    541         } else {
    542                 response = *ntlmssp_blob;
    543         }
    544 
    545         reply_sesssetup_blob(req, response, nt_status);
    546         if (wrap) {
    547                 data_blob_free(&response);
    548         }
    549 
    550         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
    551            and the other end, that we are not finished yet. */
    552 
    553         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    554                 /* NB. This is *NOT* an error case. JRA */
    555                 if (do_invalidate) {
    556                         TALLOC_FREE(*auth_ntlmssp_state);
    557                         if (!NT_STATUS_IS_OK(nt_status)) {
    558                                 /* Kill the intermediate vuid */
    559                                 invalidate_vuid(sconn, vuid);
    560                         }
    561                 }
    562         }
    563 }
    564 
    565 /****************************************************************************
    566  Is this a krb5 mechanism ?
    567 ****************************************************************************/
    568 
    569 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
    570                 DATA_BLOB blob_in,
    571                 DATA_BLOB *pblob_out,
    572                 char **kerb_mechOID)
    573 {
    574         char *OIDs[ASN1_MAX_OIDS];
    575         int i;
    576         NTSTATUS ret = NT_STATUS_OK;
    577 
    578         *kerb_mechOID = NULL;
    579 
    580         /* parse out the OIDs and the first sec blob */
    581         if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
    582                         (OIDs[0] == NULL)) {
    583                 return NT_STATUS_LOGON_FAILURE;
    584         }
    585 
    586         /* only look at the first OID for determining the mechToken --
    587            according to RFC2478, we should choose the one we want
    588            and renegotiate, but i smell a client bug here..
    589 
    590            Problem observed when connecting to a member (samba box)
    591            of an AD domain as a user in a Samba domain.  Samba member
    592            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
    593            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
    594            NTLMSSP mechtoken.                 --jerry              */
    595 
    596 #ifdef HAVE_KRB5
    597         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
    598             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
    599                 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
    600                 if (*kerb_mechOID == NULL) {
    601                         ret = NT_STATUS_NO_MEMORY;
    602                 }
    603         }
    604 #endif
    605 
    606         for (i=0;OIDs[i];i++) {
    607                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
    608                 talloc_free(OIDs[i]);
    609         }
    610         return ret;
    611 }
    612 
    613 /****************************************************************************
    614  Fall back from krb5 to NTLMSSP.
    615 ****************************************************************************/
    616 
    617 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
    618                                                 uint16 vuid)
    619 {
    620         DATA_BLOB response;
    621 
    622         reply_outbuf(req, 4, 0);
    623         SSVAL(req->outbuf,smb_uid,vuid);
    624 
    625         DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
    626                 "but set to downgrade to NTLMSSP\n"));
    627 
    628         response = spnego_gen_auth_response(talloc_tos(), NULL,
    629                         NT_STATUS_MORE_PROCESSING_REQUIRED,
    630                         OID_NTLMSSP);
    631         reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
    632         data_blob_free(&response);
    633 }
    634 
    635 /****************************************************************************
    636  Reply to a session setup spnego negotiate packet.
    637 ****************************************************************************/
    638 
    639 static void reply_spnego_negotiate(struct smb_request *req,
    640                                    uint16 vuid,
    641                                    DATA_BLOB blob1,
    642                                    struct auth_ntlmssp_state **auth_ntlmssp_state)
    643 {
    644         DATA_BLOB secblob;
    645         DATA_BLOB chal;
    646         char *kerb_mech = NULL;
    647         NTSTATUS status;
    648         struct smbd_server_connection *sconn = req->sconn;
    649 
    650         status = parse_spnego_mechanisms(talloc_tos(),
    651                         blob1, &secblob, &kerb_mech);
    652         if (!NT_STATUS_IS_OK(status)) {
    653                 /* Kill the intermediate vuid */
    654                 invalidate_vuid(sconn, vuid);
    655                 reply_nterror(req, nt_status_squash(status));
    656                 return;
    657         }
    658 
    659         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
    660                                 (unsigned long)secblob.length));
    661 
    662 #ifdef HAVE_KRB5
    663         if (kerb_mech && ((lp_security()==SEC_ADS) ||
    664                                 USE_KERBEROS_KEYTAB) ) {
    665                 bool destroy_vuid = True;
    666                 reply_spnego_kerberos(req, &secblob, kerb_mech,
    667                                       vuid, &destroy_vuid);
    668                 data_blob_free(&secblob);
    669                 if (destroy_vuid) {
    670                         /* Kill the intermediate vuid */
    671                         invalidate_vuid(sconn, vuid);
    672                 }
    673                 TALLOC_FREE(kerb_mech);
    674                 return;
    675         }
    676 #endif
    677 
    678         TALLOC_FREE(*auth_ntlmssp_state);
    679 
    680         if (kerb_mech) {
    681                 data_blob_free(&secblob);
    682                 /* The mechtoken is a krb5 ticket, but
    683                  * we need to fall back to NTLM. */
    684                 reply_spnego_downgrade_to_ntlmssp(req, vuid);
    685                 TALLOC_FREE(kerb_mech);
    686                 return;
    687         }
    688 
    689         status = auth_ntlmssp_start(auth_ntlmssp_state);
    690         if (!NT_STATUS_IS_OK(status)) {
    691                 /* Kill the intermediate vuid */
    692                 invalidate_vuid(sconn, vuid);
    693                 reply_nterror(req, nt_status_squash(status));
    694                 return;
    695         }
    696 
    697         status = auth_ntlmssp_update(*auth_ntlmssp_state,
    698                                         secblob, &chal);
    699 
    700         data_blob_free(&secblob);
    701 
    702         reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
    703                              &chal, status, OID_NTLMSSP, true);
    704 
    705         data_blob_free(&chal);
    706 
    707         /* already replied */
    708         return;
    709 }
    710 
    711 /****************************************************************************
    712  Reply to a session setup spnego auth packet.
    713 ****************************************************************************/
    714 
    715 static void reply_spnego_auth(struct smb_request *req,
    716                               uint16 vuid,
    717                               DATA_BLOB blob1,
    718                               struct auth_ntlmssp_state **auth_ntlmssp_state)
    719 {
    720         DATA_BLOB auth = data_blob_null;
    721         DATA_BLOB auth_reply = data_blob_null;
    722         DATA_BLOB secblob = data_blob_null;
    723         NTSTATUS status = NT_STATUS_LOGON_FAILURE;
    724         struct smbd_server_connection *sconn = req->sconn;
    725 
    726         if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
    727 #if 0
    728                 file_save("auth.dat", blob1.data, blob1.length);
    729 #endif
    730                 /* Kill the intermediate vuid */
    731                 invalidate_vuid(sconn, vuid);
    732 
    733                 reply_nterror(req, nt_status_squash(
    734                                       NT_STATUS_LOGON_FAILURE));
    735                 return;
    736         }
    737 
    738         if (auth.length > 0 && auth.data[0] == ASN1_APPLICATION(0)) {
    739                 /* Might be a second negTokenTarg packet */
    740                 char *kerb_mech = NULL;
    741 
    742                 status = parse_spnego_mechanisms(talloc_tos(),
    743                                 auth, &secblob, &kerb_mech);
    744 
    745                 if (!NT_STATUS_IS_OK(status)) {
    746                         /* Kill the intermediate vuid */
    747                         invalidate_vuid(sconn, vuid);
    748                         reply_nterror(req, nt_status_squash(status));
    749                         return;
    750                 }
    751 
    752                 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
    753                                 (unsigned long)secblob.length));
    754 #ifdef HAVE_KRB5
    755                 if (kerb_mech && ((lp_security()==SEC_ADS) ||
    756                                         USE_KERBEROS_KEYTAB)) {
    757                         bool destroy_vuid = True;
    758                         reply_spnego_kerberos(req, &secblob, kerb_mech,
    759                                               vuid, &destroy_vuid);
    760                         data_blob_free(&secblob);
    761                         data_blob_free(&auth);
    762                         if (destroy_vuid) {
    763                                 /* Kill the intermediate vuid */
    764                                 invalidate_vuid(sconn, vuid);
    765                         }
    766                         TALLOC_FREE(kerb_mech);
    767                         return;
    768                 }
    769 #endif
    770                 /* Can't blunder into NTLMSSP auth if we have
    771                  * a krb5 ticket. */
    772 
    773                 if (kerb_mech) {
    774                         /* Kill the intermediate vuid */
    775                         invalidate_vuid(sconn, vuid);
    776                         DEBUG(3,("reply_spnego_auth: network "
    777                                 "misconfiguration, client sent us a "
    778                                 "krb5 ticket and kerberos security "
    779                                 "not enabled\n"));
    780                         reply_nterror(req, nt_status_squash(
    781                                         NT_STATUS_LOGON_FAILURE));
    782                         TALLOC_FREE(kerb_mech);
    783                 }
    784         }
    785 
    786         /* If we get here it wasn't a negTokenTarg auth packet. */
    787         data_blob_free(&secblob);
    788 
    789         if (!*auth_ntlmssp_state) {
    790                 status = auth_ntlmssp_start(auth_ntlmssp_state);
    791                 if (!NT_STATUS_IS_OK(status)) {
    792                         /* Kill the intermediate vuid */
    793                         invalidate_vuid(sconn, vuid);
    794                         reply_nterror(req, nt_status_squash(status));
    795                         return;
    796                 }
    797         }
    798 
    799         status = auth_ntlmssp_update(*auth_ntlmssp_state,
    800                                         auth, &auth_reply);
    801 
    802         data_blob_free(&auth);
    803 
    804         /* Don't send the mechid as we've already sent this (RFC4178). */
    805 
    806         reply_spnego_ntlmssp(req, vuid,
    807                              auth_ntlmssp_state,
    808                              &auth_reply, status, NULL, true);
    809 
    810         data_blob_free(&auth_reply);
    811 
    812         /* and tell smbd that we have already replied to this packet */
    813         return;
    814 }
    815 
    816 /****************************************************************************
    817  Delete an entry on the list.
    818 ****************************************************************************/
    819 
    820 static void delete_partial_auth(struct smbd_server_connection *sconn,
    821                                 struct pending_auth_data *pad)
    822 {
    823         if (!pad) {
    824                 return;
    825         }
    826         DLIST_REMOVE(sconn->smb1.pd_list, pad);
    827         data_blob_free(&pad->partial_data);
    828         SAFE_FREE(pad);
    829 }
    830 
    831 /****************************************************************************
    832  Search for a partial SPNEGO auth fragment matching an smbpid.
    833 ****************************************************************************/
    834 
    835 static struct pending_auth_data *get_pending_auth_data(
    836                 struct smbd_server_connection *sconn,
    837                 uint16_t smbpid)
    838 {
    839         struct pending_auth_data *pad;
    840 /*
    841  * NOTE: using the smbpid here is completely wrong...
    842  *       see [MS-SMB]
    843  *       3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
    844  */
    845         for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
    846                 if (pad->smbpid == smbpid) {
    847                         break;
    848                 }
    849         }
    850         return pad;
    851 }
    852 
    853 /****************************************************************************
    854  Check the size of an SPNEGO blob. If we need more return
    855  NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
    856  the blob to be more than 64k.
    857 ****************************************************************************/
    858 
    859 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
    860                                            uint16 smbpid, uint16 vuid,
    861                                            DATA_BLOB *pblob)
    862 {
    863         struct pending_auth_data *pad = NULL;
    864         ASN1_DATA *data;
    865         size_t needed_len = 0;
    866 
    867         pad = get_pending_auth_data(sconn, smbpid);
    868 
    869         /* Ensure we have some data. */
    870         if (pblob->length == 0) {
    871                 /* Caller can cope. */
    872                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
    873                 delete_partial_auth(sconn, pad);
    874                 return NT_STATUS_OK;
    875         }
    876 
    877         /* Were we waiting for more data ? */
    878         if (pad) {
    879                 DATA_BLOB tmp_blob;
    880                 size_t copy_len = MIN(65536, pblob->length);
    881 
    882                 /* Integer wrap paranoia.... */
    883 
    884                 if (pad->partial_data.length + copy_len <
    885                                 pad->partial_data.length ||
    886                     pad->partial_data.length + copy_len < copy_len) {
    887 
    888                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
    889                                 "pad->partial_data.length = %u, "
    890                                 "copy_len = %u\n",
    891                                 (unsigned int)pad->partial_data.length,
    892                                 (unsigned int)copy_len ));
    893 
    894                         delete_partial_auth(sconn, pad);
    895                         return NT_STATUS_INVALID_PARAMETER;
    896                 }
    897 
    898                 DEBUG(10,("check_spnego_blob_complete: "
    899                         "pad->partial_data.length = %u, "
    900                         "pad->needed_len = %u, "
    901                         "copy_len = %u, "
    902                         "pblob->length = %u,\n",
    903                         (unsigned int)pad->partial_data.length,
    904                         (unsigned int)pad->needed_len,
    905                         (unsigned int)copy_len,
    906                         (unsigned int)pblob->length ));
    907 
    908                 if (pblob->length > pad->needed_len) {
    909                         DEBUG(2, ("subsequent security token data length %u "
    910                                   "exceeds expected length %u\n",
    911                                   (unsigned int)pblob->length,
    912                                   (unsigned int)pad->needed_len));
    913                 }
    914 
    915                 tmp_blob = data_blob(NULL,
    916                                 pad->partial_data.length + copy_len);
    917 
    918                 /* Concatenate the two (up to copy_len) bytes. */
    919                 memcpy(tmp_blob.data,
    920                         pad->partial_data.data,
    921                         pad->partial_data.length);
    922                 memcpy(tmp_blob.data + pad->partial_data.length,
    923                         pblob->data,
    924                         copy_len);
    925 
    926                 /* Replace the partial data. */
    927                 data_blob_free(&pad->partial_data);
    928                 pad->partial_data = tmp_blob;
    929                 ZERO_STRUCT(tmp_blob);
    930 
    931                 /* Are we done ? */
    932                 if (pblob->length >= pad->needed_len) {
    933                         /* Yes, replace pblob. */
    934                         data_blob_free(pblob);
    935                         *pblob = pad->partial_data;
    936                         ZERO_STRUCT(pad->partial_data);
    937                         delete_partial_auth(sconn, pad);
    938                         return NT_STATUS_OK;
    939                 }
    940 
    941                 /* Still need more data. */
    942                 pad->needed_len -= copy_len;
    943                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
    944         }
    945 
    946         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
    947             (pblob->data[0] != ASN1_CONTEXT(1))) {
    948                 /* Not something we can determine the
    949                  * length of.
    950                  */
    951                 return NT_STATUS_OK;
    952         }
    953 
    954         /* This is a new SPNEGO sessionsetup - see if
    955          * the data given in this blob is enough.
    956          */
    957 
    958         data = asn1_init(NULL);
    959         if (data == NULL) {
    960                 return NT_STATUS_NO_MEMORY;
    961         }
    962 
    963         asn1_load(data, *pblob);
    964         if (asn1_start_tag(data, pblob->data[0])) {
    965                 /* asn1_start_tag checks if the given
    966                    length of the blob is enough to complete
    967                    the tag. If it returns true we know
    968                    there is nothing to do - the blob is
    969                    complete. */
    970                 asn1_free(data);
    971                 return NT_STATUS_OK;
    972         }
    973 
    974         if (data->nesting == NULL) {
    975                 /* Incorrect tag, allocation failed,
    976                    or reading the tag length failed.
    977                    Let the caller catch. */
    978                 asn1_free(data);
    979                 return NT_STATUS_OK;
    980         }
    981 
    982         /* Here we know asn1_start_tag() has set data->has_error to true.
    983            asn1_tag_remaining() will have failed due to the given blob
    984            being too short. We need to work out how short. */
    985 
    986         /* Integer wrap paranoia.... */
    987 
    988         if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
    989             data->nesting->taglen + data->nesting->start < data->nesting->start) {
    990 
    991                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
    992                         "data.nesting->taglen = %u, "
    993                         "data.nesting->start = %u\n",
    994                         (unsigned int)data->nesting->taglen,
    995                         (unsigned int)data->nesting->start ));
    996 
    997                 asn1_free(data);
    998                 return NT_STATUS_INVALID_PARAMETER;
    999         }
    1000 
    1001         /* Total length of the needed asn1 is the tag length
    1002          * plus the current offset. */
    1003 
    1004         needed_len = data->nesting->taglen + data->nesting->start;
    1005         asn1_free(data);
    1006 
    1007         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
    1008                 "pblob->length = %u\n",
    1009                 (unsigned int)needed_len,
    1010                 (unsigned int)pblob->length ));
    1011 
    1012         if (needed_len <= pblob->length) {
    1013                 /* Nothing to do - blob is complete. */
    1014                 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
    1015                    above should have caught this !!! */
    1016                 DEBUG(0,("check_spnego_blob_complete: logic "
    1017                         "error (needed_len = %u, "
    1018                         "pblob->length = %u).\n",
    1019                         (unsigned int)needed_len,
    1020                         (unsigned int)pblob->length ));
    1021                 return NT_STATUS_OK;
    1022         }
    1023 
    1024         /* Refuse the blob if it's bigger than 64k. */
    1025         if (needed_len > 65536) {
    1026                 DEBUG(2,("check_spnego_blob_complete: needed_len "
    1027                         "too large (%u)\n",
    1028                         (unsigned int)needed_len ));
    1029                 return NT_STATUS_INVALID_PARAMETER;
    1030         }
    1031 
    1032         /* We must store this blob until complete. */
    1033         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
    1034                 return NT_STATUS_NO_MEMORY;
    1035         }
    1036         pad->needed_len = needed_len - pblob->length;
    1037         pad->partial_data = data_blob(pblob->data, pblob->length);
    1038         if (pad->partial_data.data == NULL) {
    1039                 SAFE_FREE(pad);
    1040                 return NT_STATUS_NO_MEMORY;
    1041         }
    1042         pad->smbpid = smbpid;
    1043         pad->vuid = vuid;
    1044         DLIST_ADD(sconn->smb1.pd_list, pad);
    1045 
    1046         return NT_STATUS_MORE_PROCESSING_REQUIRED;
    1047109}
    1048110
     
    1054116static void reply_sesssetup_and_X_spnego(struct smb_request *req)
    1055117{
    1056         const uint8 *p;
    1057         DATA_BLOB blob1;
     118        const uint8_t *p;
     119        DATA_BLOB in_blob;
     120        DATA_BLOB out_blob = data_blob_null;
    1058121        size_t bufrem;
    1059122        char *tmp;
     
    1061124        const char *native_lanman;
    1062125        const char *primary_domain;
    1063         const char *p2;
    1064         uint16 data_blob_len = SVAL(req->vwv+7, 0);
     126        uint16_t data_blob_len = SVAL(req->vwv+7, 0);
    1065127        enum remote_arch_types ra_type = get_remote_arch();
    1066         int vuid = req->vuid;
    1067         user_struct *vuser = NULL;
     128        uint64_t vuid = req->vuid;
    1068129        NTSTATUS status = NT_STATUS_OK;
    1069         uint16 smbpid = req->smbpid;
     130        struct smbXsrv_connection *xconn = req->xconn;
    1070131        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        uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
     136        uint32_t client_caps = IVAL(req->vwv+10, 0);
     137        struct smbXsrv_session_auth0 *auth;
    1071138
    1072139        DEBUG(3,("Doing spnego session setup\n"));
    1073140
    1074         if (global_client_caps == 0) {
    1075                 global_client_caps = IVAL(req->vwv+10, 0);
     141        if (!xconn->smb1.sessions.done_sesssetup) {
     142                global_client_caps = client_caps;
    1076143
    1077144                if (!(global_client_caps & CAP_STATUS32)) {
    1078145                        remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
    1079146                }
    1080 
    1081147        }
    1082148
     
    1091157        bufrem = smbreq_bufrem(req, p);
    1092158        /* pull the spnego blob */
    1093         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
     159        in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
    1094160
    1095161#if 0
    1096         file_save("negotiate.dat", blob1.data, blob1.length);
     162        file_save("negotiate.dat", in_blob.data, in_blob.length);
    1097163#endif
    1098164
    1099         p2 = (char *)req->buf + blob1.length;
    1100 
    1101         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
     165        p = req->buf + in_blob.length;
     166
     167        p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
    1102168                                     STR_TERMINATE);
    1103169        native_os = tmp ? tmp : "";
    1104170
    1105         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
     171        p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
    1106172                                     STR_TERMINATE);
    1107173        native_lanman = tmp ? tmp : "";
    1108174
    1109         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
     175        p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
    1110176                                     STR_TERMINATE);
    1111177        primary_domain = tmp ? tmp : "";
     
    1134200        }
    1135201
    1136         /* Did we get a valid vuid ? */
    1137         if (!is_partial_auth_vuid(sconn, vuid)) {
    1138                 /* No, then try and see if this is an intermediate sessionsetup
    1139                  * for a large SPNEGO packet. */
    1140                 struct pending_auth_data *pad;
    1141                 pad = get_pending_auth_data(sconn, smbpid);
    1142                 if (pad) {
    1143                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
    1144                                 "pending vuid %u\n",
    1145                                 (unsigned int)pad->vuid ));
    1146                         vuid = pad->vuid;
    1147                 }
    1148         }
    1149 
    1150         /* Do we have a valid vuid now ? */
    1151         if (!is_partial_auth_vuid(sconn, vuid)) {
    1152                 /* No, start a new authentication setup. */
    1153                 vuid = register_initial_vuid(sconn);
    1154                 if (vuid == UID_FIELD_INVALID) {
    1155                         data_blob_free(&blob1);
    1156                         reply_nterror(req, nt_status_squash(
    1157                                               NT_STATUS_INVALID_PARAMETER));
    1158                         return;
    1159                 }
    1160         }
    1161 
    1162         vuser = get_partial_auth_user_struct(sconn, vuid);
    1163         /* This MUST be valid. */
    1164         if (!vuser) {
    1165                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
    1166         }
    1167 
    1168         /* Large (greater than 4k) SPNEGO blobs are split into multiple
    1169          * sessionsetup requests as the Windows limit on the security blob
    1170          * field is 4k. Bug #4400. JRA.
    1171          */
    1172 
    1173         status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
     202        if (vuid != 0) {
     203                status = smb1srv_session_lookup(xconn,
     204                                                vuid, now,
     205                                                &session);
     206                if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
     207                        reply_force_doserror(req, ERRSRV, ERRbaduid);
     208                        return;
     209                }
     210                if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
     211                        status = NT_STATUS_OK;
     212                }
     213                if (NT_STATUS_IS_OK(status)) {
     214                        session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
     215                        status = NT_STATUS_MORE_PROCESSING_REQUIRED;
     216                        TALLOC_FREE(session->pending_auth);
     217                }
     218                if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     219                        reply_nterror(req, nt_status_squash(status));
     220                        return;
     221                }
     222        }
     223
     224        if (session == NULL) {
     225                /* create a new session */
     226                status = smbXsrv_session_create(xconn,
     227                                                now, &session);
     228                if (!NT_STATUS_IS_OK(status)) {
     229                        reply_nterror(req, nt_status_squash(status));
     230                        return;
     231                }
     232        }
     233
     234        status = smbXsrv_session_find_auth(session, xconn, now, &auth);
    1174235        if (!NT_STATUS_IS_OK(status)) {
    1175                 /*
    1176                  * Pack error response, ensuring to fill NativeOS, NativeLanMan
    1177                  * & PrimaryDomain fields on NT_STATUS_MORE_PROCESSING_REQUIRED
    1178                  */
    1179                 reply_outbuf(req, 4, 0);
    1180                 reply_sesssetup_blob(req, data_blob_null, status);
    1181                 if (!NT_STATUS_EQUAL(status,
    1182                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    1183                         /* Real error - kill the intermediate vuid */
    1184                         invalidate_vuid(sconn, vuid);
    1185                 }
    1186                 data_blob_free(&blob1);
     236                status = smbXsrv_session_create_auth(session, xconn, now,
     237                                                     0, /* flags */
     238                                                     0, /* security */
     239                                                     &auth);
     240                if (!NT_STATUS_IS_OK(status)) {
     241                        reply_nterror(req, nt_status_squash(status));
     242                        return;
     243                }
     244        }
     245
     246        if (auth->gensec == NULL) {
     247                status = auth_generic_prepare(session, xconn->remote_address,
     248                                              &auth->gensec);
     249                if (!NT_STATUS_IS_OK(status)) {
     250                        TALLOC_FREE(session);
     251                        reply_nterror(req, nt_status_squash(status));
     252                        return;
     253                }
     254
     255                gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
     256                gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
     257
     258                status = gensec_start_mech_by_oid(auth->gensec,
     259                                                  GENSEC_OID_SPNEGO);
     260                if (!NT_STATUS_IS_OK(status)) {
     261                        DEBUG(0, ("Failed to start SPNEGO handler!\n"));
     262                        TALLOC_FREE(session);;
     263                        reply_nterror(req, nt_status_squash(status));
     264                        return;
     265                }
     266        }
     267
     268        become_root();
     269        status = gensec_update(auth->gensec,
     270                               talloc_tos(),
     271                               in_blob, &out_blob);
     272        unbecome_root();
     273        if (!NT_STATUS_IS_OK(status) &&
     274            !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     275                TALLOC_FREE(session);
     276                reply_nterror(req, nt_status_squash(status));
    1187277                return;
    1188278        }
    1189279
    1190         if (blob1.data[0] == ASN1_APPLICATION(0)) {
    1191 
    1192                 /* its a negTokenTarg packet */
    1193 
    1194                 reply_spnego_negotiate(req, vuid, blob1,
    1195                                        &vuser->auth_ntlmssp_state);
    1196                 data_blob_free(&blob1);
    1197                 return;
    1198         }
    1199 
    1200         if (blob1.data[0] == ASN1_CONTEXT(1)) {
    1201 
    1202                 /* its a auth packet */
    1203 
    1204                 reply_spnego_auth(req, vuid, blob1,
    1205                                   &vuser->auth_ntlmssp_state);
    1206                 data_blob_free(&blob1);
    1207                 return;
    1208         }
    1209 
    1210         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
    1211                 DATA_BLOB chal;
    1212 
    1213                 if (!vuser->auth_ntlmssp_state) {
    1214                         status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
    1215                         if (!NT_STATUS_IS_OK(status)) {
    1216                                 /* Kill the intermediate vuid */
    1217                                 invalidate_vuid(sconn, vuid);
    1218                                 data_blob_free(&blob1);
    1219                                 reply_nterror(req, nt_status_squash(status));
     280        if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
     281                struct auth_session_info *session_info = NULL;
     282
     283                status = gensec_session_info(auth->gensec,
     284                                             session,
     285                                             &session_info);
     286                if (!NT_STATUS_IS_OK(status)) {
     287                        DEBUG(1,("Failed to generate session_info "
     288                                 "(user and group token) for session setup: %s\n",
     289                                 nt_errstr(status)));
     290                        data_blob_free(&out_blob);
     291                        TALLOC_FREE(session);
     292                        reply_nterror(req, nt_status_squash(status));
     293                        return;
     294                }
     295
     296                if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
     297                        action |= SMB_SETUP_GUEST;
     298                }
     299
     300                if (session_info->session_key.length > 0) {
     301                        struct smbXsrv_session *x = session;
     302
     303                        /*
     304                         * Note: the SMB1 signing key is not truncated to 16 byte!
     305                         */
     306                        x->global->signing_key =
     307                                data_blob_dup_talloc(x->global,
     308                                                     session_info->session_key);
     309                        if (x->global->signing_key.data == NULL) {
     310                                data_blob_free(&out_blob);
     311                                TALLOC_FREE(session);
     312                                reply_nterror(req, NT_STATUS_NO_MEMORY);
    1220313                                return;
    1221314                        }
    1222                 }
    1223 
    1224                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
    1225                                                 blob1, &chal);
    1226 
    1227                 data_blob_free(&blob1);
    1228 
    1229                 reply_spnego_ntlmssp(req, vuid,
    1230                                      &vuser->auth_ntlmssp_state,
    1231                                      &chal, status, OID_NTLMSSP, false);
    1232                 data_blob_free(&chal);
     315
     316                        /*
     317                         * clear the session key
     318                         * the first tcon will add setup the application key
     319                         */
     320                        data_blob_clear_free(&session_info->session_key);
     321                }
     322
     323                session->compat = talloc_zero(session, struct user_struct);
     324                if (session->compat == NULL) {
     325                        data_blob_free(&out_blob);
     326                        TALLOC_FREE(session);
     327                        reply_nterror(req, NT_STATUS_NO_MEMORY);
     328                        return;
     329                }
     330                session->compat->session = session;
     331                session->compat->homes_snum = -1;
     332                session->compat->session_info = session_info;
     333                session->compat->session_keystr = NULL;
     334                session->compat->vuid = session->global->session_wire_id;
     335                DLIST_ADD(sconn->users, session->compat);
     336                sconn->num_users++;
     337
     338                if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
     339                        session->compat->homes_snum =
     340                                register_homes_share(session_info->unix_info->unix_name);
     341                }
     342
     343                if (srv_is_signing_negotiated(xconn) &&
     344                    action == 0 &&
     345                    session->global->signing_key.length > 0)
     346                {
     347                        /*
     348                         * Try and turn on server signing on the first non-guest
     349                         * sessionsetup.
     350                         */
     351                        srv_set_signing(xconn,
     352                                session->global->signing_key,
     353                                data_blob_null);
     354                }
     355
     356                set_current_user_info(session_info->unix_info->sanitized_username,
     357                                      session_info->unix_info->unix_name,
     358                                      session_info->info->domain_name);
     359
     360                session->status = NT_STATUS_OK;
     361                session->global->auth_session_info = talloc_move(session->global,
     362                                                                 &session_info);
     363                session->global->auth_session_info_seqnum += 1;
     364                session->global->channels[0].auth_session_info_seqnum =
     365                        session->global->auth_session_info_seqnum;
     366                session->global->auth_time = now;
     367                if (client_caps & CAP_DYNAMIC_REAUTH) {
     368                        session->global->expiration_time =
     369                                gensec_expire_time(auth->gensec);
     370                } else {
     371                        session->global->expiration_time =
     372                                GENSEC_EXPIRE_TIME_INFINITY;
     373                }
     374
     375                if (!session_claim(session)) {
     376                        DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
     377                                  (unsigned long long)session->compat->vuid));
     378                        data_blob_free(&out_blob);
     379                        TALLOC_FREE(session);
     380                        reply_nterror(req, NT_STATUS_LOGON_FAILURE);
     381                        return;
     382                }
     383
     384                status = smbXsrv_session_update(session);
     385                if (!NT_STATUS_IS_OK(status)) {
     386                        DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
     387                                  (unsigned long long)session->compat->vuid,
     388                                  nt_errstr(status)));
     389                        data_blob_free(&out_blob);
     390                        TALLOC_FREE(session);
     391                        reply_nterror(req, NT_STATUS_LOGON_FAILURE);
     392                        return;
     393                }
     394
     395                if (!xconn->smb1.sessions.done_sesssetup) {
     396                        if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
     397                                reply_force_doserror(req, ERRSRV, ERRerror);
     398                                return;
     399                        }
     400                        xconn->smb1.sessions.max_send = smb_bufsize;
     401                        xconn->smb1.sessions.done_sesssetup = true;
     402                }
     403
     404                /* current_user_info is changed on new vuid */
     405                reload_services(sconn, conn_snum_used, true);
     406        } else if (NT_STATUS_IS_OK(status)) {
     407                struct auth_session_info *session_info = NULL;
     408
     409                status = gensec_session_info(auth->gensec,
     410                                             session,
     411                                             &session_info);
     412                if (!NT_STATUS_IS_OK(status)) {
     413                        DEBUG(1,("Failed to generate session_info "
     414                                 "(user and group token) for session setup: %s\n",
     415                                 nt_errstr(status)));
     416                        data_blob_free(&out_blob);
     417                        TALLOC_FREE(session);
     418                        reply_nterror(req, nt_status_squash(status));
     419                        return;
     420                }
     421
     422                if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
     423                        action |= SMB_SETUP_GUEST;
     424                }
     425
     426                /*
     427                 * Keep the application key
     428                 */
     429                data_blob_clear_free(&session_info->session_key);
     430                session_info->session_key =
     431                        session->global->auth_session_info->session_key;
     432                talloc_steal(session_info, session_info->session_key.data);
     433                TALLOC_FREE(session->global->auth_session_info);
     434
     435                session->compat->session_info = session_info;
     436
     437                session->compat->vuid = session->global->session_wire_id;
     438
     439                if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
     440                        session->compat->homes_snum =
     441                                register_homes_share(session_info->unix_info->unix_name);
     442                }
     443
     444                set_current_user_info(session_info->unix_info->sanitized_username,
     445                                      session_info->unix_info->unix_name,
     446                                      session_info->info->domain_name);
     447
     448                session->status = NT_STATUS_OK;
     449                session->global->auth_session_info = talloc_move(session->global,
     450                                                                 &session_info);
     451                session->global->auth_session_info_seqnum += 1;
     452                session->global->channels[0].auth_session_info_seqnum =
     453                        session->global->auth_session_info_seqnum;
     454                session->global->auth_time = now;
     455                if (client_caps & CAP_DYNAMIC_REAUTH) {
     456                        session->global->expiration_time =
     457                                gensec_expire_time(auth->gensec);
     458                } else {
     459                        session->global->expiration_time =
     460                                GENSEC_EXPIRE_TIME_INFINITY;
     461                }
     462
     463                status = smbXsrv_session_update(session);
     464                if (!NT_STATUS_IS_OK(status)) {
     465                        DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
     466                                  (unsigned long long)session->compat->vuid,
     467                                  nt_errstr(status)));
     468                        data_blob_free(&out_blob);
     469                        TALLOC_FREE(session);
     470                        reply_nterror(req, NT_STATUS_LOGON_FAILURE);
     471                        return;
     472                }
     473
     474                conn_clear_vuid_caches(sconn, session->compat->vuid);
     475
     476                /* current_user_info is changed on new vuid */
     477                reload_services(sconn, conn_snum_used, true);
     478        }
     479
     480        vuid = session->global->session_wire_id;
     481
     482        reply_outbuf(req, 4, 0);
     483
     484        SSVAL(req->outbuf, smb_uid, vuid);
     485        SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
     486        SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
     487        SSVAL(req->outbuf, smb_vwv2, action);
     488        SSVAL(req->outbuf, smb_vwv3, out_blob.length);
     489
     490        if (message_push_blob(&req->outbuf, out_blob) == -1) {
     491                data_blob_free(&out_blob);
     492                TALLOC_FREE(session);
     493                reply_nterror(req, NT_STATUS_NO_MEMORY);
    1233494                return;
    1234495        }
    1235 
    1236         /* what sort of packet is this? */
    1237         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
    1238 
    1239         data_blob_free(&blob1);
    1240 
    1241         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
     496        data_blob_free(&out_blob);
     497
     498        if (push_signature(&req->outbuf) == -1) {
     499                TALLOC_FREE(session);
     500                reply_nterror(req, NT_STATUS_NO_MEMORY);
     501                return;
     502        }
    1242503}
    1243504
     
    1253514};
    1254515
    1255 static int shutdown_other_smbds(const struct connections_key *key,
    1256                                 const struct connections_data *crec,
     516static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
    1257517                                void *private_data)
    1258518{
    1259519        struct shutdown_state *state = (struct shutdown_state *)private_data;
     520        struct server_id self_pid = messaging_server_id(state->msg_ctx);
     521        struct server_id pid = session->channels[0].server_id;
     522        const char *addr = session->channels[0].remote_address;
     523        struct server_id_buf tmp;
    1260524
    1261525        DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
    1262                    procid_str(talloc_tos(), &crec->pid), crec->addr));
    1263 
    1264         if (!process_exists(crec->pid)) {
     526                   server_id_str_buf(pid, &tmp), addr));
     527
     528        if (!process_exists(pid)) {
    1265529                DEBUG(10, ("process does not exist\n"));
    1266530                return 0;
    1267531        }
    1268532
    1269         if (procid_is_me(&crec->pid)) {
     533        if (serverid_equal(&pid, &self_pid)) {
    1270534                DEBUG(10, ("It's me\n"));
    1271535                return 0;
    1272536        }
    1273537
    1274         if (strcmp(state->ip, crec->addr) != 0) {
    1275                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
     538        /*
     539         * here we use strstr() because 'addr'
     540         * (session->channels[0].remote_address)
     541         * contains a string like:
     542         * 'ipv4:127.0.0.1:48163'
     543         */
     544        if (strstr(addr, state->ip)  == NULL) {
     545                DEBUG(10, ("%s does not match %s\n", state->ip, addr));
    1276546                return 0;
    1277547        }
    1278548
    1279549        DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
    1280                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
     550                  "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
    1281551                  state->ip));
    1282552
    1283         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
     553        messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
    1284554                       &data_blob_null);
    1285555        return 0;
     
    1305575                state.ip = addr;
    1306576                state.msg_ctx = sconn->msg_ctx;
    1307                 connections_forall_read(shutdown_other_smbds, &state);
     577                smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
    1308578                TALLOC_FREE(addr);
    1309579        }
     
    1316586void reply_sesssetup_and_X(struct smb_request *req)
    1317587{
    1318         int sess_vuid;
    1319         int smb_bufsize;
     588        uint64_t sess_vuid;
     589        uint16_t smb_bufsize;
    1320590        DATA_BLOB lm_resp;
    1321591        DATA_BLOB nt_resp;
     
    1329599        const char *primary_domain;
    1330600        struct auth_usersupplied_info *user_info = NULL;
    1331         struct auth_serversupplied_info *server_info = NULL;
    1332         uint16 smb_flag2 = req->flags2;
    1333 
     601        struct auth_session_info *session_info = NULL;
     602        uint16_t smb_flag2 = req->flags2;
     603        uint16_t action = 0;
     604        NTTIME now = timeval_to_nttime(&req->request_time);
     605        struct smbXsrv_session *session = NULL;
    1334606        NTSTATUS nt_status;
     607        struct smbXsrv_connection *xconn = req->xconn;
    1335608        struct smbd_server_connection *sconn = req->sconn;
    1336 
    1337         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
     609        bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
     610        bool signing_allowed = false;
     611        bool signing_mandatory = smb_signing_is_mandatory(
     612                xconn->smb1.signing_state);
    1338613
    1339614        START_PROFILE(SMBsesssetupX);
     
    1344619
    1345620        DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
     621
     622        if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
     623                signing_allowed = true;
     624        }
     625        if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
     626                signing_mandatory = true;
     627        }
     628
     629        /*
     630         * We can call srv_set_signing_negotiated() each time.
     631         * It finds out when it needs to turn into a noop
     632         * itself.
     633         */
     634        srv_set_signing_negotiated(xconn,
     635                                   signing_allowed,
     636                                   signing_mandatory);
    1346637
    1347638        /* a SPNEGO session setup has 12 command words, whereas a normal
     
    1350641            (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
    1351642
    1352                 if (!sconn->smb1.negprot.spnego) {
     643                if (!xconn->smb1.negprot.spnego) {
    1353644                        DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
    1354645                                 "at SPNEGO session setup when it was not "
     
    1372663
    1373664        if (get_Protocol() < PROTOCOL_NT1) {
    1374                 uint16 passlen1 = SVAL(req->vwv+7, 0);
     665                uint16_t passlen1 = SVAL(req->vwv+7, 0);
    1375666
    1376667                /* Never do NT status codes with protocols before NT1 as we
     
    1400691
    1401692        } else {
    1402                 uint16 passlen1 = SVAL(req->vwv+7, 0);
    1403                 uint16 passlen2 = SVAL(req->vwv+8, 0);
     693                uint16_t passlen1 = SVAL(req->vwv+7, 0);
     694                uint16_t passlen2 = SVAL(req->vwv+8, 0);
    1404695                enum remote_arch_types ra_type = get_remote_arch();
    1405696                const uint8_t *p = req->buf;
    1406697                const uint8_t *save_p = req->buf;
    1407                 uint16 byte_count;
    1408 
    1409 
    1410                 if(global_client_caps == 0) {
     698                uint16_t byte_count;
     699
     700                if (!xconn->smb1.sessions.done_sesssetup) {
    1411701                        global_client_caps = IVAL(req->vwv+11, 0);
    1412702
     
    1475765                        lm_resp = data_blob(p, passlen1);
    1476766                        nt_resp = data_blob(p+passlen1, passlen2);
    1477                 } else if (lp_security() != SEC_SHARE) {
    1478                         /*
    1479                          * In share level we should ignore any passwords, so
    1480                          * only read them if we're not.
    1481                          */
     767                } else {
    1482768                        char *pass = NULL;
    1483769                        bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
     
    1565851
    1566852        if (*user) {
    1567                 if (sconn->smb1.negprot.spnego) {
     853                if (xconn->smb1.negprot.spnego) {
    1568854
    1569855                        /* This has to be here, because this is a perfectly
     
    1580866                fstrcpy(sub_user, user);
    1581867        } else {
    1582                 fstrcpy(sub_user, lp_guestaccount());
     868                fstrcpy(sub_user, "");
    1583869        }
    1584870
    1585871        sub_set_smb_name(sub_user);
    1586872
    1587         reload_services(sconn->msg_ctx, sconn->sock, True);
    1588 
    1589         if (lp_security() == SEC_SHARE) {
    1590                 char *sub_user_mapped = NULL;
    1591                 /* In share level we should ignore any passwords */
    1592 
    1593                 data_blob_free(&lm_resp);
    1594                 data_blob_free(&nt_resp);
    1595                 data_blob_clear_free(&plaintext_password);
    1596 
    1597                 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
    1598                 if (!sub_user_mapped) {
    1599                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    1600                         END_PROFILE(SMBsesssetupX);
    1601                         return;
    1602                 }
    1603                 fstrcpy(sub_user, sub_user_mapped);
    1604                 add_session_user(sconn, sub_user);
    1605                 add_session_workgroup(sconn, domain);
    1606                 /* Then force it to null for the benfit of the code below */
    1607                 user = "";
    1608         }
     873        reload_services(sconn, conn_snum_used, true);
    1609874
    1610875        if (!*user) {
    1611876
    1612                 nt_status = check_guest_password(&server_info);
     877                nt_status = check_guest_password(sconn->remote_address, req, &session_info);
    1613878
    1614879        } else if (doencrypt) {
    1615                 struct auth_context *negprot_auth_context = NULL;
    1616                 negprot_auth_context = sconn->smb1.negprot.auth_context;
     880                struct auth4_context *negprot_auth_context = NULL;
     881                negprot_auth_context = xconn->smb1.negprot.auth_context;
    1617882                if (!negprot_auth_context) {
    1618883                        DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
     
    1623888                        return;
    1624889                }
    1625                 nt_status = make_user_info_for_reply_enc(&user_info, user,
    1626                                                 domain,
    1627                                                 lm_resp, nt_resp);
     890                nt_status = make_user_info_for_reply_enc(talloc_tos(),
     891                                                         &user_info, user,
     892                                                         domain,
     893                                                         sconn->remote_address,
     894                                                         lm_resp, nt_resp);
    1628895                if (NT_STATUS_IS_OK(nt_status)) {
    1629                         nt_status = negprot_auth_context->check_ntlm_password(
    1630                                         negprot_auth_context,
    1631                                         user_info,
    1632                                         &server_info);
     896                        nt_status = auth_check_password_session_info(negprot_auth_context,
     897                                                                     req, user_info, &session_info);
    1633898                }
    1634899        } else {
    1635                 struct auth_context *plaintext_auth_context = NULL;
    1636 
    1637                 nt_status = make_auth_context_subsystem(
     900                struct auth4_context *plaintext_auth_context = NULL;
     901
     902                nt_status = make_auth4_context(
    1638903                        talloc_tos(), &plaintext_auth_context);
    1639904
     
    1644909                                        plaintext_auth_context, chal);
    1645910
    1646                         if (!make_user_info_for_reply(&user_info,
    1647                                                       user, domain, chal,
     911                        if (!make_user_info_for_reply(talloc_tos(),
     912                                                      &user_info,
     913                                                      user, domain,
     914                                                      sconn->remote_address,
     915                                                      chal,
    1648916                                                      plaintext_password)) {
    1649917                                nt_status = NT_STATUS_NO_MEMORY;
     
    1651919
    1652920                        if (NT_STATUS_IS_OK(nt_status)) {
    1653                                 nt_status = plaintext_auth_context->check_ntlm_password(
    1654                                                 plaintext_auth_context,
    1655                                                 user_info,
    1656                                                 &server_info);
    1657 
    1658                                 TALLOC_FREE(plaintext_auth_context);
     921                                nt_status = auth_check_password_session_info(plaintext_auth_context,
     922                                                                             req, user_info, &session_info);
    1659923                        }
    1660                 }
    1661         }
    1662 
    1663         free_user_info(&user_info);
    1664 
    1665         if (!NT_STATUS_IS_OK(nt_status)) {
    1666                 nt_status = do_map_to_guest(nt_status, &server_info,
    1667                                 user, domain);
    1668         }
     924                        TALLOC_FREE(plaintext_auth_context);
     925                }
     926        }
     927
     928        TALLOC_FREE(user_info);
    1669929
    1670930        if (!NT_STATUS_IS_OK(nt_status)) {
     
    1677937        }
    1678938
    1679         /* Ensure we can't possible take a code path leading to a
    1680          * null defref. */
    1681         if (!server_info) {
    1682                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
    1683                 END_PROFILE(SMBsesssetupX);
    1684                 return;
    1685         }
    1686 
    1687         if (!server_info->security_token) {
    1688                 nt_status = create_local_token(server_info);
    1689 
    1690                 if (!NT_STATUS_IS_OK(nt_status)) {
    1691                         DEBUG(10, ("create_local_token failed: %s\n",
    1692                                    nt_errstr(nt_status)));
    1693                         data_blob_free(&nt_resp);
    1694                         data_blob_free(&lm_resp);
    1695                         data_blob_clear_free(&plaintext_password);
    1696                         reply_nterror(req, nt_status_squash(nt_status));
    1697                         END_PROFILE(SMBsesssetupX);
    1698                         return;
    1699                 }
    1700         }
    1701 
    1702939        data_blob_clear_free(&plaintext_password);
    1703940
    1704941        /* it's ok - setup a reply */
    1705942        reply_outbuf(req, 3, 0);
     943        SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
     944        SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
     945
    1706946        if (get_Protocol() >= PROTOCOL_NT1) {
    1707947                push_signature(&req->outbuf);
     
    1709949        }
    1710950
    1711         if (server_info->guest) {
    1712                 SSVAL(req->outbuf,smb_vwv2,1);
     951        if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
     952                action |= SMB_SETUP_GUEST;
    1713953        }
    1714954
     
    1716956           to a uid can get through without a password, on the same VC */
    1717957
    1718         if (lp_security() == SEC_SHARE) {
    1719                 sess_vuid = UID_FIELD_INVALID;
    1720                 TALLOC_FREE(server_info);
    1721         } else {
    1722                 /* Ignore the initial vuid. */
    1723                 sess_vuid = register_initial_vuid(sconn);
    1724                 if (sess_vuid == UID_FIELD_INVALID) {
     958        nt_status = smbXsrv_session_create(xconn,
     959                                           now, &session);
     960        if (!NT_STATUS_IS_OK(nt_status)) {
     961                data_blob_free(&nt_resp);
     962                data_blob_free(&lm_resp);
     963                reply_nterror(req, nt_status_squash(nt_status));
     964                END_PROFILE(SMBsesssetupX);
     965                return;
     966        }
     967
     968        if (session_info->session_key.length > 0) {
     969                uint8_t session_key[16];
     970
     971                /*
     972                 * Note: the SMB1 signing key is not truncated to 16 byte!
     973                 */
     974                session->global->signing_key =
     975                        data_blob_dup_talloc(session->global,
     976                                             session_info->session_key);
     977                if (session->global->signing_key.data == NULL) {
    1725978                        data_blob_free(&nt_resp);
    1726979                        data_blob_free(&lm_resp);
    1727                         reply_nterror(req, nt_status_squash(
    1728                                               NT_STATUS_LOGON_FAILURE));
     980                        TALLOC_FREE(session);
     981                        reply_nterror(req, NT_STATUS_NO_MEMORY);
    1729982                        END_PROFILE(SMBsesssetupX);
    1730983                        return;
    1731984                }
    1732                 /* register_existing_vuid keeps the server info */
    1733                 sess_vuid = register_existing_vuid(sconn, sess_vuid,
    1734                                         server_info,
    1735                                         nt_resp.data ? nt_resp : lm_resp,
    1736                                         sub_user);
    1737                 if (sess_vuid == UID_FIELD_INVALID) {
     985
     986                /*
     987                 * The application key is truncated/padded to 16 bytes
     988                 */
     989                ZERO_STRUCT(session_key);
     990                memcpy(session_key, session->global->signing_key.data,
     991                       MIN(session->global->signing_key.length,
     992                           sizeof(session_key)));
     993                session->global->application_key =
     994                        data_blob_talloc(session->global,
     995                                         session_key,
     996                                         sizeof(session_key));
     997                ZERO_STRUCT(session_key);
     998                if (session->global->application_key.data == NULL) {
    1738999                        data_blob_free(&nt_resp);
    17391000                        data_blob_free(&lm_resp);
    1740                         reply_nterror(req, nt_status_squash(
    1741                                               NT_STATUS_LOGON_FAILURE));
     1001                        TALLOC_FREE(session);
     1002                        reply_nterror(req, NT_STATUS_NO_MEMORY);
    17421003                        END_PROFILE(SMBsesssetupX);
    17431004                        return;
    17441005                }
    17451006
    1746                 /* current_user_info is changed on new vuid */
    1747                 reload_services(sconn->msg_ctx, sconn->sock, True);
    1748         }
     1007                /*
     1008                 * Place the application key into the session_info
     1009                 */
     1010                data_blob_clear_free(&session_info->session_key);
     1011                session_info->session_key = data_blob_dup_talloc(session_info,
     1012                                                session->global->application_key);
     1013                if (session_info->session_key.data == NULL) {
     1014                        data_blob_free(&nt_resp);
     1015                        data_blob_free(&lm_resp);
     1016                        TALLOC_FREE(session);
     1017                        reply_nterror(req, NT_STATUS_NO_MEMORY);
     1018                        END_PROFILE(SMBsesssetupX);
     1019                        return;
     1020                }
     1021        }
     1022
     1023        session->compat = talloc_zero(session, struct user_struct);
     1024        if (session->compat == NULL) {
     1025                data_blob_free(&nt_resp);
     1026                data_blob_free(&lm_resp);
     1027                TALLOC_FREE(session);
     1028                reply_nterror(req, NT_STATUS_NO_MEMORY);
     1029                END_PROFILE(SMBsesssetupX);
     1030                return;
     1031        }
     1032        session->compat->session = session;
     1033        session->compat->homes_snum = -1;
     1034        session->compat->session_info = session_info;
     1035        session->compat->session_keystr = NULL;
     1036        session->compat->vuid = session->global->session_wire_id;
     1037        DLIST_ADD(sconn->users, session->compat);
     1038        sconn->num_users++;
     1039
     1040        if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
     1041                session->compat->homes_snum =
     1042                        register_homes_share(session_info->unix_info->unix_name);
     1043        }
     1044
     1045        if (srv_is_signing_negotiated(xconn) &&
     1046            action == 0 &&
     1047            session->global->signing_key.length > 0)
     1048        {
     1049                /*
     1050                 * Try and turn on server signing on the first non-guest
     1051                 * sessionsetup.
     1052                 */
     1053                srv_set_signing(xconn,
     1054                        session->global->signing_key,
     1055                        nt_resp.data ? nt_resp : lm_resp);
     1056        }
     1057
     1058        set_current_user_info(session_info->unix_info->sanitized_username,
     1059                              session_info->unix_info->unix_name,
     1060                              session_info->info->domain_name);
     1061
     1062        session->status = NT_STATUS_OK;
     1063        session->global->auth_session_info = talloc_move(session->global,
     1064                                                         &session_info);
     1065        session->global->auth_session_info_seqnum += 1;
     1066        session->global->channels[0].auth_session_info_seqnum =
     1067                session->global->auth_session_info_seqnum;
     1068        session->global->auth_time = now;
     1069        session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
     1070
     1071        nt_status = smbXsrv_session_update(session);
     1072        if (!NT_STATUS_IS_OK(nt_status)) {
     1073                DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
     1074                          (unsigned long long)session->compat->vuid,
     1075                          nt_errstr(nt_status)));
     1076                data_blob_free(&nt_resp);
     1077                data_blob_free(&lm_resp);
     1078                TALLOC_FREE(session);
     1079                reply_nterror(req, nt_status_squash(nt_status));
     1080                END_PROFILE(SMBsesssetupX);
     1081                return;
     1082        }
     1083
     1084        if (!session_claim(session)) {
     1085                DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
     1086                          (unsigned long long)session->compat->vuid));
     1087                data_blob_free(&nt_resp);
     1088                data_blob_free(&lm_resp);
     1089                TALLOC_FREE(session);
     1090                reply_nterror(req, NT_STATUS_LOGON_FAILURE);
     1091                END_PROFILE(SMBsesssetupX);
     1092                return;
     1093        }
     1094
     1095        /* current_user_info is changed on new vuid */
     1096        reload_services(sconn, conn_snum_used, true);
     1097
     1098        sess_vuid = session->global->session_wire_id;
    17491099
    17501100        data_blob_free(&nt_resp);
    17511101        data_blob_free(&lm_resp);
    17521102
     1103        SSVAL(req->outbuf,smb_vwv2,action);
    17531104        SSVAL(req->outbuf,smb_uid,sess_vuid);
    1754         SSVAL(req->inbuf,smb_uid,sess_vuid);
     1105        SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
    17551106        req->vuid = sess_vuid;
    17561107
    1757         if (!sconn->smb1.sessions.done_sesssetup) {
    1758                 sconn->smb1.sessions.max_send =
    1759                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
    1760         }
    1761         sconn->smb1.sessions.done_sesssetup = true;
     1108        if (!xconn->smb1.sessions.done_sesssetup) {
     1109                if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
     1110                        reply_force_doserror(req, ERRSRV, ERRerror);
     1111                        END_PROFILE(SMBsesssetupX);
     1112                        return;
     1113                }
     1114                xconn->smb1.sessions.max_send = smb_bufsize;
     1115                xconn->smb1.sessions.done_sesssetup = true;
     1116        }
    17621117
    17631118        END_PROFILE(SMBsesssetupX);
    1764         chain_reply(req);
    1765         return;
    17661119}
Note: See TracChangeset for help on using the changeset viewer.