From: Andreas Schneider Date: Tue, 8 Mar 2022 06:34:16 +0000 (+0100) Subject: s4:kdc: Use samba_kdc_update_pac() in mit_samba_update_pac() X-Git-Tag: tevent-0.12.0~427 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c78f5b724be429ad313adc7215cd42b2a3eddb2c;p=thirdparty%2Fsamba.git s4:kdc: Use samba_kdc_update_pac() in mit_samba_update_pac() This is for MIT Kerberos >= 1.20. Signed-off-by: Andreas Schneider Reviewed-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- diff --git a/source4/kdc/mit_samba.c b/source4/kdc/mit_samba.c index e0121585ed4..5405eb3d747 100644 --- a/source4/kdc/mit_samba.c +++ b/source4/kdc/mit_samba.c @@ -644,7 +644,7 @@ done: #else krb5_error_code mit_samba_update_pac(struct mit_samba_context *ctx, krb5_context context, - int flags, + int kdc_flags, krb5_db_entry *client, krb5_db_entry *server, krb5_db_entry *krbtgt, @@ -653,28 +653,12 @@ krb5_error_code mit_samba_update_pac(struct mit_samba_context *ctx, { TALLOC_CTX *tmp_ctx = NULL; krb5_error_code code; - NTSTATUS nt_status; - DATA_BLOB *pac_blob = NULL; - DATA_BLOB *upn_blob = NULL; - DATA_BLOB *requester_sid_blob = NULL; struct samba_kdc_entry *client_skdc_entry = NULL; struct samba_kdc_entry *server_skdc_entry = NULL; struct samba_kdc_entry *krbtgt_skdc_entry = NULL; bool is_in_db = false; bool is_untrusted = false; - bool is_krbtgt = false; - size_t num_types = 0; - uint32_t *types = NULL; - size_t i = 0; - ssize_t logon_info_idx = -1; - ssize_t delegation_idx = -1; - ssize_t logon_name_idx = -1; - ssize_t upn_dns_info_idx = -1; - ssize_t srv_checksum_idx = -1; - ssize_t kdc_checksum_idx = -1; - ssize_t tkt_checksum_idx = -1; - ssize_t attrs_info_idx = -1; - ssize_t requester_sid_idx = -1; + uint32_t flags = SAMBA_KDC_FLAG_SKIP_PAC_BUFFER; /* Create a memory context early so code can use talloc_stackframe() */ tmp_ctx = talloc_named(ctx, 0, "mit_samba_update_pac context"); @@ -686,17 +670,6 @@ krb5_error_code mit_samba_update_pac(struct mit_samba_context *ctx, client_skdc_entry = talloc_get_type_abort(client->e_data, struct samba_kdc_entry); - - /* - * Check the objectSID of the client and pac data are the same. - * Does a parse and SID check, but no crypto. - */ - code = samba_kdc_validate_pac_blob(context, - client_skdc_entry, - old_pac); - if (code != 0) { - goto done; - } } if (krbtgt == NULL) { @@ -707,6 +680,10 @@ krb5_error_code mit_samba_update_pac(struct mit_samba_context *ctx, talloc_get_type_abort(krbtgt->e_data, struct samba_kdc_entry); + server_skdc_entry = + talloc_get_type_abort(server->e_data, + struct samba_kdc_entry); + /* * If the krbtgt was generated by an RODC, and we are not that * RODC, then we need to regenerate the PAC - we can't trust @@ -724,367 +701,40 @@ krb5_error_code mit_samba_update_pac(struct mit_samba_context *ctx, } if (is_untrusted) { - struct auth_user_info_dc *user_info_dc = NULL; - WERROR werr; - - if (client == NULL) { - code = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - goto done; - } - - nt_status = samba_kdc_get_pac_blobs(tmp_ctx, - client_skdc_entry, - &pac_blob, - NULL, - &upn_blob, - NULL, - PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY, - &requester_sid_blob, - &user_info_dc); - if (!NT_STATUS_IS_OK(nt_status)) { - code = KRB5KDC_ERR_TGT_REVOKED; - goto done; - } - - /* - * Check if the SID list in the user_info_dc intersects - * correctly with the RODC allow/deny lists. - */ - werr = samba_rodc_confirm_user_is_allowed(user_info_dc->num_sids, - user_info_dc->sids, - krbtgt_skdc_entry, - client_skdc_entry); - if (!W_ERROR_IS_OK(werr)) { - code = KRB5KDC_ERR_TGT_REVOKED; - if (W_ERROR_EQUAL(werr, - WERR_DOMAIN_CONTROLLER_NOT_FOUND)) { - code = KRB5KDC_ERR_POLICY; - } - goto done; - } - } else { - pac_blob = talloc_zero(tmp_ctx, DATA_BLOB); - if (pac_blob == NULL) { - code = ENOMEM; - goto done; - } - - nt_status = samba_kdc_update_pac_blob(tmp_ctx, - context, - krbtgt_skdc_entry->kdc_db_ctx->samdb, - old_pac, - pac_blob, - NULL, - NULL); - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0, ("Update PAC blob failed: %s\n", - nt_errstr(nt_status))); - code = EINVAL; - goto done; - } - } - - /* Check the types of the given PAC */ - code = krb5_pac_get_types(context, old_pac, &num_types, &types); - if (code != 0) { - goto done; - } - - for (i = 0; i < num_types; i++) { - switch (types[i]) { - case PAC_TYPE_LOGON_INFO: - if (logon_info_idx != -1) { - DBG_WARNING("logon info type[%u] twice [%zd] and " - "[%zu]: \n", - types[i], - logon_info_idx, - i); - code = EINVAL; - goto done; - } - logon_info_idx = i; - break; - case PAC_TYPE_CONSTRAINED_DELEGATION: - if (delegation_idx != -1) { - DBG_WARNING("constrained delegation type[%u] " - "twice [%zd] and [%zu]: \n", - types[i], - delegation_idx, - i); - code = EINVAL; - goto done; - } - delegation_idx = i; - break; - case PAC_TYPE_LOGON_NAME: - if (logon_name_idx != -1) { - DBG_WARNING("logon name type[%u] twice [%zd] " - "and [%zu]: \n", - types[i], - logon_name_idx, - i); - code = EINVAL; - goto done; - } - logon_name_idx = i; - break; - case PAC_TYPE_UPN_DNS_INFO: - if (upn_dns_info_idx != -1) { - DBG_WARNING("upn dns info type[%u] twice [%zd] " - "and [%zu]: \n", - types[i], - upn_dns_info_idx, - i); - code = EINVAL; - goto done; - } - upn_dns_info_idx = i; - break; - case PAC_TYPE_SRV_CHECKSUM: - if (srv_checksum_idx != -1) { - DBG_WARNING("srv checksum type[%u] twice [%zd] " - "and [%zu]: \n", - types[i], - srv_checksum_idx, - i); - code = EINVAL; - goto done; - } - srv_checksum_idx = i; - break; - case PAC_TYPE_KDC_CHECKSUM: - if (kdc_checksum_idx != -1) { - DBG_WARNING("kdc checksum type[%u] twice [%zd] " - "and [%zu]: \n", - types[i], - kdc_checksum_idx, - i); - code = EINVAL; - goto done; - } - kdc_checksum_idx = i; - break; - case PAC_TYPE_TICKET_CHECKSUM: - if (tkt_checksum_idx != -1) { - DBG_WARNING("ticket checksum type[%u] twice " - "[%zd] and [%zu]: \n", - types[i], - tkt_checksum_idx, - i); - code = EINVAL; - goto done; - } - tkt_checksum_idx = i; - break; - case PAC_TYPE_ATTRIBUTES_INFO: - if (attrs_info_idx != -1) { - DBG_WARNING("attributes info type[%u] twice " - "[%zd] and [%zu]: \n", - types[i], - attrs_info_idx, - i); - code = EINVAL; - goto done; - } - attrs_info_idx = i; - break; - case PAC_TYPE_REQUESTER_SID: - if (requester_sid_idx != -1) { - DBG_WARNING("requester sid type[%u] twice" - "[%zd] and [%zu]: \n", - types[i], - requester_sid_idx, - i); - code = EINVAL; - goto done; - } - requester_sid_idx = i; - break; - default: - continue; - } - } - - if (logon_info_idx == -1) { - DBG_WARNING("PAC_TYPE_LOGON_INFO missing\n"); - code = EINVAL; - goto done; - } - if (logon_name_idx == -1) { - DBG_WARNING("PAC_TYPE_LOGON_NAME missing\n"); - code = EINVAL; - goto done; - } - if (srv_checksum_idx == -1) { - DBG_WARNING("PAC_TYPE_SRV_CHECKSUM missing\n"); - code = EINVAL; - goto done; - } - if (kdc_checksum_idx == -1) { - DBG_WARNING("PAC_TYPE_KDC_CHECKSUM missing\n"); - code = EINVAL; - goto done; - } - if (!(flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) && - requester_sid_idx == -1) { - DBG_WARNING("PAC_TYPE_REQUESTER_SID missing\n"); - code = KRB5KDC_ERR_TGT_REVOKED; - goto done; + flags |= SAMBA_KDC_FLAG_KRBTGT_IS_UNTRUSTED; } - server_skdc_entry = talloc_get_type_abort(server->e_data, - struct samba_kdc_entry); + if (is_in_db) { + flags |= SAMBA_KDC_FLAG_KRBTGT_IN_DB; - /* - * The server account may be set not to want the PAC. - * - * While this is wasteful if the above cacluations were done - * and now thrown away, this is cleaner as we do any ticket - * signature checking etc always. - * - * UF_NO_AUTH_DATA_REQUIRED is the rare case and most of the - * time (eg not accepting a ticket from the RODC) we do not - * need to re-generate anything anyway. - */ - if (!samba_princ_needs_pac(server_skdc_entry)) { - code = 0; - goto done; } - is_krbtgt = ks_is_tgs_principal(ctx, server->princ); - - if (!is_untrusted && !is_krbtgt) { - /* - * The client may have requested no PAC when obtaining the - * TGT. - */ - bool requested_pac = false; - - code = samba_client_requested_pac(context, - &old_pac, - tmp_ctx, - &requested_pac); - if (code != 0 || !requested_pac) { - goto done; - } + if (kdc_flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) { + flags |= SAMBA_KDC_FLAG_CONSTRAINED_DELEGATION; } -#define MAX_PAC_BUFFERS 64 /* Avoid infinite loops */ - - for (i = 0; i < MAX_PAC_BUFFERS;) { - krb5_data type_data; - DATA_BLOB type_blob = data_blob_null; - uint32_t type; - - if (i < num_types) { - type = types[i]; - i++; - } else { - break; - } - - switch (type) { - case PAC_TYPE_LOGON_INFO: - type_blob = *pac_blob; - break; - case PAC_TYPE_CREDENTIAL_INFO: - /* - * Note that we copy the credential blob, - * as it's only usable with the PKINIT based - * AS-REP reply key, it's only available on the - * host which did the AS-REQ/AS-REP exchange. - * - * This matches Windows 2008R2... - */ - break; - case PAC_TYPE_LOGON_NAME: - /* - * This is generated in the main KDC code - */ - continue; - case PAC_TYPE_UPN_DNS_INFO: - /* - * Replace in the RODC case, otherwise - * upn_blob is NULL and we just copy. - */ - if (upn_blob != NULL) { - type_blob = *upn_blob; - } - break; - case PAC_TYPE_SRV_CHECKSUM: - /* - * This is generated in the main KDC code - */ - continue; - case PAC_TYPE_KDC_CHECKSUM: - /* - * This is generated in the main KDC code - */ - continue; - case PAC_TYPE_TICKET_CHECKSUM: - /* - * This is generated in the main KDC code - */ - continue; - case PAC_TYPE_CONSTRAINED_DELEGATION: + code = samba_kdc_update_pac(tmp_ctx, + context, + krbtgt_skdc_entry->kdc_db_ctx->samdb, + flags, + client_skdc_entry, + server->princ, + server_skdc_entry, + krbtgt_skdc_entry, + NULL, + old_pac, + new_pac); + if (code != 0) { + if (code == ENODATA) { /* - * This is generated in the main KDC code + * We can't tell the KDC to not issue a PAC. It will + * just return the newly allocated empty PAC. */ - continue; - case PAC_TYPE_ATTRIBUTES_INFO: - if (!is_untrusted && is_krbtgt) { - /* just copy... */ - break; - } else { - continue; - } - case PAC_TYPE_REQUESTER_SID: - if (is_krbtgt) { - /* - * Replace in the RODC case, otherwise - * requester_sid_blob is NULL and we just copy. - */ - if (requester_sid_blob != NULL) { - type_blob = *requester_sid_blob; - } - break; - } else { - continue; - } - default: - /* just copy... */ - break; - } - - if (type_blob.length != 0) { - code = smb_krb5_copy_data_contents(&type_data, - type_blob.data, - type_blob.length); - if (code != 0) { - goto done; - } - } else { - code = krb5_pac_get_buffer(context, - old_pac, - type, - &type_data); - if (code != 0) { - goto done; - } - } - - code = krb5_pac_add_buffer(context, - new_pac, - type, - &type_data); - smb_krb5_free_data_contents(context, &type_data); - if (code != 0) { - goto done; + code = 0; } } done: - SAFE_FREE(types); talloc_free(tmp_ctx); return code; }