From c10c49b3f00f7da2319d59b707a8c9d2acefc172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Filipensk=C3=BD?= Date: Mon, 12 Feb 2024 12:19:14 +0100 Subject: [PATCH] s3:libads: Remove ads_keytab_create_default & friends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG: https://bugzilla.samba.org/show_bug.cgi?id=6750 Signed-off-by: Pavel Filipenský Reviewed-by: Stefan Metzmacher --- lib/krb5_wrap/krb5_samba.c | 110 ----- lib/krb5_wrap/krb5_samba.h | 7 - source3/libads/ads_proto.h | 13 - source3/libads/kerberos_keytab.c | 780 ------------------------------- source3/libads/ldap.c | 234 ---------- 5 files changed, 1144 deletions(-) diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index e9e144be4e0..451616c79e5 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -1936,116 +1936,6 @@ out: return ret; } -/** - * @brief Add a keytab entry for the given principal - * - * @param[in] context The krb5 context to use. - * - * @param[in] keytab The keytab to add the entry to. - * - * @param[in] kvno The kvno to use. - * - * @param[in] princ_s The principal as a string. - * - * @param[in] salt_principal The salt principal to salt the password with. - * Only needed for keys which support salting. - * If no salt is used set no_salt to false and - * pass NULL here. - * - * @param[in] enctype The encryption type of the keytab entry. - * - * @param[in] password The password of the keytab entry. - * - * @retval 0 on Success - * - * @return A corresponding KRB5 error code. - * - * @see smb_krb5_kt_open() - */ -krb5_error_code smb_krb5_kt_add_password(krb5_context context, - krb5_keytab keytab, - krb5_kvno kvno, - const char *princ_s, - const char *salt_principal, - krb5_enctype enctype, - krb5_data *password) -{ - krb5_error_code ret; - krb5_keytab_entry kt_entry; - krb5_principal princ = NULL; - krb5_keyblock *keyp; - krb5_principal salt_princ = NULL; - - ZERO_STRUCT(kt_entry); - - ret = smb_krb5_parse_name(context, princ_s, &princ); - if (ret) { - DEBUG(1, (__location__ ": smb_krb5_parse_name(%s) " - "failed (%s)\n", princ_s, error_message(ret))); - goto out; - } - - /* Seek and delete old keytab entries */ - ret = smb_krb5_kt_seek_and_delete_old_entries(context, - keytab, - true, /* keep_old_kvno */ - kvno, - true, /* enctype_only */ - enctype, - princ_s, - princ, - false); /* flush */ - if (ret) { - goto out; - } - - /* If we get here, we have deleted all the old entries with kvno's - * not equal to the current kvno-1. */ - - keyp = KRB5_KT_KEY(&kt_entry); - - /* Now add keytab entries for all encryption types */ - ret = smb_krb5_parse_name(context, salt_principal, &salt_princ); - if (ret) { - DBG_WARNING("krb5_parse_name(%s) failed (%s)\n", - salt_principal, error_message(ret)); - goto out; - } - - ret = smb_krb5_create_key_from_string(context, - salt_princ, - NULL, - password, - enctype, - keyp); - krb5_free_principal(context, salt_princ); - if (ret != 0) { - goto out; - } - - kt_entry.principal = princ; - kt_entry.vno = kvno; - - DEBUG(3, (__location__ ": adding keytab entry for (%s) with " - "encryption type (%d) and version (%d)\n", - princ_s, enctype, kt_entry.vno)); - ret = samba_krb5_kt_add_entry(context, keytab, &kt_entry); - krb5_free_keyblock_contents(context, keyp); - ZERO_STRUCT(kt_entry); - if (ret) { - DEBUG(1, (__location__ ": adding entry to keytab " - "failed (%s)\n", error_message(ret))); - goto out; - } - -out: - if (princ) { - krb5_free_principal(context, princ); - } - - return ret; -} - #if defined(HAVE_KRB5_GET_CREDS_OPT_SET_IMPERSONATE) && \ defined(HAVE_KRB5_GET_CREDS_OPT_ALLOC) && \ defined(HAVE_KRB5_GET_CREDS) diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h index d7ab06c951f..0acf567371c 100644 --- a/lib/krb5_wrap/krb5_samba.h +++ b/lib/krb5_wrap/krb5_samba.h @@ -392,13 +392,6 @@ krb5_error_code smb_krb5_kt_seek_and_delete_old_entries(krb5_context context, const char *princ_s, krb5_principal princ, bool flush); -krb5_error_code smb_krb5_kt_add_password(krb5_context context, - krb5_keytab keytab, - krb5_kvno kvno, - const char *princ_s, - const char *salt_principal, - krb5_enctype enctype, - krb5_data *password); krb5_error_code smb_krb5_get_credentials(krb5_context context, krb5_ccache ccache, diff --git a/source3/libads/ads_proto.h b/source3/libads/ads_proto.h index edfa53237da..8440c35e46d 100644 --- a/source3/libads/ads_proto.h +++ b/source3/libads/ads_proto.h @@ -62,11 +62,7 @@ void ads_disp_sd(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct security_descripto /* The following definitions come from libads/kerberos_keytab.c */ -int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, - bool update_ads); -int ads_keytab_delete_entry(ADS_STRUCT *ads, const char *srvPrinc); int ads_keytab_flush(ADS_STRUCT *ads); -int ads_keytab_create_default(ADS_STRUCT *ads); int ads_keytab_list(const char *keytab_name); /* The following definitions come from libads/net_ads_setspn.c */ @@ -107,8 +103,6 @@ char *ads_ou_string(ADS_STRUCT *ads, const char *org_unit); char *ads_default_ou_string(ADS_STRUCT *ads, const char *wknguid); ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, const char *name, const char **vals); -uint32_t ads_get_kvno(ADS_STRUCT *ads, const char *account_name); -uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name); bool ads_element_in_array(const char **el_array, size_t num_el, const char *el); @@ -144,14 +138,7 @@ ADS_STATUS ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx, const char *extended_dn, enum ads_extended_dn_flags flags, struct dom_sid *sid); -char* ads_get_dnshostname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name ); -ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx, - ADS_STRUCT *ads, - const char *machine_name, - char ***hostnames_array, - size_t *num_hostnames); char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name ); -bool ads_has_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name ); ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name, uint32_t account_type, const char *org_unit); ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname); diff --git a/source3/libads/kerberos_keytab.c b/source3/libads/kerberos_keytab.c index 6dd8db72fa4..c482031be93 100644 --- a/source3/libads/kerberos_keytab.c +++ b/source3/libads/kerberos_keytab.c @@ -1000,514 +1000,6 @@ out: return ret; } -static bool fill_default_spns(TALLOC_CTX *ctx, const char *machine_name, - const char *my_fqdn, const char *spn, - const char ***spns) -{ - char *psp1, *psp2; - - if (*spns == NULL) { - *spns = talloc_zero_array(ctx, const char*, 3); - if (*spns == NULL) { - return false; - } - } - - psp1 = talloc_asprintf(ctx, - "%s/%s", - spn, - machine_name); - if (psp1 == NULL) { - return false; - } - - if (!strlower_m(&psp1[strlen(spn) + 1])) { - return false; - } - (*spns)[0] = psp1; - - psp2 = talloc_asprintf(ctx, - "%s/%s", - spn, - my_fqdn); - if (psp2 == NULL) { - return false; - } - - if (!strlower_m(&psp2[strlen(spn) + 1])) { - return false; - } - - (*spns)[1] = psp2; - - return true; -} - -static bool ads_set_machine_account_spns(TALLOC_CTX *ctx, - ADS_STRUCT *ads, - const char *service_or_spn, - const char *my_fqdn) -{ - const char **spn_names = NULL; - ADS_STATUS aderr; - struct spn_struct* spn_struct = NULL; - char *tmp = NULL; - - /* SPN should have '/' */ - tmp = strchr_m(service_or_spn, '/'); - if (tmp != NULL) { - spn_struct = parse_spn(ctx, service_or_spn); - if (spn_struct == NULL) { - return false; - } - } - - DBG_INFO("Attempting to add/update '%s'\n", service_or_spn); - - if (spn_struct != NULL) { - spn_names = talloc_zero_array(ctx, const char*, 2); - spn_names[0] = service_or_spn; - } else { - bool ok; - - ok = fill_default_spns(ctx, - lp_netbios_name(), - my_fqdn, - service_or_spn, - &spn_names); - if (!ok) { - return false; - } - } - aderr = ads_add_service_principal_names(ads, - lp_netbios_name(), - spn_names); - if (!ADS_ERR_OK(aderr)) { - DBG_WARNING("Failed to add service principal name.\n"); - return false; - } - - return true; -} - -/* - * Create kerberos principal(s) from SPN or service name. - */ -static bool service_or_spn_to_kerberos_princ(TALLOC_CTX *ctx, - const char *service_or_spn, - const char *my_fqdn, - char **p_princ_s, - char **p_short_princ_s) -{ - char *princ_s = NULL; - char *short_princ_s = NULL; - const char *service = service_or_spn; - const char *host = my_fqdn; - struct spn_struct* spn_struct = NULL; - char *tmp = NULL; - bool ok = true; - - /* SPN should have '/' */ - tmp = strchr_m(service_or_spn, '/'); - if (tmp != NULL) { - spn_struct = parse_spn(ctx, service_or_spn); - if (spn_struct == NULL) { - ok = false; - goto out; - } - } - if (spn_struct != NULL) { - service = spn_struct->serviceclass; - host = spn_struct->host; - } - princ_s = talloc_asprintf(ctx, "%s/%s@%s", - service, - host, lp_realm()); - if (princ_s == NULL) { - ok = false; - goto out; - } - - if (spn_struct == NULL) { - short_princ_s = talloc_asprintf(ctx, "%s/%s@%s", - service, lp_netbios_name(), - lp_realm()); - if (short_princ_s == NULL) { - ok = false; - goto out; - } - } - *p_princ_s = princ_s; - *p_short_princ_s = short_princ_s; -out: - return ok; -} - -static int add_kt_entry_etypes(krb5_context context, TALLOC_CTX *tmpctx, - ADS_STRUCT *ads, const char *salt_princ_s, - krb5_keytab keytab, krb5_kvno kvno, - const char *srvPrinc, const char *my_fqdn, - krb5_data *password, bool update_ads) -{ - krb5_error_code ret = 0; - char *princ_s = NULL; - char *short_princ_s = NULL; - krb5_enctype enctypes[4] = { - ENCTYPE_AES256_CTS_HMAC_SHA1_96, - ENCTYPE_AES128_CTS_HMAC_SHA1_96, - ENCTYPE_ARCFOUR_HMAC, - 0 - }; - size_t i; - - /* Construct our principal */ - if (strchr_m(srvPrinc, '@')) { - /* It's a fully-named principal. */ - princ_s = talloc_asprintf(tmpctx, "%s", srvPrinc); - if (!princ_s) { - ret = -1; - goto out; - } - } else if (srvPrinc[strlen(srvPrinc)-1] == '$') { - /* It's the machine account, as used by smbclient clients. */ - princ_s = talloc_asprintf(tmpctx, "%s@%s", - srvPrinc, lp_realm()); - if (!princ_s) { - ret = -1; - goto out; - } - } else { - /* It's a normal service principal. Add the SPN now so that we - * can obtain credentials for it and double-check the salt value - * used to generate the service's keys. */ - - if (!service_or_spn_to_kerberos_princ(tmpctx, - srvPrinc, - my_fqdn, - &princ_s, - &short_princ_s)) { - ret = -1; - goto out; - } - - /* According to http://support.microsoft.com/kb/326985/en-us, - certain principal names are automatically mapped to the - host/... principal in the AD account. - So only create these in the keytab, not in AD. --jerry */ - - if (update_ads && !strequal(srvPrinc, "cifs") && - !strequal(srvPrinc, "host")) { - if (!ads_set_machine_account_spns(tmpctx, - ads, - srvPrinc, - my_fqdn)) { - ret = -1; - goto out; - } - } - } - - for (i = 0; enctypes[i]; i++) { - - /* add the fqdn principal to the keytab */ - ret = smb_krb5_kt_add_password(context, - keytab, - kvno, - princ_s, - salt_princ_s, - enctypes[i], - password); - if (ret) { - DBG_WARNING("Failed to add entry to keytab\n"); - goto out; - } - - /* add the short principal name if we have one */ - if (short_princ_s) { - ret = smb_krb5_kt_add_password(context, - keytab, - kvno, - short_princ_s, - salt_princ_s, - enctypes[i], - password); - if (ret) { - DBG_WARNING("Failed to add short entry to keytab\n"); - goto out; - } - } - } -out: - return ret; -} - -/********************************************************************** - Adds a single service principal, i.e. 'host' to the system keytab -***********************************************************************/ - -int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc, bool update_ads) -{ - krb5_error_code ret = 0; - krb5_context context = NULL; - krb5_keytab keytab = NULL; - krb5_data password; - krb5_kvno kvno; - char *salt_princ_s = NULL; - char *password_s = NULL; - char *my_fqdn; - TALLOC_CTX *tmpctx = NULL; - char **hostnames_array = NULL; - size_t num_hostnames = 0; - - ret = smb_krb5_init_context_common(&context); - if (ret) { - DBG_ERR("kerberos init context failed (%s)\n", - error_message(ret)); - return -1; - } - - ret = ads_keytab_open(context, &keytab); - if (ret != 0) { - goto out; - } - - /* retrieve the password */ - if (!secrets_init()) { - DBG_WARNING("secrets_init failed\n"); - ret = -1; - goto out; - } - password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); - if (!password_s) { - DBG_WARNING("failed to fetch machine password\n"); - ret = -1; - goto out; - } - ZERO_STRUCT(password); - password.data = password_s; - password.length = strlen(password_s); - - /* we need the dNSHostName value here */ - tmpctx = talloc_init(__location__); - if (!tmpctx) { - DBG_ERR("talloc_init() failed!\n"); - ret = -1; - goto out; - } - - my_fqdn = ads_get_dnshostname(ads, tmpctx, lp_netbios_name()); - if (!my_fqdn) { - DBG_ERR("unable to determine machine account's dns name in " - "AD!\n"); - ret = -1; - goto out; - } - - /* make sure we have a single instance of the computer account */ - if (!ads_has_samaccountname(ads, tmpctx, lp_netbios_name())) { - DBG_ERR("unable to determine machine account's short name in " - "AD!\n"); - ret = -1; - goto out; - } - - kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name()); - if (kvno == -1) { - /* -1 indicates failure, everything else is OK */ - DBG_WARNING("ads_get_machine_kvno failed to determine the " - "system's kvno.\n"); - ret = -1; - goto out; - } - - salt_princ_s = kerberos_secrets_fetch_salt_princ(); - if (salt_princ_s == NULL) { - DBG_WARNING("kerberos_secrets_fetch_salt_princ() failed\n"); - ret = -1; - goto out; - } - - ret = add_kt_entry_etypes(context, tmpctx, ads, salt_princ_s, keytab, - kvno, srvPrinc, my_fqdn, &password, - update_ads); - if (ret != 0) { - goto out; - } - - if (ADS_ERR_OK(ads_get_additional_dns_hostnames(tmpctx, ads, - lp_netbios_name(), - &hostnames_array, - &num_hostnames))) { - size_t i; - - for (i = 0; i < num_hostnames; i++) { - - ret = add_kt_entry_etypes(context, tmpctx, ads, - salt_princ_s, keytab, - kvno, srvPrinc, - hostnames_array[i], - &password, update_ads); - if (ret != 0) { - goto out; - } - } - } - -out: - SAFE_FREE(salt_princ_s); - TALLOC_FREE(tmpctx); - - if (keytab) { - krb5_kt_close(context, keytab); - } - if (context) { - krb5_free_context(context); - } - return (int)ret; -} - -/********************************************************************** - Delete a single service principal, i.e. 'host' from the system keytab -***********************************************************************/ - -int ads_keytab_delete_entry(ADS_STRUCT *ads, const char *srvPrinc) -{ - TALLOC_CTX *frame = talloc_stackframe(); - krb5_error_code ret = 0; - krb5_context context = NULL; - krb5_keytab keytab = NULL; - char *princ_s = NULL; - krb5_principal princ = NULL; - char *short_princ_s = NULL; - krb5_principal short_princ = NULL; - bool ok; - - ret = smb_krb5_init_context_common(&context); - if (ret) { - DBG_ERR("kerberos init context failed (%s)\n", - error_message(ret)); - goto out; - } - - ret = ads_keytab_open(context, &keytab); - if (ret != 0) { - goto out; - } - - /* Construct our principal */ - if (strchr_m(srvPrinc, '@')) { - /* It's a fully-named principal. */ - princ_s = talloc_asprintf(frame, "%s", srvPrinc); - if (!princ_s) { - ret = -1; - goto out; - } - } else if (srvPrinc[strlen(srvPrinc)-1] == '$') { - /* It's the machine account, as used by smbclient clients. */ - princ_s = talloc_asprintf(frame, "%s@%s", - srvPrinc, lp_realm()); - if (!princ_s) { - ret = -1; - goto out; - } - } else { - /* - * It's a normal service principal. - */ - char *my_fqdn = NULL; - char *tmp = NULL; - - /* - * SPN should have '/' otherwise we - * need to fallback and find our dnshostname - */ - tmp = strchr_m(srvPrinc, '/'); - if (tmp == NULL) { - my_fqdn = ads_get_dnshostname(ads, frame, lp_netbios_name()); - if (!my_fqdn) { - DBG_ERR("unable to determine machine account's dns name in " - "AD!\n"); - ret = -1; - goto out; - } - } - - ok = service_or_spn_to_kerberos_princ(frame, - srvPrinc, - my_fqdn, - &princ_s, - &short_princ_s); - if (!ok) { - ret = -1; - goto out; - } - } - - ret = smb_krb5_parse_name(context, princ_s, &princ); - if (ret) { - DEBUG(1, (__location__ ": smb_krb5_parse_name(%s) " - "failed (%s)\n", princ_s, error_message(ret))); - goto out; - } - - if (short_princ_s != NULL) { - ret = smb_krb5_parse_name(context, short_princ_s, &short_princ); - if (ret) { - DEBUG(1, (__location__ ": smb_krb5_parse_name(%s) " - "failed (%s)\n", short_princ_s, error_message(ret))); - goto out; - } - } - - /* Seek and delete old keytab entries */ - ret = smb_krb5_kt_seek_and_delete_old_entries(context, - keytab, - false, /* keep_old_kvno */ - -1, - false, /* enctype_only */ - ENCTYPE_NULL, - princ_s, - princ, - false); /* flush */ - if (ret) { - goto out; - } - - if (short_princ_s == NULL) { - goto out; - } - - /* Seek and delete old keytab entries */ - ret = smb_krb5_kt_seek_and_delete_old_entries(context, - keytab, - false, /* keep_old_kvno */ - -1, - false, /* enctype_only */ - ENCTYPE_NULL, - short_princ_s, - short_princ, - false); /* flush */ - if (ret) { - goto out; - } - -out: - if (princ) { - krb5_free_principal(context, princ); - } - if (short_princ) { - krb5_free_principal(context, short_princ); - } - if (keytab) { - krb5_kt_close(context, keytab); - } - if (context) { - krb5_free_context(context); - } - TALLOC_FREE(frame); - return ret; -} - /********************************************************************** Flushes all entries from the system keytab. ***********************************************************************/ @@ -1563,278 +1055,6 @@ out: return ret; } -/********************************************************************** - Adds all the required service principals to the system keytab. -***********************************************************************/ - -int ads_keytab_create_default(ADS_STRUCT *ads) -{ - krb5_error_code ret = 0; - krb5_context context = NULL; - krb5_keytab keytab = NULL; - krb5_kt_cursor cursor = {0}; - krb5_keytab_entry kt_entry = {0}; - krb5_kvno kvno; - size_t found = 0; - char *sam_account_name, *upn; - char **oldEntries = NULL, *princ_s[26]; - TALLOC_CTX *frame; - char *machine_name; - char **spn_array; - size_t num_spns; - size_t i; - bool ok = false; - ADS_STATUS status; - - ZERO_STRUCT(kt_entry); - ZERO_STRUCT(cursor); - - frame = talloc_stackframe(); - if (frame == NULL) { - ret = -1; - goto done; - } - - status = ads_get_service_principal_names(frame, - ads, - lp_netbios_name(), - &spn_array, - &num_spns); - if (!ADS_ERR_OK(status)) { - ret = -1; - goto done; - } - - for (i = 0; i < num_spns; i++) { - char *srv_princ; - char *p; - - srv_princ = strlower_talloc(frame, spn_array[i]); - if (srv_princ == NULL) { - ret = -1; - goto done; - } - - p = strchr_m(srv_princ, '/'); - if (p == NULL) { - continue; - } - p[0] = '\0'; - - /* Add the SPNs found on the DC */ - ret = ads_keytab_add_entry(ads, srv_princ, false); - if (ret != 0) { - DEBUG(1, ("ads_keytab_add_entry failed while " - "adding '%s' principal.\n", - spn_array[i])); - goto done; - } - } - -#if 0 /* don't create the CIFS/... keytab entries since no one except smbd - really needs them and we will fall back to verifying against - secrets.tdb */ - - ret = ads_keytab_add_entry(ads, "cifs", false)); - if (ret != 0 ) { - DEBUG(1, (__location__ ": ads_keytab_add_entry failed while " - "adding 'cifs'.\n")); - return ret; - } -#endif - - memset(princ_s, '\0', sizeof(princ_s)); - - ret = smb_krb5_init_context_common(&context); - if (ret) { - DBG_ERR("kerberos init context failed (%s)\n", - error_message(ret)); - goto done; - } - - machine_name = talloc_strdup(frame, lp_netbios_name()); - if (!machine_name) { - ret = -1; - goto done; - } - - /* now add the userPrincipalName and sAMAccountName entries */ - ok = ads_has_samaccountname(ads, frame, machine_name); - if (!ok) { - DEBUG(0, (__location__ ": unable to determine machine " - "account's name in AD!\n")); - ret = -1; - goto done; - } - - /* - * append '$' to netbios name so 'ads_keytab_add_entry' recognises - * it as a machine account rather than a service or Windows SPN. - */ - sam_account_name = talloc_asprintf(frame, "%s$",machine_name); - if (sam_account_name == NULL) { - ret = -1; - goto done; - } - /* upper case the sAMAccountName to make it easier for apps to - know what case to use in the keytab file */ - if (!strupper_m(sam_account_name)) { - ret = -1; - goto done; - } - - ret = ads_keytab_add_entry(ads, sam_account_name, false); - if (ret != 0) { - DEBUG(1, (__location__ ": ads_keytab_add_entry() failed " - "while adding sAMAccountName (%s)\n", - sam_account_name)); - goto done; - } - - /* remember that not every machine account will have a upn */ - upn = ads_get_upn(ads, frame, machine_name); - if (upn) { - ret = ads_keytab_add_entry(ads, upn, false); - if (ret != 0) { - DEBUG(1, (__location__ ": ads_keytab_add_entry() " - "failed while adding UPN (%s)\n", upn)); - goto done; - } - } - - /* Now loop through the keytab and update any other existing entries */ - kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name); - if (kvno == (krb5_kvno)-1) { - DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to " - "determine the system's kvno.\n")); - goto done; - } - - DEBUG(3, (__location__ ": Searching for keytab entries to preserve " - "and update.\n")); - - ret = ads_keytab_open(context, &keytab); - if (ret != 0) { - goto done; - } - - ret = krb5_kt_start_seq_get(context, keytab, &cursor); - if (ret != KRB5_KT_END && ret != ENOENT ) { - while ((ret = samba_krb5_kt_next_entry( - context, keytab, &kt_entry, &cursor)) == 0) - { - smb_krb5_kt_free_entry(context, &kt_entry); - ZERO_STRUCT(kt_entry); - found++; - } - } - krb5_kt_end_seq_get(context, keytab, &cursor); - ZERO_STRUCT(cursor); - - /* - * Hmmm. There is no "rewind" function for the keytab. This means we - * have a race condition where someone else could add entries after - * we've counted them. Re-open asap to minimise the race. JRA. - */ - DEBUG(3, (__location__ ": Found %zd entries in the keytab.\n", found)); - if (!found) { - goto done; - } - - oldEntries = talloc_zero_array(frame, char *, found + 1); - if (!oldEntries) { - DEBUG(1, (__location__ ": Failed to allocate space to store " - "the old keytab entries (talloc failed?).\n")); - ret = -1; - goto done; - } - - ret = krb5_kt_start_seq_get(context, keytab, &cursor); - if (ret == KRB5_KT_END || ret == ENOENT) { - krb5_kt_end_seq_get(context, keytab, &cursor); - ZERO_STRUCT(cursor); - goto done; - } - - while (samba_krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == - 0) - { - if (kt_entry.vno != kvno) { - char *ktprinc = NULL; - char *p; - - /* This returns a malloc'ed string in ktprinc. */ - ret = smb_krb5_unparse_name(oldEntries, - context, - kt_entry.principal, - &ktprinc); - if (ret) { - DEBUG(1, (__location__ - ": smb_krb5_unparse_name failed " - "(%s)\n", error_message(ret))); - goto done; - } - /* - * From looking at the krb5 source they don't seem to - * take locale or mb strings into account. - * Maybe this is because they assume utf8 ? - * In this case we may need to convert from utf8 to - * mb charset here ? JRA. - */ - p = strchr_m(ktprinc, '@'); - if (p) { - *p = '\0'; - } - - p = strchr_m(ktprinc, '/'); - if (p) { - *p = '\0'; - } - for (i = 0; i < found; i++) { - if (!oldEntries[i]) { - oldEntries[i] = ktprinc; - break; - } - if (!strcmp(oldEntries[i], ktprinc)) { - TALLOC_FREE(ktprinc); - break; - } - } - if (i == found) { - TALLOC_FREE(ktprinc); - } - } - smb_krb5_kt_free_entry(context, &kt_entry); - ZERO_STRUCT(kt_entry); - } - krb5_kt_end_seq_get(context, keytab, &cursor); - ZERO_STRUCT(cursor); - - ret = 0; - for (i = 0; oldEntries[i]; i++) { - ret |= ads_keytab_add_entry(ads, oldEntries[i], false); - TALLOC_FREE(oldEntries[i]); - } - -done: - TALLOC_FREE(oldEntries); - TALLOC_FREE(frame); - - if (context) { - if (!all_zero((uint8_t *)&kt_entry, sizeof(kt_entry))) { - smb_krb5_kt_free_entry(context, &kt_entry); - } - if (!all_zero((uint8_t *)&cursor, sizeof(cursor)) && keytab) { - krb5_kt_end_seq_get(context, keytab, &cursor); - } - if (keytab) { - krb5_kt_close(context, keytab); - } - krb5_free_context(context); - } - return ret; -} - #endif /* HAVE_ADS */ /********************************************************************** diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index b5412a0dd87..6fad112ca00 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2284,86 +2284,6 @@ ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, (const void *) vals); } -/** - * Determines the an account's current KVNO via an LDAP lookup - * @param ads An initialized ADS_STRUCT - * @param account_name the NT samaccountname. - * @return the kvno for the account, or -1 in case of a failure. - **/ - -uint32_t ads_get_kvno(ADS_STRUCT *ads, const char *account_name) -{ - LDAPMessage *res = NULL; - uint32_t kvno = (uint32_t)-1; /* -1 indicates a failure */ - char *filter; - const char *attrs[] = {"msDS-KeyVersionNumber", NULL}; - char *dn_string = NULL; - ADS_STATUS ret; - - DEBUG(5,("ads_get_kvno: Searching for account %s\n", account_name)); - if (asprintf(&filter, "(samAccountName=%s)", account_name) == -1) { - return kvno; - } - ret = ads_search(ads, &res, filter, attrs); - SAFE_FREE(filter); - if (!ADS_ERR_OK(ret) || (ads_count_replies(ads, res) != 1)) { - DEBUG(1,("ads_get_kvno: Account for %s not found.\n", account_name)); - ads_msgfree(ads, res); - return kvno; - } - - dn_string = ads_get_dn(ads, talloc_tos(), res); - if (!dn_string) { - DEBUG(0,("ads_get_kvno: out of memory.\n")); - ads_msgfree(ads, res); - return kvno; - } - DEBUG(5,("ads_get_kvno: Using: %s\n", dn_string)); - TALLOC_FREE(dn_string); - - /* --------------------------------------------------------- - * 0 is returned as a default KVNO from this point on... - * This is done because Windows 2000 does not support key - * version numbers. Chances are that a failure in the next - * step is simply due to Windows 2000 being used for a - * domain controller. */ - kvno = 0; - - if (!ads_pull_uint32(ads, res, "msDS-KeyVersionNumber", &kvno)) { - DEBUG(3,("ads_get_kvno: Error Determining KVNO!\n")); - DEBUG(3,("ads_get_kvno: Windows 2000 does not support KVNO's, so this may be normal.\n")); - ads_msgfree(ads, res); - return kvno; - } - - /* Success */ - DEBUG(5,("ads_get_kvno: Looked Up KVNO of: %d\n", kvno)); - ads_msgfree(ads, res); - return kvno; -} - -/** - * Determines the computer account's current KVNO via an LDAP lookup - * @param ads An initialized ADS_STRUCT - * @param machine_name the NetBIOS name of the computer, which is used to identify the computer account. - * @return the kvno for the computer account, or -1 in case of a failure. - **/ - -uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name) -{ - char *computer_account = NULL; - uint32_t kvno = -1; - - if (asprintf(&computer_account, "%s$", machine_name) < 0) { - return kvno; - } - - kvno = ads_get_kvno(ads, computer_account); - free(computer_account); - - return kvno; -} - /** * This clears out all registered spn's for a given hostname * @param ads An initialized ADS_STRUCT @@ -4178,124 +4098,6 @@ ADS_STATUS ads_get_sid_from_extended_dn(TALLOC_CTX *mem_ctx, /******************************************************************** ********************************************************************/ -char* ads_get_dnshostname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name ) -{ - LDAPMessage *res = NULL; - ADS_STATUS status; - int count = 0; - char *name = NULL; - - status = ads_find_machine_acct(ads, &res, machine_name); - if (!ADS_ERR_OK(status)) { - DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n", - lp_netbios_name())); - goto out; - } - - if ( (count = ads_count_replies(ads, res)) != 1 ) { - DEBUG(1,("ads_get_dnshostname: %d entries returned!\n", count)); - goto out; - } - - if ( (name = ads_pull_string(ads, ctx, res, "dNSHostName")) == NULL ) { - DEBUG(0,("ads_get_dnshostname: No dNSHostName attribute!\n")); - } - -out: - ads_msgfree(ads, res); - - return name; -} - -/******************************************************************** -********************************************************************/ - -static char **get_addl_hosts(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, - LDAPMessage *msg, size_t *num_values) -{ - const char *field = "msDS-AdditionalDnsHostName"; - struct berval **values = NULL; - char **ret = NULL; - size_t i, converted_size; - - /* - * Windows DC implicitly adds a short name for each FQDN added to - * msDS-AdditionalDnsHostName, but it comes with a strange binary - * suffix "\0$" which we should ignore (see bug #14406). - */ - - values = ldap_get_values_len(ads->ldap.ld, msg, field); - if (values == NULL) { - return NULL; - } - - *num_values = ldap_count_values_len(values); - - ret = talloc_array(mem_ctx, char *, *num_values + 1); - if (ret == NULL) { - ldap_value_free_len(values); - return NULL; - } - - for (i = 0; i < *num_values; i++) { - ret[i] = NULL; - if (!convert_string_talloc(mem_ctx, CH_UTF8, CH_UNIX, - values[i]->bv_val, - strnlen(values[i]->bv_val, - values[i]->bv_len), - &ret[i], &converted_size)) { - ldap_value_free_len(values); - return NULL; - } - } - ret[i] = NULL; - - ldap_value_free_len(values); - return ret; -} - -ADS_STATUS ads_get_additional_dns_hostnames(TALLOC_CTX *mem_ctx, - ADS_STRUCT *ads, - const char *machine_name, - char ***hostnames_array, - size_t *num_hostnames) -{ - ADS_STATUS status; - LDAPMessage *res = NULL; - int count; - - status = ads_find_machine_acct(ads, - &res, - machine_name); - if (!ADS_ERR_OK(status)) { - DEBUG(1,("Host Account for %s not found... skipping operation.\n", - machine_name)); - return status; - } - - count = ads_count_replies(ads, res); - if (count != 1) { - status = ADS_ERROR(LDAP_NO_SUCH_OBJECT); - goto done; - } - - *hostnames_array = get_addl_hosts(ads, mem_ctx, res, num_hostnames); - if (*hostnames_array == NULL) { - DEBUG(1, ("Host account for %s does not have msDS-AdditionalDnsHostName.\n", - machine_name)); - status = ADS_ERROR(LDAP_NO_SUCH_OBJECT); - goto done; - } - -done: - ads_msgfree(ads, res); - - return status; -} - -/******************************************************************** -********************************************************************/ - char* ads_get_upn( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name ) { LDAPMessage *res = NULL; @@ -4325,42 +4127,6 @@ out: return name; } -/******************************************************************** -********************************************************************/ - -bool ads_has_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name ) -{ - LDAPMessage *res = NULL; - ADS_STATUS status; - int count = 0; - char *name = NULL; - bool ok = false; - - status = ads_find_machine_acct(ads, &res, machine_name); - if (!ADS_ERR_OK(status)) { - DEBUG(0,("ads_has_samaccountname: Failed to find account for %s\n", - lp_netbios_name())); - goto out; - } - - if ( (count = ads_count_replies(ads, res)) != 1 ) { - DEBUG(1,("ads_has_samaccountname: %d entries returned!\n", count)); - goto out; - } - - if ( (name = ads_pull_string(ads, ctx, res, "sAMAccountName")) == NULL ) { - DEBUG(0,("ads_has_samaccountname: No sAMAccountName attribute!\n")); - } - -out: - ads_msgfree(ads, res); - if (name != NULL) { - ok = (strlen(name) > 0); - } - TALLOC_FREE(name); - return ok; -} - #if 0 SAVED CODE - we used to join via ldap - remember how we did this. JRA.