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 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 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 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 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 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 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 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 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