s3:utils: add new 'net ads setspn add' subcommand
authorNoel Power <noel.power@suse.com>
Wed, 24 Jan 2018 14:41:06 +0000 (14:41 +0000)
committerAndreas Schneider <asn@cryptomilk.org>
Fri, 2 Mar 2018 13:07:14 +0000 (14:07 +0100)
This patch adds 'add' 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 add <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 d806ce49c160deb3a5be888a9bf5dbc43e3ee9b1..f7a9f426639548aac9056de13ae1a7c6e914e2e0 100644 (file)
@@ -56,7 +56,8 @@ int ads_keytab_list(const char *keytab_name);
 
 /* The following definitions come from libads/net_ads_setspn.c  */
 bool ads_setspn_list(ADS_STRUCT *ads, const char *machine);
-
+bool ads_setspn_add(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 7bef330bf51d1ec828474332ae99abc5c253a6f2..41d698be7dbf5c8e0cafbf32a0e85ffee5f46b1f 100644 (file)
@@ -51,4 +51,82 @@ done:
        return ok;
 }
 
+/* returns true if spn exists in spn_array (match is NOT case-sensitive) */
+static bool find_spn_in_spnlist(TALLOC_CTX *ctx,
+                               const char *spn,
+                               char **spn_array,
+                               size_t num_spns)
+{
+       char *lc_spn = NULL;
+       size_t i = 0;
+
+       lc_spn = strlower_talloc(ctx, spn);
+       if (lc_spn == NULL) {
+               DBG_ERR("Out of memory, lowercasing %s.\n",
+                       spn);
+               return false;
+       }
+
+       for (i = 0; i < num_spns; i++) {
+               char *lc_spn_attr = strlower_talloc(ctx, spn_array[i]);
+               if (lc_spn_attr == NULL) {
+                       DBG_ERR("Out of memory, lowercasing %s.\n",
+                               spn_array[i]);
+                       return false;
+               }
+
+               if (strequal(lc_spn, lc_spn_attr)) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+bool ads_setspn_add(ADS_STRUCT *ads, const char *machine_name, const char * spn)
+{
+       bool ret = false;
+       TALLOC_CTX *frame = NULL;
+       ADS_STATUS status;
+       struct spn_struct *spn_struct = NULL;
+       const char *spns[2] = {NULL, NULL};
+       char **existing_spns = NULL;
+       size_t num_spns = 0;
+       bool found = false;
+
+       frame = talloc_stackframe();
+       spns[0] = spn;
+       spn_struct = parse_spn(frame, spn);
+       if (spn_struct == NULL) {
+               goto done;
+       }
+
+       status = ads_get_service_principal_names(frame,
+                                                ads,
+                                                machine_name,
+                                                &existing_spns,
+                                                &num_spns);
+
+       if (!ADS_ERR_OK(status)) {
+               goto done;
+       }
+
+       found = find_spn_in_spnlist(frame, spn, existing_spns, num_spns);
+       if (found) {
+               d_printf("Duplicate SPN found, aborting operation.\n");
+               goto done;
+       }
+
+       d_printf("Registering SPN %s for object %s\n", spn, machine_name);
+       status = ads_add_service_principal_names(ads, machine_name, spns);
+       if (!ADS_ERR_OK(status)) {
+               goto done;
+       }
+       ret = true;
+       d_printf("Updated object\n");
+done:
+       TALLOC_FREE(frame);
+       return ret;
+}
+
 #endif /* HAVE_ADS */
index 4243cacc2d266dfb61338cc486a1c57071580aa1..3f59f51a41954d4f6d8b0206a18f91a8e6d14218 100644 (file)
@@ -3036,6 +3036,37 @@ done:
        return ret;
 }
 
+static int net_ads_setspn_add(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 add <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_add(ads, argv[0], argv[1]);
+       } else {
+               ok = ads_setspn_add(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[] = {
@@ -3047,6 +3078,14 @@ int net_ads_setspn(struct net_context *c, int argc, const char **argv)
                        N_("net ads setspn list machine\n"
                           "    List Service Principal Names (SPN)")
                },
+               {
+                       "add",
+                       net_ads_setspn_add,
+                       NET_TRANSPORT_ADS,
+                       N_("Add Service Principal Names (SPN)"),
+                       N_("net ads setspn add machine spn\n"
+                          "    Add Service Principal Names (SPN)")
+               },
                {NULL, NULL, 0, NULL, NULL}
        };