xref: /freebsd/crypto/krb5/src/lib/kadm5/srv/kadm5_hook.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/kadm5/srv/kadm5_hook.c */
3 /*
4  * Copyright (C) 2010 by the Massachusetts Institute of Technology.
5  * All rights reserved.
6  *
7  * Export of this software from the United States of America may
8  *   require a specific license from the United States Government.
9  *   It is the responsibility of any person or organization contemplating
10  *   export to obtain such a license before exporting.
11  *
12  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13  * distribute this software and its documentation for any purpose and
14  * without fee is hereby granted, provided that the above copyright
15  * notice appear in all copies and that both that copyright notice and
16  * this permission notice appear in supporting documentation, and that
17  * the name of M.I.T. not be used in advertising or publicity pertaining
18  * to distribution of the software without specific, written prior
19  * permission.  Furthermore if you modify this software you must label
20  * your software as modified software and not distribute it in such a
21  * fashion that it might be confused with the original M.I.T. software.
22  * M.I.T. makes no representations about the suitability of
23  * this software for any purpose.  It is provided "as is" without express
24  * or implied warranty.
25  */
26 /* Consumer interface for kadm5_hook plugins. */
27 
28 #include "k5-int.h"
29 #include "server_internal.h"
30 #include <krb5/kadm5_hook_plugin.h>
31 #include <adm_proto.h>
32 #include <syslog.h>
33 
34 struct kadm5_hook_handle_st {
35     kadm5_hook_vftable_1 vt;
36     kadm5_hook_modinfo *data;
37 };
38 
39 krb5_error_code
k5_kadm5_hook_load(krb5_context context,kadm5_hook_handle ** handles_out)40 k5_kadm5_hook_load(krb5_context context,
41                    kadm5_hook_handle **handles_out)
42 {
43     krb5_error_code ret;
44     krb5_plugin_initvt_fn *modules = NULL, *mod;
45     size_t count;
46     kadm5_hook_handle *list = NULL, handle = NULL;
47 
48     *handles_out = NULL;
49 
50     ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_KADM5_HOOK, &modules);
51     if (ret != 0)
52         goto cleanup;
53 
54     /* Allocate a large enough list of handles. */
55     for (count = 0; modules[count] != NULL; count++);
56     list = k5calloc(count + 1, sizeof(*list), &ret);
57     if (list == NULL)
58         goto cleanup;
59 
60     /* For each module, allocate a handle, initialize its vtable, and
61      * initialize the module. */
62     count = 0;
63     for (mod = modules; *mod != NULL; mod++) {
64         handle = k5alloc(sizeof(*handle), &ret);
65         if (handle == NULL)
66             goto cleanup;
67         ret = (*mod)(context, 1, 2, (krb5_plugin_vtable)&handle->vt);
68         if (ret != 0) {         /* Failed vtable init is non-fatal. */
69             free(handle);
70             handle = NULL;
71             continue;
72         }
73         handle->data = NULL;
74         if (handle->vt.init != NULL) {
75             ret = handle->vt.init(context, &handle->data);
76             if (ret != 0)       /* Failed initialization is fatal. */
77                 goto cleanup;
78         }
79         list[count++] = handle;
80         list[count] = NULL;
81         handle = NULL;
82     }
83     list[count] = NULL;
84 
85     ret = 0;
86     *handles_out = list;
87     list = NULL;
88 
89 cleanup:
90     free(handle);
91     k5_plugin_free_modules(context, modules);
92     k5_kadm5_hook_free_handles(context, list);
93     return ret;
94 }
95 
96 void
k5_kadm5_hook_free_handles(krb5_context context,kadm5_hook_handle * handles)97 k5_kadm5_hook_free_handles(krb5_context context, kadm5_hook_handle *handles)
98 {
99     kadm5_hook_handle *hp, handle;
100 
101     if (handles == NULL)
102         return;
103     for (hp = handles; *hp != NULL; hp++) {
104         handle = *hp;
105         if (handle->vt.fini != NULL)
106             handle->vt.fini(context, handle->data);
107         free(handle);
108     }
109     free(handles);
110 }
111 
112 static void
log_failure(krb5_context context,const char * name,const char * function,krb5_error_code ret)113 log_failure(krb5_context context,
114             const char *name,
115             const char *function,
116             krb5_error_code ret)
117 {
118     const char *e = krb5_get_error_message(context, ret);
119 
120     krb5_klog_syslog(LOG_ERR, _("kadm5_hook %s failed postcommit %s: %s"),
121                      name, function, e);
122     krb5_free_error_message(context, e);
123 }
124 
125 #define ITERATE(operation, params)                                      \
126     for (; *handles; handles++) {                                       \
127         kadm5_hook_handle h = *handles;                                 \
128         krb5_error_code ret = 0;                                        \
129         if (h->vt.operation) {                                          \
130             ret = h->vt.operation params;                               \
131         }                                                               \
132         if (ret) {                                                      \
133             if (stage == KADM5_HOOK_STAGE_PRECOMMIT)                    \
134                 return ret;                                             \
135             else                                                        \
136                 log_failure(context, h->vt.name, #operation, ret);      \
137         }                                                               \
138     }
139 
140 
141 kadm5_ret_t
k5_kadm5_hook_chpass(krb5_context context,kadm5_hook_handle * handles,int stage,krb5_principal princ,krb5_boolean keepold,int n_ks_tuple,krb5_key_salt_tuple * ks_tuple,const char * newpass)142 k5_kadm5_hook_chpass(krb5_context context, kadm5_hook_handle *handles,
143                      int stage, krb5_principal princ, krb5_boolean keepold,
144                      int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
145                      const char *newpass)
146 {
147     ITERATE(chpass, (context, h->data,
148                      stage, princ, keepold,
149                      n_ks_tuple, ks_tuple, newpass));
150     return 0;
151 }
152 
153 kadm5_ret_t
k5_kadm5_hook_create(krb5_context context,kadm5_hook_handle * handles,int stage,kadm5_principal_ent_t princ,long mask,int n_ks_tuple,krb5_key_salt_tuple * ks_tuple,const char * newpass)154 k5_kadm5_hook_create(krb5_context context, kadm5_hook_handle *handles,
155                      int stage, kadm5_principal_ent_t princ, long mask,
156                      int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
157                      const char *newpass)
158 {
159     ITERATE(create, (context, h->data,
160                      stage, princ, mask, n_ks_tuple, ks_tuple, newpass));
161     return 0;
162 }
163 
164 kadm5_ret_t
k5_kadm5_hook_modify(krb5_context context,kadm5_hook_handle * handles,int stage,kadm5_principal_ent_t princ,long mask)165 k5_kadm5_hook_modify(krb5_context context, kadm5_hook_handle *handles,
166                      int stage, kadm5_principal_ent_t princ, long mask)
167 {
168     ITERATE(modify, (context, h->data, stage, princ, mask));
169     return 0;
170 }
171 
172 kadm5_ret_t
k5_kadm5_hook_rename(krb5_context context,kadm5_hook_handle * handles,int stage,krb5_principal oprinc,krb5_principal nprinc)173 k5_kadm5_hook_rename(krb5_context context, kadm5_hook_handle *handles,
174                      int stage, krb5_principal oprinc, krb5_principal nprinc)
175 {
176     ITERATE(rename, (context, h->data, stage, oprinc, nprinc));
177     return 0;
178 }
179 
180 kadm5_ret_t
k5_kadm5_hook_remove(krb5_context context,kadm5_hook_handle * handles,int stage,krb5_principal princ)181 k5_kadm5_hook_remove(krb5_context context, kadm5_hook_handle *handles,
182                      int stage, krb5_principal princ)
183 {
184     ITERATE(remove, (context, h->data, stage, princ));
185     return 0;
186 }
187