LCOV - code coverage report
Current view: top level - source3/libads - net_ads_setspn.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 93 116 80.2 %
Date: 2024-04-21 15:09:00 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    net ads setspn routines
       4             :    Copyright (C) Noel Power 2018
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "ads.h"
      22             : 
      23             : #ifdef HAVE_ADS
      24          16 : bool ads_setspn_list(ADS_STRUCT *ads, const char *machine_name)
      25             : {
      26          16 :         size_t i = 0;
      27          16 :         TALLOC_CTX *frame = NULL;
      28          16 :         char **spn_array = NULL;
      29          16 :         size_t num_spns = 0;
      30          16 :         bool ok = false;
      31           0 :         ADS_STATUS status;
      32             : 
      33          16 :         frame = talloc_stackframe();
      34          16 :         status = ads_get_service_principal_names(frame,
      35             :                                                  ads,
      36             :                                                  machine_name,
      37             :                                                  &spn_array,
      38             :                                                  &num_spns);
      39          16 :         if (!ADS_ERR_OK(status)) {
      40           0 :                 goto done;
      41             :         }
      42             : 
      43          16 :         d_printf("Registered SPNs for %s\n", machine_name);
      44          98 :         for (i = 0; i < num_spns; i++) {
      45          82 :                 d_printf("\t%s\n", spn_array[i]);
      46             :         }
      47             : 
      48          16 :         ok = true;
      49          16 : done:
      50          16 :         TALLOC_FREE(frame);
      51          16 :         return ok;
      52             : }
      53             : 
      54             : /* returns true if spn exists in spn_array (match is NOT case-sensitive) */
      55           4 : static bool find_spn_in_spnlist(TALLOC_CTX *ctx,
      56             :                                 const char *spn,
      57             :                                 char **spn_array,
      58             :                                 size_t num_spns)
      59             : {
      60           4 :         char *lc_spn = NULL;
      61           4 :         size_t i = 0;
      62             : 
      63           4 :         lc_spn = strlower_talloc(ctx, spn);
      64           4 :         if (lc_spn == NULL) {
      65           0 :                 DBG_ERR("Out of memory, lowercasing %s.\n",
      66             :                         spn);
      67           0 :                 return false;
      68             :         }
      69             : 
      70          20 :         for (i = 0; i < num_spns; i++) {
      71          18 :                 char *lc_spn_attr = strlower_talloc(ctx, spn_array[i]);
      72          18 :                 if (lc_spn_attr == NULL) {
      73           0 :                         DBG_ERR("Out of memory, lowercasing %s.\n",
      74             :                                 spn_array[i]);
      75           0 :                         return false;
      76             :                 }
      77             : 
      78          18 :                 if (strequal(lc_spn, lc_spn_attr)) {
      79           2 :                         return true;
      80             :                 }
      81             :         }
      82             : 
      83           2 :         return false;
      84             : }
      85             : 
      86           6 : bool ads_setspn_add(ADS_STRUCT *ads, const char *machine_name, const char * spn)
      87             : {
      88           6 :         bool ret = false;
      89           6 :         TALLOC_CTX *frame = NULL;
      90           0 :         ADS_STATUS status;
      91           6 :         struct spn_struct *spn_struct = NULL;
      92           6 :         const char *spns[2] = {NULL, NULL};
      93           6 :         char **existing_spns = NULL;
      94           6 :         size_t num_spns = 0;
      95           6 :         bool found = false;
      96             : 
      97           6 :         frame = talloc_stackframe();
      98           6 :         spns[0] = spn;
      99           6 :         spn_struct = parse_spn(frame, spn);
     100           6 :         if (spn_struct == NULL) {
     101           2 :                 goto done;
     102             :         }
     103             : 
     104           4 :         status = ads_get_service_principal_names(frame,
     105             :                                                  ads,
     106             :                                                  machine_name,
     107             :                                                  &existing_spns,
     108             :                                                  &num_spns);
     109             : 
     110           4 :         if (!ADS_ERR_OK(status)) {
     111           0 :                 goto done;
     112             :         }
     113             : 
     114           4 :         found = find_spn_in_spnlist(frame, spn, existing_spns, num_spns);
     115           4 :         if (found) {
     116           2 :                 d_printf("Duplicate SPN found, aborting operation.\n");
     117           2 :                 goto done;
     118             :         }
     119             : 
     120           2 :         d_printf("Registering SPN %s for object %s\n", spn, machine_name);
     121           2 :         status = ads_add_service_principal_names(ads, machine_name, spns);
     122           2 :         if (!ADS_ERR_OK(status)) {
     123           0 :                 goto done;
     124             :         }
     125           2 :         ret = true;
     126           2 :         d_printf("Updated object\n");
     127           6 : done:
     128           6 :         TALLOC_FREE(frame);
     129           6 :         return ret;
     130             : }
     131             : 
     132           2 : bool ads_setspn_delete(ADS_STRUCT *ads,
     133             :                        const char *machine_name,
     134             :                        const char * spn)
     135             : {
     136           2 :         size_t i = 0, j = 0;
     137           2 :         TALLOC_CTX *frame = NULL;
     138           2 :         char **spn_array = NULL;
     139           2 :         const char **new_spn_array = NULL;
     140           2 :         char *lc_spn = NULL;
     141           2 :         size_t num_spns = 0;
     142           0 :         ADS_STATUS status;
     143           0 :         ADS_MODLIST mods;
     144           2 :         bool ok = false;
     145           2 :         LDAPMessage *res = NULL;
     146             : 
     147           2 :         frame = talloc_stackframe();
     148             : 
     149           2 :         lc_spn = strlower_talloc(frame, spn);
     150           2 :         if (lc_spn == NULL) {
     151           0 :                 DBG_ERR("Out of memory, lowercasing %s.\n", spn);
     152           0 :                 goto done;
     153             :         }
     154             : 
     155           2 :         status = ads_find_machine_acct(ads,
     156             :                                        &res,
     157             :                                        machine_name);
     158           2 :         if (!ADS_ERR_OK(status)) {
     159           0 :                 goto done;
     160             :         }
     161             : 
     162           2 :         status = ads_get_service_principal_names(frame,
     163             :                                                  ads,
     164             :                                                  machine_name,
     165             :                                                  &spn_array,
     166             :                                                  &num_spns);
     167           2 :         if (!ADS_ERR_OK(status)) {
     168           0 :                 goto done;
     169             :         }
     170             : 
     171           2 :         new_spn_array = talloc_zero_array(frame, const char*, num_spns + 1);
     172           2 :         if (!new_spn_array) {
     173           0 :                 DBG_ERR("Out of memory, failed to allocate array.\n");
     174           0 :                 goto done;
     175             :         }
     176             : 
     177             :         /*
     178             :          * create new spn list to write to object (excluding the spn to
     179             :          * be deleted).
     180             :          */
     181          12 :         for (i = 0, j = 0; i < num_spns; i++) {
     182             :                 /*
     183             :                  * windows setspn.exe deletes matching spn in a case
     184             :                  * insensitive way.
     185             :                  */
     186          10 :                 char *lc_spn_attr = strlower_talloc(frame, spn_array[i]);
     187          10 :                 if (lc_spn_attr == NULL) {
     188           0 :                         DBG_ERR("Out of memory, lowercasing %s.\n",
     189             :                                 spn_array[i]);
     190           0 :                         goto done;
     191             :                 }
     192             : 
     193          10 :                 if (!strequal(lc_spn, lc_spn_attr)) {
     194           8 :                         new_spn_array[j++] = spn_array[i];
     195             :                 }
     196             :         }
     197             : 
     198             :         /* found and removed spn */
     199           2 :         if (j < num_spns) {
     200           2 :                 char *dn = NULL;
     201           2 :                 mods = ads_init_mods(frame);
     202           2 :                 if (mods == NULL) {
     203           0 :                         goto done;
     204             :                 }
     205           2 :                 d_printf("Unregistering SPN %s for %s\n", spn, machine_name);
     206           2 :                 status = ads_mod_strlist(frame, &mods, "servicePrincipalName", new_spn_array);
     207           2 :                 if (!ADS_ERR_OK(status)) {
     208           0 :                         goto done;
     209             :                 }
     210             : 
     211           2 :                 dn = ads_get_dn(ads, frame, res);
     212           2 :                 if (dn == NULL ) {
     213           0 :                         goto done;
     214             :                 }
     215             : 
     216           2 :                 status = ads_gen_mod(ads, dn, mods);
     217           2 :                 if (!ADS_ERR_OK(status)) {
     218           0 :                         goto done;
     219             :                 }
     220             :         }
     221           2 :         d_printf("Updated object\n");
     222             : 
     223           2 :         ok = true;
     224           2 : done:
     225           2 :         TALLOC_FREE(frame);
     226           2 :         return ok;
     227             : }
     228             : 
     229             : #endif /* HAVE_ADS */

Generated by: LCOV version 1.14