xref: /freebsd/crypto/krb5/src/kadmin/server/server_stubs.c (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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