diff options
Diffstat (limited to 'lib/kadm5/context_s.c')
-rw-r--r-- | lib/kadm5/context_s.c | 146 |
1 files changed, 126 insertions, 20 deletions
diff --git a/lib/kadm5/context_s.c b/lib/kadm5/context_s.c index e121a48994b8..4aeee5df0176 100644 --- a/lib/kadm5/context_s.c +++ b/lib/kadm5/context_s.c @@ -35,6 +35,63 @@ RCSID("$Id$"); +static kadm5_ret_t +kadm5_s_lock(void *server_handle) +{ + kadm5_server_context *context = server_handle; + kadm5_ret_t ret; + + if (context->keep_open) { + /* + * We open/close around every operation, but we retain the DB + * open if the DB was locked with a prior call to kadm5_lock(), + * so if it's open here that must be because the DB is locked. + */ + heim_assert(context->db->lock_count > 0, + "Internal error in tracking HDB locks"); + return KADM5_ALREADY_LOCKED; + } + + ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0); + if (ret) + return ret; + + ret = context->db->hdb_lock(context->context, context->db, HDB_WLOCK); + if (ret) { + (void) context->db->hdb_close(context->context, context->db); + return ret; + } + + /* + * Attempt to recover the log. This will generally fail on slaves, + * and we can't tell if we're on a slave here. + * + * Perhaps we could set a flag in the kadm5_server_context to + * indicate whether a read has been done without recovering the log, + * in which case we could fail any subsequent writes. + */ + if (kadm5_log_init(context) == 0) + (void) kadm5_log_end(context); + + context->keep_open = 1; + return 0; +} + +static kadm5_ret_t +kadm5_s_unlock(void *server_handle) +{ + kadm5_server_context *context = server_handle; + kadm5_ret_t ret; + + if (!context->keep_open) + return KADM5_NOT_LOCKED; + + context->keep_open = 0; + ret = context->db->hdb_unlock(context->context, context->db); + (void) context->db->hdb_close(context->context, context->db); + return ret; +} + static void set_funcs(kadm5_server_context *c) { @@ -51,6 +108,9 @@ set_funcs(kadm5_server_context *c) SET(c, modify_principal); SET(c, randkey_principal); SET(c, rename_principal); + SET(c, lock); + SET(c, unlock); + SET(c, setkey_principal_3); } #ifndef NO_UNIX_SOCKETS @@ -81,6 +141,7 @@ find_db_spec(kadm5_server_context *ctx) krb5_context context = ctx->context; struct hdb_dbinfo *info, *d; krb5_error_code ret; + int aret; if (ctx->config.realm) { /* fetch the databases */ @@ -97,20 +158,32 @@ find_db_spec(kadm5_server_context *ctx) continue; p = hdb_dbinfo_get_dbname(context, d); - if (p) + if (p) { ctx->config.dbname = strdup(p); + if (ctx->config.dbname == NULL) + return ENOMEM; + } p = hdb_dbinfo_get_acl_file(context, d); - if (p) + if (p) { ctx->config.acl_file = strdup(p); + if (ctx->config.acl_file == NULL) + return ENOMEM; + } p = hdb_dbinfo_get_mkey_file(context, d); - if (p) + if (p) { ctx->config.stash_file = strdup(p); + if (ctx->config.stash_file == NULL) + return ENOMEM; + } p = hdb_dbinfo_get_log_file(context, d); - if (p) + if (p) { ctx->log_context.log_file = strdup(p); + if (ctx->log_context.log_file == NULL) + return ENOMEM; + } break; } hdb_free_dbinfo(context, &info); @@ -118,14 +191,29 @@ find_db_spec(kadm5_server_context *ctx) /* If any of the values was unset, pick up the default value */ - if (ctx->config.dbname == NULL) + if (ctx->config.dbname == NULL) { ctx->config.dbname = strdup(hdb_default_db(context)); - if (ctx->config.acl_file == NULL) - asprintf(&ctx->config.acl_file, "%s/kadmind.acl", hdb_db_dir(context)); - if (ctx->config.stash_file == NULL) - asprintf(&ctx->config.stash_file, "%s/m-key", hdb_db_dir(context)); - if (ctx->log_context.log_file == NULL) - asprintf(&ctx->log_context.log_file, "%s/log", hdb_db_dir(context)); + if (ctx->config.dbname == NULL) + return ENOMEM; + } + if (ctx->config.acl_file == NULL) { + aret = asprintf(&ctx->config.acl_file, "%s/kadmind.acl", + hdb_db_dir(context)); + if (aret == -1) + return ENOMEM; + } + if (ctx->config.stash_file == NULL) { + aret = asprintf(&ctx->config.stash_file, "%s/m-key", + hdb_db_dir(context)); + if (aret == -1) + return ENOMEM; + } + if (ctx->log_context.log_file == NULL) { + aret = asprintf(&ctx->log_context.log_file, "%s/log", + hdb_db_dir(context)); + if (aret == -1) + return ENOMEM; + } #ifndef NO_UNIX_SOCKETS set_socket_name(context, &ctx->log_context.socket_name); @@ -141,24 +229,42 @@ _kadm5_s_init_context(kadm5_server_context **ctx, kadm5_config_params *params, krb5_context context) { - *ctx = malloc(sizeof(**ctx)); - if(*ctx == NULL) + kadm5_ret_t ret = 0; + + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) return ENOMEM; - memset(*ctx, 0, sizeof(**ctx)); + (*ctx)->log_context.socket_fd = rk_INVALID_SOCKET; + set_funcs(*ctx); (*ctx)->context = context; krb5_add_et_list (context, initialize_kadm5_error_table_r); + #define is_set(M) (params && params->mask & KADM5_CONFIG_ ## M) - if(is_set(REALM)) + if (is_set(REALM)) { (*ctx)->config.realm = strdup(params->realm); - else - krb5_get_default_realm(context, &(*ctx)->config.realm); - if(is_set(DBNAME)) + if ((*ctx)->config.realm == NULL) + return ENOMEM; + } else { + ret = krb5_get_default_realm(context, &(*ctx)->config.realm); + if (ret) + return ret; + } + if (is_set(DBNAME)) { (*ctx)->config.dbname = strdup(params->dbname); - if(is_set(ACL_FILE)) + if ((*ctx)->config.dbname == NULL) + return ENOMEM; + } + if (is_set(ACL_FILE)) { (*ctx)->config.acl_file = strdup(params->acl_file); - if(is_set(STASH_FILE)) + if ((*ctx)->config.acl_file == NULL) + return ENOMEM; + } + if (is_set(STASH_FILE)) { (*ctx)->config.stash_file = strdup(params->stash_file); + if ((*ctx)->config.stash_file == NULL) + return ENOMEM; + } find_db_spec(*ctx); |