File 0019-Add-add-service-principal-and-remove-service-princip.patch of Package adcli
xxxxxxxxxx
1
From 2f77e6338346c738eb2d75404d8db39aab4c8977 Mon Sep 17 00:00:00 2001
2
From: Sumit Bose <sbose@redhat.com>
3
Date: Thu, 14 Jun 2018 16:49:26 +0200
4
Subject: [PATCH 19/25] Add add-service-principal and remove-service-principal
5
options
6
7
Currently it is only possible to specific a service name for service
8
principals but not to set the full service principal. This is e.g.
9
needed if there is a service running on a host which should be reachable
10
by a different DNS name as well.
11
12
With this patch service principal can be added and removed by specifying
13
the full name.
14
15
Related to https://bugzilla.redhat.com/show_bug.cgi?id=1547014
16
---
17
doc/adcli.xml | 21 ++++++++
18
library/adenroll.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++++++--
19
library/adenroll.h | 8 +++
20
library/adldap.c | 16 ++++--
21
tools/computer.c | 13 +++++
22
5 files changed, 189 insertions(+), 8 deletions(-)
23
24
diff --git a/doc/adcli.xml b/doc/adcli.xml
25
index 2cd56fb..7003e5f 100644
26
--- a/doc/adcli.xml
27
+++ b/doc/adcli.xml
28
29
not allow that Kerberos tickets can be forwarded to the
30
host.</para></listitem>
31
</varlistentry>
32
+ <varlistentry>
33
+ <term><option>--add-service-principal=<parameter>service/hostname</parameter></option></term>
34
+ <listitem><para>Add a service principal name. In
35
+ contrast to the <option>--service-name</option> the
36
+ hostname part can be specified as well in case the
37
+ service should be accessible with a different host
38
+ name as well.</para></listitem>
39
+ </varlistentry>
40
<varlistentry>
41
<term><option>--show-details</option></term>
42
<listitem><para>After a successful join print out information
43
44
not allow that Kerberos tickets can be forwarded to the
45
host.</para></listitem>
46
</varlistentry>
47
+ <varlistentry>
48
+ <term><option>--add-service-principal=<parameter>service/hostname</parameter></option></term>
49
+ <listitem><para>Add a service principal name. In
50
+ contrast to the <option>--service-name</option> the
51
+ hostname part can be specified as well in case the
52
+ service should be accessible with a different host
53
+ name as well.</para></listitem>
54
+ </varlistentry>
55
+ <varlistentry>
56
+ <term><option>--remove-service-principal=<parameter>service/hostname</parameter></option></term>
57
+ <listitem><para>Remove a service principal name from
58
+ the keytab and the AD host object.</para></listitem>
59
+ </varlistentry>
60
<varlistentry>
61
<term><option>--show-details</option></term>
62
<listitem><para>After a successful join print out information
63
diff --git a/library/adenroll.c b/library/adenroll.c
64
index deaef0f..df1f551 100644
65
--- a/library/adenroll.c
66
+++ b/library/adenroll.c
67
68
char **service_principals;
69
int service_principals_explicit;
70
71
+ char **service_principals_to_add;
72
+ char **service_principals_to_remove;
73
+
74
char *user_principal;
75
int user_princpal_generate;
76
77
78
return ADCLI_SUCCESS;
79
}
80
81
+static adcli_result
82
+add_and_remove_service_principals (adcli_enroll *enroll)
83
+{
84
+ int length = 0;
85
+ size_t c;
86
+ const char **list;
87
+
88
+ if (enroll->service_principals != NULL) {
89
+ length = seq_count (enroll->service_principals);
90
+ }
91
+
92
+ list = adcli_enroll_get_service_principals_to_add (enroll);
93
+ if (list != NULL) {
94
+ for (c = 0; list[c] != NULL; c++) {
95
+ enroll->service_principals = _adcli_strv_add (enroll->service_principals,
96
+ strdup (list[c]),
97
+ &length);
98
+ if (enroll->service_principals == NULL) {
99
+ return ADCLI_ERR_UNEXPECTED;
100
+ }
101
+ }
102
+ }
103
+
104
+ list = adcli_enroll_get_service_principals_to_remove (enroll);
105
+ if (list != NULL) {
106
+ for (c = 0; list[c] != NULL; c++) {
107
+ /* enroll->service_principals typically refects the
108
+ * order of the principal in the keytabm so it is not
109
+ * ordered. */
110
+ _adcli_strv_remove_unsorted (enroll->service_principals,
111
+ list[c], &length);
112
+ }
113
+ }
114
+
115
+ return ADCLI_SUCCESS;
116
+}
117
+
118
static adcli_result
119
ensure_service_principals (adcli_result res,
120
adcli_enroll *enroll)
121
122
123
if (!enroll->service_principals) {
124
assert (enroll->service_names != NULL);
125
- return add_service_names_to_service_principals (enroll);
126
+ res = add_service_names_to_service_principals (enroll);
127
}
128
129
- return ADCLI_SUCCESS;
130
+ if (res == ADCLI_SUCCESS) {
131
+ res = add_and_remove_service_principals (enroll);
132
+ }
133
+
134
+ return res;
135
}
136
137
static adcli_result
138
139
free (salts);
140
}
141
142
+static adcli_result
143
+remove_principal_from_keytab (adcli_enroll *enroll,
144
+ krb5_context k5,
145
+ const char *principal_name)
146
+{
147
+ krb5_error_code code;
148
+ krb5_principal principal;
149
+ match_principal_kvno closure;
150
+
151
+ code = krb5_parse_name (k5, principal_name, &principal);
152
+ if (code != 0) {
153
+ _adcli_err ("Couldn't parse principal: %s: %s",
154
+ principal_name, krb5_get_error_message (k5, code));
155
+ return ADCLI_ERR_FAIL;
156
+ }
157
+
158
+ closure.kvno = enroll->kvno;
159
+ closure.principal = principal;
160
+ closure.matched = 0;
161
+
162
+ code = _adcli_krb5_keytab_clear (k5, enroll->keytab,
163
+ match_principal_and_kvno, &closure);
164
+ krb5_free_principal (k5, principal);
165
+
166
+ if (code != 0) {
167
+ _adcli_err ("Couldn't update keytab: %s: %s",
168
+ enroll->keytab_name, krb5_get_error_message (k5, code));
169
+ return ADCLI_ERR_FAIL;
170
+ }
171
+
172
+ return ADCLI_SUCCESS;
173
+}
174
+
175
static adcli_result
176
add_principal_to_keytab (adcli_enroll *enroll,
177
krb5_context k5,
178
179
return res;
180
}
181
182
+ if (enroll->service_principals_to_remove != NULL) {
183
+ for (i = 0; enroll->service_principals_to_remove[i] != NULL; i++) {
184
+ res = remove_principal_from_keytab (enroll, k5,
185
+ enroll->service_principals_to_remove[i]);
186
+ if (res != ADCLI_SUCCESS) {
187
+ _adcli_warn ("Failed to remove %s from keytab.",
188
+ enroll->service_principals_to_remove[i]);
189
+ }
190
+ }
191
+ }
192
+
193
return ADCLI_SUCCESS;
194
}
195
196
197
if (_adcli_check_nt_time_string_lifetime (value,
198
adcli_enroll_get_computer_password_lifetime (enroll))) {
199
/* Do not update keytab if neither new service principals have
200
- * to be added nor the user principal has to be changed. */
201
- if (enroll->service_names == NULL && (enroll->user_principal == NULL || enroll->user_princpal_generate)) {
202
+ * to be added or deleted nor the user principal has to be changed. */
203
+ if (enroll->service_names == NULL
204
+ && (enroll->user_principal == NULL || enroll->user_princpal_generate)
205
+ && enroll->service_principals_to_add == NULL
206
+ && enroll->service_principals_to_remove == NULL) {
207
flags |= ADCLI_ENROLL_NO_KEYTAB;
208
}
209
flags |= ADCLI_ENROLL_PASSWORD_VALID;
210
211
enroll->trusted_for_delegation = value;
212
enroll->trusted_for_delegation_explicit = 1;
213
}
214
+
215
+const char **
216
+adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll)
217
+{
218
+ return_val_if_fail (enroll != NULL, NULL);
219
+
220
+ return (const char **)enroll->service_principals_to_add;
221
+}
222
+
223
+void
224
+adcli_enroll_add_service_principal_to_add (adcli_enroll *enroll,
225
+ const char *value)
226
+{
227
+ return_if_fail (enroll != NULL);
228
+ return_if_fail (value != NULL);
229
+
230
+ enroll->service_principals_to_add = _adcli_strv_add (enroll->service_principals_to_add,
231
+ strdup (value), NULL);
232
+ return_if_fail (enroll->service_principals_to_add != NULL);
233
+}
234
+
235
+const char **
236
+adcli_enroll_get_service_principals_to_remove (adcli_enroll *enroll)
237
+{
238
+ return_val_if_fail (enroll != NULL, NULL);
239
+
240
+ return (const char **)enroll->service_principals_to_remove;
241
+}
242
+
243
+void
244
+adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll,
245
+ const char *value)
246
+{
247
+ return_if_fail (enroll != NULL);
248
+ return_if_fail (value != NULL);
249
+
250
+ enroll->service_principals_to_remove = _adcli_strv_add (enroll->service_principals_to_remove,
251
+ strdup (value), NULL);
252
+ return_if_fail (enroll->service_principals_to_remove != NULL);
253
+}
254
diff --git a/library/adenroll.h b/library/adenroll.h
255
index ccf19e7..5a24c42 100644
256
--- a/library/adenroll.h
257
+++ b/library/adenroll.h
258
259
void adcli_enroll_set_service_principals (adcli_enroll *enroll,
260
const char **value);
261
262
+const char ** adcli_enroll_get_service_principals_to_add (adcli_enroll *enroll);
263
+void adcli_enroll_add_service_principal_to_add (adcli_enroll *enroll,
264
+ const char *value);
265
+
266
+const char ** adcli_enroll_get_service_principals_to_remove (adcli_enroll *enroll);
267
+void adcli_enroll_add_service_principal_to_remove (adcli_enroll *enroll,
268
+ const char *value);
269
+
270
const char * adcli_enroll_get_user_principal (adcli_enroll *enroll);
271
272
void adcli_enroll_set_user_principal (adcli_enroll *enroll,
273
diff --git a/library/adldap.c b/library/adldap.c
274
index 07dc373..d93efb7 100644
275
--- a/library/adldap.c
276
+++ b/library/adldap.c
277
278
struct berval *vals;
279
struct berval **pvals;
280
int count = 0;
281
+ int count_have = 0;
282
int i;
283
int ret;
284
285
- /* Already in berval format, just compare */
286
- if (mod->mod_op & LDAP_MOD_BVALUES)
287
- return _adcli_ldap_have_vals (mod->mod_vals.modv_bvals, have);
288
-
289
/* Count number of values */
290
for (i = 0; mod->mod_vals.modv_strvals[i] != 0; i++)
291
count++;
292
+ for (i = 0; have[i] != 0; i++)
293
+ count_have++;
294
+
295
+ /* If numbers different something has to be added or removed */
296
+ if (count != count_have) {
297
+ return 0;
298
+ }
299
+
300
+ /* Already in berval format, just compare */
301
+ if (mod->mod_op & LDAP_MOD_BVALUES)
302
+ return _adcli_ldap_have_vals (mod->mod_vals.modv_bvals, have);
303
304
vals = malloc (sizeof (struct berval) * (count + 1));
305
pvals = malloc (sizeof (struct berval *) * (count + 1));
306
diff --git a/tools/computer.c b/tools/computer.c
307
index 5348648..7a0c6f5 100644
308
--- a/tools/computer.c
309
+++ b/tools/computer.c
310
311
opt_user_principal,
312
opt_computer_password_lifetime,
313
opt_trusted_for_delegation,
314
+ opt_add_service_principal,
315
+ opt_remove_service_principal,
316
} Option;
317
318
static adcli_tool_desc common_usages[] = {
319
320
{ opt_computer_password_lifetime, "lifetime of the host accounts password in days", },
321
{ opt_trusted_for_delegation, "set/unset the TRUSTED_FOR_DELEGATION flag\n"
322
"in the userAccountControl attribute", },
323
+ { opt_add_service_principal, "add the given service principal to the account\n" },
324
+ { opt_remove_service_principal, "remove the given service principal from the account\n" },
325
{ opt_no_password, "don't prompt for or read a password" },
326
{ opt_prompt_password, "prompt for a password if necessary" },
327
{ opt_stdin_password, "read a password from stdin (until EOF) if\n"
328
329
adcli_enroll_set_trusted_for_delegation (enroll, false);
330
}
331
return;
332
+ case opt_add_service_principal:
333
+ adcli_enroll_add_service_principal_to_add (enroll, optarg);
334
+ return;
335
+ case opt_remove_service_principal:
336
+ adcli_enroll_add_service_principal_to_remove (enroll, optarg);
337
+ return;
338
case opt_verbose:
339
return;
340
341
342
{ "os-service-pack", optional_argument, NULL, opt_os_service_pack },
343
{ "user-principal", optional_argument, NULL, opt_user_principal },
344
{ "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation },
345
+ { "add-service-principal", required_argument, NULL, opt_add_service_principal },
346
{ "show-details", no_argument, NULL, opt_show_details },
347
{ "show-password", no_argument, NULL, opt_show_password },
348
{ "verbose", no_argument, NULL, opt_verbose },
349
350
{ "user-principal", optional_argument, NULL, opt_user_principal },
351
{ "computer-password-lifetime", optional_argument, NULL, opt_computer_password_lifetime },
352
{ "trusted-for-delegation", required_argument, NULL, opt_trusted_for_delegation },
353
+ { "add-service-principal", required_argument, NULL, opt_add_service_principal },
354
+ { "remove-service-principal", required_argument, NULL, opt_remove_service_principal },
355
{ "show-details", no_argument, NULL, opt_show_details },
356
{ "show-password", no_argument, NULL, opt_show_password },
357
{ "verbose", no_argument, NULL, opt_verbose },
358
--
359
2.16.4
360
361