keytab_str,
sizeof(keytab_str) - 2);
if (ret != 0) {
- DBG_WARNING("Failed to get default keytab name");
+ DBG_WARNING("Failed to get default keytab name\n");
goto out;
}
keytab_name = keytab_str;
char *princ_s = NULL;
char *short_princ_s = NULL;
krb5_enctype enctypes[4] = {
-#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
ENCTYPE_AES256_CTS_HMAC_SHA1_96,
-#endif
-#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
ENCTYPE_AES128_CTS_HMAC_SHA1_96,
-#endif
ENCTYPE_ARCFOUR_HMAC,
0
};
for (i = 0; enctypes[i]; i++) {
/* add the fqdn principal to the keytab */
- ret = smb_krb5_kt_add_entry(context,
- keytab,
- kvno,
- princ_s,
- salt_princ_s,
- enctypes[i],
- password,
- false,
- false);
+ 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_entry(context,
- keytab,
- kvno,
- short_princ_s,
- salt_princ_s,
- enctypes[i],
- password,
- false,
- false);
+ 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;
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) {
goto out;
}
- /* make sure we have a single instance of a the computer account */
+ /* 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");
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);
}
/**********************************************************************
- Flushes all entries from the system keytab.
+ Delete a single service principal, i.e. 'host' from the system keytab
***********************************************************************/
-int ads_keytab_flush(ADS_STRUCT *ads)
+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;
- krb5_kvno kvno;
- ADS_STATUS aderr;
+ 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));
- return ret;
+ goto out;
}
ret = ads_keytab_open(context, &keytab);
goto out;
}
- kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name());
- if (kvno == -1) {
- /* -1 indicates a failure */
- DEBUG(1, (__location__ ": Error determining the kvno.\n"));
- ret = -1;
+ /* 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,
- kvno,
+ 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.
+***********************************************************************/
+
+int ads_keytab_flush(ADS_STRUCT *ads)
+{
+ krb5_error_code ret = 0;
+ krb5_context context = NULL;
+ krb5_keytab keytab = NULL;
+ ADS_STATUS aderr;
+
+ ret = smb_krb5_init_context_common(&context);
+ if (ret) {
+ DBG_ERR("kerberos init context failed (%s)\n",
+ error_message(ret));
+ return ret;
+ }
+
+ ret = ads_keytab_open(context, &keytab);
+ if (ret != 0) {
+ goto out;
+ }
+
+ /* Seek and delete all old keytab entries */
+ ret = smb_krb5_kt_seek_and_delete_old_entries(context,
+ keytab,
+ false, /* keep_old_kvno */
+ -1,
+ false, /* enctype_only */
ENCTYPE_NULL,
NULL,
NULL,
- true,
- false);
+ true); /* flush */
if (ret) {
goto out;
}
ret = smb_krb5_enctype_to_string(context, enctype, &etype_s);
if (ret &&
- (asprintf(&etype_s, "UNKNOWN: %d\n", enctype) == -1)) {
+ (asprintf(&etype_s, "UNKNOWN: %d", enctype) == -1)) {
TALLOC_FREE(princ_s);
goto out;
}