From: Stefan Metzmacher Date: Wed, 19 Feb 2025 14:15:39 +0000 (+0100) Subject: s4:kdc: split out samba_kdc_get_pac() from samba_wdc_get_pac() X-Git-Tag: tevent-0.17.0~663 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b5628d0f4ac245d91dd29f05f26433e3db7087a0;p=thirdparty%2Fsamba.git s4:kdc: split out samba_kdc_get_pac() from samba_wdc_get_pac() samba_kdc_get_pac() will be re-used by mit_samba_get_pac() in the next step. Signed-off-by: Stefan Metzmacher Reviewed-by: Ralph Boehme --- diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 5c179049b38..7c9d8a918a6 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -898,6 +898,26 @@ static bool samba_kdc_entry_pac_issued_by_trust(const struct samba_kdc_entry_pac return entry.pac != NULL && samba_kdc_entry_is_trust(entry.krbtgt); } +/* + * Return true if a principal is represented. + * + * This only returns false if the following are + * all NULL pointers: + * + * struct samba_kdc_entry *entry; + * const struct samba_kdc_entry *krbtgt; + * krb5_const_pac pac; + * + * This should only for a 'device_pac_entry' if FAST was not used + * and there's no decive ticket. Or similar cases where it + * represents optional things. + */ +static bool samba_kdc_entry_pac_valid_principal( + const struct samba_kdc_entry_pac entry) +{ + return entry.pac != NULL || entry.entry != NULL || entry.krbtgt != NULL; +} + NTSTATUS samba_kdc_get_logon_info_blob(TALLOC_CTX *mem_ctx, const struct auth_user_info_dc *user_info_dc, const enum auth_group_inclusion group_inclusion, @@ -2289,6 +2309,265 @@ done: return code; } +krb5_error_code samba_kdc_get_pac(TALLOC_CTX *mem_ctx, + krb5_context context, + struct samba_kdc_db_context *kdc_db_ctx, + uint32_t flags, + struct samba_kdc_entry *client, + const krb5_const_principal server_principal, + const struct samba_kdc_entry *server, + const struct samba_kdc_entry_pac device, + const krb5_keyblock *pk_reply_key, + uint64_t pac_attributes, + krb5_pac new_pac, + struct authn_audit_info **server_audit_info_out, + NTSTATUS *status_out) +{ + TALLOC_CTX *frame = talloc_stackframe(); + DATA_BLOB *logon_blob = NULL; + DATA_BLOB *cred_ndr = NULL; + DATA_BLOB **cred_ndr_ptr = NULL; + DATA_BLOB _cred_blob = data_blob_null; + DATA_BLOB *cred_blob = NULL; + DATA_BLOB *upn_blob = NULL; + DATA_BLOB *pac_attrs_blob = NULL; + DATA_BLOB *requester_sid_blob = NULL; + DATA_BLOB client_claims_blob = {}; + krb5_error_code ret; + NTSTATUS nt_status; + bool is_krbtgt = false; + enum auth_group_inclusion group_inclusion; + bool is_s4u2self = flags & SAMBA_KDC_FLAG_PROTOCOL_TRANSITION; + enum samba_asserted_identity asserted_identity = + (is_s4u2self) ? + SAMBA_ASSERTED_IDENTITY_SERVICE : + SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY; + bool pkinit_freshness = flags & SAMBA_KDC_FLAG_PKINIT_FRESHNESS_USED; + const struct auth_user_info_dc *user_info_dc_const = NULL; + struct auth_user_info_dc *user_info_dc = NULL; + struct auth_claims auth_claims = {}; + + if (server_audit_info_out != NULL) { + *server_audit_info_out = NULL; + } + + if (status_out != NULL) { + *status_out = NT_STATUS_OK; + } + + { + int result = smb_krb5_principal_is_tgs(context, server_principal); + if (result == -1) { + TALLOC_FREE(frame); + return ENOMEM; + } + + is_krbtgt = result; + } + + /* Only include resource groups in a service ticket. */ + if (is_krbtgt) { + group_inclusion = AUTH_EXCLUDE_RESOURCE_GROUPS; + } else if (server->supported_enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED) { + group_inclusion = AUTH_INCLUDE_RESOURCE_GROUPS; + } else { + group_inclusion = AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED; + } + + if (pk_reply_key != NULL) { + cred_ndr_ptr = &cred_ndr; + } + + ret = samba_kdc_get_user_info_from_db(frame, + kdc_db_ctx, + client, + client->msg, + &user_info_dc_const); + if (ret) { + TALLOC_FREE(frame); + return ret; + } + + /* Make a shallow copy of the user_info_dc structure. */ + nt_status = authsam_shallow_copy_user_info_dc(frame, + user_info_dc_const, + &user_info_dc); + user_info_dc_const = NULL; + + if (!NT_STATUS_IS_OK(nt_status)) { + DBG_ERR("Failed to allocate user_info_dc SIDs: %s\n", + nt_errstr(nt_status)); + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + + nt_status = samba_kdc_add_asserted_identity(asserted_identity, + user_info_dc); + if (!NT_STATUS_IS_OK(nt_status)) { + DBG_ERR("Failed to add asserted identity: %s\n", + nt_errstr(nt_status)); + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + + nt_status = samba_kdc_add_claims_valid(user_info_dc); + if (!NT_STATUS_IS_OK(nt_status)) { + DBG_ERR("Failed to add Claims Valid: %s\n", + nt_errstr(nt_status)); + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + + if (pkinit_freshness) { + nt_status = samba_kdc_add_fresh_public_key_identity(user_info_dc); + if (!NT_STATUS_IS_OK(nt_status)) { + DBG_ERR("Failed to add Fresh Public Key Identity: %s\n", + nt_errstr(nt_status)); + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + } + + ret = samba_kdc_get_claims_data_from_db(kdc_db_ctx->samdb, + client, + &auth_claims.user_claims); + if (ret) { + TALLOC_FREE(frame); + return ret; + } + + nt_status = claims_data_encoded_claims_set(frame, + auth_claims.user_claims, + &client_claims_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return map_errno_from_nt_status(nt_status); + } + + /* + * For an S4U2Self request, the authentication policy is not enforced. + */ + if (!is_s4u2self && + authn_policy_restrictions_present(server->server_policy)) + { + const struct auth_user_info_dc *device_info_dc = NULL; + + if (samba_kdc_entry_pac_valid_principal(device)) { + ret = samba_kdc_get_user_info_dc(frame, + context, + kdc_db_ctx, + device, + &device_info_dc, + NULL /* resource_groups_out */); + if (ret) { + TALLOC_FREE(frame); + return ret; + } + + ret = samba_kdc_get_claims_data(frame, + context, + kdc_db_ctx, + device, + &auth_claims.device_claims); + if (ret) { + TALLOC_FREE(frame); + return ret; + } + } + + /* + * Allocate the audit info and output status on to the parent + * mem_ctx, not the temporary context. + */ + ret = samba_kdc_allowed_to_authenticate_to(mem_ctx, + kdc_db_ctx, + client, + user_info_dc, + device_info_dc, + auth_claims, + server, + server_audit_info_out, + status_out); + if (ret) { + TALLOC_FREE(frame); + return ret; + } + } + + nt_status = samba_kdc_get_logon_info_blob(frame, + user_info_dc, + group_inclusion, + &logon_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + + if (cred_ndr_ptr != NULL) { + nt_status = samba_kdc_get_cred_ndr_blob(frame, + client, + cred_ndr_ptr); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + } + + nt_status = samba_kdc_get_upn_info_blob(frame, + user_info_dc, + &upn_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + + if (is_krbtgt) { + nt_status = samba_kdc_get_pac_attrs_blob(frame, + pac_attributes, + &pac_attrs_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + + nt_status = samba_kdc_get_requester_sid_blob(frame, + user_info_dc, + &requester_sid_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + TALLOC_FREE(frame); + return map_errno_from_nt_status(nt_status); + } + } + + if (pk_reply_key != NULL && cred_ndr != NULL) { + ret = samba_kdc_encrypt_pac_credentials(context, + pk_reply_key, + cred_ndr, + frame, + &_cred_blob); + if (ret != 0) { + TALLOC_FREE(frame); + return ret; + } + cred_blob = &_cred_blob; + } + + ret = samba_make_krb5_pac(context, + logon_blob, + cred_blob, + upn_blob, + pac_attrs_blob, + requester_sid_blob, + NULL, /* deleg_blob */ + &client_claims_blob, + NULL, /* device_info_blob */ + NULL, /* device_claims_blob */ + new_pac); + + TALLOC_FREE(frame); + return ret; +} + /** * @brief Update a PAC * diff --git a/source4/kdc/pac-glue.h b/source4/kdc/pac-glue.h index 974801df0e3..fe7c3440274 100644 --- a/source4/kdc/pac-glue.h +++ b/source4/kdc/pac-glue.h @@ -43,6 +43,7 @@ enum samba_asserted_identity { enum { SAMBA_KDC_FLAG_PROTOCOL_TRANSITION = 0x00000001, SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION = 0x00000002, + SAMBA_KDC_FLAG_PKINIT_FRESHNESS_USED = 0x00000004, }; bool samba_kdc_entry_is_trust(const struct samba_kdc_entry *entry); @@ -126,6 +127,19 @@ krb5_error_code samba_kdc_verify_pac(TALLOC_CTX *mem_ctx, const struct samba_kdc_entry *krbtgt); struct authn_audit_info; +krb5_error_code samba_kdc_get_pac(TALLOC_CTX *mem_ctx, + krb5_context context, + struct samba_kdc_db_context *kdc_db_ctx, + uint32_t flags, + struct samba_kdc_entry *client, + const krb5_const_principal server_principal, + const struct samba_kdc_entry *server, + const struct samba_kdc_entry_pac device, + const krb5_keyblock *pk_reply_key, + uint64_t pac_attributes, + krb5_pac new_pac, + struct authn_audit_info **server_audit_info_out, + NTSTATUS *status_out); krb5_error_code samba_kdc_update_pac(TALLOC_CTX *mem_ctx, krb5_context context, struct samba_kdc_db_context *kdc_db_ctx, diff --git a/source4/kdc/wdc-samba4.c b/source4/kdc/wdc-samba4.c index b49b2d641f5..685d25b88b9 100644 --- a/source4/kdc/wdc-samba4.c +++ b/source4/kdc/wdc-samba4.c @@ -76,271 +76,99 @@ static krb5_error_code samba_wdc_get_pac(void *priv, { krb5_context context = kdc_request_get_context((kdc_request_t)r); TALLOC_CTX *mem_ctx; - DATA_BLOB *logon_blob = NULL; - DATA_BLOB *cred_ndr = NULL; - DATA_BLOB **cred_ndr_ptr = NULL; - DATA_BLOB _cred_blob = data_blob_null; - DATA_BLOB *cred_blob = NULL; - DATA_BLOB *upn_blob = NULL; - DATA_BLOB *pac_attrs_blob = NULL; - DATA_BLOB *requester_sid_blob = NULL; - DATA_BLOB client_claims_blob = {}; krb5_error_code ret; - NTSTATUS nt_status; - struct samba_kdc_entry *skdc_entry = + struct samba_kdc_entry *client_entry = talloc_get_type_abort(client->context, struct samba_kdc_entry); const struct samba_kdc_entry *server_entry = talloc_get_type_abort(server->context, struct samba_kdc_entry); - bool is_krbtgt = krb5_principal_is_krbtgt(context, server->principal); - enum auth_group_inclusion group_inclusion; + const hdb_entry *device = kdc_request_get_armor_client(r); + struct samba_kdc_entry_pac device_pac_entry = {}; bool is_s4u2self = samba_wdc_is_s4u2self_req(r); - enum samba_asserted_identity asserted_identity = - (is_s4u2self) ? - SAMBA_ASSERTED_IDENTITY_SERVICE : - SAMBA_ASSERTED_IDENTITY_AUTHENTICATION_AUTHORITY; + uint32_t flags = 0; struct authn_audit_info *server_audit_info = NULL; NTSTATUS reply_status = NT_STATUS_OK; - const struct auth_user_info_dc *user_info_dc_const = NULL; - struct auth_user_info_dc *user_info_dc_shallow_copy = NULL; - struct auth_claims auth_claims = {}; - - /* Only include resource groups in a service ticket. */ - if (is_krbtgt) { - group_inclusion = AUTH_EXCLUDE_RESOURCE_GROUPS; - } else if (server_entry->supported_enctypes & KERB_ENCTYPE_RESOURCE_SID_COMPRESSION_DISABLED) { - group_inclusion = AUTH_INCLUDE_RESOURCE_GROUPS; - } else { - group_inclusion = AUTH_INCLUDE_RESOURCE_GROUPS_COMPRESSED; - } - - mem_ctx = talloc_named(client->context, 0, "samba_wdc_get_pac context"); - if (!mem_ctx) { - return ENOMEM; - } - - if (pk_reply_key != NULL) { - cred_ndr_ptr = &cred_ndr; - } - - ret = samba_kdc_get_user_info_from_db(mem_ctx, - server_entry->kdc_db_ctx, - skdc_entry, - skdc_entry->msg, - &user_info_dc_const); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - - /* Make a shallow copy of the user_info_dc structure. */ - nt_status = authsam_shallow_copy_user_info_dc(mem_ctx, - user_info_dc_const, - &user_info_dc_shallow_copy); - user_info_dc_const = NULL; - - if (!NT_STATUS_IS_OK(nt_status)) { - DBG_ERR("Failed to allocate user_info_dc SIDs: %s\n", - nt_errstr(nt_status)); - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); - } - - nt_status = samba_kdc_add_asserted_identity(asserted_identity, - user_info_dc_shallow_copy); - if (!NT_STATUS_IS_OK(nt_status)) { - DBG_ERR("Failed to add asserted identity: %s\n", - nt_errstr(nt_status)); - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); + if (pac == NULL) { + return EINVAL; } - nt_status = samba_kdc_add_claims_valid(user_info_dc_shallow_copy); - if (!NT_STATUS_IS_OK(nt_status)) { - DBG_ERR("Failed to add Claims Valid: %s\n", - nt_errstr(nt_status)); - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); + if (is_s4u2self) { + flags |= SAMBA_KDC_FLAG_PROTOCOL_TRANSITION; } if (kdc_request_get_pkinit_freshness_used(r)) { - nt_status = samba_kdc_add_fresh_public_key_identity(user_info_dc_shallow_copy); - if (!NT_STATUS_IS_OK(nt_status)) { - DBG_ERR("Failed to add Fresh Public Key Identity: %s\n", - nt_errstr(nt_status)); - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); - } + flags |= SAMBA_KDC_FLAG_PKINIT_FRESHNESS_USED; } - ret = samba_kdc_get_claims_data_from_db(server_entry->kdc_db_ctx->samdb, - skdc_entry, - &auth_claims.user_claims); - if (ret) { - talloc_free(mem_ctx); - return ret; + mem_ctx = talloc_named(client->context, 0, "samba_wdc_get_pac context"); + if (!mem_ctx) { + return ENOMEM; } - nt_status = claims_data_encoded_claims_set(mem_ctx, - auth_claims.user_claims, - &client_claims_blob); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); - } + if (device != NULL) { + const hdb_entry *device_krbtgt = NULL; + struct samba_kdc_entry *device_skdc_entry = NULL; + const struct samba_kdc_entry *device_krbtgt_skdc_entry = NULL; + const krb5_const_pac device_pac = kdc_request_get_armor_pac(r); - /* - * For an S4U2Self request, the authentication policy is not enforced. - */ - if (!is_s4u2self && authn_policy_restrictions_present(server_entry->server_policy)) { - const hdb_entry *device = kdc_request_get_armor_client(r); - const struct auth_user_info_dc *device_info = NULL; - - if (device != NULL) { - const hdb_entry *device_krbtgt = NULL; - struct samba_kdc_entry *device_skdc_entry = NULL; - const struct samba_kdc_entry *device_krbtgt_skdc_entry = NULL; - const krb5_const_pac device_pac = kdc_request_get_armor_pac(r); - struct samba_kdc_entry_pac device_pac_entry = {}; - - device_skdc_entry = talloc_get_type_abort(device->context, - struct samba_kdc_entry); - - device_krbtgt = kdc_request_get_armor_server(r); - if (device_krbtgt != NULL) { - device_krbtgt_skdc_entry = talloc_get_type_abort(device_krbtgt->context, - struct samba_kdc_entry); - } - - device_pac_entry = samba_kdc_entry_pac(device_pac, - device_skdc_entry, - device_krbtgt_skdc_entry); - - ret = samba_kdc_get_user_info_dc(mem_ctx, - context, - server_entry->kdc_db_ctx, - device_pac_entry, - &device_info, - NULL /* resource_groups_out */); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - - ret = samba_kdc_get_claims_data(mem_ctx, - context, - server_entry->kdc_db_ctx, - device_pac_entry, - &auth_claims.device_claims); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - } + device_skdc_entry = talloc_get_type_abort(device->context, + struct samba_kdc_entry); - ret = samba_kdc_allowed_to_authenticate_to(mem_ctx, - server_entry->kdc_db_ctx, - skdc_entry, - user_info_dc_shallow_copy, - device_info, - auth_claims, - server_entry, - &server_audit_info, - &reply_status); - if (server_audit_info != NULL) { - krb5_error_code ret2; - - ret2 = hdb_samba4_set_steal_server_audit_info(r, server_audit_info); - if (ret == 0) { - ret = ret2; - } + device_krbtgt = kdc_request_get_armor_server(r); + if (device_krbtgt != NULL) { + device_krbtgt_skdc_entry = talloc_get_type_abort(device_krbtgt->context, + struct samba_kdc_entry); } - if (!NT_STATUS_IS_OK(reply_status)) { - krb5_error_code ret2; - ret2 = hdb_samba4_set_ntstatus(r, reply_status, ret); - if (ret == 0) { - ret = ret2; - } - } - if (ret) { - talloc_free(mem_ctx); - return ret; - } - } - - nt_status = samba_kdc_get_logon_info_blob(mem_ctx, - user_info_dc_shallow_copy, - group_inclusion, - &logon_blob); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); + device_pac_entry = samba_kdc_entry_pac(device_pac, + device_skdc_entry, + device_krbtgt_skdc_entry); } - if (cred_ndr_ptr != NULL) { - nt_status = samba_kdc_get_cred_ndr_blob(mem_ctx, - skdc_entry, - cred_ndr_ptr); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); - } - } - - nt_status = samba_kdc_get_upn_info_blob(mem_ctx, - user_info_dc_shallow_copy, - &upn_blob); - if (!NT_STATUS_IS_OK(nt_status)) { + ret = krb5_pac_init(context, pac); + if (ret != 0) { talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); + return ret; } - if (is_krbtgt) { - nt_status = samba_kdc_get_pac_attrs_blob(mem_ctx, - pac_attributes, - &pac_attrs_blob); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); - } + ret = samba_kdc_get_pac(mem_ctx, + context, + server_entry->kdc_db_ctx, + flags, + client_entry, + server->principal, + server_entry, + device_pac_entry, + pk_reply_key, + pac_attributes, + *pac, + &server_audit_info, + &reply_status); + if (server_audit_info != NULL) { + krb5_error_code ret2; - nt_status = samba_kdc_get_requester_sid_blob(mem_ctx, - user_info_dc_shallow_copy, - &requester_sid_blob); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(mem_ctx); - return map_errno_from_nt_status(nt_status); + ret2 = hdb_samba4_set_steal_server_audit_info(r, server_audit_info); + if (ret == 0) { + ret = ret2; } } + if (!NT_STATUS_IS_OK(reply_status)) { + krb5_error_code ret2; - if (pk_reply_key != NULL && cred_ndr != NULL) { - ret = samba_kdc_encrypt_pac_credentials(context, - pk_reply_key, - cred_ndr, - mem_ctx, - &_cred_blob); - if (ret != 0) { - talloc_free(mem_ctx); - return ret; + ret2 = hdb_samba4_set_ntstatus(r, reply_status, ret); + if (ret == 0) { + ret = ret2; } - cred_blob = &_cred_blob; } - - ret = krb5_pac_init(context, pac); - if (ret != 0) { + if (ret) { + krb5_pac_free(context, *pac); + *pac = NULL; talloc_free(mem_ctx); return ret; } - ret = samba_make_krb5_pac(context, logon_blob, cred_blob, - upn_blob, pac_attrs_blob, - requester_sid_blob, NULL, - &client_claims_blob, NULL, NULL, - *pac); - talloc_free(mem_ctx); return ret; }