/ kdc / main.c
main.c
  1  /*
  2   * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
  3   * (Royal Institute of Technology, Stockholm, Sweden).
  4   * All rights reserved.
  5   *
  6   * Portions Copyright (c) 2009 Apple Inc. 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 "kdc_locl.h"
 37  #ifdef HAVE_UTIL_H
 38  #include <util.h>
 39  #endif
 40  
 41  #ifdef __APPLE__
 42  #include <sandbox.h>
 43  
 44  int sandbox_flag = 1;
 45  #endif
 46  
 47  #ifdef HAVE_CAPNG
 48  #include <cap-ng.h>
 49  #endif
 50  
 51  static void terminated(void *ctx) __attribute__((noreturn));
 52  
 53  
 54  #ifdef SUPPORT_DETACH
 55  int detach_from_console = -1;
 56  #endif
 57  
 58  /*
 59   * Allow dropping root bit, since heimdal reopens the database all the
 60   * time the database needs to be owned by the user you are switched
 61   * too. A better solution is to split the kdc in to more processes and
 62   * run the network facing part with very low privilege.
 63   */
 64  
 65  static void
 66  switch_environment(void)
 67  {
 68  #ifdef HAVE_GETEUID
 69      if ((runas_string || chroot_string) && geteuid() != 0)
 70  	errx(1, "no running as root, can't switch user/chroot");
 71  
 72      if (chroot_string && chroot(chroot_string) != 0)
 73  	errx(1, "chroot(%s)", "chroot_string failed");
 74  
 75      if (runas_string) {
 76  	struct passwd *pw;
 77  
 78  	pw = getpwnam(runas_string);
 79  	if (pw == NULL)
 80  	    errx(1, "unknown user %s", runas_string);
 81  
 82  	if (initgroups(pw->pw_name, pw->pw_gid) < 0)
 83  	    err(1, "initgroups failed");
 84  
 85  #ifndef HAVE_CAPNG
 86  	if (setgid(pw->pw_gid) < 0)
 87  	    err(1, "setgid(%s) failed", runas_string);
 88  
 89  	if (setuid(pw->pw_uid) < 0)
 90  	    err(1, "setuid(%s)", runas_string);
 91  #else
 92  	capng_clear (CAPNG_EFFECTIVE | CAPNG_PERMITTED);
 93  	if (capng_updatev (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
 94  	                   CAP_NET_BIND_SERVICE, CAP_SETPCAP, -1) < 0)
 95  	    err(1, "capng_updateev");
 96  
 97  	if (capng_change_id(pw->pw_uid, pw->pw_gid,
 98  	                    CAPNG_CLEAR_BOUNDING) < 0)
 99  	    err(1, "capng_change_id(%s)", runas_string);
100  #endif
101      }
102  #endif
103  }
104  
105  static krb5_context context;
106  static krb5_kdc_configuration *config;
107  
108  static heim_array_t
109  get_realms(void)
110  {
111      heim_array_t array;
112      char **realms, **r;
113      unsigned int i;
114      int ret;
115  
116      array = heim_array_create();
117  
118      for(i = 0; i < config->num_db; i++) {
119  
120  	if (config->db[i]->hdb_get_realms == NULL)
121  	    continue;
122  	
123  	ret = (config->db[i]->hdb_get_realms)(context, config->db[i], &realms);
124  	if (ret == 0) {
125  	    for (r = realms; r && *r; r++) {
126  		heim_string_t s = heim_string_create(*r);
127  		if (s)
128  		    heim_array_append_value(array, s);
129  		heim_release(s);
130  	    }
131  	    krb5_free_host_realm(context, realms);
132  	}
133      }
134  
135      return array;
136  }
137  
138  static void
139  terminated(void *ctx)
140  {
141      kdc_log(context, config, 0, "Terminated: %s", (char *)ctx);
142      exit(1);
143  }
144  
145  int
146  main(int argc, char **argv)
147  {
148      krb5_error_code ret;
149  
150      setprogname(argv[0]);
151  
152      ret = krb5_init_context(&context);
153      if (ret == KRB5_CONFIG_BADFORMAT)
154  	errx (1, "krb5_init_context failed to parse configuration file");
155      else if (ret)
156  	errx (1, "krb5_init_context failed: %d", ret);
157  
158      ret = krb5_kt_register(context, &hdb_kt_ops);
159      if (ret)
160  	errx (1, "krb5_kt_register(HDB) failed: %d", ret);
161  
162      config = configure(context, argc, argv);
163  
164  #ifdef SIGPIPE
165  #ifdef HAVE_SIGACTION
166      {
167  	struct sigaction sa;
168  
169  	sa.sa_flags = 0;
170  	sigemptyset(&sa.sa_mask);
171  
172  	sa.sa_handler = SIG_IGN;
173  	sigaction(SIGPIPE, &sa, NULL);
174      }
175  #else
176      signal(SIGPIPE, SIG_IGN);
177  #endif
178  #endif /* SIGPIPE */
179  
180  
181  
182  #ifdef SUPPORT_DETACH
183      if (detach_from_console)
184  	daemon(0, 0);
185  #endif
186  #ifdef __APPLE__
187      if (sandbox_flag) {
188  	char *errorstring;
189  	ret = sandbox_init("kdc", SANDBOX_NAMED, &errorstring);
190  	if (ret)
191  	    errx(1, "sandbox_init failed: %d: %s", ret, errorstring);
192      }
193      bonjour_announce(get_realms);
194  #endif /* __APPLE__ */
195      pidfile(NULL);
196  
197      switch_environment();
198  
199      setup_listeners(context, config, listen_on_ipc, listen_on_network);
200  
201      heim_sipc_signal_handler(SIGINT, terminated, "SIGINT");
202      heim_sipc_signal_handler(SIGTERM, terminated, "SIGTERM");
203  #ifdef SIGXCPU
204      heim_sipc_signal_handler(SIGXCPU, terminated, "CPU time limit exceeded");
205  #endif
206  
207      heim_ipc_main();
208  }