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.
***********************************************************************/
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 */
/**********************************************************************
(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
/********************************************************************
********************************************************************/
-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;
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.