1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
4 *
5 */
6
7 #include <k5-int.h>
8 #include <socket-utils.h>
9 #include <gssapi/gssapi.h>
10 #include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */
11 #include <krb5.h>
12 #include <kadm5/admin.h>
13 #include <kadm5/kadm_rpc.h>
14 #include <kadm5/server_internal.h>
15 #include <syslog.h>
16 #include <adm_proto.h> /* krb5_klog_syslog */
17 #include "misc.h"
18 #include "auth.h"
19
20 /* A principal changing its own keys may retain at most this many key
21 * versions. */
22 #define MAX_SELF_KEEPOLD 5
23
24 extern gss_name_t gss_changepw_name;
25 extern gss_name_t gss_oldchangepw_name;
26 extern void * global_server_handle;
27
28 #define CHANGEPW_SERVICE(rqstp) \
29 (cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), gss_changepw_name) | \
30 (gss_oldchangepw_name && \
31 cmp_gss_names_rel_1(acceptor_name(rqstp->rq_svccred), \
32 gss_oldchangepw_name)))
33
34
35 static int gss_to_krb5_name(kadm5_server_handle_t handle,
36 gss_name_t gss_name, krb5_principal *princ);
37
38 static int gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str);
39
40 static gss_name_t acceptor_name(gss_ctx_id_t context);
41
42 gss_name_t rqst2name(struct svc_req *rqstp);
43
cmp_gss_names(gss_name_t n1,gss_name_t n2)44 static int cmp_gss_names(gss_name_t n1, gss_name_t n2)
45 {
46 OM_uint32 emin;
47 int equal;
48
49 if (GSS_ERROR(gss_compare_name(&emin, n1, n2, &equal)))
50 return(0);
51
52 return(equal);
53 }
54
55 /* Does a comparison of the names and then releases the first entity */
56 /* For use above in CHANGEPW_SERVICE */
cmp_gss_names_rel_1(gss_name_t n1,gss_name_t n2)57 static int cmp_gss_names_rel_1(gss_name_t n1, gss_name_t n2)
58 {
59 OM_uint32 min_stat;
60 int ret;
61
62 ret = cmp_gss_names(n1, n2);
63 if (n1) (void) gss_release_name(&min_stat, &n1);
64 return ret;
65 }
66
67 /*
68 * Function check_handle
69 *
70 * Purpose: Check a server handle and return a com_err code if it is
71 * invalid or 0 if it is valid.
72 *
73 * Arguments:
74 *
75 * handle The server handle.
76 */
77
check_handle(void * handle)78 static int check_handle(void *handle)
79 {
80 CHECK_HANDLE(handle);
81 return 0;
82 }
83
84 /*
85 * Function: new_server_handle
86 *
87 * Purpose: Constructs a server handle suitable for passing into the
88 * server library API functions, by folding the client's API version
89 * and calling principal into the server handle returned by
90 * kadm5_init.
91 *
92 * Arguments:
93 * api_version (input) The API version specified by the client
94 * rqstp (input) The RPC request
95 * handle (output) The returned handle
96 * <return value> (output) An error code, or 0 if no error occurred
97 *
98 * Effects:
99 * Returns a pointer to allocated storage containing the server
100 * handle. If an error occurs, then no allocated storage is
101 * returned, and the return value of the function will be a
102 * non-zero com_err code.
103 *
104 * The allocated storage for the handle should be freed with
105 * free_server_handle (see below) when it is no longer needed.
106 */
107
new_server_handle(krb5_ui_4 api_version,struct svc_req * rqstp,kadm5_server_handle_t * out_handle)108 static kadm5_ret_t new_server_handle(krb5_ui_4 api_version,
109 struct svc_req *rqstp,
110 kadm5_server_handle_t
111 *out_handle)
112 {
113 kadm5_server_handle_t handle;
114
115 *out_handle = NULL;
116
117 if (! (handle = (kadm5_server_handle_t)
118 malloc(sizeof(*handle))))
119 return ENOMEM;
120
121 *handle = *(kadm5_server_handle_t)global_server_handle;
122 handle->api_version = api_version;
123
124 if (! gss_to_krb5_name(handle, rqst2name(rqstp),
125 &handle->current_caller)) {
126 free(handle);
127 return KADM5_FAILURE;
128 }
129
130 *out_handle = handle;
131 return 0;
132 }
133
134 /*
135 * Function: free_server_handle
136 *
137 * Purpose: Free handle memory allocated by new_server_handle
138 *
139 * Arguments:
140 * handle (input/output) The handle to free
141 */
free_server_handle(kadm5_server_handle_t handle)142 static void free_server_handle(kadm5_server_handle_t handle)
143 {
144 if (!handle)
145 return;
146 krb5_free_principal(handle->context, handle->current_caller);
147 free(handle);
148 }
149
150 /* Result is stored in a static buffer and is invalidated by the next call. */
151 const char *
client_addr(SVCXPRT * xprt)152 client_addr(SVCXPRT *xprt)
153 {
154 static char abuf[128];
155 struct sockaddr_storage ss;
156 socklen_t len = sizeof(ss);
157
158 if (getpeername(xprt->xp_sock, ss2sa(&ss), &len) != 0)
159 return "(unknown)";
160 k5_print_addr(ss2sa(&ss), abuf, sizeof(abuf));
161 return abuf;
162 }
163
164 /*
165 * Function: setup_gss_names
166 *
167 * Purpose: Create printable representations of the client and server
168 * names.
169 *
170 * Arguments:
171 * rqstp (r) the RPC request
172 * client_name (w) the gss_buffer_t for the client name
173 * server_name (w) the gss_buffer_t for the server name
174 *
175 * Effects:
176 *
177 * Unparses the client and server names into client_name and
178 * server_name, both of which must be freed by the caller. Returns 0
179 * on success and -1 on failure.
180 */
setup_gss_names(struct svc_req * rqstp,gss_buffer_desc * client_name,gss_buffer_desc * server_name)181 int setup_gss_names(struct svc_req *rqstp,
182 gss_buffer_desc *client_name,
183 gss_buffer_desc *server_name)
184 {
185 OM_uint32 maj_stat, min_stat;
186 gss_name_t server_gss_name;
187
188 if (gss_name_to_string(rqst2name(rqstp), client_name) != 0)
189 return -1;
190 maj_stat = gss_inquire_context(&min_stat, rqstp->rq_svccred, NULL,
191 &server_gss_name, NULL, NULL, NULL,
192 NULL, NULL);
193 if (maj_stat != GSS_S_COMPLETE) {
194 gss_release_buffer(&min_stat, client_name);
195 gss_release_name(&min_stat, &server_gss_name);
196 return -1;
197 }
198 if (gss_name_to_string(server_gss_name, server_name) != 0) {
199 gss_release_buffer(&min_stat, client_name);
200 gss_release_name(&min_stat, &server_gss_name);
201 return -1;
202 }
203 gss_release_name(&min_stat, &server_gss_name);
204 return 0;
205 }
206
acceptor_name(gss_ctx_id_t context)207 static gss_name_t acceptor_name(gss_ctx_id_t context)
208 {
209 OM_uint32 maj_stat, min_stat;
210 gss_name_t name;
211
212 maj_stat = gss_inquire_context(&min_stat, context, NULL, &name,
213 NULL, NULL, NULL, NULL, NULL);
214 if (maj_stat != GSS_S_COMPLETE)
215 return NULL;
216 return name;
217 }
218
gss_to_krb5_name(kadm5_server_handle_t handle,gss_name_t gss_name,krb5_principal * princ)219 static int gss_to_krb5_name(kadm5_server_handle_t handle,
220 gss_name_t gss_name, krb5_principal *princ)
221 {
222 krb5_error_code ret;
223 OM_uint32 minor_stat;
224 gss_buffer_desc gss_str;
225 int success;
226 char *s;
227
228 if (gss_name_to_string(gss_name, &gss_str) != 0)
229 return 0;
230 s = k5memdup0(gss_str.value, gss_str.length, &ret);
231 if (s == NULL) {
232 gss_release_buffer(&minor_stat, &gss_str);
233 return 0;
234 }
235 success = (krb5_parse_name(handle->context, s, princ) == 0);
236 free(s);
237 gss_release_buffer(&minor_stat, &gss_str);
238 return success;
239 }
240
241 static int
gss_name_to_string(gss_name_t gss_name,gss_buffer_desc * str)242 gss_name_to_string(gss_name_t gss_name, gss_buffer_desc *str)
243 {
244 OM_uint32 status, minor_stat;
245 gss_OID gss_type;
246 const char pref[] = KRB5_WELLKNOWN_NAMESTR "/" KRB5_ANONYMOUS_PRINCSTR "@";
247 const size_t preflen = sizeof(pref) - 1;
248
249 status = gss_display_name(&minor_stat, gss_name, str, &gss_type);
250 if (status != GSS_S_COMPLETE)
251 return 1;
252 if (gss_oid_equal(gss_type, GSS_C_NT_ANONYMOUS)) {
253 /* Guard against non-krb5 mechs with different anonymous displays. */
254 if (str->length < preflen || memcmp(str->value, pref, preflen) != 0)
255 return 1;
256 } else if (!gss_oid_equal(gss_type, GSS_KRB5_NT_PRINCIPAL_NAME)) {
257 return 1;
258 }
259 return 0;
260 }
261
262 /*
263 * Perform common initialization for server stub functions. A subset of the
264 * output arguments may be set on failure; the caller is responsible for
265 * initializing outputs and calling stub_cleanup() on success or failure.
266 * princ and princ_str_out may be NULL to omit unparsing a principal name.
267 */
268 static kadm5_ret_t
stub_setup(krb5_ui_4 api_version,struct svc_req * rqstp,krb5_principal princ,kadm5_server_handle_t * handle_out,krb5_ui_4 * api_version_out,gss_buffer_t client_name_out,gss_buffer_t service_name_out,char ** princ_str_out,kadm5_principal_ent_rec * rec_out)269 stub_setup(krb5_ui_4 api_version, struct svc_req *rqstp, krb5_principal princ,
270 kadm5_server_handle_t *handle_out, krb5_ui_4 *api_version_out,
271 gss_buffer_t client_name_out, gss_buffer_t service_name_out,
272 char **princ_str_out, kadm5_principal_ent_rec *rec_out)
273 {
274 kadm5_ret_t ret;
275
276 ret = new_server_handle(api_version, rqstp, handle_out);
277 if (ret)
278 return ret;
279
280 ret = check_handle(*handle_out);
281 if (ret)
282 return ret;
283
284 *api_version_out = (*handle_out)->api_version;
285
286 if (setup_gss_names(rqstp, client_name_out, service_name_out) < 0)
287 return KADM5_FAILURE;
288
289 if (princ_str_out != NULL) {
290 if (princ == NULL)
291 return KADM5_BAD_PRINCIPAL;
292 if (krb5_unparse_name((*handle_out)->context, princ, princ_str_out))
293 return KADM5_BAD_PRINCIPAL;
294 }
295
296 if (rec_out != NULL) {
297 if (princ == NULL)
298 return KADM5_BAD_PRINCIPAL;
299 return kadm5_get_principal(*handle_out, princ, rec_out,
300 KADM5_PRINCIPAL | KADM5_ATTRIBUTES);
301 }
302
303 return KADM5_OK;
304 }
305
306 /* Perform common cleanup for server stub functions. */
307 static void
stub_cleanup(kadm5_server_handle_t handle,char * princ_str,gss_buffer_t client_name,gss_buffer_t service_name)308 stub_cleanup(kadm5_server_handle_t handle, char *princ_str,
309 gss_buffer_t client_name, gss_buffer_t service_name)
310 {
311 OM_uint32 minor_stat;
312
313 auth_end(handle->context);
314 free_server_handle(handle);
315 free(princ_str);
316 gss_release_buffer(&minor_stat, client_name);
317 gss_release_buffer(&minor_stat, service_name);
318 }
319
320 static krb5_boolean
stub_auth(kadm5_server_handle_t handle,int opcode,krb5_const_principal p1,krb5_const_principal p2,const char * s1,const char * s2)321 stub_auth(kadm5_server_handle_t handle, int opcode, krb5_const_principal p1,
322 krb5_const_principal p2, const char *s1, const char *s2)
323 {
324 return auth(handle->context, opcode, handle->current_caller, p1, p2,
325 s1, s2, NULL, 0);
326 }
327
328 static krb5_boolean
stub_auth_pol(kadm5_server_handle_t handle,int opcode,const char * policy,const kadm5_policy_ent_rec * polent,long mask)329 stub_auth_pol(kadm5_server_handle_t handle, int opcode, const char *policy,
330 const kadm5_policy_ent_rec *polent, long mask)
331 {
332 return auth(handle->context, opcode, handle->current_caller, NULL, NULL,
333 policy, NULL, polent, mask);
334 }
335
336 static krb5_boolean
stub_auth_restrict(kadm5_server_handle_t handle,int opcode,krb5_const_principal princ,kadm5_principal_ent_t ent,long * mask)337 stub_auth_restrict(kadm5_server_handle_t handle, int opcode,
338 krb5_const_principal princ, kadm5_principal_ent_t ent,
339 long *mask)
340 {
341 return auth_restrict(handle->context, opcode, handle->current_caller,
342 princ, ent, mask);
343 }
344
345 /* Return true if the client authenticated to kadmin/changepw and princ is not
346 * the client principal. */
347 static krb5_boolean
changepw_not_self(kadm5_server_handle_t handle,struct svc_req * rqstp,krb5_const_principal princ)348 changepw_not_self(kadm5_server_handle_t handle, struct svc_req *rqstp,
349 krb5_const_principal princ)
350 {
351 return CHANGEPW_SERVICE(rqstp) &&
352 !krb5_principal_compare(handle->context, handle->current_caller,
353 princ);
354 }
355
356 static krb5_boolean
ticket_is_initial(struct svc_req * rqstp)357 ticket_is_initial(struct svc_req *rqstp)
358 {
359 OM_uint32 status, minor_stat;
360 krb5_flags flags;
361
362 status = gss_krb5_get_tkt_flags(&minor_stat, rqstp->rq_svccred, &flags);
363 if (status != GSS_S_COMPLETE)
364 return 0;
365 return (flags & TKT_FLG_INITIAL) != 0;
366 }
367
368 /* If a key change request is for the client's own principal, verify that the
369 * client used an initial ticket and enforce the policy min_life. */
370 static kadm5_ret_t
check_self_keychange(kadm5_server_handle_t handle,struct svc_req * rqstp,krb5_principal princ)371 check_self_keychange(kadm5_server_handle_t handle, struct svc_req *rqstp,
372 krb5_principal princ)
373 {
374 if (!krb5_principal_compare(handle->context, handle->current_caller,
375 princ))
376 return 0;
377
378 if (!ticket_is_initial(rqstp))
379 return KADM5_AUTH_INITIAL;
380
381 return check_min_life(handle, princ, NULL, 0);
382 }
383
384 /*
385 * Return the appropriate libkadm5 keepold value for a key change request,
386 * given the boolean keepold input from the client. 0 means discard all old
387 * keys, 1 means retain all old keys, and a greater value means to retain that
388 * many key versions including the new one. A principal modifying its own keys
389 * is allowed to retain only a limited number of key versions.
390 */
391 static unsigned int
clamp_self_keepold(kadm5_server_handle_t handle,krb5_principal princ,krb5_boolean keepold)392 clamp_self_keepold(kadm5_server_handle_t handle, krb5_principal princ,
393 krb5_boolean keepold)
394 {
395 if (!keepold)
396 return 0;
397 if (krb5_principal_compare(handle->context, handle->current_caller, princ))
398 return MAX_SELF_KEEPOLD;
399 return 1;
400 }
401
402 static int
log_unauth(char * op,char * target,gss_buffer_t client,gss_buffer_t server,struct svc_req * rqstp)403 log_unauth(
404 char *op,
405 char *target,
406 gss_buffer_t client,
407 gss_buffer_t server,
408 struct svc_req *rqstp)
409 {
410 size_t tlen, clen, slen;
411 char *tdots, *cdots, *sdots;
412
413 tlen = strlen(target);
414 trunc_name(&tlen, &tdots);
415 clen = client->length;
416 trunc_name(&clen, &cdots);
417 slen = server->length;
418 trunc_name(&slen, &sdots);
419
420 /* okay to cast lengths to int because trunc_name limits max value */
421 return krb5_klog_syslog(LOG_NOTICE,
422 _("Unauthorized request: %s, %.*s%s, "
423 "client=%.*s%s, service=%.*s%s, addr=%s"),
424 op, (int)tlen, target, tdots,
425 (int)clen, (char *)client->value, cdots,
426 (int)slen, (char *)server->value, sdots,
427 client_addr(rqstp->rq_xprt));
428 }
429
430 static int
log_done(char * op,char * target,const char * errmsg,gss_buffer_t client,gss_buffer_t server,struct svc_req * rqstp)431 log_done(
432 char *op,
433 char *target,
434 const char *errmsg,
435 gss_buffer_t client,
436 gss_buffer_t server,
437 struct svc_req *rqstp)
438 {
439 size_t tlen, clen, slen;
440 char *tdots, *cdots, *sdots;
441
442 if (errmsg == NULL)
443 errmsg = _("success");
444 tlen = strlen(target);
445 trunc_name(&tlen, &tdots);
446 clen = client->length;
447 trunc_name(&clen, &cdots);
448 slen = server->length;
449 trunc_name(&slen, &sdots);
450
451 /* okay to cast lengths to int because trunc_name limits max value */
452 return krb5_klog_syslog(LOG_NOTICE,
453 _("Request: %s, %.*s%s, %s, "
454 "client=%.*s%s, service=%.*s%s, addr=%s"),
455 op, (int)tlen, target, tdots, errmsg,
456 (int)clen, (char *)client->value, cdots,
457 (int)slen, (char *)server->value, sdots,
458 client_addr(rqstp->rq_xprt));
459 }
460
461 bool_t
create_principal_2_svc(cprinc_arg * arg,generic_ret * ret,struct svc_req * rqstp)462 create_principal_2_svc(cprinc_arg *arg, generic_ret *ret,
463 struct svc_req *rqstp)
464 {
465 char *prime_arg = NULL;
466 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
467 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
468 kadm5_server_handle_t handle;
469 const char *errmsg = NULL;
470
471 ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
472 &handle, &ret->api_version, &client_name,
473 &service_name, &prime_arg, NULL);
474 if (ret->code)
475 goto exit_func;
476
477 if (CHANGEPW_SERVICE(rqstp) ||
478 !stub_auth_restrict(handle, OP_ADDPRINC, arg->rec.principal,
479 &arg->rec, &arg->mask)) {
480 ret->code = KADM5_AUTH_ADD;
481 log_unauth("kadm5_create_principal", prime_arg,
482 &client_name, &service_name, rqstp);
483 } else {
484 ret->code = kadm5_create_principal(handle, &arg->rec, arg->mask,
485 arg->passwd);
486
487 if (ret->code != 0)
488 errmsg = krb5_get_error_message(handle->context, ret->code);
489
490 log_done("kadm5_create_principal", prime_arg, errmsg,
491 &client_name, &service_name, rqstp);
492
493 if (errmsg != NULL)
494 krb5_free_error_message(handle->context, errmsg);
495 }
496
497 exit_func:
498 stub_cleanup(handle, prime_arg, &client_name, &service_name);
499 return TRUE;
500 }
501
502 bool_t
create_principal3_2_svc(cprinc3_arg * arg,generic_ret * ret,struct svc_req * rqstp)503 create_principal3_2_svc(cprinc3_arg *arg, generic_ret *ret,
504 struct svc_req *rqstp)
505 {
506 char *prime_arg = NULL;
507 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
508 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
509 kadm5_server_handle_t handle;
510 const char *errmsg = NULL;
511
512 ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
513 &handle, &ret->api_version, &client_name,
514 &service_name, &prime_arg, NULL);
515 if (ret->code)
516 goto exit_func;
517
518 if (CHANGEPW_SERVICE(rqstp) ||
519 !stub_auth_restrict(handle, OP_ADDPRINC, arg->rec.principal, &arg->rec,
520 &arg->mask)) {
521 ret->code = KADM5_AUTH_ADD;
522 log_unauth("kadm5_create_principal", prime_arg,
523 &client_name, &service_name, rqstp);
524 } else {
525 ret->code = kadm5_create_principal_3(handle, &arg->rec, arg->mask,
526 arg->n_ks_tuple, arg->ks_tuple,
527 arg->passwd);
528 if (ret->code != 0)
529 errmsg = krb5_get_error_message(handle->context, ret->code);
530
531 log_done("kadm5_create_principal", prime_arg, errmsg,
532 &client_name, &service_name, rqstp);
533
534 if (errmsg != NULL)
535 krb5_free_error_message(handle->context, errmsg);
536 }
537
538 exit_func:
539 stub_cleanup(handle, prime_arg, &client_name, &service_name);
540 return TRUE;
541 }
542
543 /* Return KADM5_PROTECT_KEYS if KRB5_KDB_LOCKDOWN_KEYS is set for rec. */
544 static inline kadm5_ret_t
check_lockdown(kadm5_principal_ent_t rec)545 check_lockdown(kadm5_principal_ent_t rec)
546 {
547 return (rec->attributes & KRB5_KDB_LOCKDOWN_KEYS) ? KADM5_PROTECT_KEYS : 0;
548 }
549
550 static kadm5_ret_t
check_lockdown_by_princ(kadm5_server_handle_t handle,krb5_principal princ)551 check_lockdown_by_princ(kadm5_server_handle_t handle, krb5_principal princ)
552 {
553 kadm5_principal_ent_rec rec;
554 kadm5_ret_t ret;
555
556 ret = kadm5_get_principal(handle, princ, &rec, KADM5_ATTRIBUTES);
557 if (ret)
558 return ret;
559 ret = check_lockdown(&rec);
560 kadm5_free_principal_ent(handle, &rec);
561 return ret;
562 }
563
564 bool_t
delete_principal_2_svc(dprinc_arg * arg,generic_ret * ret,struct svc_req * rqstp)565 delete_principal_2_svc(dprinc_arg *arg, generic_ret *ret,
566 struct svc_req *rqstp)
567 {
568 char *prime_arg = NULL;
569 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
570 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
571 kadm5_server_handle_t handle;
572 const char *errmsg = NULL;
573
574 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
575 &ret->api_version, &client_name, &service_name,
576 &prime_arg, NULL);
577 if (ret->code)
578 goto exit_func;
579
580 if (CHANGEPW_SERVICE(rqstp) ||
581 !stub_auth(handle, OP_DELPRINC, arg->princ, NULL, NULL, NULL)) {
582 ret->code = KADM5_AUTH_DELETE;
583 log_unauth("kadm5_delete_principal", prime_arg,
584 &client_name, &service_name, rqstp);
585 } else {
586 ret->code = check_lockdown_by_princ(handle, arg->princ);
587 if (ret->code == KADM5_PROTECT_KEYS) {
588 log_unauth("kadm5_delete_principal", prime_arg, &client_name,
589 &service_name, rqstp);
590 ret->code = KADM5_AUTH_DELETE;
591 }
592 }
593
594 if (ret->code == KADM5_OK)
595 ret->code = kadm5_delete_principal(handle, arg->princ);
596 if (ret->code != KADM5_AUTH_DELETE) {
597 if (ret->code != 0)
598 errmsg = krb5_get_error_message(handle->context, ret->code);
599
600 log_done("kadm5_delete_principal", prime_arg, errmsg,
601 &client_name, &service_name, rqstp);
602
603 if (errmsg != NULL)
604 krb5_free_error_message(handle->context, errmsg);
605
606 }
607
608 exit_func:
609 stub_cleanup(handle, prime_arg, &client_name, &service_name);
610 return TRUE;
611 }
612
613 bool_t
modify_principal_2_svc(mprinc_arg * arg,generic_ret * ret,struct svc_req * rqstp)614 modify_principal_2_svc(mprinc_arg *arg, generic_ret *ret,
615 struct svc_req *rqstp)
616 {
617 char *prime_arg = NULL;
618 kadm5_principal_ent_rec rec = { 0 }, rec_copy;
619 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
620 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
621 kadm5_server_handle_t handle;
622 const char *errmsg = NULL;
623
624 ret->code = stub_setup(arg->api_version, rqstp, arg->rec.principal,
625 &handle, &ret->api_version, &client_name,
626 &service_name, &prime_arg, &rec);
627 if (ret->code)
628 goto exit_func;
629
630 if (CHANGEPW_SERVICE(rqstp) ||
631 !stub_auth_restrict(handle, OP_MODPRINC, rec.principal, &arg->rec,
632 &arg->mask)) {
633 ret->code = KADM5_AUTH_MODIFY;
634 log_unauth("kadm5_modify_principal", prime_arg,
635 &client_name, &service_name, rqstp);
636 } else if ((arg->mask & KADM5_ATTRIBUTES) &&
637 (!(arg->rec.attributes & KRB5_KDB_LOCKDOWN_KEYS))) {
638 ret->code = check_lockdown(&rec);
639 if (ret->code == KADM5_PROTECT_KEYS) {
640 log_unauth("kadm5_modify_principal", prime_arg, &client_name,
641 &service_name, rqstp);
642 ret->code = KADM5_AUTH_MODIFY;
643 }
644 }
645
646 if (ret->code == KADM5_OK) {
647 /* Modify via the canonicalized principal name using a shallow copy of
648 * arg->rec, to ensure consistency with the ACL check. */
649 rec_copy = arg->rec;
650 rec_copy.principal = rec.principal;
651 ret->code = kadm5_modify_principal(handle, &rec_copy, arg->mask);
652 if (ret->code != 0)
653 errmsg = krb5_get_error_message(handle->context, ret->code);
654
655 log_done("kadm5_modify_principal", prime_arg, errmsg,
656 &client_name, &service_name, rqstp);
657
658 if (errmsg != NULL)
659 krb5_free_error_message(handle->context, errmsg);
660 }
661
662 exit_func:
663 kadm5_free_principal_ent(handle, &rec);
664 stub_cleanup(handle, prime_arg, &client_name, &service_name);
665 return TRUE;
666 }
667
668 bool_t
rename_principal_2_svc(rprinc_arg * arg,generic_ret * ret,struct svc_req * rqstp)669 rename_principal_2_svc(rprinc_arg *arg, generic_ret *ret,
670 struct svc_req *rqstp)
671 {
672 char *prime_arg1 = NULL, *prime_arg2 = NULL;
673 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
674 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
675 kadm5_server_handle_t handle;
676 const char *errmsg = NULL;
677 size_t tlen1, tlen2, clen, slen;
678 char *tdots1, *tdots2, *cdots, *sdots;
679
680 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
681 &ret->api_version, &client_name, &service_name,
682 NULL, NULL);
683 if (ret->code)
684 goto exit_func;
685
686 if (krb5_unparse_name(handle->context, arg->src, &prime_arg1) ||
687 krb5_unparse_name(handle->context, arg->dest, &prime_arg2)) {
688 ret->code = KADM5_BAD_PRINCIPAL;
689 goto exit_func;
690 }
691 tlen1 = strlen(prime_arg1);
692 trunc_name(&tlen1, &tdots1);
693 tlen2 = strlen(prime_arg2);
694 trunc_name(&tlen2, &tdots2);
695 clen = client_name.length;
696 trunc_name(&clen, &cdots);
697 slen = service_name.length;
698 trunc_name(&slen, &sdots);
699
700 if (CHANGEPW_SERVICE(rqstp) ||
701 !stub_auth(handle, OP_RENPRINC, arg->src, arg->dest, NULL, NULL)) {
702 ret->code = KADM5_AUTH_INSUFFICIENT;
703 log_unauth("kadm5_rename_principal", prime_arg1, &client_name,
704 &service_name, rqstp);
705 } else {
706 ret->code = check_lockdown_by_princ(handle, arg->src);
707 if (ret->code == KADM5_PROTECT_KEYS) {
708 log_unauth("kadm5_rename_principal", prime_arg1, &client_name,
709 &service_name, rqstp);
710 ret->code = KADM5_AUTH_DELETE;
711 }
712 }
713 if (ret->code != KADM5_OK) {
714 /* okay to cast lengths to int because trunc_name limits max value */
715 krb5_klog_syslog(LOG_NOTICE,
716 _("Unauthorized request: kadm5_rename_principal, "
717 "%.*s%s to %.*s%s, "
718 "client=%.*s%s, service=%.*s%s, addr=%s"),
719 (int)tlen1, prime_arg1, tdots1,
720 (int)tlen2, prime_arg2, tdots2,
721 (int)clen, (char *)client_name.value, cdots,
722 (int)slen, (char *)service_name.value, sdots,
723 client_addr(rqstp->rq_xprt));
724 } else {
725 ret->code = kadm5_rename_principal(handle, arg->src, arg->dest);
726 if (ret->code != 0)
727 errmsg = krb5_get_error_message(handle->context, ret->code);
728
729 /* okay to cast lengths to int because trunc_name limits max value */
730 krb5_klog_syslog(LOG_NOTICE,
731 _("Request: kadm5_rename_principal, "
732 "%.*s%s to %.*s%s, %s, "
733 "client=%.*s%s, service=%.*s%s, addr=%s"),
734 (int)tlen1, prime_arg1, tdots1,
735 (int)tlen2, prime_arg2, tdots2,
736 errmsg ? errmsg : _("success"),
737 (int)clen, (char *)client_name.value, cdots,
738 (int)slen, (char *)service_name.value, sdots,
739 client_addr(rqstp->rq_xprt));
740
741 if (errmsg != NULL)
742 krb5_free_error_message(handle->context, errmsg);
743
744 }
745 exit_func:
746 free(prime_arg1);
747 free(prime_arg2);
748 stub_cleanup(handle, NULL, &client_name, &service_name);
749 return TRUE;
750 }
751
752 bool_t
get_principal_2_svc(gprinc_arg * arg,gprinc_ret * ret,struct svc_req * rqstp)753 get_principal_2_svc(gprinc_arg *arg, gprinc_ret *ret, struct svc_req *rqstp)
754 {
755 char *funcname, *prime_arg = NULL;
756 kadm5_principal_ent_rec rec = { 0 };
757 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
758 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
759 kadm5_server_handle_t handle;
760 const char *errmsg = NULL;
761
762 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
763 &ret->api_version, &client_name, &service_name,
764 &prime_arg, &rec);
765 if (ret->code)
766 goto exit_func;
767
768 funcname = "kadm5_get_principal";
769
770 if (changepw_not_self(handle, rqstp, rec.principal) ||
771 !stub_auth(handle, OP_GETPRINC, rec.principal, NULL, NULL, NULL)) {
772 ret->code = KADM5_AUTH_GET;
773 log_unauth(funcname, prime_arg,
774 &client_name, &service_name, rqstp);
775 } else {
776 ret->code = kadm5_get_principal(handle, rec.principal, &ret->rec,
777 arg->mask);
778
779 if (ret->code != 0)
780 errmsg = krb5_get_error_message(handle->context, ret->code);
781
782 log_done(funcname, prime_arg, errmsg,
783 &client_name, &service_name, rqstp);
784
785 if (errmsg != NULL)
786 krb5_free_error_message(handle->context, errmsg);
787 }
788
789 exit_func:
790 kadm5_free_principal_ent(handle, &rec);
791 stub_cleanup(handle, prime_arg, &client_name, &service_name);
792 return TRUE;
793 }
794
795 bool_t
get_princs_2_svc(gprincs_arg * arg,gprincs_ret * ret,struct svc_req * rqstp)796 get_princs_2_svc(gprincs_arg *arg, gprincs_ret *ret, struct svc_req *rqstp)
797 {
798 char *prime_arg = NULL;
799 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
800 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
801 kadm5_server_handle_t handle;
802 const char *errmsg = NULL;
803
804 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
805 &ret->api_version, &client_name, &service_name,
806 NULL, NULL);
807 if (ret->code)
808 goto exit_func;
809
810 prime_arg = arg->exp;
811 if (prime_arg == NULL)
812 prime_arg = "*";
813
814 if (CHANGEPW_SERVICE(rqstp) ||
815 !stub_auth(handle, OP_LISTPRINCS, NULL, NULL, NULL, NULL)) {
816 ret->code = KADM5_AUTH_LIST;
817 log_unauth("kadm5_get_principals", prime_arg,
818 &client_name, &service_name, rqstp);
819 } else {
820 ret->code = kadm5_get_principals(handle, arg->exp, &ret->princs,
821 &ret->count);
822 if (ret->code != 0)
823 errmsg = krb5_get_error_message(handle->context, ret->code);
824
825 log_done("kadm5_get_principals", prime_arg, errmsg,
826 &client_name, &service_name, rqstp);
827
828 if (errmsg != NULL)
829 krb5_free_error_message(handle->context, errmsg);
830
831 }
832
833 exit_func:
834 stub_cleanup(handle, NULL, &client_name, &service_name);
835 return TRUE;
836 }
837
838 bool_t
chpass_principal_2_svc(chpass_arg * arg,generic_ret * ret,struct svc_req * rqstp)839 chpass_principal_2_svc(chpass_arg *arg, generic_ret *ret,
840 struct svc_req *rqstp)
841 {
842 char *prime_arg = NULL;
843 kadm5_principal_ent_rec rec = { 0 };
844 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
845 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
846 kadm5_server_handle_t handle;
847 const char *errmsg = NULL;
848
849 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
850 &ret->api_version, &client_name, &service_name,
851 &prime_arg, &rec);
852 if (ret->code)
853 goto exit_func;
854
855 ret->code = check_lockdown(&rec);
856 if (ret->code != KADM5_OK) {
857 if (ret->code == KADM5_PROTECT_KEYS) {
858 log_unauth("kadm5_chpass_principal", prime_arg, &client_name,
859 &service_name, rqstp);
860 ret->code = KADM5_AUTH_CHANGEPW;
861 }
862 } else if (changepw_not_self(handle, rqstp, rec.principal) ||
863 !stub_auth(handle, OP_CPW, rec.principal, NULL, NULL, NULL)) {
864 ret->code = KADM5_AUTH_CHANGEPW;
865 log_unauth("kadm5_chpass_principal", prime_arg,
866 &client_name, &service_name, rqstp);
867 } else {
868 ret->code = check_self_keychange(handle, rqstp, rec.principal);
869 if (!ret->code) {
870 ret->code = kadm5_chpass_principal(handle, rec.principal,
871 arg->pass);
872 }
873 }
874
875 if (ret->code != KADM5_AUTH_CHANGEPW) {
876 if (ret->code != 0)
877 errmsg = krb5_get_error_message(handle->context, ret->code);
878
879 log_done("kadm5_chpass_principal", prime_arg, errmsg,
880 &client_name, &service_name, rqstp);
881
882 if (errmsg != NULL)
883 krb5_free_error_message(handle->context, errmsg);
884 }
885
886 exit_func:
887 kadm5_free_principal_ent(handle, &rec);
888 stub_cleanup(handle, prime_arg, &client_name, &service_name);
889 return TRUE;
890 }
891
892 bool_t
chpass_principal3_2_svc(chpass3_arg * arg,generic_ret * ret,struct svc_req * rqstp)893 chpass_principal3_2_svc(chpass3_arg *arg, generic_ret *ret,
894 struct svc_req *rqstp)
895 {
896 char *prime_arg = NULL;
897 kadm5_principal_ent_rec rec = { 0 };
898 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
899 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
900 unsigned int keepold;
901 kadm5_server_handle_t handle;
902 const char *errmsg = NULL;
903
904 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
905 &ret->api_version, &client_name, &service_name,
906 &prime_arg, &rec);
907 if (ret->code)
908 goto exit_func;
909
910 ret->code = check_lockdown(&rec);
911 if (ret->code != KADM5_OK) {
912 if (ret->code == KADM5_PROTECT_KEYS) {
913 log_unauth("kadm5_chpass_principal", prime_arg, &client_name,
914 &service_name, rqstp);
915 ret->code = KADM5_AUTH_CHANGEPW;
916 }
917 } else if (changepw_not_self(handle, rqstp, rec.principal) ||
918 !stub_auth(handle, OP_CPW, rec.principal, NULL, NULL, NULL)) {
919 ret->code = KADM5_AUTH_CHANGEPW;
920 log_unauth("kadm5_chpass_principal", prime_arg,
921 &client_name, &service_name, rqstp);
922 } else {
923 ret->code = check_self_keychange(handle, rqstp, rec.principal);
924 if (!ret->code) {
925 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold);
926 ret->code = kadm5_chpass_principal_3(handle, rec.principal,
927 keepold, arg->n_ks_tuple,
928 arg->ks_tuple, arg->pass);
929 }
930 }
931
932 if (ret->code != KADM5_AUTH_CHANGEPW) {
933 if (ret->code != 0)
934 errmsg = krb5_get_error_message(handle->context, ret->code);
935
936 log_done("kadm5_chpass_principal", prime_arg, errmsg,
937 &client_name, &service_name, rqstp);
938
939 if (errmsg != NULL)
940 krb5_free_error_message(handle->context, errmsg);
941 }
942
943 exit_func:
944 kadm5_free_principal_ent(handle, &rec);
945 stub_cleanup(handle, prime_arg, &client_name, &service_name);
946 return TRUE;
947 }
948
949 bool_t
setkey_principal_2_svc(setkey_arg * arg,generic_ret * ret,struct svc_req * rqstp)950 setkey_principal_2_svc(setkey_arg *arg, generic_ret *ret,
951 struct svc_req *rqstp)
952 {
953 char *prime_arg = NULL;
954 kadm5_principal_ent_rec rec = { 0 };
955 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
956 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
957 kadm5_server_handle_t handle;
958 const char *errmsg = NULL;
959
960 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
961 &ret->api_version, &client_name, &service_name,
962 &prime_arg, &rec);
963 if (ret->code)
964 goto exit_func;
965
966 ret->code = check_lockdown(&rec);
967 if (ret->code != KADM5_OK) {
968 if (ret->code == KADM5_PROTECT_KEYS) {
969 log_unauth("kadm5_setkey_principal", prime_arg, &client_name,
970 &service_name, rqstp);
971 ret->code = KADM5_AUTH_SETKEY;
972 }
973 } else if (!(CHANGEPW_SERVICE(rqstp)) &&
974 stub_auth(handle, OP_SETKEY, rec.principal, NULL, NULL, NULL)) {
975 ret->code = kadm5_setkey_principal(handle, rec.principal,
976 arg->keyblocks, arg->n_keys);
977 } else {
978 log_unauth("kadm5_setkey_principal", prime_arg,
979 &client_name, &service_name, rqstp);
980 ret->code = KADM5_AUTH_SETKEY;
981 }
982
983 if (ret->code != KADM5_AUTH_SETKEY) {
984 if (ret->code != 0)
985 errmsg = krb5_get_error_message(handle->context, ret->code);
986
987 log_done("kadm5_setkey_principal", prime_arg, errmsg,
988 &client_name, &service_name, rqstp);
989
990 if (errmsg != NULL)
991 krb5_free_error_message(handle->context, errmsg);
992 }
993
994 exit_func:
995 kadm5_free_principal_ent(handle, &rec);
996 stub_cleanup(handle, prime_arg, &client_name, &service_name);
997 return TRUE;
998 }
999
1000 bool_t
setkey_principal3_2_svc(setkey3_arg * arg,generic_ret * ret,struct svc_req * rqstp)1001 setkey_principal3_2_svc(setkey3_arg *arg, generic_ret *ret,
1002 struct svc_req *rqstp)
1003 {
1004 char *prime_arg = NULL;
1005 kadm5_principal_ent_rec rec = { 0 };
1006 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1007 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1008 unsigned int keepold;
1009 kadm5_server_handle_t handle;
1010 const char *errmsg = NULL;
1011
1012 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1013 &ret->api_version, &client_name, &service_name,
1014 &prime_arg, &rec);
1015 if (ret->code)
1016 goto exit_func;
1017
1018 ret->code = check_lockdown(&rec);
1019 if (ret->code != KADM5_OK) {
1020 if (ret->code == KADM5_PROTECT_KEYS) {
1021 log_unauth("kadm5_setkey_principal", prime_arg, &client_name,
1022 &service_name, rqstp);
1023 ret->code = KADM5_AUTH_SETKEY;
1024 }
1025 } else if (!(CHANGEPW_SERVICE(rqstp)) &&
1026 stub_auth(handle, OP_SETKEY, rec.principal, NULL, NULL, NULL)) {
1027 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold);
1028 ret->code = kadm5_setkey_principal_3(handle, rec.principal, keepold,
1029 arg->n_ks_tuple, arg->ks_tuple,
1030 arg->keyblocks, arg->n_keys);
1031 } else {
1032 log_unauth("kadm5_setkey_principal", prime_arg,
1033 &client_name, &service_name, rqstp);
1034 ret->code = KADM5_AUTH_SETKEY;
1035 }
1036
1037 if (ret->code != KADM5_AUTH_SETKEY) {
1038 if (ret->code != 0)
1039 errmsg = krb5_get_error_message(handle->context, ret->code);
1040
1041 log_done("kadm5_setkey_principal", prime_arg, errmsg,
1042 &client_name, &service_name, rqstp);
1043
1044 if (errmsg != NULL)
1045 krb5_free_error_message(handle->context, errmsg);
1046 }
1047
1048 exit_func:
1049 kadm5_free_principal_ent(handle, &rec);
1050 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1051 return TRUE;
1052 }
1053
1054 bool_t
setkey_principal4_2_svc(setkey4_arg * arg,generic_ret * ret,struct svc_req * rqstp)1055 setkey_principal4_2_svc(setkey4_arg *arg, generic_ret *ret,
1056 struct svc_req *rqstp)
1057 {
1058 char *prime_arg = NULL;
1059 kadm5_principal_ent_rec rec = { 0 };
1060 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1061 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1062 unsigned int keepold;
1063 kadm5_server_handle_t handle;
1064 const char *errmsg = NULL;
1065
1066 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1067 &ret->api_version, &client_name, &service_name,
1068 &prime_arg, &rec);
1069 if (ret->code)
1070 goto exit_func;
1071
1072 ret->code = check_lockdown(&rec);
1073 if (ret->code != KADM5_OK) {
1074 if (ret->code == KADM5_PROTECT_KEYS) {
1075 log_unauth("kadm5_setkey_principal", prime_arg, &client_name,
1076 &service_name, rqstp);
1077 ret->code = KADM5_AUTH_SETKEY;
1078 }
1079 } else if (!(CHANGEPW_SERVICE(rqstp)) &&
1080 stub_auth(handle, OP_SETKEY, rec.principal, NULL, NULL, NULL)) {
1081 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold);
1082 ret->code = kadm5_setkey_principal_4(handle, rec.principal, keepold,
1083 arg->key_data, arg->n_key_data);
1084 } else {
1085 log_unauth("kadm5_setkey_principal", prime_arg, &client_name,
1086 &service_name, rqstp);
1087 ret->code = KADM5_AUTH_SETKEY;
1088 }
1089
1090 if (ret->code != KADM5_AUTH_SETKEY) {
1091 if (ret->code != 0)
1092 errmsg = krb5_get_error_message(handle->context, ret->code);
1093
1094 log_done("kadm5_setkey_principal", prime_arg, errmsg, &client_name,
1095 &service_name, rqstp);
1096
1097 if (errmsg != NULL)
1098 krb5_free_error_message(handle->context, errmsg);
1099 }
1100
1101 exit_func:
1102 kadm5_free_principal_ent(handle, &rec);
1103 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1104 return TRUE;
1105 }
1106
1107 /* Empty out *keys / *nkeys if princ is protected with the lockdown
1108 * attribute, or if we fail to check. */
1109 static kadm5_ret_t
chrand_check_lockdown(kadm5_server_handle_t handle,kadm5_principal_ent_t rec,krb5_keyblock ** keys,int * nkeys)1110 chrand_check_lockdown(kadm5_server_handle_t handle, kadm5_principal_ent_t rec,
1111 krb5_keyblock **keys, int *nkeys)
1112 {
1113 kadm5_ret_t ret;
1114 int i;
1115
1116 ret = check_lockdown(rec);
1117 if (!ret)
1118 return 0;
1119
1120 for (i = 0; i < *nkeys; i++)
1121 krb5_free_keyblock_contents(handle->context, &((*keys)[i]));
1122 free(*keys);
1123 *keys = NULL;
1124 *nkeys = 0;
1125 return (ret == KADM5_PROTECT_KEYS) ? KADM5_OK : ret;
1126 }
1127
1128 bool_t
chrand_principal_2_svc(chrand_arg * arg,chrand_ret * ret,struct svc_req * rqstp)1129 chrand_principal_2_svc(chrand_arg *arg, chrand_ret *ret, struct svc_req *rqstp)
1130 {
1131 char *funcname, *prime_arg = NULL;
1132 kadm5_principal_ent_rec rec = { 0 };
1133 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1134 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1135 krb5_keyblock *k;
1136 int nkeys;
1137 kadm5_server_handle_t handle;
1138 const char *errmsg = NULL;
1139
1140 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1141 &ret->api_version, &client_name, &service_name,
1142 &prime_arg, &rec);
1143 if (ret->code)
1144 goto exit_func;
1145
1146 funcname = "kadm5_randkey_principal";
1147
1148 if (changepw_not_self(handle, rqstp, rec.principal) ||
1149 !stub_auth(handle, OP_CHRAND, rec.principal, NULL, NULL, NULL)) {
1150 ret->code = KADM5_AUTH_CHANGEPW;
1151 log_unauth(funcname, prime_arg,
1152 &client_name, &service_name, rqstp);
1153 } else {
1154 ret->code = check_self_keychange(handle, rqstp, rec.principal);
1155 if (!ret->code) {
1156 ret->code = kadm5_randkey_principal(handle, rec.principal,
1157 &k, &nkeys);
1158 }
1159 }
1160
1161 if (ret->code == KADM5_OK) {
1162 ret->code = chrand_check_lockdown(handle, &rec, &k, &nkeys);
1163 if (ret->code == KADM5_PROTECT_KEYS)
1164 ret->code = KADM5_OK;
1165 ret->keys = k;
1166 ret->n_keys = nkeys;
1167 }
1168
1169 if (ret->code != KADM5_AUTH_CHANGEPW) {
1170 if (ret->code != 0)
1171 errmsg = krb5_get_error_message(handle->context, ret->code);
1172
1173 log_done(funcname, prime_arg, errmsg,
1174 &client_name, &service_name, rqstp);
1175
1176 if (errmsg != NULL)
1177 krb5_free_error_message(handle->context, errmsg);
1178 }
1179
1180 exit_func:
1181 kadm5_free_principal_ent(handle, &rec);
1182 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1183 return TRUE;
1184 }
1185
1186 bool_t
chrand_principal3_2_svc(chrand3_arg * arg,chrand_ret * ret,struct svc_req * rqstp)1187 chrand_principal3_2_svc(chrand3_arg *arg, chrand_ret *ret,
1188 struct svc_req *rqstp)
1189 {
1190 char *funcname, *prime_arg = NULL;
1191 kadm5_principal_ent_rec rec = { 0 };
1192 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1193 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1194 krb5_keyblock *k;
1195 int nkeys;
1196 unsigned int keepold;
1197 kadm5_server_handle_t handle;
1198 const char *errmsg = NULL;
1199
1200 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1201 &ret->api_version, &client_name, &service_name,
1202 &prime_arg, &rec);
1203 if (ret->code)
1204 goto exit_func;
1205
1206 funcname = "kadm5_randkey_principal";
1207
1208 if (changepw_not_self(handle, rqstp, rec.principal) ||
1209 !stub_auth(handle, OP_CHRAND, rec.principal, NULL, NULL, NULL)) {
1210 ret->code = KADM5_AUTH_CHANGEPW;
1211 log_unauth(funcname, prime_arg,
1212 &client_name, &service_name, rqstp);
1213 } else {
1214 ret->code = check_self_keychange(handle, rqstp, rec.principal);
1215 if (!ret->code) {
1216 keepold = clamp_self_keepold(handle, rec.principal, arg->keepold);
1217 ret->code = kadm5_randkey_principal_3(handle, rec.principal,
1218 keepold, arg->n_ks_tuple,
1219 arg->ks_tuple, &k, &nkeys);
1220 }
1221 }
1222
1223 if (ret->code == KADM5_OK) {
1224 ret->code = chrand_check_lockdown(handle, &rec, &k, &nkeys);
1225 if (ret->code == KADM5_PROTECT_KEYS)
1226 ret->code = KADM5_OK;
1227 ret->keys = k;
1228 ret->n_keys = nkeys;
1229 }
1230
1231 if (ret->code != KADM5_AUTH_CHANGEPW) {
1232 if (ret->code != 0)
1233 errmsg = krb5_get_error_message(handle->context, ret->code);
1234
1235 log_done(funcname, prime_arg, errmsg,
1236 &client_name, &service_name, rqstp);
1237
1238 if (errmsg != NULL)
1239 krb5_free_error_message(handle->context, errmsg);
1240 }
1241
1242 exit_func:
1243 kadm5_free_principal_ent(handle, &rec);
1244 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1245 return TRUE;
1246 }
1247
1248 bool_t
create_policy_2_svc(cpol_arg * arg,generic_ret * ret,struct svc_req * rqstp)1249 create_policy_2_svc(cpol_arg *arg, generic_ret *ret, struct svc_req *rqstp)
1250 {
1251 char *prime_arg = NULL;
1252 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1253 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1254 kadm5_server_handle_t handle;
1255 const char *errmsg = NULL;
1256
1257 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
1258 &ret->api_version, &client_name, &service_name,
1259 NULL, NULL);
1260 if (ret->code)
1261 goto exit_func;
1262
1263 prime_arg = arg->rec.policy;
1264
1265 if (CHANGEPW_SERVICE(rqstp) ||
1266 !stub_auth_pol(handle, OP_ADDPOL, arg->rec.policy,
1267 &arg->rec, arg->mask)) {
1268 ret->code = KADM5_AUTH_ADD;
1269 log_unauth("kadm5_create_policy", prime_arg,
1270 &client_name, &service_name, rqstp);
1271
1272 } else {
1273 ret->code = kadm5_create_policy(handle, &arg->rec, arg->mask);
1274 if (ret->code != 0)
1275 errmsg = krb5_get_error_message(handle->context, ret->code);
1276
1277 log_done("kadm5_create_policy",
1278 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
1279 &client_name, &service_name, rqstp);
1280
1281 if (errmsg != NULL)
1282 krb5_free_error_message(handle->context, errmsg);
1283 }
1284
1285 exit_func:
1286 stub_cleanup(handle, NULL, &client_name, &service_name);
1287 return TRUE;
1288 }
1289
1290 bool_t
delete_policy_2_svc(dpol_arg * arg,generic_ret * ret,struct svc_req * rqstp)1291 delete_policy_2_svc(dpol_arg *arg, generic_ret *ret, struct svc_req *rqstp)
1292 {
1293 char *prime_arg = NULL;
1294 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1295 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1296 kadm5_server_handle_t handle;
1297 const char *errmsg = NULL;
1298
1299 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
1300 &ret->api_version, &client_name, &service_name,
1301 NULL, NULL);
1302 if (ret->code)
1303 goto exit_func;
1304
1305 prime_arg = arg->name;
1306
1307 if (CHANGEPW_SERVICE(rqstp) ||
1308 !stub_auth(handle, OP_DELPOL, NULL, NULL, arg->name, NULL)) {
1309 log_unauth("kadm5_delete_policy", prime_arg,
1310 &client_name, &service_name, rqstp);
1311 ret->code = KADM5_AUTH_DELETE;
1312 } else {
1313 ret->code = kadm5_delete_policy(handle, arg->name);
1314 if (ret->code != 0)
1315 errmsg = krb5_get_error_message(handle->context, ret->code);
1316
1317 log_done("kadm5_delete_policy",
1318 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
1319 &client_name, &service_name, rqstp);
1320
1321 if (errmsg != NULL)
1322 krb5_free_error_message(handle->context, errmsg);
1323 }
1324
1325 exit_func:
1326 stub_cleanup(handle, NULL, &client_name, &service_name);
1327 return TRUE;
1328 }
1329
1330 bool_t
modify_policy_2_svc(mpol_arg * arg,generic_ret * ret,struct svc_req * rqstp)1331 modify_policy_2_svc(mpol_arg *arg, generic_ret *ret, struct svc_req *rqstp)
1332 {
1333 char *prime_arg = NULL;
1334 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1335 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1336 kadm5_server_handle_t handle;
1337 const char *errmsg = NULL;
1338
1339 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
1340 &ret->api_version, &client_name, &service_name,
1341 NULL, NULL);
1342 if (ret->code)
1343 goto exit_func;
1344
1345 prime_arg = arg->rec.policy;
1346
1347 if (CHANGEPW_SERVICE(rqstp) ||
1348 !stub_auth_pol(handle, OP_MODPOL, arg->rec.policy,
1349 &arg->rec, arg->mask)) {
1350 log_unauth("kadm5_modify_policy", prime_arg,
1351 &client_name, &service_name, rqstp);
1352 ret->code = KADM5_AUTH_MODIFY;
1353 } else {
1354 ret->code = kadm5_modify_policy(handle, &arg->rec, arg->mask);
1355 if (ret->code != 0)
1356 errmsg = krb5_get_error_message(handle->context, ret->code);
1357
1358 log_done("kadm5_modify_policy",
1359 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
1360 &client_name, &service_name, rqstp);
1361
1362 if (errmsg != NULL)
1363 krb5_free_error_message(handle->context, errmsg);
1364 }
1365
1366 exit_func:
1367 stub_cleanup(handle, NULL, &client_name, &service_name);
1368 return TRUE;
1369 }
1370
1371 bool_t
get_policy_2_svc(gpol_arg * arg,gpol_ret * ret,struct svc_req * rqstp)1372 get_policy_2_svc(gpol_arg *arg, gpol_ret *ret, struct svc_req *rqstp)
1373 {
1374 char *funcname, *prime_arg = NULL;
1375 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1376 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1377 kadm5_ret_t ret2;
1378 kadm5_principal_ent_rec caller_ent;
1379 kadm5_server_handle_t handle;
1380 const char *errmsg = NULL, *cpolicy = NULL;
1381
1382 memset(&caller_ent, 0, sizeof(caller_ent));
1383
1384 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
1385 &ret->api_version, &client_name, &service_name,
1386 NULL, NULL);
1387 if (ret->code)
1388 goto exit_func;
1389
1390 funcname = "kadm5_get_policy";
1391
1392 prime_arg = arg->name;
1393
1394 /* Look up the client principal's policy value. */
1395 ret2 = kadm5_get_principal(handle->lhandle, handle->current_caller,
1396 &caller_ent, KADM5_PRINCIPAL_NORMAL_MASK);
1397 if (ret2 == KADM5_OK && (caller_ent.aux_attributes & KADM5_POLICY))
1398 cpolicy = caller_ent.policy;
1399
1400 ret->code = KADM5_AUTH_GET;
1401 if ((CHANGEPW_SERVICE(rqstp) &&
1402 (cpolicy == NULL || strcmp(cpolicy, arg->name) != 0)) ||
1403 !stub_auth(handle, OP_GETPOL, NULL, NULL, arg->name, cpolicy)) {
1404 ret->code = KADM5_AUTH_GET;
1405 log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp);
1406 } else {
1407 ret->code = kadm5_get_policy(handle, arg->name, &ret->rec);
1408 if (ret->code != 0)
1409 errmsg = krb5_get_error_message(handle->context, ret->code);
1410
1411 log_done(funcname,
1412 ((prime_arg == NULL) ? "(null)" : prime_arg), errmsg,
1413 &client_name, &service_name, rqstp);
1414 if (errmsg != NULL)
1415 krb5_free_error_message(handle->context, errmsg);
1416 }
1417
1418 exit_func:
1419 (void)kadm5_free_principal_ent(handle->lhandle, &caller_ent);
1420 stub_cleanup(handle, NULL, &client_name, &service_name);
1421 return TRUE;
1422 }
1423
1424 bool_t
get_pols_2_svc(gpols_arg * arg,gpols_ret * ret,struct svc_req * rqstp)1425 get_pols_2_svc(gpols_arg *arg, gpols_ret *ret, struct svc_req *rqstp)
1426 {
1427 char *prime_arg = NULL;
1428 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1429 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1430 kadm5_server_handle_t handle;
1431 const char *errmsg = NULL;
1432
1433 ret->code = stub_setup(arg->api_version, rqstp, NULL, &handle,
1434 &ret->api_version, &client_name, &service_name,
1435 NULL, NULL);
1436 if (ret->code)
1437 goto exit_func;
1438
1439 prime_arg = arg->exp;
1440 if (prime_arg == NULL)
1441 prime_arg = "*";
1442
1443 if (CHANGEPW_SERVICE(rqstp) ||
1444 !stub_auth(handle, OP_LISTPOLS, NULL, NULL, NULL, NULL)) {
1445 ret->code = KADM5_AUTH_LIST;
1446 log_unauth("kadm5_get_policies", prime_arg,
1447 &client_name, &service_name, rqstp);
1448 } else {
1449 ret->code = kadm5_get_policies(handle, arg->exp, &ret->pols,
1450 &ret->count);
1451 if (ret->code != 0)
1452 errmsg = krb5_get_error_message(handle->context, ret->code);
1453
1454 log_done("kadm5_get_policies", prime_arg, errmsg,
1455 &client_name, &service_name, rqstp);
1456
1457 if (errmsg != NULL)
1458 krb5_free_error_message(handle->context, errmsg);
1459 }
1460
1461 exit_func:
1462 stub_cleanup(handle, NULL, &client_name, &service_name);
1463 return TRUE;
1464 }
1465
1466 bool_t
get_privs_2_svc(krb5_ui_4 * arg,getprivs_ret * ret,struct svc_req * rqstp)1467 get_privs_2_svc(krb5_ui_4 *arg, getprivs_ret *ret, struct svc_req *rqstp)
1468 {
1469 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1470 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1471 kadm5_server_handle_t handle;
1472 const char *errmsg = NULL;
1473
1474 ret->code = stub_setup(*arg, rqstp, NULL, &handle, &ret->api_version,
1475 &client_name, &service_name, NULL, NULL);
1476 if (ret->code)
1477 goto exit_func;
1478
1479 ret->code = kadm5_get_privs(handle, &ret->privs);
1480 if (ret->code != 0)
1481 errmsg = krb5_get_error_message(handle->context, ret->code);
1482
1483 log_done("kadm5_get_privs", client_name.value, errmsg,
1484 &client_name, &service_name, rqstp);
1485
1486 if (errmsg != NULL)
1487 krb5_free_error_message(handle->context, errmsg);
1488
1489 exit_func:
1490 stub_cleanup(handle, NULL, &client_name, &service_name);
1491 return TRUE;
1492 }
1493
1494 bool_t
purgekeys_2_svc(purgekeys_arg * arg,generic_ret * ret,struct svc_req * rqstp)1495 purgekeys_2_svc(purgekeys_arg *arg, generic_ret *ret, struct svc_req *rqstp)
1496 {
1497 char *funcname, *prime_arg = NULL;
1498 kadm5_principal_ent_rec rec = { 0 };
1499 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1500 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1501 kadm5_server_handle_t handle;
1502
1503 const char *errmsg = NULL;
1504
1505 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1506 &ret->api_version, &client_name, &service_name,
1507 &prime_arg, &rec);
1508 if (ret->code)
1509 goto exit_func;
1510
1511 funcname = "kadm5_purgekeys";
1512
1513 if (CHANGEPW_SERVICE(rqstp) ||
1514 !stub_auth(handle, OP_PURGEKEYS, rec.principal, NULL, NULL, NULL)) {
1515 ret->code = KADM5_AUTH_MODIFY;
1516 log_unauth(funcname, prime_arg, &client_name, &service_name, rqstp);
1517 } else {
1518 ret->code = kadm5_purgekeys(handle, rec.principal, arg->keepkvno);
1519 if (ret->code != 0)
1520 errmsg = krb5_get_error_message(handle->context, ret->code);
1521
1522 log_done(funcname, prime_arg, errmsg,
1523 &client_name, &service_name, rqstp);
1524
1525 if (errmsg != NULL)
1526 krb5_free_error_message(handle->context, errmsg);
1527 }
1528
1529 exit_func:
1530 kadm5_free_principal_ent(handle, &rec);
1531 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1532 return TRUE;
1533 }
1534
1535 bool_t
get_strings_2_svc(gstrings_arg * arg,gstrings_ret * ret,struct svc_req * rqstp)1536 get_strings_2_svc(gstrings_arg *arg, gstrings_ret *ret, struct svc_req *rqstp)
1537 {
1538 char *prime_arg = NULL;
1539 kadm5_principal_ent_rec rec = { 0 };
1540 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1541 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1542 kadm5_server_handle_t handle;
1543 const char *errmsg = NULL;
1544
1545 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1546 &ret->api_version, &client_name, &service_name,
1547 &prime_arg, &rec);
1548 if (ret->code)
1549 goto exit_func;
1550
1551 if (CHANGEPW_SERVICE(rqstp) ||
1552 !stub_auth(handle, OP_GETSTRS, rec.principal, NULL, NULL, NULL)) {
1553 ret->code = KADM5_AUTH_GET;
1554 log_unauth("kadm5_get_strings", prime_arg,
1555 &client_name, &service_name, rqstp);
1556 } else {
1557 ret->code = kadm5_get_strings(handle, rec.principal, &ret->strings,
1558 &ret->count);
1559 if (ret->code != 0)
1560 errmsg = krb5_get_error_message(handle->context, ret->code);
1561
1562 log_done("kadm5_get_strings", prime_arg, errmsg,
1563 &client_name, &service_name, rqstp);
1564
1565 if (errmsg != NULL)
1566 krb5_free_error_message(handle->context, errmsg);
1567 }
1568
1569 exit_func:
1570 kadm5_free_principal_ent(handle, &rec);
1571 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1572 return TRUE;
1573 }
1574
1575 bool_t
set_string_2_svc(sstring_arg * arg,generic_ret * ret,struct svc_req * rqstp)1576 set_string_2_svc(sstring_arg *arg, generic_ret *ret, struct svc_req *rqstp)
1577 {
1578 char *prime_arg = NULL;
1579 kadm5_principal_ent_rec rec = { 0 };
1580 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1581 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1582 kadm5_server_handle_t handle;
1583 const char *errmsg = NULL;
1584
1585 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1586 &ret->api_version, &client_name, &service_name,
1587 &prime_arg, &rec);
1588 if (ret->code)
1589 goto exit_func;
1590
1591 if (CHANGEPW_SERVICE(rqstp) ||
1592 !stub_auth(handle, OP_SETSTR, rec.principal, NULL,
1593 arg->key, arg->value)) {
1594 ret->code = KADM5_AUTH_MODIFY;
1595 log_unauth("kadm5_mod_strings", prime_arg,
1596 &client_name, &service_name, rqstp);
1597 } else {
1598 ret->code = kadm5_set_string(handle, rec.principal,
1599 arg->key, arg->value);
1600 if (ret->code != 0)
1601 errmsg = krb5_get_error_message(handle->context, ret->code);
1602
1603 log_done("kadm5_mod_strings", prime_arg, errmsg,
1604 &client_name, &service_name, rqstp);
1605
1606 if (errmsg != NULL)
1607 krb5_free_error_message(handle->context, errmsg);
1608 }
1609
1610 exit_func:
1611 kadm5_free_principal_ent(handle, &rec);
1612 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1613 return TRUE;
1614 }
1615
1616 bool_t
init_2_svc(krb5_ui_4 * arg,generic_ret * ret,struct svc_req * rqstp)1617 init_2_svc(krb5_ui_4 *arg, generic_ret *ret, struct svc_req *rqstp)
1618 {
1619 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1620 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1621 kadm5_server_handle_t handle;
1622 const char *errmsg = NULL;
1623 size_t clen, slen;
1624 char *cdots, *sdots;
1625
1626 ret->code = stub_setup(*arg, rqstp, NULL, &handle, &ret->api_version,
1627 &client_name, &service_name, NULL, NULL);
1628 if (ret->code)
1629 goto exit_func;
1630
1631 if (ret->code != 0)
1632 errmsg = krb5_get_error_message(handle->context, ret->code);
1633
1634 clen = client_name.length;
1635 trunc_name(&clen, &cdots);
1636 slen = service_name.length;
1637 trunc_name(&slen, &sdots);
1638 /* okay to cast lengths to int because trunc_name limits max value */
1639 krb5_klog_syslog(LOG_NOTICE, _("Request: kadm5_init, %.*s%s, %s, "
1640 "client=%.*s%s, service=%.*s%s, addr=%s, "
1641 "vers=%d, flavor=%d"),
1642 (int)clen, (char *)client_name.value, cdots,
1643 errmsg ? errmsg : _("success"),
1644 (int)clen, (char *)client_name.value, cdots,
1645 (int)slen, (char *)service_name.value, sdots,
1646 client_addr(rqstp->rq_xprt),
1647 ret->api_version & ~(KADM5_API_VERSION_MASK),
1648 rqstp->rq_cred.oa_flavor);
1649 if (errmsg != NULL)
1650 krb5_free_error_message(handle->context, errmsg);
1651
1652 exit_func:
1653 stub_cleanup(handle, NULL, &client_name, &service_name);
1654 return TRUE;
1655 }
1656
1657 gss_name_t
rqst2name(struct svc_req * rqstp)1658 rqst2name(struct svc_req *rqstp)
1659 {
1660
1661 if (rqstp->rq_cred.oa_flavor == RPCSEC_GSS)
1662 return rqstp->rq_clntname;
1663 else
1664 return rqstp->rq_clntcred;
1665 }
1666
1667 bool_t
get_principal_keys_2_svc(getpkeys_arg * arg,getpkeys_ret * ret,struct svc_req * rqstp)1668 get_principal_keys_2_svc(getpkeys_arg *arg, getpkeys_ret *ret,
1669 struct svc_req *rqstp)
1670 {
1671 char *prime_arg = NULL;
1672 kadm5_principal_ent_rec rec = { 0 };
1673 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1674 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1675 kadm5_server_handle_t handle;
1676 const char *errmsg = NULL;
1677
1678 ret->code = stub_setup(arg->api_version, rqstp, arg->princ, &handle,
1679 &ret->api_version, &client_name, &service_name,
1680 &prime_arg, &rec);
1681 if (ret->code)
1682 goto exit_func;
1683
1684 if (!(CHANGEPW_SERVICE(rqstp)) &&
1685 stub_auth(handle, OP_EXTRACT, rec.principal, NULL, NULL, NULL)) {
1686 ret->code = kadm5_get_principal_keys(handle, rec.principal, arg->kvno,
1687 &ret->key_data, &ret->n_key_data);
1688 } else {
1689 log_unauth("kadm5_get_principal_keys", prime_arg,
1690 &client_name, &service_name, rqstp);
1691 ret->code = KADM5_AUTH_EXTRACT;
1692 }
1693
1694 if (ret->code == KADM5_OK) {
1695 ret->code = check_lockdown(&rec);
1696 if (ret->code != KADM5_OK) {
1697 kadm5_free_kadm5_key_data(handle->context, ret->n_key_data,
1698 ret->key_data);
1699 ret->key_data = NULL;
1700 ret->n_key_data = 0;
1701 }
1702 if (ret->code == KADM5_PROTECT_KEYS) {
1703 log_unauth("kadm5_get_principal_keys", prime_arg,
1704 &client_name, &service_name, rqstp);
1705 ret->code = KADM5_AUTH_EXTRACT;
1706 }
1707 }
1708
1709 if (ret->code != KADM5_AUTH_EXTRACT) {
1710 if (ret->code != 0)
1711 errmsg = krb5_get_error_message(handle->context, ret->code);
1712
1713 log_done("kadm5_get_principal_keys", prime_arg, errmsg,
1714 &client_name, &service_name, rqstp);
1715
1716 if (errmsg != NULL)
1717 krb5_free_error_message(handle->context, errmsg);
1718 }
1719
1720 exit_func:
1721 kadm5_free_principal_ent(handle, &rec);
1722 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1723 return TRUE;
1724 }
1725
1726 bool_t
create_alias_2_svc(calias_arg * arg,generic_ret * ret,struct svc_req * rqstp)1727 create_alias_2_svc(calias_arg *arg, generic_ret *ret, struct svc_req *rqstp)
1728 {
1729 char *prime_arg = NULL;
1730 gss_buffer_desc client_name = GSS_C_EMPTY_BUFFER;
1731 gss_buffer_desc service_name = GSS_C_EMPTY_BUFFER;
1732 kadm5_server_handle_t handle;
1733 const char *errmsg = NULL;
1734
1735 ret->code = stub_setup(arg->api_version, rqstp, arg->alias, &handle,
1736 &ret->api_version, &client_name, &service_name,
1737 &prime_arg, NULL);
1738 if (ret->code)
1739 goto exit_func;
1740
1741 if (CHANGEPW_SERVICE(rqstp) ||
1742 !stub_auth(handle, OP_ADDALIAS, arg->alias, arg->target, NULL, NULL)) {
1743 ret->code = KADM5_AUTH_INSUFFICIENT;
1744 log_unauth("kadm5_create_alias", prime_arg, &client_name,
1745 &service_name, rqstp);
1746 } else {
1747 ret->code = kadm5_create_alias(handle, arg->alias, arg->target);
1748 if (ret->code)
1749 errmsg = krb5_get_error_message(handle->context, ret->code);
1750 log_done("kadm5_create_alias", prime_arg, errmsg, &client_name,
1751 &service_name, rqstp);
1752 if (errmsg != NULL)
1753 krb5_free_error_message(handle->context, errmsg);
1754 }
1755
1756 exit_func:
1757 stub_cleanup(handle, prime_arg, &client_name, &service_name);
1758 return TRUE;
1759 }
1760