155682Smarkm/*
2233294Sstas * Copyright (c) 1997-2005 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
755682Smarkm *
8233294Sstas * Redistribution and use in source and binary forms, with or without
9233294Sstas * modification, are permitted provided that the following conditions
10233294Sstas * are met:
1155682Smarkm *
12233294Sstas * 1. Redistributions of source code must retain the above copyright
13233294Sstas *    notice, this list of conditions and the following disclaimer.
1455682Smarkm *
15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
16233294Sstas *    notice, this list of conditions and the following disclaimer in the
17233294Sstas *    documentation and/or other materials provided with the distribution.
1855682Smarkm *
19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors
20233294Sstas *    may be used to endorse or promote products derived from this software
21233294Sstas *    without specific prior written permission.
22233294Sstas *
23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33233294Sstas * SUCH DAMAGE.
3455682Smarkm */
3555682Smarkm
3655682Smarkm#include "kdc_locl.h"
37102644Snectar#ifdef HAVE_UTIL_H
38102644Snectar#include <util.h>
39102644Snectar#endif
4055682Smarkm
41233294Sstas#ifdef HAVE_CAPNG
42233294Sstas#include <cap-ng.h>
43233294Sstas#endif
4455682Smarkm
4555682Smarkmsig_atomic_t exit_flag = 0;
4655682Smarkm
47233294Sstas#ifdef SUPPORT_DETACH
48178825Sdfrint detach_from_console = -1;
49233294Sstas#endif
50102644Snectar
5155682Smarkmstatic RETSIGTYPE
5255682Smarkmsigterm(int sig)
5355682Smarkm{
54178825Sdfr    exit_flag = sig;
5555682Smarkm}
5655682Smarkm
57233294Sstas/*
58233294Sstas * Allow dropping root bit, since heimdal reopens the database all the
59233294Sstas * time the database needs to be owned by the user you are switched
60233294Sstas * too. A better solution is to split the kdc in to more processes and
61233294Sstas * run the network facing part with very low privilege.
62233294Sstas */
63233294Sstas
64233294Sstasstatic void
65233294Sstasswitch_environment(void)
66233294Sstas{
67233294Sstas#ifdef HAVE_GETEUID
68233294Sstas    if ((runas_string || chroot_string) && geteuid() != 0)
69233294Sstas	errx(1, "no running as root, can't switch user/chroot");
70233294Sstas
71233294Sstas    if (chroot_string && chroot(chroot_string) != 0)
72233294Sstas	errx(1, "chroot(%s)", "chroot_string failed");
73233294Sstas
74233294Sstas    if (runas_string) {
75233294Sstas	struct passwd *pw;
76233294Sstas
77233294Sstas	pw = getpwnam(runas_string);
78233294Sstas	if (pw == NULL)
79233294Sstas	    errx(1, "unknown user %s", runas_string);
80233294Sstas
81233294Sstas	if (initgroups(pw->pw_name, pw->pw_gid) < 0)
82233294Sstas	    err(1, "initgroups failed");
83233294Sstas
84233294Sstas#ifndef HAVE_CAPNG
85233294Sstas	if (setgid(pw->pw_gid) < 0)
86233294Sstas	    err(1, "setgid(%s) failed", runas_string);
87233294Sstas
88233294Sstas	if (setuid(pw->pw_uid) < 0)
89233294Sstas	    err(1, "setuid(%s)", runas_string);
90233294Sstas#else
91233294Sstas	capng_clear (CAPNG_EFFECTIVE | CAPNG_PERMITTED);
92233294Sstas	if (capng_updatev (CAPNG_ADD, CAPNG_EFFECTIVE | CAPNG_PERMITTED,
93233294Sstas	                   CAP_NET_BIND_SERVICE, CAP_SETPCAP, -1) < 0)
94233294Sstas	    err(1, "capng_updateev");
95233294Sstas
96233294Sstas	if (capng_change_id(pw->pw_uid, pw->pw_gid,
97233294Sstas	                    CAPNG_CLEAR_BOUNDING) < 0)
98233294Sstas	    err(1, "capng_change_id(%s)", runas_string);
99233294Sstas#endif
100233294Sstas    }
101233294Sstas#endif
102233294Sstas}
103233294Sstas
104233294Sstas
10555682Smarkmint
10655682Smarkmmain(int argc, char **argv)
10755682Smarkm{
10855682Smarkm    krb5_error_code ret;
109178825Sdfr    krb5_context context;
110178825Sdfr    krb5_kdc_configuration *config;
111178825Sdfr
11278527Sassar    setprogname(argv[0]);
113233294Sstas
11472445Sassar    ret = krb5_init_context(&context);
115178825Sdfr    if (ret == KRB5_CONFIG_BADFORMAT)
116178825Sdfr	errx (1, "krb5_init_context failed to parse configuration file");
117178825Sdfr    else if (ret)
11872445Sassar	errx (1, "krb5_init_context failed: %d", ret);
11955682Smarkm
120178825Sdfr    ret = krb5_kt_register(context, &hdb_kt_ops);
121178825Sdfr    if (ret)
122178825Sdfr	errx (1, "krb5_kt_register(HDB) failed: %d", ret);
12355682Smarkm
124178825Sdfr    config = configure(context, argc, argv);
12555682Smarkm
12655682Smarkm#ifdef HAVE_SIGACTION
12755682Smarkm    {
12855682Smarkm	struct sigaction sa;
12955682Smarkm
13055682Smarkm	sa.sa_flags = 0;
13155682Smarkm	sa.sa_handler = sigterm;
13255682Smarkm	sigemptyset(&sa.sa_mask);
13355682Smarkm
13455682Smarkm	sigaction(SIGINT, &sa, NULL);
13572445Sassar	sigaction(SIGTERM, &sa, NULL);
136233294Sstas#ifdef SIGXCPU
137178825Sdfr	sigaction(SIGXCPU, &sa, NULL);
138233294Sstas#endif
139178825Sdfr
140178825Sdfr	sa.sa_handler = SIG_IGN;
141233294Sstas#ifdef SIGPIPE
142178825Sdfr	sigaction(SIGPIPE, &sa, NULL);
143233294Sstas#endif
14455682Smarkm    }
14555682Smarkm#else
14655682Smarkm    signal(SIGINT, sigterm);
14772445Sassar    signal(SIGTERM, sigterm);
148233294Sstas#ifdef SIGXCPU
149178825Sdfr    signal(SIGXCPU, sigterm);
150233294Sstas#endif
151233294Sstas#ifdef SIGPIPE
152178825Sdfr    signal(SIGPIPE, SIG_IGN);
15355682Smarkm#endif
154233294Sstas#endif
155233294Sstas#ifdef SUPPORT_DETACH
156102644Snectar    if (detach_from_console)
157102644Snectar	daemon(0, 0);
158233294Sstas#endif
159233294Sstas#ifdef __APPLE__
160233294Sstas    bonjour_announce(context, config);
161233294Sstas#endif
16272445Sassar    pidfile(NULL);
163233294Sstas
164233294Sstas    switch_environment();
165233294Sstas
166178825Sdfr    loop(context, config);
16755682Smarkm    krb5_free_context(context);
16855682Smarkm    return 0;
16955682Smarkm}
170