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