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