diff options
Diffstat (limited to 'source3/smbd/sesssetup.c')
-rw-r--r-- | source3/smbd/sesssetup.c | 545 |
1 files changed, 0 insertions, 545 deletions
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index c70ab17e3c..2c0587803d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -130,276 +130,6 @@ static NTSTATUS check_guest_password(const struct tsocket_address *remote_addres return nt_status; } - -#ifdef HAVE_KRB5 - -#if 0 -/* Experiment that failed. See "only happens with a KDC" comment below. */ -/**************************************************************************** - Cerate a clock skew error blob for a Windows client. -****************************************************************************/ - -static bool make_krb5_skew_error(DATA_BLOB *pblob_out) -{ - krb5_context context = NULL; - krb5_error_code kerr = 0; - krb5_data reply; - krb5_principal host_princ = NULL; - char *host_princ_s = NULL; - bool ret = False; - - *pblob_out = data_blob_null; - - initialize_krb5_error_table(); - kerr = krb5_init_context(&context); - if (kerr) { - return False; - } - /* Create server principal. */ - asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm()); - if (!host_princ_s) { - goto out; - } - strlower_m(host_princ_s); - - kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ); - if (kerr) { - DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed " - "for name %s: Error %s\n", - host_princ_s, error_message(kerr) )); - goto out; - } - - kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, - host_princ, &reply); - if (kerr) { - DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error " - "failed: Error %s\n", - error_message(kerr) )); - goto out; - } - - *pblob_out = data_blob(reply.data, reply.length); - kerberos_free_data_contents(context,&reply); - ret = True; - - out: - - if (host_princ_s) { - SAFE_FREE(host_princ_s); - } - if (host_princ) { - krb5_free_principal(context, host_princ); - } - krb5_free_context(context); - return ret; -} -#endif - -/**************************************************************************** - Reply to a session setup spnego negotiate packet for kerberos. -****************************************************************************/ - -static void reply_spnego_kerberos(struct smb_request *req, - DATA_BLOB *secblob, - const char *mechOID, - uint16 vuid, - bool *p_invalidate_vuid) -{ - TALLOC_CTX *mem_ctx; - DATA_BLOB ticket; - struct passwd *pw; - int sess_vuid = req->vuid; - NTSTATUS ret = NT_STATUS_OK; - DATA_BLOB ap_rep, ap_rep_wrapped, response; - struct auth_session_info *session_info = NULL; - DATA_BLOB session_key = data_blob_null; - uint8 tok_id[2]; - DATA_BLOB nullblob = data_blob_null; - bool map_domainuser_to_guest = False; - bool username_was_mapped; - struct PAC_LOGON_INFO *logon_info = NULL; - struct smbd_server_connection *sconn = req->sconn; - char *principal; - char *user; - char *domain; - char *real_username; - - ZERO_STRUCT(ticket); - ZERO_STRUCT(ap_rep); - ZERO_STRUCT(ap_rep_wrapped); - ZERO_STRUCT(response); - - /* Normally we will always invalidate the intermediate vuid. */ - *p_invalidate_vuid = True; - - mem_ctx = talloc_init("reply_spnego_kerberos"); - if (mem_ctx == NULL) { - reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY)); - return; - } - - if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) { - talloc_destroy(mem_ctx); - reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE)); - return; - } - - ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, - &principal, &logon_info, &ap_rep, - &session_key, True); - - data_blob_free(&ticket); - - if (!NT_STATUS_IS_OK(ret)) { -#if 0 - /* Experiment that failed. - * See "only happens with a KDC" comment below. */ - - if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { - - /* - * Windows in this case returns - * NT_STATUS_MORE_PROCESSING_REQUIRED - * with a negTokenTarg blob containing an krb5_error - * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW. - * The client then fixes its clock and continues rather - * than giving an error. JRA. - * -- Looks like this only happens with a KDC. JRA. - */ - - bool ok = make_krb5_skew_error(&ap_rep); - if (!ok) { - talloc_destroy(mem_ctx); - return ERROR_NT(nt_status_squash( - NT_STATUS_LOGON_FAILURE)); - } - ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, - TOK_ID_KRB_ERROR); - response = spnego_gen_auth_response(&ap_rep_wrapped, - ret, OID_KERBEROS5_OLD); - reply_sesssetup_blob(conn, inbuf, outbuf, response, - NT_STATUS_MORE_PROCESSING_REQUIRED); - - /* - * In this one case we don't invalidate the - * intermediate vuid as we're expecting the client - * to re-use it for the next sessionsetupX packet. JRA. - */ - - *p_invalidate_vuid = False; - - data_blob_free(&ap_rep); - data_blob_free(&ap_rep_wrapped); - data_blob_free(&response); - talloc_destroy(mem_ctx); - return -1; /* already replied */ - } -#else - if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { - ret = NT_STATUS_LOGON_FAILURE; - } -#endif - DEBUG(1,("Failed to verify incoming ticket with error %s!\n", - nt_errstr(ret))); - talloc_destroy(mem_ctx); - reply_nterror(req, nt_status_squash(ret)); - return; - } - - ret = get_user_from_kerberos_info(talloc_tos(), - sconn->remote_hostname, - principal, logon_info, - &username_was_mapped, - &map_domainuser_to_guest, - &user, &domain, - &real_username, &pw); - if (!NT_STATUS_IS_OK(ret)) { - data_blob_free(&ap_rep); - data_blob_free(&session_key); - talloc_destroy(mem_ctx); - reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE)); - return; - } - - /* save the PAC data if we have it */ - if (logon_info) { - netsamlogon_cache_store(user, &logon_info->info3); - } - - /* setup the string used by %U */ - sub_set_smb_name(real_username); - - /* reload services so that the new %U is taken into account */ - reload_services(sconn, conn_snum_used, true); - - ret = make_session_info_krb5(mem_ctx, - user, domain, real_username, pw, - logon_info, map_domainuser_to_guest, - username_was_mapped, - &session_key, - &session_info); - data_blob_free(&session_key); - if (!NT_STATUS_IS_OK(ret)) { - DEBUG(1, ("make_server_info_krb5 failed!\n")); - data_blob_free(&ap_rep); - TALLOC_FREE(mem_ctx); - reply_nterror(req, nt_status_squash(ret)); - return; - } - - if (!is_partial_auth_vuid(sconn, sess_vuid)) { - sess_vuid = register_initial_vuid(sconn); - } - - /* register_existing_vuid keeps the server info */ - /* register_existing_vuid takes ownership of session_key on success, - * no need to free after this on success. A better interface would copy - * it.... */ - - sess_vuid = register_existing_vuid(sconn, sess_vuid, - session_info, nullblob); - - reply_outbuf(req, 4, 0); - SSVAL(req->outbuf,smb_uid,sess_vuid); - - if (sess_vuid == UID_FIELD_INVALID ) { - ret = NT_STATUS_LOGON_FAILURE; - } else { - /* current_user_info is changed on new vuid */ - reload_services(sconn, conn_snum_used, true); - - SSVAL(req->outbuf, smb_vwv3, 0); - - if (security_session_user_level(session_info, NULL) < SECURITY_USER) { - SSVAL(req->outbuf,smb_vwv2,1); - } - - SSVAL(req->outbuf, smb_uid, sess_vuid); - - /* Successful logon. Keep this vuid. */ - *p_invalidate_vuid = False; - } - - /* wrap that up in a nice GSS-API wrapping */ - if (NT_STATUS_IS_OK(ret)) { - ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep, - TOK_ID_KRB_AP_REP); - } else { - ap_rep_wrapped = data_blob_null; - } - response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret, - mechOID); - reply_sesssetup_blob(req, response, ret); - - data_blob_free(&ap_rep); - data_blob_free(&ap_rep_wrapped); - data_blob_free(&response); - TALLOC_FREE(mem_ctx); -} - -#endif - /**************************************************************************** Send a session setup reply, wrapped in SPNEGO. Get vuid and check first. @@ -492,281 +222,6 @@ static void reply_spnego_ntlmssp(struct smb_request *req, } /**************************************************************************** - Is this a krb5 mechanism ? -****************************************************************************/ - -NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx, - DATA_BLOB blob_in, - DATA_BLOB *pblob_out, - char **kerb_mechOID) -{ - char *OIDs[ASN1_MAX_OIDS]; - int i; - NTSTATUS ret = NT_STATUS_OK; - - *kerb_mechOID = NULL; - - /* parse out the OIDs and the first sec blob */ - if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) || - (OIDs[0] == NULL)) { - return NT_STATUS_LOGON_FAILURE; - } - - /* only look at the first OID for determining the mechToken -- - according to RFC2478, we should choose the one we want - and renegotiate, but i smell a client bug here.. - - Problem observed when connecting to a member (samba box) - of an AD domain as a user in a Samba domain. Samba member - server sent back krb5/mskrb5/ntlmssp as mechtypes, but the - client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an - NTLMSSP mechtoken. --jerry */ - -#ifdef HAVE_KRB5 - if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || - strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { - *kerb_mechOID = talloc_strdup(ctx, OIDs[0]); - if (*kerb_mechOID == NULL) { - ret = NT_STATUS_NO_MEMORY; - } - } -#endif - - for (i=0;OIDs[i];i++) { - DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i])); - talloc_free(OIDs[i]); - } - return ret; -} - -/**************************************************************************** - Fall back from krb5 to NTLMSSP. -****************************************************************************/ - -static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req, - uint16 vuid) -{ - DATA_BLOB response; - - reply_outbuf(req, 4, 0); - SSVAL(req->outbuf,smb_uid,vuid); - - DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO " - "but set to downgrade to NTLMSSP\n")); - - response = spnego_gen_auth_response(talloc_tos(), NULL, - NT_STATUS_MORE_PROCESSING_REQUIRED, - OID_NTLMSSP); - reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED); - data_blob_free(&response); -} - -/**************************************************************************** - Reply to a session setup spnego negotiate packet. -****************************************************************************/ - -static void reply_spnego_negotiate(struct smb_request *req, - uint16 vuid, - DATA_BLOB blob1, - struct gensec_security **gensec_security) -{ - DATA_BLOB secblob; - DATA_BLOB chal; - char *kerb_mech = NULL; - NTSTATUS status; - struct smbd_server_connection *sconn = req->sconn; - - status = parse_spnego_mechanisms(talloc_tos(), - blob1, &secblob, &kerb_mech); - if (!NT_STATUS_IS_OK(status)) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - reply_nterror(req, nt_status_squash(status)); - return; - } - - DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", - (unsigned long)secblob.length)); - -#ifdef HAVE_KRB5 - if (kerb_mech && ((lp_security()==SEC_ADS) || - USE_KERBEROS_KEYTAB) ) { - bool destroy_vuid = True; - reply_spnego_kerberos(req, &secblob, kerb_mech, - vuid, &destroy_vuid); - data_blob_free(&secblob); - if (destroy_vuid) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - } - TALLOC_FREE(kerb_mech); - return; - } -#endif - - TALLOC_FREE(*gensec_security); - - if (kerb_mech) { - data_blob_free(&secblob); - /* The mechtoken is a krb5 ticket, but - * we need to fall back to NTLM. */ - reply_spnego_downgrade_to_ntlmssp(req, vuid); - TALLOC_FREE(kerb_mech); - return; - } - - status = auth_generic_prepare(NULL, sconn->remote_address, - gensec_security); - if (!NT_STATUS_IS_OK(status)) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - reply_nterror(req, nt_status_squash(status)); - return; - } - - gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY); - gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN); - - status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP); - if (!NT_STATUS_IS_OK(status)) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - reply_nterror(req, nt_status_squash(status)); - return; - } - - status = gensec_update(*gensec_security, talloc_tos(), - NULL, secblob, &chal); - - data_blob_free(&secblob); - - reply_spnego_ntlmssp(req, vuid, gensec_security, - &chal, status, OID_NTLMSSP, true); - - data_blob_free(&chal); - - /* already replied */ - return; -} - -/**************************************************************************** - Reply to a session setup spnego auth packet. -****************************************************************************/ - -static void reply_spnego_auth(struct smb_request *req, - uint16 vuid, - DATA_BLOB blob1, - struct gensec_security **gensec_security) -{ - DATA_BLOB auth = data_blob_null; - DATA_BLOB auth_reply = data_blob_null; - DATA_BLOB secblob = data_blob_null; - NTSTATUS status = NT_STATUS_LOGON_FAILURE; - struct smbd_server_connection *sconn = req->sconn; - - if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) { -#if 0 - file_save("auth.dat", blob1.data, blob1.length); -#endif - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - - reply_nterror(req, nt_status_squash( - NT_STATUS_LOGON_FAILURE)); - return; - } - - if (auth.data[0] == ASN1_APPLICATION(0)) { - /* Might be a second negTokenTarg packet */ - char *kerb_mech = NULL; - - status = parse_spnego_mechanisms(talloc_tos(), - auth, &secblob, &kerb_mech); - - if (!NT_STATUS_IS_OK(status)) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - reply_nterror(req, nt_status_squash(status)); - return; - } - - DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", - (unsigned long)secblob.length)); -#ifdef HAVE_KRB5 - if (kerb_mech && ((lp_security()==SEC_ADS) || - USE_KERBEROS_KEYTAB)) { - bool destroy_vuid = True; - reply_spnego_kerberos(req, &secblob, kerb_mech, - vuid, &destroy_vuid); - data_blob_free(&secblob); - data_blob_free(&auth); - if (destroy_vuid) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - } - TALLOC_FREE(kerb_mech); - return; - } -#endif - /* Can't blunder into NTLMSSP auth if we have - * a krb5 ticket. */ - - if (kerb_mech) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - DEBUG(3,("reply_spnego_auth: network " - "misconfiguration, client sent us a " - "krb5 ticket and kerberos security " - "not enabled\n")); - reply_nterror(req, nt_status_squash( - NT_STATUS_LOGON_FAILURE)); - TALLOC_FREE(kerb_mech); - } - } - - /* If we get here it wasn't a negTokenTarg auth packet. */ - data_blob_free(&secblob); - - if (!*gensec_security) { - status = auth_generic_prepare(NULL, sconn->remote_address, - gensec_security); - if (!NT_STATUS_IS_OK(status)) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - reply_nterror(req, nt_status_squash(status)); - return; - } - - gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY); - gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN); - - status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP); - if (!NT_STATUS_IS_OK(status)) { - /* Kill the intermediate vuid */ - invalidate_vuid(sconn, vuid); - reply_nterror(req, nt_status_squash(status)); - return; - } - } - - status = gensec_update(*gensec_security, talloc_tos(), - NULL, auth, &auth_reply); - - data_blob_free(&auth); - - /* Don't send the mechid as we've already sent this (RFC4178). */ - - reply_spnego_ntlmssp(req, vuid, - gensec_security, - &auth_reply, status, NULL, true); - - data_blob_free(&auth_reply); - - /* and tell smbd that we have already replied to this packet */ - return; -} - -/**************************************************************************** Reply to a session setup command. conn POINTER CAN BE NULL HERE ! ****************************************************************************/ |