Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/smbd/smb2_sesssetup.c

    r414 r745  
    44
    55   Copyright (C) Stefan Metzmacher 2009
     6   Copyright (C) Jeremy Allison 2010
    67
    78   This program is free software; you can redistribute it and/or modify
     
    2021
    2122#include "includes.h"
     23#include "smbd/smbd.h"
    2224#include "smbd/globals.h"
    2325#include "../libcli/smb/smb_common.h"
    2426#include "../libcli/auth/spnego.h"
    25 
    26 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
     27#include "../libcli/auth/ntlmssp.h"
     28#include "ntlmssp_wrap.h"
     29#include "../librpc/gen_ndr/krb5pac.h"
     30#include "libads/kerberos_proto.h"
     31#include "../lib/util/asn1.h"
     32#include "auth.h"
     33
     34static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
    2735                                        uint64_t in_session_id,
    2836                                        uint8_t in_security_mode,
     
    3240                                        uint64_t *out_session_id);
    3341
    34 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *req)
     42NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
    3543{
    3644        const uint8_t *inhdr;
    3745        const uint8_t *inbody;
    38         int i = req->current_idx;
     46        int i = smb2req->current_idx;
    3947        uint8_t *outhdr;
    4048        DATA_BLOB outbody;
     
    5361        NTSTATUS status;
    5462
    55         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
    56 
    57         if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
    58                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    59         }
    60 
    61         inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
     63        inhdr = (const uint8_t *)smb2req->in.vector[i+0].iov_base;
     64
     65        if (smb2req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
     66                return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     67        }
     68
     69        inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base;
    6270
    6371        body_size = SVAL(inbody, 0x00);
    6472        if (body_size != expected_body_size) {
    65                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
     73                return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
    6674        }
    6775
     
    7078
    7179        if (in_security_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
    72                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
    73         }
    74 
    75         if (in_security_length > req->in.vector[i+2].iov_len) {
    76                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
     80                return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
     81        }
     82
     83        if (in_security_length > smb2req->in.vector[i+2].iov_len) {
     84                return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
    7785        }
    7886
    7987        in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
    8088        in_security_mode = CVAL(inbody, 0x03);
    81         in_security_buffer.data = (uint8_t *)req->in.vector[i+2].iov_base;
     89        in_security_buffer.data = (uint8_t *)smb2req->in.vector[i+2].iov_base;
    8290        in_security_buffer.length = in_security_length;
    8391
    84         status = smbd_smb2_session_setup(req,
     92        status = smbd_smb2_session_setup(smb2req,
    8593                                         in_session_id,
    8694                                         in_security_mode,
     
    92100            !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    93101                status = nt_status_squash(status);
    94                 return smbd_smb2_request_error(req, status);
     102                return smbd_smb2_request_error(smb2req, status);
    95103        }
    96104
    97105        out_security_offset = SMB2_HDR_BODY + 0x08;
    98106
    99         outhdr = (uint8_t *)req->out.vector[i].iov_base;
    100 
    101         outbody = data_blob_talloc(req->out.vector, NULL, 0x08);
     107        outhdr = (uint8_t *)smb2req->out.vector[i].iov_base;
     108
     109        outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x08);
    102110        if (outbody.data == NULL) {
    103                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
     111                return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
    104112        }
    105113
     
    116124        outdyn = out_security_buffer;
    117125
    118         return smbd_smb2_request_done_ex(req, status, outbody, &outdyn,
     126        return smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
    119127                                         __location__);
    120128}
     
    142150}
    143151
    144 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
     152static NTSTATUS setup_ntlmssp_session_info(struct smbd_smb2_session *session,
     153                                NTSTATUS status)
     154{
     155        if (NT_STATUS_IS_OK(status)) {
     156                status = auth_ntlmssp_steal_session_info(session,
     157                                session->auth_ntlmssp_state,
     158                                &session->session_info);
     159        } else {
     160                /* Note that this session_info won't have a session
     161                 * key.  But for map to guest, that's exactly the right
     162                 * thing - we can't reasonably guess the key the
     163                 * client wants, as the password was wrong */
     164                status = do_map_to_guest(status,
     165                        &session->session_info,
     166                        auth_ntlmssp_get_username(session->auth_ntlmssp_state),
     167                        auth_ntlmssp_get_domain(session->auth_ntlmssp_state));
     168        }
     169        return status;
     170}
     171
     172#ifdef HAVE_KRB5
     173static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
     174                                        struct smbd_smb2_request *smb2req,
     175                                        uint8_t in_security_mode,
     176                                        const DATA_BLOB *secblob,
     177                                        const char *mechOID,
     178                                        uint16_t *out_session_flags,
     179                                        DATA_BLOB *out_security_buffer,
     180                                        uint64_t *out_session_id)
     181{
     182        DATA_BLOB ap_rep = data_blob_null;
     183        DATA_BLOB ap_rep_wrapped = data_blob_null;
     184        DATA_BLOB ticket = data_blob_null;
     185        DATA_BLOB session_key = data_blob_null;
     186        DATA_BLOB secblob_out = data_blob_null;
     187        uint8 tok_id[2];
     188        struct PAC_LOGON_INFO *logon_info = NULL;
     189        char *principal = NULL;
     190        char *user = NULL;
     191        char *domain = NULL;
     192        struct passwd *pw = NULL;
     193        NTSTATUS status;
     194        char *real_username;
     195        fstring tmp;
     196        bool username_was_mapped = false;
     197        bool map_domainuser_to_guest = false;
     198
     199        if (!spnego_parse_krb5_wrap(talloc_tos(), *secblob, &ticket, tok_id)) {
     200                status = NT_STATUS_LOGON_FAILURE;
     201                goto fail;
     202        }
     203
     204        status = ads_verify_ticket(smb2req, lp_realm(), 0, &ticket,
     205                                   &principal, &logon_info, &ap_rep,
     206                                   &session_key, true);
     207
     208        if (!NT_STATUS_IS_OK(status)) {
     209                DEBUG(1,("smb2: Failed to verify incoming ticket with error %s!\n",
     210                        nt_errstr(status)));
     211                if (!NT_STATUS_EQUAL(status, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
     212                        status = NT_STATUS_LOGON_FAILURE;
     213                }
     214                goto fail;
     215        }
     216
     217        status = get_user_from_kerberos_info(talloc_tos(),
     218                                             smb2req->sconn->client_id.name,
     219                                             principal, logon_info,
     220                                             &username_was_mapped,
     221                                             &map_domainuser_to_guest,
     222                                             &user, &domain,
     223                                             &real_username, &pw);
     224        if (!NT_STATUS_IS_OK(status)) {
     225                goto fail;
     226        }
     227
     228        /* save the PAC data if we have it */
     229        if (logon_info) {
     230                netsamlogon_cache_store(user, &logon_info->info3);
     231        }
     232
     233        /* setup the string used by %U */
     234        sub_set_smb_name(real_username);
     235
     236        /* reload services so that the new %U is taken into account */
     237        reload_services(smb2req->sconn->msg_ctx, smb2req->sconn->sock, true);
     238
     239        status = make_server_info_krb5(session,
     240                                        user, domain, real_username, pw,
     241                                        logon_info, map_domainuser_to_guest,
     242                                        &session->session_info);
     243        if (!NT_STATUS_IS_OK(status)) {
     244                DEBUG(1, ("smb2: make_server_info_krb5 failed\n"));
     245                goto fail;
     246        }
     247
     248
     249        session->session_info->nss_token |= username_was_mapped;
     250
     251        /* we need to build the token for the user. make_session_info_guest()
     252           already does this */
     253
     254        if (!session->session_info->security_token ) {
     255                status = create_local_token(session->session_info);
     256                if (!NT_STATUS_IS_OK(status)) {
     257                        DEBUG(10,("smb2: failed to create local token: %s\n",
     258                                nt_errstr(status)));
     259                        goto fail;
     260                }
     261        }
     262
     263        if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
     264             lp_server_signing() == Required) {
     265                session->do_signing = true;
     266        }
     267
     268        if (session->session_info->guest) {
     269                /* we map anonymous to guest internally */
     270                *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
     271                *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
     272                /* force no signing */
     273                session->do_signing = false;
     274        }
     275
     276        data_blob_free(&session->session_info->user_session_key);
     277        session->session_info->user_session_key =
     278                        data_blob_talloc(
     279                                session->session_info,
     280                                session_key.data,
     281                                session_key.length);
     282        if (session_key.length > 0) {
     283                if (session->session_info->user_session_key.data == NULL) {
     284                        status = NT_STATUS_NO_MEMORY;
     285                        goto fail;
     286                }
     287        }
     288        session->session_key = session->session_info->user_session_key;
     289
     290        session->compat_vuser = talloc_zero(session, user_struct);
     291        if (session->compat_vuser == NULL) {
     292                status = NT_STATUS_NO_MEMORY;
     293                goto fail;
     294        }
     295        session->compat_vuser->auth_ntlmssp_state = NULL;
     296        session->compat_vuser->homes_snum = -1;
     297        session->compat_vuser->session_info = session->session_info;
     298        session->compat_vuser->session_keystr = NULL;
     299        session->compat_vuser->vuid = session->vuid;
     300        DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
     301
     302        /* This is a potentially untrusted username */
     303        alpha_strcpy(tmp, user, ". _-$", sizeof(tmp));
     304        session->session_info->sanitized_username =
     305                                talloc_strdup(session->session_info, tmp);
     306
     307        if (!session->session_info->guest) {
     308                session->compat_vuser->homes_snum =
     309                        register_homes_share(session->session_info->unix_name);
     310        }
     311
     312        if (!session_claim(session->sconn, session->compat_vuser)) {
     313                DEBUG(1, ("smb2: Failed to claim session "
     314                        "for vuid=%d\n",
     315                        session->compat_vuser->vuid));
     316                goto fail;
     317        }
     318
     319        session->status = NT_STATUS_OK;
     320
     321        /*
     322         * we attach the session to the request
     323         * so that the response can be signed
     324         */
     325        smb2req->session = session;
     326        if (session->do_signing) {
     327                smb2req->do_signing = true;
     328        }
     329
     330        global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
     331        status = NT_STATUS_OK;
     332
     333        /* wrap that up in a nice GSS-API wrapping */
     334        ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
     335                                TOK_ID_KRB_AP_REP);
     336
     337        secblob_out = spnego_gen_auth_response(
     338                                        talloc_tos(),
     339                                        &ap_rep_wrapped,
     340                                        status,
     341                                        mechOID);
     342
     343        *out_security_buffer = data_blob_talloc(smb2req,
     344                                                secblob_out.data,
     345                                                secblob_out.length);
     346        if (secblob_out.data && out_security_buffer->data == NULL) {
     347                status = NT_STATUS_NO_MEMORY;
     348                goto fail;
     349        }
     350
     351        data_blob_free(&ap_rep);
     352        data_blob_free(&ap_rep_wrapped);
     353        data_blob_free(&ticket);
     354        data_blob_free(&session_key);
     355        data_blob_free(&secblob_out);
     356
     357        *out_session_id = session->vuid;
     358
     359        return NT_STATUS_OK;
     360
     361  fail:
     362
     363        data_blob_free(&ap_rep);
     364        data_blob_free(&ap_rep_wrapped);
     365        data_blob_free(&ticket);
     366        data_blob_free(&session_key);
     367        data_blob_free(&secblob_out);
     368
     369        ap_rep_wrapped = data_blob_null;
     370        secblob_out = spnego_gen_auth_response(
     371                                        talloc_tos(),
     372                                        &ap_rep_wrapped,
     373                                        status,
     374                                        mechOID);
     375
     376        *out_security_buffer = data_blob_talloc(smb2req,
     377                                                secblob_out.data,
     378                                                secblob_out.length);
     379        data_blob_free(&secblob_out);
     380        return status;
     381}
     382#endif
     383
     384static NTSTATUS smbd_smb2_spnego_negotiate(struct smbd_smb2_session *session,
     385                                        struct smbd_smb2_request *smb2req,
     386                                        uint8_t in_security_mode,
     387                                        DATA_BLOB in_security_buffer,
     388                                        uint16_t *out_session_flags,
     389                                        DATA_BLOB *out_security_buffer,
     390                                        uint64_t *out_session_id)
     391{
     392        DATA_BLOB secblob_in = data_blob_null;
     393        DATA_BLOB chal_out = data_blob_null;
     394        char *kerb_mech = NULL;
     395        NTSTATUS status;
     396
     397        /* Ensure we have no old NTLM state around. */
     398        TALLOC_FREE(session->auth_ntlmssp_state);
     399
     400        status = parse_spnego_mechanisms(talloc_tos(), in_security_buffer,
     401                        &secblob_in, &kerb_mech);
     402        if (!NT_STATUS_IS_OK(status)) {
     403                goto out;
     404        }
     405
     406#ifdef HAVE_KRB5
     407        if (kerb_mech && ((lp_security()==SEC_ADS) ||
     408                                USE_KERBEROS_KEYTAB) ) {
     409                status = smbd_smb2_session_setup_krb5(session,
     410                                smb2req,
     411                                in_security_mode,
     412                                &secblob_in,
     413                                kerb_mech,
     414                                out_session_flags,
     415                                out_security_buffer,
     416                                out_session_id);
     417
     418                goto out;
     419        }
     420#endif
     421
     422        if (kerb_mech) {
     423                /* The mechtoken is a krb5 ticket, but
     424                 * we need to fall back to NTLM. */
     425
     426                DEBUG(3,("smb2: Got krb5 ticket in SPNEGO "
     427                        "but set to downgrade to NTLMSSP\n"));
     428
     429                status = NT_STATUS_MORE_PROCESSING_REQUIRED;
     430        } else {
     431                /* Fall back to NTLMSSP. */
     432                status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
     433                if (!NT_STATUS_IS_OK(status)) {
     434                        goto out;
     435                }
     436
     437                status = auth_ntlmssp_update(session->auth_ntlmssp_state,
     438                                             secblob_in,
     439                                             &chal_out);
     440        }
     441
     442        if (!NT_STATUS_IS_OK(status) &&
     443                        !NT_STATUS_EQUAL(status,
     444                                NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     445                goto out;
     446        }
     447
     448        *out_security_buffer = spnego_gen_auth_response(smb2req,
     449                                                &chal_out,
     450                                                status,
     451                                                OID_NTLMSSP);
     452        if (out_security_buffer->data == NULL) {
     453                status = NT_STATUS_NO_MEMORY;
     454                goto out;
     455        }
     456        *out_session_id = session->vuid;
     457
     458  out:
     459
     460        data_blob_free(&secblob_in);
     461        data_blob_free(&chal_out);
     462        TALLOC_FREE(kerb_mech);
     463        if (!NT_STATUS_IS_OK(status) &&
     464                        !NT_STATUS_EQUAL(status,
     465                                NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     466                TALLOC_FREE(session->auth_ntlmssp_state);
     467                TALLOC_FREE(session);
     468        }
     469        return status;
     470}
     471
     472static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *session,
     473                                        struct smbd_smb2_request *smb2req,
     474                                        uint8_t in_security_mode,
     475                                        DATA_BLOB in_security_buffer,
     476                                        uint16_t *out_session_flags,
     477                                        uint64_t *out_session_id)
     478{
     479        fstring tmp;
     480
     481        if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
     482            lp_server_signing() == Required) {
     483                session->do_signing = true;
     484        }
     485
     486        if (session->session_info->guest) {
     487                /* we map anonymous to guest internally */
     488                *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
     489                *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
     490                /* force no signing */
     491                session->do_signing = false;
     492        }
     493
     494        session->session_key = session->session_info->user_session_key;
     495
     496        session->compat_vuser = talloc_zero(session, user_struct);
     497        if (session->compat_vuser == NULL) {
     498                TALLOC_FREE(session->auth_ntlmssp_state);
     499                TALLOC_FREE(session);
     500                return NT_STATUS_NO_MEMORY;
     501        }
     502        session->compat_vuser->auth_ntlmssp_state = session->auth_ntlmssp_state;
     503        session->compat_vuser->homes_snum = -1;
     504        session->compat_vuser->session_info = session->session_info;
     505        session->compat_vuser->session_keystr = NULL;
     506        session->compat_vuser->vuid = session->vuid;
     507        DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
     508
     509        /* This is a potentially untrusted username */
     510        alpha_strcpy(tmp,
     511                     auth_ntlmssp_get_username(session->auth_ntlmssp_state),
     512                     ". _-$",
     513                     sizeof(tmp));
     514        session->session_info->sanitized_username = talloc_strdup(
     515                session->session_info, tmp);
     516
     517        if (!session->compat_vuser->session_info->guest) {
     518                session->compat_vuser->homes_snum =
     519                        register_homes_share(session->session_info->unix_name);
     520        }
     521
     522        if (!session_claim(session->sconn, session->compat_vuser)) {
     523                DEBUG(1, ("smb2: Failed to claim session "
     524                        "for vuid=%d\n",
     525                        session->compat_vuser->vuid));
     526                TALLOC_FREE(session->auth_ntlmssp_state);
     527                TALLOC_FREE(session);
     528                return NT_STATUS_LOGON_FAILURE;
     529        }
     530
     531
     532        session->status = NT_STATUS_OK;
     533
     534        /*
     535         * we attach the session to the request
     536         * so that the response can be signed
     537         */
     538        smb2req->session = session;
     539        if (session->do_signing) {
     540                smb2req->do_signing = true;
     541        }
     542
     543        global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
     544
     545        *out_session_id = session->vuid;
     546
     547        return NT_STATUS_OK;
     548}
     549
     550static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
     551                                        struct smbd_smb2_request *smb2req,
     552                                        uint8_t in_security_mode,
     553                                        DATA_BLOB in_security_buffer,
     554                                        uint16_t *out_session_flags,
     555                                        DATA_BLOB *out_security_buffer,
     556                                        uint64_t *out_session_id)
     557{
     558        DATA_BLOB auth = data_blob_null;
     559        DATA_BLOB auth_out = data_blob_null;
     560        NTSTATUS status;
     561
     562        if (!spnego_parse_auth(talloc_tos(), in_security_buffer, &auth)) {
     563                TALLOC_FREE(session);
     564                return NT_STATUS_LOGON_FAILURE;
     565        }
     566
     567        if (auth.data[0] == ASN1_APPLICATION(0)) {
     568                /* Might be a second negTokenTarg packet */
     569                DATA_BLOB secblob_in = data_blob_null;
     570                char *kerb_mech = NULL;
     571
     572                status = parse_spnego_mechanisms(talloc_tos(),
     573                                in_security_buffer,
     574                                &secblob_in, &kerb_mech);
     575                if (!NT_STATUS_IS_OK(status)) {
     576                        TALLOC_FREE(session);
     577                        return status;
     578                }
     579
     580#ifdef HAVE_KRB5
     581                if (kerb_mech && ((lp_security()==SEC_ADS) ||
     582                                        USE_KERBEROS_KEYTAB) ) {
     583                        status = smbd_smb2_session_setup_krb5(session,
     584                                        smb2req,
     585                                        in_security_mode,
     586                                        &secblob_in,
     587                                        kerb_mech,
     588                                        out_session_flags,
     589                                        out_security_buffer,
     590                                        out_session_id);
     591
     592                        data_blob_free(&secblob_in);
     593                        TALLOC_FREE(kerb_mech);
     594                        if (!NT_STATUS_IS_OK(status)) {
     595                                TALLOC_FREE(session);
     596                        }
     597                        return status;
     598                }
     599#endif
     600
     601                /* Can't blunder into NTLMSSP auth if we have
     602                 * a krb5 ticket. */
     603
     604                if (kerb_mech) {
     605                        DEBUG(3,("smb2: network "
     606                                "misconfiguration, client sent us a "
     607                                "krb5 ticket and kerberos security "
     608                                "not enabled\n"));
     609                        TALLOC_FREE(session);
     610                        data_blob_free(&secblob_in);
     611                        TALLOC_FREE(kerb_mech);
     612                        return NT_STATUS_LOGON_FAILURE;
     613                }
     614
     615                data_blob_free(&secblob_in);
     616        }
     617
     618        if (session->auth_ntlmssp_state == NULL) {
     619                status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
     620                if (!NT_STATUS_IS_OK(status)) {
     621                        data_blob_free(&auth);
     622                        TALLOC_FREE(session);
     623                        return status;
     624                }
     625        }
     626
     627        status = auth_ntlmssp_update(session->auth_ntlmssp_state,
     628                                     auth,
     629                                     &auth_out);
     630        /* We need to call setup_ntlmssp_session_info() if status==NT_STATUS_OK,
     631           or if status is anything except NT_STATUS_MORE_PROCESSING_REQUIRED,
     632           as this can trigger map to guest. */
     633        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     634                status = setup_ntlmssp_session_info(session, status);
     635        }
     636
     637        if (!NT_STATUS_IS_OK(status) &&
     638                        !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     639                TALLOC_FREE(session->auth_ntlmssp_state);
     640                data_blob_free(&auth);
     641                TALLOC_FREE(session);
     642                return status;
     643        }
     644
     645        data_blob_free(&auth);
     646
     647        *out_security_buffer = spnego_gen_auth_response(smb2req,
     648                                &auth_out, status, NULL);
     649
     650        if (out_security_buffer->data == NULL) {
     651                TALLOC_FREE(session->auth_ntlmssp_state);
     652                TALLOC_FREE(session);
     653                return NT_STATUS_NO_MEMORY;
     654        }
     655
     656        *out_session_id = session->vuid;
     657
     658        if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     659                return NT_STATUS_MORE_PROCESSING_REQUIRED;
     660        }
     661
     662        /* We're done - claim the session. */
     663        return smbd_smb2_common_ntlmssp_auth_return(session,
     664                                                smb2req,
     665                                                in_security_mode,
     666                                                in_security_buffer,
     667                                                out_session_flags,
     668                                                out_session_id);
     669}
     670
     671static NTSTATUS smbd_smb2_raw_ntlmssp_auth(struct smbd_smb2_session *session,
     672                                        struct smbd_smb2_request *smb2req,
     673                                        uint8_t in_security_mode,
     674                                        DATA_BLOB in_security_buffer,
     675                                        uint16_t *out_session_flags,
     676                                        DATA_BLOB *out_security_buffer,
     677                                        uint64_t *out_session_id)
     678{
     679        NTSTATUS status;
     680        DATA_BLOB secblob_out = data_blob_null;
     681
     682        if (session->auth_ntlmssp_state == NULL) {
     683                status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
     684                if (!NT_STATUS_IS_OK(status)) {
     685                        TALLOC_FREE(session);
     686                        return status;
     687                }
     688        }
     689
     690        /* RAW NTLMSSP */
     691        status = auth_ntlmssp_update(session->auth_ntlmssp_state,
     692                                     in_security_buffer,
     693                                     &secblob_out);
     694
     695        if (NT_STATUS_IS_OK(status) ||
     696                        NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     697                *out_security_buffer = data_blob_talloc(smb2req,
     698                                                secblob_out.data,
     699                                                secblob_out.length);
     700                if (secblob_out.data && out_security_buffer->data == NULL) {
     701                        TALLOC_FREE(session->auth_ntlmssp_state);
     702                        TALLOC_FREE(session);
     703                        return NT_STATUS_NO_MEMORY;
     704                }
     705        }
     706
     707        if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     708                *out_session_id = session->vuid;
     709                return status;
     710        }
     711
     712        status = setup_ntlmssp_session_info(session, status);
     713
     714        if (!NT_STATUS_IS_OK(status)) {
     715                TALLOC_FREE(session->auth_ntlmssp_state);
     716                TALLOC_FREE(session);
     717                return status;
     718        }
     719        *out_session_id = session->vuid;
     720
     721        return smbd_smb2_common_ntlmssp_auth_return(session,
     722                                                smb2req,
     723                                                in_security_mode,
     724                                                in_security_buffer,
     725                                                out_session_flags,
     726                                                out_session_id);
     727}
     728
     729static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
    145730                                        uint64_t in_session_id,
    146731                                        uint8_t in_security_mode,
     
    151736{
    152737        struct smbd_smb2_session *session;
    153         NTSTATUS status;
    154738
    155739        *out_session_flags = 0;
     
    160744
    161745                /* create a new session */
    162                 session = talloc_zero(req->sconn, struct smbd_smb2_session);
     746                session = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
    163747                if (session == NULL) {
    164748                        return NT_STATUS_NO_MEMORY;
    165749                }
    166750                session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
    167                 id = idr_get_new_random(req->sconn->smb2.sessions.idtree,
     751                id = idr_get_new_random(smb2req->sconn->smb2.sessions.idtree,
    168752                                        session,
    169                                         req->sconn->smb2.sessions.limit);
     753                                        smb2req->sconn->smb2.sessions.limit);
    170754                if (id == -1) {
    171755                        return NT_STATUS_INSUFFICIENT_RESOURCES;
     
    180764                session->tcons.list = NULL;
    181765
    182                 DLIST_ADD_END(req->sconn->smb2.sessions.list, session,
     766                DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, session,
    183767                              struct smbd_smb2_session *);
    184                 session->sconn = req->sconn;
     768                session->sconn = smb2req->sconn;
    185769                talloc_set_destructor(session, smbd_smb2_session_destructor);
    186770        } else {
     
    188772
    189773                /* lookup an existing session */
    190                 p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
     774                p = idr_find(smb2req->sconn->smb2.sessions.idtree, in_session_id);
    191775                if (p == NULL) {
    192776                        return NT_STATUS_USER_SESSION_DELETED;
     
    199783        }
    200784
    201         if (session->auth_ntlmssp_state == NULL) {
    202                 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
    203                 if (!NT_STATUS_IS_OK(status)) {
    204                         TALLOC_FREE(session);
    205                         return status;
    206                 }
    207         }
    208 
    209785        if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
    210                 DATA_BLOB secblob_in;
    211                 DATA_BLOB chal_out;
    212                 char *kerb_mech = NULL;
    213 
    214                 status = parse_spnego_mechanisms(in_security_buffer,
    215                                 &secblob_in, &kerb_mech);
    216                 if (!NT_STATUS_IS_OK(status)) {
    217                         TALLOC_FREE(session);
    218                         return nt_status_squash(status);
    219                 }
    220 
    221                 /* For now, just SPNEGO NTLMSSP - krb5 goes here later.. */
    222                 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
    223                                              secblob_in,
    224                                              &chal_out);
    225 
    226                 if (!NT_STATUS_IS_OK(status) &&
    227                                 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    228                         auth_ntlmssp_end(&session->auth_ntlmssp_state);
    229                         TALLOC_FREE(session);
    230                         return nt_status_squash(status);
    231                 }
    232 
    233                 *out_security_buffer = spnego_gen_auth_response(&chal_out,
    234                                 status, OID_NTLMSSP);
    235 
    236                 *out_session_id = session->vuid;
    237                 return status;
     786                return smbd_smb2_spnego_negotiate(session,
     787                                                smb2req,
     788                                                in_security_mode,
     789                                                in_security_buffer,
     790                                                out_session_flags,
     791                                                out_security_buffer,
     792                                                out_session_id);
    238793        } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
    239                 DATA_BLOB auth = data_blob_null;
    240                 DATA_BLOB auth_out = data_blob_null;
    241 
    242                 /* its an auth packet */
    243                 if (!spnego_parse_auth(in_security_buffer, &auth)) {
    244                         TALLOC_FREE(session);
    245                         return NT_STATUS_LOGON_FAILURE;
    246                 }
    247                 /* For now, just SPNEGO NTLMSSP - krb5 goes here later.. */
    248                 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
    249                                              auth,
    250                                              &auth_out);
    251                 if (!NT_STATUS_IS_OK(status)) {
    252                         auth_ntlmssp_end(&session->auth_ntlmssp_state);
    253                         TALLOC_FREE(session);
    254                         return nt_status_squash(status);
    255                 }
    256 
    257                 *out_security_buffer = spnego_gen_auth_response(&auth_out,
    258                                 status, NULL);
    259 
    260                 *out_session_id = session->vuid;
     794                return smbd_smb2_spnego_auth(session,
     795                                                smb2req,
     796                                                in_security_mode,
     797                                                in_security_buffer,
     798                                                out_session_flags,
     799                                                out_security_buffer,
     800                                                out_session_id);
    261801        } else if (strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0) {
    262 
    263                 /* RAW NTLMSSP */
    264                 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
    265                                              in_security_buffer,
    266                                              out_security_buffer);
    267 
    268                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    269                         *out_session_id = session->vuid;
    270                         return status;
    271                 }
    272                 if (!NT_STATUS_IS_OK(status)) {
    273                         auth_ntlmssp_end(&session->auth_ntlmssp_state);
    274                         TALLOC_FREE(session);
    275                         return nt_status_squash(status);
    276                 }
    277                 *out_session_id = session->vuid;
    278         }
    279 
    280         /* TODO: setup session key for signing */
    281 
    282         if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
    283             lp_server_signing() == Required) {
    284                 session->do_signing = true;
    285         }
    286 
    287         if (session->auth_ntlmssp_state->server_info->guest) {
    288                 /* we map anonymous to guest internally */
    289                 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
    290                 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
    291                 /* force no signing */
    292                 session->do_signing = false;
    293         }
    294 
    295         session->server_info = session->auth_ntlmssp_state->server_info;
    296         data_blob_free(&session->server_info->user_session_key);
    297         session->server_info->user_session_key =
    298                         data_blob_talloc(
    299                         session->server_info,
    300                         session->auth_ntlmssp_state->ntlmssp_state->session_key.data,
    301                         session->auth_ntlmssp_state->ntlmssp_state->session_key.length);
    302         if (session->auth_ntlmssp_state->ntlmssp_state->session_key.length > 0) {
    303                 if (session->server_info->user_session_key.data == NULL) {
    304                         TALLOC_FREE(session);
    305                         return NT_STATUS_NO_MEMORY;
    306                 }
    307         }
    308         session->session_key = session->server_info->user_session_key;
    309 
    310         session->compat_vuser = talloc_zero(session, user_struct);
    311         if (session->compat_vuser == NULL) {
    312                 TALLOC_FREE(session);
    313                 return NT_STATUS_NO_MEMORY;
    314         }
    315         session->compat_vuser->auth_ntlmssp_state = session->auth_ntlmssp_state;
    316         session->compat_vuser->homes_snum = -1;
    317         session->compat_vuser->server_info = session->server_info;
    318         session->compat_vuser->session_keystr = NULL;
    319         session->compat_vuser->vuid = session->vuid;
    320         DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
    321 
    322         session->status = NT_STATUS_OK;
    323 
    324         /*
    325          * we attach the session to the request
    326          * so that the response can be signed
    327          */
    328         req->session = session;
    329         if (session->do_signing) {
    330                 req->do_signing = true;
    331         }
    332 
    333         *out_session_id = session->vuid;
    334         return status;
     802                return smbd_smb2_raw_ntlmssp_auth(session,
     803                                                smb2req,
     804                                                in_security_mode,
     805                                                in_security_buffer,
     806                                                out_session_flags,
     807                                                out_security_buffer,
     808                                                out_session_id);
     809        }
     810
     811        /* Unknown packet type. */
     812        DEBUG(1,("Unknown packet type %u in smb2 sessionsetup\n",
     813                (unsigned int)in_security_buffer.data[0] ));
     814        TALLOC_FREE(session->auth_ntlmssp_state);
     815        TALLOC_FREE(session);
     816        return NT_STATUS_LOGON_FAILURE;
    335817}
    336818
     
    338820{
    339821        const uint8_t *inhdr;
     822        const uint8_t *outhdr;
    340823        int i = req->current_idx;
    341824        uint64_t in_session_id;
    342825        void *p;
    343826        struct smbd_smb2_session *session;
     827        bool chained_fixup = false;
    344828
    345829        inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
    346830
    347831        in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
     832
     833        if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
     834                if (req->async) {
     835                        /*
     836                         * async request - fill in session_id from
     837                         * already setup request out.vector[].iov_base.
     838                         */
     839                        outhdr = (const uint8_t *)req->out.vector[i].iov_base;
     840                        in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
     841                } else if (i > 2) {
     842                        /*
     843                         * Chained request - fill in session_id from
     844                         * the previous request out.vector[].iov_base.
     845                         */
     846                        outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
     847                        in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
     848                        chained_fixup = true;
     849                }
     850        }
    348851
    349852        /* lookup an existing session */
     
    358861        }
    359862
    360         set_current_user_info(session->server_info->sanitized_username,
    361                               session->server_info->unix_name,
    362                               pdb_get_domain(session->server_info->sam_account));
     863        set_current_user_info(session->session_info->sanitized_username,
     864                              session->session_info->unix_name,
     865                              session->session_info->info3->base.domain.string);
    363866
    364867        req->session = session;
     868
     869        if (chained_fixup) {
     870                /* Fix up our own outhdr. */
     871                outhdr = (const uint8_t *)req->out.vector[i].iov_base;
     872                SBVAL(outhdr, SMB2_HDR_SESSION_ID, in_session_id);
     873        }
    365874        return NT_STATUS_OK;
    366875}
Note: See TracChangeset for help on using the changeset viewer.