1/* $NetBSD: context_s.c,v 1.2 2017/01/28 21:31:49 christos Exp $ */ 2 3/* 4 * Copyright (c) 1997 - 2002 Kungliga Tekniska H��gskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "kadm5_locl.h" 37 38__RCSID("$NetBSD: context_s.c,v 1.2 2017/01/28 21:31:49 christos Exp $"); 39 40static kadm5_ret_t 41kadm5_s_lock(void *server_handle) 42{ 43 kadm5_server_context *context = server_handle; 44 kadm5_ret_t ret; 45 46 if (context->keep_open) { 47 /* 48 * We open/close around every operation, but we retain the DB 49 * open if the DB was locked with a prior call to kadm5_lock(), 50 * so if it's open here that must be because the DB is locked. 51 */ 52 heim_assert(context->db->lock_count > 0, 53 "Internal error in tracking HDB locks"); 54 return KADM5_ALREADY_LOCKED; 55 } 56 57 ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); 58 if (ret) 59 return ret; 60 61 ret = context->db->hdb_lock(context->context, context->db, HDB_WLOCK); 62 if (ret) { 63 (void) context->db->hdb_close(context->context, context->db); 64 return ret; 65 } 66 67 /* 68 * Attempt to recover the log. This will generally fail on slaves, 69 * and we can't tell if we're on a slave here. 70 * 71 * Perhaps we could set a flag in the kadm5_server_context to 72 * indicate whether a read has been done without recovering the log, 73 * in which case we could fail any subsequent writes. 74 */ 75 if (kadm5_log_init(context) == 0) 76 (void) kadm5_log_end(context); 77 78 context->keep_open = 1; 79 return 0; 80} 81 82static kadm5_ret_t 83kadm5_s_unlock(void *server_handle) 84{ 85 kadm5_server_context *context = server_handle; 86 kadm5_ret_t ret; 87 88 if (!context->keep_open) 89 return KADM5_NOT_LOCKED; 90 91 context->keep_open = 0; 92 ret = context->db->hdb_unlock(context->context, context->db); 93 (void) context->db->hdb_close(context->context, context->db); 94 return ret; 95} 96 97static void 98set_funcs(kadm5_server_context *c) 99{ 100#define SET(C, F) (C)->funcs.F = kadm5_s_ ## F 101 SET(c, chpass_principal); 102 SET(c, chpass_principal_with_key); 103 SET(c, create_principal); 104 SET(c, delete_principal); 105 SET(c, destroy); 106 SET(c, flush); 107 SET(c, get_principal); 108 SET(c, get_principals); 109 SET(c, get_privs); 110 SET(c, modify_principal); 111 SET(c, randkey_principal); 112 SET(c, rename_principal); 113 SET(c, lock); 114 SET(c, unlock); 115 SET(c, setkey_principal_3); 116} 117 118#ifndef NO_UNIX_SOCKETS 119 120static void 121set_socket_name(krb5_context context, struct sockaddr_un *un) 122{ 123 const char *fn = kadm5_log_signal_socket(context); 124 125 memset(un, 0, sizeof(*un)); 126 un->sun_family = AF_UNIX; 127 strlcpy (un->sun_path, fn, sizeof(un->sun_path)); 128 129} 130#else 131 132static void 133set_socket_info(krb5_context context, struct addrinfo **info) 134{ 135 kadm5_log_signal_socket_info(context, 0, info); 136} 137 138#endif 139 140static kadm5_ret_t 141find_db_spec(kadm5_server_context *ctx) 142{ 143 krb5_context context = ctx->context; 144 struct hdb_dbinfo *info, *d; 145 krb5_error_code ret; 146 int aret; 147 148 if (ctx->config.realm) { 149 /* fetch the databases */ 150 ret = hdb_get_dbinfo(context, &info); 151 if (ret) 152 return ret; 153 154 d = NULL; 155 while ((d = hdb_dbinfo_get_next(info, d)) != NULL) { 156 const char *p = hdb_dbinfo_get_realm(context, d); 157 158 /* match default (realm-less) */ 159 if(p != NULL && strcmp(ctx->config.realm, p) != 0) 160 continue; 161 162 p = hdb_dbinfo_get_dbname(context, d); 163 if (p) { 164 ctx->config.dbname = strdup(p); 165 if (ctx->config.dbname == NULL) 166 return ENOMEM; 167 } 168 169 p = hdb_dbinfo_get_acl_file(context, d); 170 if (p) { 171 ctx->config.acl_file = strdup(p); 172 if (ctx->config.acl_file == NULL) 173 return ENOMEM; 174 } 175 176 p = hdb_dbinfo_get_mkey_file(context, d); 177 if (p) { 178 ctx->config.stash_file = strdup(p); 179 if (ctx->config.stash_file == NULL) 180 return ENOMEM; 181 } 182 183 p = hdb_dbinfo_get_log_file(context, d); 184 if (p) { 185 ctx->log_context.log_file = strdup(p); 186 if (ctx->log_context.log_file == NULL) 187 return ENOMEM; 188 } 189 break; 190 } 191 hdb_free_dbinfo(context, &info); 192 } 193 194 /* If any of the values was unset, pick up the default value */ 195 196 if (ctx->config.dbname == NULL) { 197 ctx->config.dbname = strdup(hdb_default_db(context)); 198 if (ctx->config.dbname == NULL) 199 return ENOMEM; 200 } 201 if (ctx->config.acl_file == NULL) { 202 aret = asprintf(&ctx->config.acl_file, "%s/kadmind.acl", 203 hdb_db_dir(context)); 204 if (aret == -1) 205 return ENOMEM; 206 } 207 if (ctx->config.stash_file == NULL) { 208 aret = asprintf(&ctx->config.stash_file, "%s/m-key", 209 hdb_db_dir(context)); 210 if (aret == -1) 211 return ENOMEM; 212 } 213 if (ctx->log_context.log_file == NULL) { 214 aret = asprintf(&ctx->log_context.log_file, "%s/log", 215 hdb_db_dir(context)); 216 if (aret == -1) 217 return ENOMEM; 218 } 219 220#ifndef NO_UNIX_SOCKETS 221 set_socket_name(context, &ctx->log_context.socket_name); 222#else 223 set_socket_info(context, &ctx->log_context.socket_info); 224#endif 225 226 return 0; 227} 228 229kadm5_ret_t 230_kadm5_s_init_context(kadm5_server_context **ctx, 231 kadm5_config_params *params, 232 krb5_context context) 233{ 234 kadm5_ret_t ret = 0; 235 236 *ctx = calloc(1, sizeof(**ctx)); 237 if (*ctx == NULL) 238 return ENOMEM; 239 (*ctx)->log_context.socket_fd = rk_INVALID_SOCKET; 240 241 set_funcs(*ctx); 242 (*ctx)->context = context; 243 krb5_add_et_list (context, initialize_kadm5_error_table_r); 244 245#define is_set(M) (params && params->mask & KADM5_CONFIG_ ## M) 246 if (is_set(REALM)) { 247 (*ctx)->config.realm = strdup(params->realm); 248 if ((*ctx)->config.realm == NULL) 249 return ENOMEM; 250 } else { 251 ret = krb5_get_default_realm(context, &(*ctx)->config.realm); 252 if (ret) 253 return ret; 254 } 255 if (is_set(DBNAME)) { 256 (*ctx)->config.dbname = strdup(params->dbname); 257 if ((*ctx)->config.dbname == NULL) 258 return ENOMEM; 259 } 260 if (is_set(ACL_FILE)) { 261 (*ctx)->config.acl_file = strdup(params->acl_file); 262 if ((*ctx)->config.acl_file == NULL) 263 return ENOMEM; 264 } 265 if (is_set(STASH_FILE)) { 266 (*ctx)->config.stash_file = strdup(params->stash_file); 267 if ((*ctx)->config.stash_file == NULL) 268 return ENOMEM; 269 } 270 271 find_db_spec(*ctx); 272 273 /* PROFILE can't be specified for now */ 274 /* KADMIND_PORT is supposed to be used on the server also, 275 but this doesn't make sense */ 276 /* ADMIN_SERVER is client only */ 277 /* ADNAME is not used at all (as far as I can tell) */ 278 /* ADB_LOCKFILE ditto */ 279 /* DICT_FILE */ 280 /* ADMIN_KEYTAB */ 281 /* MKEY_FROM_KEYBOARD is not supported */ 282 /* MKEY_NAME neither */ 283 /* ENCTYPE */ 284 /* MAX_LIFE */ 285 /* MAX_RLIFE */ 286 /* EXPIRATION */ 287 /* FLAGS */ 288 /* ENCTYPES */ 289 290 return 0; 291} 292 293HDB * 294_kadm5_s_get_db(void *server_handle) 295{ 296 kadm5_server_context *context = server_handle; 297 return context->db; 298} 299