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