/ kadmin / kadmind.c
kadmind.c
  1  /*
  2   * Copyright (c) 1997-2004 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 "kadmin_locl.h"
 35  #include <gssapi.h>
 36  #include <gssapi_krb5.h>
 37  #include <gssapi_spi.h>
 38  
 39  
 40  
 41  #ifdef __APPLE__
 42  #include <sandbox.h>
 43  
 44  int sandbox_flag = 1;
 45  #endif
 46  
 47  krb5_error_code _gsskrb5_init (krb5_context *);
 48  
 49  static char *check_library  = NULL;
 50  static char *check_function = NULL;
 51  static getarg_strings policy_libraries = { 0, NULL };
 52  static char *config_file;
 53  static char sHDB[] = "HDB:";
 54  static char *keytab_str = sHDB;
 55  static int help_flag;
 56  static int version_flag;
 57  static int debug_flag;
 58  static char *port_str;
 59  char *realm;
 60  
 61  static struct getargs args[] = {
 62      {
 63  	"config-file",	'c',	arg_string,	&config_file,
 64  	"location of config file",	"file"
 65      },
 66      {
 67  	"keytab",	0,	arg_string, &keytab_str,
 68  	"what keytab to use", "keytab"
 69      },
 70      {	"realm",	'r',	arg_string,   &realm,
 71  	"realm to use", "realm"
 72      },
 73  #ifdef HAVE_DLOPEN
 74      { "check-library", 0, arg_string, &check_library,
 75        "library to load password check function from", "library" },
 76      { "check-function", 0, arg_string, &check_function,
 77        "password check function to load", "function" },
 78      { "policy-libraries", 0, arg_strings, &policy_libraries,
 79        "password check function to load", "function" },
 80  #endif
 81      {	"debug",	'd',	arg_flag,   &debug_flag,
 82  	"enable debugging", NULL
 83      },
 84      {	"ports",	'p',	arg_string, &port_str,
 85  	"ports to listen to", "port" },
 86  #ifdef __APPLE__
 87      {	"sandbox",	0, 	arg_negative_flag, &sandbox_flag,
 88  	"use sandbox or not"
 89      },
 90  #endif /* __APPLE__ */
 91      {	"help",		'h',	arg_flag,   &help_flag },
 92      {	"version",	'v',	arg_flag,   &version_flag }
 93  };
 94  
 95  static int num_args = sizeof(args) / sizeof(args[0]);
 96  
 97  krb5_context context;
 98  
 99  static void
100  usage(int ret)
101  {
102      arg_printusage (args, num_args, NULL, "");
103      exit (ret);
104  }
105  
106  static void
107  setup_context(krb5_context ctx)
108  {
109      krb5_log_facility *logfacility;
110      krb5_error_code ret;
111      char **files;
112  
113      if (config_file == NULL) {
114  	asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(ctx));
115  	if (config_file == NULL)
116  	    errx(1, "out of memory");
117      }
118  
119      ret = krb5_prepend_config_files_default(config_file, &files);
120      if (ret)
121  	krb5_err(ctx, 1, ret, "getting configuration files");
122  
123      ret = krb5_set_config_files(ctx, files);
124      krb5_free_config_files(files);
125      if(ret)
126  	krb5_err(ctx, 1, ret, "reading configuration files");
127  
128      ret = krb5_openlog(ctx, "kadmind", &logfacility);
129      if (ret)
130  	krb5_err(ctx, 1, ret, "krb5_openlog");
131      ret = krb5_set_warn_dest(ctx, logfacility);
132      if (ret)
133  	krb5_err(ctx, 1, ret, "krb5_set_warn_dest");
134  
135      ret = krb5_kt_register(ctx, &hdb_kt_ops);
136      if(ret)
137  	krb5_err(ctx, 1, ret, "krb5_kt_register");
138  }
139  
140  int
141  main(int argc, char **argv)
142  {
143      krb5_error_code ret;
144      int optidx = 0;
145      int i;
146      krb5_keytab keytab;
147      krb5_socket_t sfd = rk_INVALID_SOCKET;
148  
149      setprogname(argv[0]);
150  
151      ret = krb5_init_context(&context);
152      if (ret)
153  	errx (1, "krb5_init_context failed: %d", ret);
154  
155      if (getarg(args, num_args, argc, argv, &optidx)) {
156  	warnx("error at argument `%s'", argv[optidx]);
157  	usage(1);
158      }
159  
160      if (help_flag)
161  	usage (0);
162  
163      if (version_flag) {
164  	print_version(NULL);
165  	exit(0);
166      }
167  
168      setup_context(context);
169  
170      /*
171       * Now, do the same for the gssapi thread we are going to be running in
172       */
173      {
174  	krb5_context gssctx;
175  	ret = _gsskrb5_init(&gssctx);
176  	if (ret)
177  	    errx(1, "failed to setup gssapi context");
178  	setup_context(gssctx);
179  	krb5_gss_register_acceptor_identity("HDB:");
180      }
181  
182      ret = krb5_kt_resolve(context, keytab_str, &keytab);
183      if(ret)
184  	krb5_err(context, 1, ret, "krb5_kt_resolve");
185  
186      kadm5_setup_passwd_quality_check (context, check_library, check_function);
187  
188      for (i = 0; i < policy_libraries.num_strings; i++) {
189  	ret = kadm5_add_passwd_quality_verifier(context,
190  						policy_libraries.strings[i]);
191  	if (ret)
192  	    krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
193      }
194      ret = kadm5_add_passwd_quality_verifier(context, NULL);
195      if (ret)
196  	krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
197  
198  #ifdef __APPLE__
199      if (sandbox_flag) {
200  	char *errorstring;
201  	ret = sandbox_init("kadmind", SANDBOX_NAMED, &errorstring);
202  	if (ret)
203  	    errx(1, "sandbox_init failed: %d: %s", ret, errorstring);
204      }
205  #endif
206  
207      if(debug_flag) {
208  	int debug_port;
209  
210  	if(port_str == NULL)
211  	    debug_port = krb5_getportbyname (context, "kerberos-adm",
212  					     "tcp", 749);
213  	else
214  	    debug_port = htons(atoi(port_str));
215  	mini_inetd(debug_port, &sfd);
216      } else {
217  #ifdef _WIN32
218  	pidfile(NULL);
219  	start_server(context, port_str);
220  #else
221  	struct sockaddr_storage __ss;
222  	struct sockaddr *sa = (struct sockaddr *)&__ss;
223  	socklen_t sa_size = sizeof(__ss);
224  
225  	/*
226  	 * Check if we are running inside inetd or not, if not, start
227  	 * our own server.
228  	 */
229  
230  	if(roken_getsockname(STDIN_FILENO, sa, &sa_size) < 0 &&
231  	   rk_SOCK_ERRNO == ENOTSOCK) {
232  	    pidfile(NULL);
233  	    start_server(context, port_str);
234  	}
235  #endif /* _WIN32 */
236  	sfd = STDIN_FILENO;
237      }
238  
239      if(realm)
240  	krb5_set_default_realm(context, realm); /* XXX */
241  
242      kadmind_loop(context, keytab, sfd);
243  
244      return 0;
245  }