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 */
|