s3:utils: add new 'net ads setspn delete' subcommand
authorNoel Power <noel.power@suse.com>
Wed, 24 Jan 2018 14:51:03 +0000 (14:51 +0000)
committerAndreas Schneider <asn@cryptomilk.org>
Fri, 2 Mar 2018 13:07:14 +0000 (14:07 +0100)
This patch adds 'delete' to the 'net ads setspn' subcommand

(see https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/cc731241(v=ws.11)

Usage:

    net ads setspn delete <computer> <SPN>

Note: <computer> is optional, if not specified the computer account
associated with value returned by lp_netbios_name() is used instead.

Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/libads/ads_proto.h
source3/libads/net_ads_setspn.c
source3/utils/net_ads.c

index f7a9f426639548aac9056de13ae1a7c6e914e2e0..3934c1cfe27a480b92a0177e8719daa88c23794e 100644 (file)
@@ -58,6 +58,9 @@ int ads_keytab_list(const char *keytab_name);
 bool ads_setspn_list(ADS_STRUCT *ads, const char *machine);
 bool ads_setspn_add(ADS_STRUCT *ads, const char *machine_name,
                    const char * spn);
+bool ads_setspn_delete(ADS_STRUCT *ads, const char *machine_name,
+                      const char * spn);
+
 /* The following definitions come from libads/krb5_errs.c  */
 
 /* The following definitions come from libads/kerberos_util.c  */
index 41d698be7dbf5c8e0cafbf32a0e85ffee5f46b1f..b163184326367154b6545255e85d347e96a2019c 100644 (file)
@@ -129,4 +129,101 @@ done:
        return ret;
 }
 
+bool ads_setspn_delete(ADS_STRUCT *ads,
+                      const char *machine_name,
+                      const char * spn)
+{
+       size_t i = 0, j = 0;
+       TALLOC_CTX *frame = NULL;
+       char **spn_array = NULL;
+       const char **new_spn_array = NULL;
+       char *lc_spn = NULL;
+       size_t num_spns = 0;
+       ADS_STATUS status;
+       ADS_MODLIST mods;
+       bool ok = false;
+       LDAPMessage *res = NULL;
+
+       frame = talloc_stackframe();
+
+       lc_spn = strlower_talloc(frame, spn);
+       if (lc_spn == NULL) {
+               DBG_ERR("Out of memory, lowercasing %s.\n", spn);
+               goto done;
+       }
+
+       status = ads_find_machine_acct(ads,
+                                      &res,
+                                      machine_name);
+       if (!ADS_ERR_OK(status)) {
+               goto done;
+       }
+
+       status = ads_get_service_principal_names(frame,
+                                                ads,
+                                                machine_name,
+                                                &spn_array,
+                                                &num_spns);
+       if (!ADS_ERR_OK(status)) {
+               goto done;
+       }
+
+       new_spn_array = talloc_zero_array(frame, const char*, num_spns + 1);
+       if (!new_spn_array) {
+               DBG_ERR("Out of memory, failed to allocate array.\n");
+               goto done;
+       }
+
+       /*
+        * create new spn list to write to object (excluding the spn to
+        * be deleted).
+        */
+       for (i = 0, j = 0; i < num_spns; i++) {
+               /*
+                * windows setspn.exe deletes matching spn in a case
+                * insensitive way.
+                */
+               char *lc_spn_attr = strlower_talloc(frame, spn_array[i]);
+               if (lc_spn_attr == NULL) {
+                       DBG_ERR("Out of memory, lowercasing %s.\n",
+                               spn_array[i]);
+                       goto done;
+               }
+
+               if (!strequal(lc_spn, lc_spn_attr)) {
+                       new_spn_array[j++] = spn_array[i];
+               }
+       }
+
+       /* found and removed spn */
+       if (j < num_spns) {
+               char *dn = NULL;
+               mods = ads_init_mods(frame);
+               if (mods == NULL) {
+                       goto done;
+               }
+               d_printf("Unregistering SPN %s for %s\n", spn, machine_name);
+               status = ads_mod_strlist(frame, &mods, "servicePrincipalName", new_spn_array);
+               if (!ADS_ERR_OK(status)) {
+                       goto done;
+               }
+
+               dn = ads_get_dn(ads, frame, res);
+               if (dn == NULL ) {
+                       goto done;
+               }
+
+               status = ads_gen_mod(ads, dn, mods);
+               if (!ADS_ERR_OK(status)) {
+                       goto done;
+               }
+       }
+       d_printf("Updated object\n");
+
+       ok = true;
+done:
+       TALLOC_FREE(frame);
+       return ok;
+}
+
 #endif /* HAVE_ADS */
index 3f59f51a41954d4f6d8b0206a18f91a8e6d14218..a5d1928f30b5e1ad69ac83f55016a919a8791d74 100644 (file)
@@ -3067,6 +3067,37 @@ done:
        return ret;
 }
 
+static int net_ads_setspn_delete(struct net_context *c, int argc, const char **argv)
+{
+       int ret = 0;
+       bool ok = false;
+       ADS_STRUCT *ads = NULL;
+       if (c->display_usage || argc < 1) {
+               d_printf("%s\n%s",
+                        _("Usage:"),
+                        _("net ads setspn delete <machinename> SPN\n"));
+               ret = 0;
+               goto done;
+       }
+       if (!ADS_ERR_OK(ads_startup(c, true, &ads))) {
+               ret = -1;
+               goto done;
+       }
+       if (argc > 1) {
+               ok = ads_setspn_delete(ads, argv[0], argv[1]);
+       } else {
+               ok = ads_setspn_delete(ads, lp_netbios_name(), argv[0]);
+       }
+       if (!ok) {
+               ret = -1;
+       }
+done:
+       if (ads) {
+               ads_destroy(&ads);
+       }
+       return ret;
+}
+
 int net_ads_setspn(struct net_context *c, int argc, const char **argv)
 {
        struct functable func[] = {
@@ -3086,6 +3117,14 @@ int net_ads_setspn(struct net_context *c, int argc, const char **argv)
                        N_("net ads setspn add machine spn\n"
                           "    Add Service Principal Names (SPN)")
                },
+               {
+                       "delete",
+                       net_ads_setspn_delete,
+                       NET_TRANSPORT_ADS,
+                       N_("Delete Service Principal Names (SPN)"),
+                       N_("net ads setspn delete machine spn\n"
+                          "    Delete Service Principal Names (SPN)")
+               },
                {NULL, NULL, 0, NULL, NULL}
        };