VERSION: Bump version up to 4.10.8...
[Samba.git] / source3 / libads / net_ads_setspn.c
blobb163184326367154b6545255e85d347e96a2019c
1 /*
2 Unix SMB/CIFS implementation.
3 net ads setspn routines
4 Copyright (C) Noel Power 2018
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.
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.
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/>.
20 #include "includes.h"
21 #include "ads.h"
23 #ifdef HAVE_ADS
24 bool ads_setspn_list(ADS_STRUCT *ads, const char *machine_name)
26 size_t i = 0;
27 TALLOC_CTX *frame = NULL;
28 char **spn_array = NULL;
29 size_t num_spns = 0;
30 bool ok = false;
31 ADS_STATUS status;
33 frame = talloc_stackframe();
34 status = ads_get_service_principal_names(frame,
35 ads,
36 machine_name,
37 &spn_array,
38 &num_spns);
39 if (!ADS_ERR_OK(status)) {
40 goto done;
43 d_printf("Registered SPNs for %s\n", machine_name);
44 for (i = 0; i < num_spns; i++) {
45 d_printf("\t%s\n", spn_array[i]);
48 ok = true;
49 done:
50 TALLOC_FREE(frame);
51 return ok;
54 /* returns true if spn exists in spn_array (match is NOT case-sensitive) */
55 static bool find_spn_in_spnlist(TALLOC_CTX *ctx,
56 const char *spn,
57 char **spn_array,
58 size_t num_spns)
60 char *lc_spn = NULL;
61 size_t i = 0;
63 lc_spn = strlower_talloc(ctx, spn);
64 if (lc_spn == NULL) {
65 DBG_ERR("Out of memory, lowercasing %s.\n",
66 spn);
67 return false;
70 for (i = 0; i < num_spns; i++) {
71 char *lc_spn_attr = strlower_talloc(ctx, spn_array[i]);
72 if (lc_spn_attr == NULL) {
73 DBG_ERR("Out of memory, lowercasing %s.\n",
74 spn_array[i]);
75 return false;
78 if (strequal(lc_spn, lc_spn_attr)) {
79 return true;
83 return false;
86 bool ads_setspn_add(ADS_STRUCT *ads, const char *machine_name, const char * spn)
88 bool ret = false;
89 TALLOC_CTX *frame = NULL;
90 ADS_STATUS status;
91 struct spn_struct *spn_struct = NULL;
92 const char *spns[2] = {NULL, NULL};
93 char **existing_spns = NULL;
94 size_t num_spns = 0;
95 bool found = false;
97 frame = talloc_stackframe();
98 spns[0] = spn;
99 spn_struct = parse_spn(frame, spn);
100 if (spn_struct == NULL) {
101 goto done;
104 status = ads_get_service_principal_names(frame,
105 ads,
106 machine_name,
107 &existing_spns,
108 &num_spns);
110 if (!ADS_ERR_OK(status)) {
111 goto done;
114 found = find_spn_in_spnlist(frame, spn, existing_spns, num_spns);
115 if (found) {
116 d_printf("Duplicate SPN found, aborting operation.\n");
117 goto done;
120 d_printf("Registering SPN %s for object %s\n", spn, machine_name);
121 status = ads_add_service_principal_names(ads, machine_name, spns);
122 if (!ADS_ERR_OK(status)) {
123 goto done;
125 ret = true;
126 d_printf("Updated object\n");
127 done:
128 TALLOC_FREE(frame);
129 return ret;
132 bool ads_setspn_delete(ADS_STRUCT *ads,
133 const char *machine_name,
134 const char * spn)
136 size_t i = 0, j = 0;
137 TALLOC_CTX *frame = NULL;
138 char **spn_array = NULL;
139 const char **new_spn_array = NULL;
140 char *lc_spn = NULL;
141 size_t num_spns = 0;
142 ADS_STATUS status;
143 ADS_MODLIST mods;
144 bool ok = false;
145 LDAPMessage *res = NULL;
147 frame = talloc_stackframe();
149 lc_spn = strlower_talloc(frame, spn);
150 if (lc_spn == NULL) {
151 DBG_ERR("Out of memory, lowercasing %s.\n", spn);
152 goto done;
155 status = ads_find_machine_acct(ads,
156 &res,
157 machine_name);
158 if (!ADS_ERR_OK(status)) {
159 goto done;
162 status = ads_get_service_principal_names(frame,
163 ads,
164 machine_name,
165 &spn_array,
166 &num_spns);
167 if (!ADS_ERR_OK(status)) {
168 goto done;
171 new_spn_array = talloc_zero_array(frame, const char*, num_spns + 1);
172 if (!new_spn_array) {
173 DBG_ERR("Out of memory, failed to allocate array.\n");
174 goto done;
178 * create new spn list to write to object (excluding the spn to
179 * be deleted).
181 for (i = 0, j = 0; i < num_spns; i++) {
183 * windows setspn.exe deletes matching spn in a case
184 * insensitive way.
186 char *lc_spn_attr = strlower_talloc(frame, spn_array[i]);
187 if (lc_spn_attr == NULL) {
188 DBG_ERR("Out of memory, lowercasing %s.\n",
189 spn_array[i]);
190 goto done;
193 if (!strequal(lc_spn, lc_spn_attr)) {
194 new_spn_array[j++] = spn_array[i];
198 /* found and removed spn */
199 if (j < num_spns) {
200 char *dn = NULL;
201 mods = ads_init_mods(frame);
202 if (mods == NULL) {
203 goto done;
205 d_printf("Unregistering SPN %s for %s\n", spn, machine_name);
206 status = ads_mod_strlist(frame, &mods, "servicePrincipalName", new_spn_array);
207 if (!ADS_ERR_OK(status)) {
208 goto done;
211 dn = ads_get_dn(ads, frame, res);
212 if (dn == NULL ) {
213 goto done;
216 status = ads_gen_mod(ads, dn, mods);
217 if (!ADS_ERR_OK(status)) {
218 goto done;
221 d_printf("Updated object\n");
223 ok = true;
224 done:
225 TALLOC_FREE(frame);
226 return ok;
229 #endif /* HAVE_ADS */