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