1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
4*7f2fe78bSCy Schubert *
5*7f2fe78bSCy Schubert */
6*7f2fe78bSCy Schubert
7*7f2fe78bSCy Schubert /*
8*7f2fe78bSCy Schubert * Copyright (C) 1998 by the FundsXpress, INC.
9*7f2fe78bSCy Schubert *
10*7f2fe78bSCy Schubert * All rights reserved.
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * Export of this software from the United States of America may require
13*7f2fe78bSCy Schubert * a specific license from the United States Government. It is the
14*7f2fe78bSCy Schubert * responsibility of any person or organization contemplating export to
15*7f2fe78bSCy Schubert * obtain such a license before exporting.
16*7f2fe78bSCy Schubert *
17*7f2fe78bSCy Schubert * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18*7f2fe78bSCy Schubert * distribute this software and its documentation for any purpose and
19*7f2fe78bSCy Schubert * without fee is hereby granted, provided that the above copyright
20*7f2fe78bSCy Schubert * notice appear in all copies and that both that copyright notice and
21*7f2fe78bSCy Schubert * this permission notice appear in supporting documentation, and that
22*7f2fe78bSCy Schubert * the name of FundsXpress. not be used in advertising or publicity pertaining
23*7f2fe78bSCy Schubert * to distribution of the software without specific, written prior
24*7f2fe78bSCy Schubert * permission. FundsXpress makes no representations about the suitability of
25*7f2fe78bSCy Schubert * this software for any purpose. It is provided "as is" without express
26*7f2fe78bSCy Schubert * or implied warranty.
27*7f2fe78bSCy Schubert *
28*7f2fe78bSCy Schubert * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29*7f2fe78bSCy Schubert * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30*7f2fe78bSCy Schubert * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31*7f2fe78bSCy Schubert */
32*7f2fe78bSCy Schubert
33*7f2fe78bSCy Schubert #include <k5-platform.h>
34*7f2fe78bSCy Schubert #include <errno.h>
35*7f2fe78bSCy Schubert #include <locale.h>
36*7f2fe78bSCy Schubert #include <stdio.h>
37*7f2fe78bSCy Schubert #include <signal.h>
38*7f2fe78bSCy Schubert #include <syslog.h>
39*7f2fe78bSCy Schubert #include <sys/types.h>
40*7f2fe78bSCy Schubert #ifdef _AIX
41*7f2fe78bSCy Schubert #include <sys/select.h>
42*7f2fe78bSCy Schubert #endif
43*7f2fe78bSCy Schubert #include <sys/time.h>
44*7f2fe78bSCy Schubert #include <sys/socket.h>
45*7f2fe78bSCy Schubert #include <unistd.h>
46*7f2fe78bSCy Schubert #include <netinet/in.h>
47*7f2fe78bSCy Schubert #include <netdb.h>
48*7f2fe78bSCy Schubert #include <gssrpc/rpc.h>
49*7f2fe78bSCy Schubert #include <gssapi/gssapi.h>
50*7f2fe78bSCy Schubert #include "gssapiP_krb5.h" /* for kg_get_context */
51*7f2fe78bSCy Schubert #include <gssrpc/auth_gssapi.h>
52*7f2fe78bSCy Schubert #include <kadm5/admin.h>
53*7f2fe78bSCy Schubert #include <kadm5/kadm_rpc.h>
54*7f2fe78bSCy Schubert #include <adm_proto.h>
55*7f2fe78bSCy Schubert #include "kdb_kt.h" /* for krb5_ktkdb_set_context */
56*7f2fe78bSCy Schubert #include <string.h>
57*7f2fe78bSCy Schubert #include <kdb_log.h>
58*7f2fe78bSCy Schubert
59*7f2fe78bSCy Schubert #include "misc.h"
60*7f2fe78bSCy Schubert #include "auth.h"
61*7f2fe78bSCy Schubert
62*7f2fe78bSCy Schubert #if defined(NEED_DAEMON_PROTO)
63*7f2fe78bSCy Schubert int daemon(int, int);
64*7f2fe78bSCy Schubert #endif
65*7f2fe78bSCy Schubert
66*7f2fe78bSCy Schubert #define TIMEOUT 15
67*7f2fe78bSCy Schubert
68*7f2fe78bSCy Schubert gss_name_t gss_changepw_name = NULL, gss_oldchangepw_name = NULL;
69*7f2fe78bSCy Schubert void *global_server_handle;
70*7f2fe78bSCy Schubert int nofork = 0;
71*7f2fe78bSCy Schubert char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL;
72*7f2fe78bSCy Schubert char *kprop = KPROPD_DEFAULT_KPROP;
73*7f2fe78bSCy Schubert char *dump_file = KPROP_DEFAULT_FILE;
74*7f2fe78bSCy Schubert char *kprop_port = NULL;
75*7f2fe78bSCy Schubert
76*7f2fe78bSCy Schubert static krb5_context context;
77*7f2fe78bSCy Schubert static char *progname;
78*7f2fe78bSCy Schubert
79*7f2fe78bSCy Schubert static void
usage()80*7f2fe78bSCy Schubert usage()
81*7f2fe78bSCy Schubert {
82*7f2fe78bSCy Schubert fprintf(stderr, _("Usage: kadmind [-x db_args]* [-r realm] [-m] [-nofork] "
83*7f2fe78bSCy Schubert "[-port port-number]\n"
84*7f2fe78bSCy Schubert "\t\t[-proponly] [-p path-to-kdb5_util] [-F dump-file]\n"
85*7f2fe78bSCy Schubert "\t\t[-K path-to-kprop] [-k kprop-port] [-P pid_file]\n"
86*7f2fe78bSCy Schubert "\nwhere,\n\t[-x db_args]* - any number of database "
87*7f2fe78bSCy Schubert "specific arguments.\n"
88*7f2fe78bSCy Schubert "\t\t\tLook at each database documentation for "
89*7f2fe78bSCy Schubert "supported arguments\n"));
90*7f2fe78bSCy Schubert exit(1);
91*7f2fe78bSCy Schubert }
92*7f2fe78bSCy Schubert
93*7f2fe78bSCy Schubert /*
94*7f2fe78bSCy Schubert * Output a message to stderr and the admin server log, and exit with status 1.
95*7f2fe78bSCy Schubert * msg should not be punctuated. If code is given, msg should indicate what
96*7f2fe78bSCy Schubert * operation was taking place in the present progressive. Otherwise msg should
97*7f2fe78bSCy Schubert * be capitalized and should indicate what went wrong.
98*7f2fe78bSCy Schubert */
99*7f2fe78bSCy Schubert static void
fail_to_start(krb5_error_code code,const char * msg)100*7f2fe78bSCy Schubert fail_to_start(krb5_error_code code, const char *msg)
101*7f2fe78bSCy Schubert {
102*7f2fe78bSCy Schubert const char *errmsg;
103*7f2fe78bSCy Schubert
104*7f2fe78bSCy Schubert if (code) {
105*7f2fe78bSCy Schubert errmsg = krb5_get_error_message(context, code);
106*7f2fe78bSCy Schubert fprintf(stderr, _("%s: %s while %s, aborting\n"), progname, errmsg,
107*7f2fe78bSCy Schubert msg);
108*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR, _("%s while %s, aborting\n"), errmsg, msg);
109*7f2fe78bSCy Schubert } else {
110*7f2fe78bSCy Schubert fprintf(stderr, _("%s: %s, aborting\n"), progname, msg);
111*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR, _("%s, aborting"), msg);
112*7f2fe78bSCy Schubert }
113*7f2fe78bSCy Schubert exit(1);
114*7f2fe78bSCy Schubert }
115*7f2fe78bSCy Schubert
116*7f2fe78bSCy Schubert static int
write_pid_file(const char * pid_file)117*7f2fe78bSCy Schubert write_pid_file(const char *pid_file)
118*7f2fe78bSCy Schubert {
119*7f2fe78bSCy Schubert FILE *file;
120*7f2fe78bSCy Schubert unsigned long pid;
121*7f2fe78bSCy Schubert int st1, st2;
122*7f2fe78bSCy Schubert
123*7f2fe78bSCy Schubert file = fopen(pid_file, "w");
124*7f2fe78bSCy Schubert if (file == NULL)
125*7f2fe78bSCy Schubert return errno;
126*7f2fe78bSCy Schubert pid = (unsigned long)getpid();
127*7f2fe78bSCy Schubert st1 = (fprintf(file, "%ld\n", pid) < 0) ? errno : 0;
128*7f2fe78bSCy Schubert st2 = (fclose(file) == EOF) ? errno : 0;
129*7f2fe78bSCy Schubert return st1 ? st1 : st2;
130*7f2fe78bSCy Schubert }
131*7f2fe78bSCy Schubert
132*7f2fe78bSCy Schubert /* Set up the main loop. If proponly is set, don't set up ports for kpasswd or
133*7f2fe78bSCy Schubert * kadmin. May set *ctx_out even on error. */
134*7f2fe78bSCy Schubert static krb5_error_code
setup_loop(kadm5_config_params * params,int proponly,verto_ctx ** ctx_out)135*7f2fe78bSCy Schubert setup_loop(kadm5_config_params *params, int proponly, verto_ctx **ctx_out)
136*7f2fe78bSCy Schubert {
137*7f2fe78bSCy Schubert krb5_error_code ret;
138*7f2fe78bSCy Schubert verto_ctx *ctx;
139*7f2fe78bSCy Schubert
140*7f2fe78bSCy Schubert *ctx_out = ctx = loop_init(VERTO_EV_TYPE_SIGNAL);
141*7f2fe78bSCy Schubert if (ctx == NULL)
142*7f2fe78bSCy Schubert return ENOMEM;
143*7f2fe78bSCy Schubert ret = loop_setup_signals(ctx, &global_server_handle, NULL);
144*7f2fe78bSCy Schubert if (ret)
145*7f2fe78bSCy Schubert return ret;
146*7f2fe78bSCy Schubert if (!proponly) {
147*7f2fe78bSCy Schubert ret = loop_add_udp_address(params->kpasswd_port,
148*7f2fe78bSCy Schubert params->kpasswd_listen);
149*7f2fe78bSCy Schubert if (ret)
150*7f2fe78bSCy Schubert return ret;
151*7f2fe78bSCy Schubert ret = loop_add_tcp_address(params->kpasswd_port,
152*7f2fe78bSCy Schubert params->kpasswd_listen);
153*7f2fe78bSCy Schubert if (ret)
154*7f2fe78bSCy Schubert return ret;
155*7f2fe78bSCy Schubert ret = loop_add_rpc_service(params->kadmind_port,
156*7f2fe78bSCy Schubert params->kadmind_listen,
157*7f2fe78bSCy Schubert KADM, KADMVERS, kadm_1);
158*7f2fe78bSCy Schubert if (ret)
159*7f2fe78bSCy Schubert return ret;
160*7f2fe78bSCy Schubert }
161*7f2fe78bSCy Schubert #ifndef DISABLE_IPROP
162*7f2fe78bSCy Schubert if (params->iprop_enabled) {
163*7f2fe78bSCy Schubert ret = loop_add_rpc_service(params->iprop_port, params->iprop_listen,
164*7f2fe78bSCy Schubert KRB5_IPROP_PROG, KRB5_IPROP_VERS,
165*7f2fe78bSCy Schubert krb5_iprop_prog_1);
166*7f2fe78bSCy Schubert if (ret)
167*7f2fe78bSCy Schubert return ret;
168*7f2fe78bSCy Schubert }
169*7f2fe78bSCy Schubert #endif
170*7f2fe78bSCy Schubert return loop_setup_network(ctx, &global_server_handle, progname,
171*7f2fe78bSCy Schubert DEFAULT_TCP_LISTEN_BACKLOG);
172*7f2fe78bSCy Schubert }
173*7f2fe78bSCy Schubert
174*7f2fe78bSCy Schubert /* Point GSSAPI at the KDB keytab so we don't need an actual file keytab. */
175*7f2fe78bSCy Schubert static krb5_error_code
setup_kdb_keytab()176*7f2fe78bSCy Schubert setup_kdb_keytab()
177*7f2fe78bSCy Schubert {
178*7f2fe78bSCy Schubert krb5_error_code ret;
179*7f2fe78bSCy Schubert
180*7f2fe78bSCy Schubert ret = krb5_ktkdb_set_context(context);
181*7f2fe78bSCy Schubert if (ret)
182*7f2fe78bSCy Schubert return ret;
183*7f2fe78bSCy Schubert ret = krb5_db_register_keytab(context);
184*7f2fe78bSCy Schubert if (ret)
185*7f2fe78bSCy Schubert return ret;
186*7f2fe78bSCy Schubert return krb5_gss_register_acceptor_identity("KDB:");
187*7f2fe78bSCy Schubert }
188*7f2fe78bSCy Schubert
189*7f2fe78bSCy Schubert
190*7f2fe78bSCy Schubert /* Return "name@realm". */
191*7f2fe78bSCy Schubert static char *
build_princ_name(char * name,char * realm)192*7f2fe78bSCy Schubert build_princ_name(char *name, char *realm)
193*7f2fe78bSCy Schubert {
194*7f2fe78bSCy Schubert char *fullname;
195*7f2fe78bSCy Schubert
196*7f2fe78bSCy Schubert if (asprintf(&fullname, "%s@%s", name, realm) < 0)
197*7f2fe78bSCy Schubert return NULL;
198*7f2fe78bSCy Schubert return fullname;
199*7f2fe78bSCy Schubert }
200*7f2fe78bSCy Schubert
201*7f2fe78bSCy Schubert /* Callback from GSSRPC for garbled/forged/replayed/etc messages. */
202*7f2fe78bSCy Schubert static void
log_badverf(gss_name_t client_name,gss_name_t server_name,struct svc_req * rqst,struct rpc_msg * msg,char * data)203*7f2fe78bSCy Schubert log_badverf(gss_name_t client_name, gss_name_t server_name,
204*7f2fe78bSCy Schubert struct svc_req *rqst, struct rpc_msg *msg, char *data)
205*7f2fe78bSCy Schubert {
206*7f2fe78bSCy Schubert static const struct {
207*7f2fe78bSCy Schubert rpcproc_t proc;
208*7f2fe78bSCy Schubert const char *proc_name;
209*7f2fe78bSCy Schubert } proc_names[] = {
210*7f2fe78bSCy Schubert {1, "CREATE_PRINCIPAL"},
211*7f2fe78bSCy Schubert {2, "DELETE_PRINCIPAL"},
212*7f2fe78bSCy Schubert {3, "MODIFY_PRINCIPAL"},
213*7f2fe78bSCy Schubert {4, "RENAME_PRINCIPAL"},
214*7f2fe78bSCy Schubert {5, "GET_PRINCIPAL"},
215*7f2fe78bSCy Schubert {6, "CHPASS_PRINCIPAL"},
216*7f2fe78bSCy Schubert {7, "CHRAND_PRINCIPAL"},
217*7f2fe78bSCy Schubert {8, "CREATE_POLICY"},
218*7f2fe78bSCy Schubert {9, "DELETE_POLICY"},
219*7f2fe78bSCy Schubert {10, "MODIFY_POLICY"},
220*7f2fe78bSCy Schubert {11, "GET_POLICY"},
221*7f2fe78bSCy Schubert {12, "GET_PRIVS"},
222*7f2fe78bSCy Schubert {13, "INIT"},
223*7f2fe78bSCy Schubert {14, "GET_PRINCS"},
224*7f2fe78bSCy Schubert {15, "GET_POLS"},
225*7f2fe78bSCy Schubert {16, "SETKEY_PRINCIPAL"},
226*7f2fe78bSCy Schubert /* 17 was "SETV4KEY_PRINCIPAL" */
227*7f2fe78bSCy Schubert {18, "CREATE_PRINCIPAL3"},
228*7f2fe78bSCy Schubert {19, "CHPASS_PRINCIPAL3"},
229*7f2fe78bSCy Schubert {20, "CHRAND_PRINCIPAL3"},
230*7f2fe78bSCy Schubert {21, "SETKEY_PRINCIPAL3"},
231*7f2fe78bSCy Schubert {22, "PURGEKEYS"},
232*7f2fe78bSCy Schubert {23, "GET_STRINGS"},
233*7f2fe78bSCy Schubert {24, "SET_STRING"}
234*7f2fe78bSCy Schubert };
235*7f2fe78bSCy Schubert OM_uint32 minor;
236*7f2fe78bSCy Schubert gss_buffer_desc client, server;
237*7f2fe78bSCy Schubert gss_OID gss_type;
238*7f2fe78bSCy Schubert const char *a;
239*7f2fe78bSCy Schubert rpcproc_t proc;
240*7f2fe78bSCy Schubert unsigned int i;
241*7f2fe78bSCy Schubert const char *procname;
242*7f2fe78bSCy Schubert size_t clen, slen;
243*7f2fe78bSCy Schubert char *cdots, *sdots;
244*7f2fe78bSCy Schubert
245*7f2fe78bSCy Schubert client.length = 0;
246*7f2fe78bSCy Schubert client.value = NULL;
247*7f2fe78bSCy Schubert server.length = 0;
248*7f2fe78bSCy Schubert server.value = NULL;
249*7f2fe78bSCy Schubert
250*7f2fe78bSCy Schubert (void)gss_display_name(&minor, client_name, &client, &gss_type);
251*7f2fe78bSCy Schubert (void)gss_display_name(&minor, server_name, &server, &gss_type);
252*7f2fe78bSCy Schubert if (client.value == NULL) {
253*7f2fe78bSCy Schubert client.value = "(null)";
254*7f2fe78bSCy Schubert clen = sizeof("(null)") - 1;
255*7f2fe78bSCy Schubert } else {
256*7f2fe78bSCy Schubert clen = client.length;
257*7f2fe78bSCy Schubert }
258*7f2fe78bSCy Schubert trunc_name(&clen, &cdots);
259*7f2fe78bSCy Schubert if (server.value == NULL) {
260*7f2fe78bSCy Schubert server.value = "(null)";
261*7f2fe78bSCy Schubert slen = sizeof("(null)") - 1;
262*7f2fe78bSCy Schubert } else {
263*7f2fe78bSCy Schubert slen = server.length;
264*7f2fe78bSCy Schubert }
265*7f2fe78bSCy Schubert trunc_name(&slen, &sdots);
266*7f2fe78bSCy Schubert a = client_addr(rqst->rq_xprt);
267*7f2fe78bSCy Schubert
268*7f2fe78bSCy Schubert proc = msg->rm_call.cb_proc;
269*7f2fe78bSCy Schubert procname = NULL;
270*7f2fe78bSCy Schubert for (i = 0; i < sizeof(proc_names) / sizeof(*proc_names); i++) {
271*7f2fe78bSCy Schubert if (proc_names[i].proc == proc) {
272*7f2fe78bSCy Schubert procname = proc_names[i].proc_name;
273*7f2fe78bSCy Schubert break;
274*7f2fe78bSCy Schubert }
275*7f2fe78bSCy Schubert }
276*7f2fe78bSCy Schubert if (procname != NULL) {
277*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_NOTICE,
278*7f2fe78bSCy Schubert _("WARNING! Forged/garbled request: %s, claimed "
279*7f2fe78bSCy Schubert "client = %.*s%s, server = %.*s%s, addr = %s"),
280*7f2fe78bSCy Schubert procname, (int)clen, (char *)client.value, cdots,
281*7f2fe78bSCy Schubert (int)slen, (char *)server.value, sdots, a);
282*7f2fe78bSCy Schubert } else {
283*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_NOTICE,
284*7f2fe78bSCy Schubert _("WARNING! Forged/garbled request: %d, claimed "
285*7f2fe78bSCy Schubert "client = %.*s%s, server = %.*s%s, addr = %s"),
286*7f2fe78bSCy Schubert proc, (int)clen, (char *)client.value, cdots,
287*7f2fe78bSCy Schubert (int)slen, (char *)server.value, sdots, a);
288*7f2fe78bSCy Schubert }
289*7f2fe78bSCy Schubert
290*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &client);
291*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor, &server);
292*7f2fe78bSCy Schubert }
293*7f2fe78bSCy Schubert
294*7f2fe78bSCy Schubert /* Callback from GSSRPC for miscellaneous errors */
295*7f2fe78bSCy Schubert static void
log_miscerr(struct svc_req * rqst,struct rpc_msg * msg,char * error,char * data)296*7f2fe78bSCy Schubert log_miscerr(struct svc_req *rqst, struct rpc_msg *msg, char *error, char *data)
297*7f2fe78bSCy Schubert {
298*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_NOTICE, _("Miscellaneous RPC error: %s, %s"),
299*7f2fe78bSCy Schubert client_addr(rqst->rq_xprt), error);
300*7f2fe78bSCy Schubert }
301*7f2fe78bSCy Schubert
302*7f2fe78bSCy Schubert static void
log_badauth_display_status_1(char * m,OM_uint32 code,int type)303*7f2fe78bSCy Schubert log_badauth_display_status_1(char *m, OM_uint32 code, int type)
304*7f2fe78bSCy Schubert {
305*7f2fe78bSCy Schubert OM_uint32 gssstat, minor_stat;
306*7f2fe78bSCy Schubert gss_buffer_desc msg;
307*7f2fe78bSCy Schubert OM_uint32 msg_ctx;
308*7f2fe78bSCy Schubert
309*7f2fe78bSCy Schubert msg_ctx = 0;
310*7f2fe78bSCy Schubert while (1) {
311*7f2fe78bSCy Schubert gssstat = gss_display_status(&minor_stat, code, type, GSS_C_NULL_OID,
312*7f2fe78bSCy Schubert &msg_ctx, &msg);
313*7f2fe78bSCy Schubert if (gssstat != GSS_S_COMPLETE) {
314*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_ERR, _("%s Cannot decode status %d"), m,
315*7f2fe78bSCy Schubert (int)code);
316*7f2fe78bSCy Schubert return;
317*7f2fe78bSCy Schubert }
318*7f2fe78bSCy Schubert
319*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_NOTICE, "%s %.*s", m, (int)msg.length,
320*7f2fe78bSCy Schubert (char *)msg.value);
321*7f2fe78bSCy Schubert (void)gss_release_buffer(&minor_stat, &msg);
322*7f2fe78bSCy Schubert
323*7f2fe78bSCy Schubert if (!msg_ctx)
324*7f2fe78bSCy Schubert break;
325*7f2fe78bSCy Schubert }
326*7f2fe78bSCy Schubert }
327*7f2fe78bSCy Schubert
328*7f2fe78bSCy Schubert /* Callback from GSSRPC for authentication failures */
329*7f2fe78bSCy Schubert void
log_badauth(OM_uint32 major,OM_uint32 minor,SVCXPRT * xprt,char * data)330*7f2fe78bSCy Schubert log_badauth(OM_uint32 major, OM_uint32 minor, SVCXPRT *xprt, char *data)
331*7f2fe78bSCy Schubert {
332*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_NOTICE, _("Authentication attempt failed: %s, "
333*7f2fe78bSCy Schubert "GSS-API error strings are:"),
334*7f2fe78bSCy Schubert client_addr(xprt));
335*7f2fe78bSCy Schubert log_badauth_display_status_1(" ", major, GSS_C_GSS_CODE);
336*7f2fe78bSCy Schubert log_badauth_display_status_1(" ", minor, GSS_C_MECH_CODE);
337*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_NOTICE, _(" GSS-API error strings complete."));
338*7f2fe78bSCy Schubert }
339*7f2fe78bSCy Schubert
340*7f2fe78bSCy Schubert int
main(int argc,char * argv[])341*7f2fe78bSCy Schubert main(int argc, char *argv[])
342*7f2fe78bSCy Schubert {
343*7f2fe78bSCy Schubert OM_uint32 minor_status;
344*7f2fe78bSCy Schubert gss_buffer_desc in_buf;
345*7f2fe78bSCy Schubert gss_OID nt_krb5_name_oid = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME;
346*7f2fe78bSCy Schubert auth_gssapi_name names[4];
347*7f2fe78bSCy Schubert kadm5_config_params params;
348*7f2fe78bSCy Schubert verto_ctx *vctx;
349*7f2fe78bSCy Schubert const char *pid_file = NULL;
350*7f2fe78bSCy Schubert char **db_args = NULL, **tmpargs;
351*7f2fe78bSCy Schubert const char *acl_file;
352*7f2fe78bSCy Schubert int ret, i, db_args_size = 0, proponly = 0;
353*7f2fe78bSCy Schubert
354*7f2fe78bSCy Schubert setlocale(LC_ALL, "");
355*7f2fe78bSCy Schubert setvbuf(stderr, NULL, _IONBF, 0);
356*7f2fe78bSCy Schubert
357*7f2fe78bSCy Schubert names[0].name = names[1].name = names[2].name = names[3].name = NULL;
358*7f2fe78bSCy Schubert names[0].type = names[1].type = names[2].type = names[3].type =
359*7f2fe78bSCy Schubert nt_krb5_name_oid;
360*7f2fe78bSCy Schubert
361*7f2fe78bSCy Schubert progname = (strrchr(argv[0], '/') != NULL) ? strrchr(argv[0], '/') + 1 :
362*7f2fe78bSCy Schubert argv[0];
363*7f2fe78bSCy Schubert
364*7f2fe78bSCy Schubert memset(¶ms, 0, sizeof(params));
365*7f2fe78bSCy Schubert
366*7f2fe78bSCy Schubert argc--, argv++;
367*7f2fe78bSCy Schubert while (argc) {
368*7f2fe78bSCy Schubert if (strcmp(*argv, "-x") == 0) {
369*7f2fe78bSCy Schubert argc--, argv++;
370*7f2fe78bSCy Schubert if (!argc)
371*7f2fe78bSCy Schubert usage();
372*7f2fe78bSCy Schubert db_args_size++;
373*7f2fe78bSCy Schubert tmpargs = realloc(db_args, sizeof(char *) * (db_args_size + 1));
374*7f2fe78bSCy Schubert if (tmpargs == NULL) {
375*7f2fe78bSCy Schubert fprintf(stderr, _("%s: cannot initialize. Not enough "
376*7f2fe78bSCy Schubert "memory\n"), progname);
377*7f2fe78bSCy Schubert exit(1);
378*7f2fe78bSCy Schubert }
379*7f2fe78bSCy Schubert db_args = tmpargs;
380*7f2fe78bSCy Schubert db_args[db_args_size - 1] = *argv;
381*7f2fe78bSCy Schubert db_args[db_args_size] = NULL;
382*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-r") == 0) {
383*7f2fe78bSCy Schubert argc--, argv++;
384*7f2fe78bSCy Schubert if (!argc)
385*7f2fe78bSCy Schubert usage();
386*7f2fe78bSCy Schubert params.realm = *argv;
387*7f2fe78bSCy Schubert params.mask |= KADM5_CONFIG_REALM;
388*7f2fe78bSCy Schubert argc--, argv++;
389*7f2fe78bSCy Schubert continue;
390*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-m") == 0) {
391*7f2fe78bSCy Schubert params.mkey_from_kbd = 1;
392*7f2fe78bSCy Schubert params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
393*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-nofork") == 0) {
394*7f2fe78bSCy Schubert nofork = 1;
395*7f2fe78bSCy Schubert #ifndef DISABLE_IPROP
396*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-proponly") == 0) {
397*7f2fe78bSCy Schubert proponly = 1;
398*7f2fe78bSCy Schubert #endif
399*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-port") == 0) {
400*7f2fe78bSCy Schubert argc--, argv++;
401*7f2fe78bSCy Schubert if (!argc)
402*7f2fe78bSCy Schubert usage();
403*7f2fe78bSCy Schubert params.kadmind_port = atoi(*argv);
404*7f2fe78bSCy Schubert params.mask |= KADM5_CONFIG_KADMIND_PORT;
405*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-P") == 0) {
406*7f2fe78bSCy Schubert argc--, argv++;
407*7f2fe78bSCy Schubert if (!argc)
408*7f2fe78bSCy Schubert usage();
409*7f2fe78bSCy Schubert pid_file = *argv;
410*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-W") == 0) {
411*7f2fe78bSCy Schubert /* Ignore (deprecated weak random option). */
412*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-p") == 0) {
413*7f2fe78bSCy Schubert argc--, argv++;
414*7f2fe78bSCy Schubert if (!argc)
415*7f2fe78bSCy Schubert usage();
416*7f2fe78bSCy Schubert kdb5_util = *argv;
417*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-F") == 0) {
418*7f2fe78bSCy Schubert argc--, argv++;
419*7f2fe78bSCy Schubert if (!argc)
420*7f2fe78bSCy Schubert usage();
421*7f2fe78bSCy Schubert dump_file = *argv;
422*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-K") == 0) {
423*7f2fe78bSCy Schubert argc--, argv++;
424*7f2fe78bSCy Schubert if (!argc)
425*7f2fe78bSCy Schubert usage();
426*7f2fe78bSCy Schubert kprop = *argv;
427*7f2fe78bSCy Schubert } else if (strcmp(*argv, "-k") == 0) {
428*7f2fe78bSCy Schubert argc--, argv++;
429*7f2fe78bSCy Schubert if (!argc)
430*7f2fe78bSCy Schubert usage();
431*7f2fe78bSCy Schubert kprop_port = *argv;
432*7f2fe78bSCy Schubert } else {
433*7f2fe78bSCy Schubert break;
434*7f2fe78bSCy Schubert }
435*7f2fe78bSCy Schubert argc--, argv++;
436*7f2fe78bSCy Schubert }
437*7f2fe78bSCy Schubert
438*7f2fe78bSCy Schubert if (argc != 0)
439*7f2fe78bSCy Schubert usage();
440*7f2fe78bSCy Schubert
441*7f2fe78bSCy Schubert ret = kadm5_init_krb5_context(&context);
442*7f2fe78bSCy Schubert if (ret) {
443*7f2fe78bSCy Schubert fprintf(stderr, _("%s: %s while initializing context, aborting\n"),
444*7f2fe78bSCy Schubert progname, error_message(ret));
445*7f2fe78bSCy Schubert exit(1);
446*7f2fe78bSCy Schubert }
447*7f2fe78bSCy Schubert
448*7f2fe78bSCy Schubert krb5_klog_init(context, "admin_server", progname, 1);
449*7f2fe78bSCy Schubert
450*7f2fe78bSCy Schubert ret = kadm5_init(context, "kadmind", NULL, NULL, ¶ms,
451*7f2fe78bSCy Schubert KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args,
452*7f2fe78bSCy Schubert &global_server_handle);
453*7f2fe78bSCy Schubert if (ret)
454*7f2fe78bSCy Schubert fail_to_start(ret, _("initializing"));
455*7f2fe78bSCy Schubert
456*7f2fe78bSCy Schubert ret = kadm5_get_config_params(context, 1, ¶ms, ¶ms);
457*7f2fe78bSCy Schubert if (ret)
458*7f2fe78bSCy Schubert fail_to_start(ret, _("getting config parameters"));
459*7f2fe78bSCy Schubert if (!(params.mask & KADM5_CONFIG_REALM))
460*7f2fe78bSCy Schubert fail_to_start(0, _("Missing required realm configuration"));
461*7f2fe78bSCy Schubert if (!(params.mask & KADM5_CONFIG_ACL_FILE))
462*7f2fe78bSCy Schubert fail_to_start(0, _("Missing required ACL file configuration"));
463*7f2fe78bSCy Schubert if (proponly && !params.iprop_enabled) {
464*7f2fe78bSCy Schubert fail_to_start(0, _("-proponly can only be used when "
465*7f2fe78bSCy Schubert "iprop_enable is true"));
466*7f2fe78bSCy Schubert }
467*7f2fe78bSCy Schubert
468*7f2fe78bSCy Schubert ret = setup_loop(¶ms, proponly, &vctx);
469*7f2fe78bSCy Schubert if (ret)
470*7f2fe78bSCy Schubert fail_to_start(ret, _("initializing network"));
471*7f2fe78bSCy Schubert
472*7f2fe78bSCy Schubert names[0].name = build_princ_name(KADM5_ADMIN_SERVICE, params.realm);
473*7f2fe78bSCy Schubert names[1].name = build_princ_name(KADM5_CHANGEPW_SERVICE, params.realm);
474*7f2fe78bSCy Schubert if (names[0].name == NULL || names[1].name == NULL)
475*7f2fe78bSCy Schubert fail_to_start(0, _("Cannot build GSSAPI auth names"));
476*7f2fe78bSCy Schubert
477*7f2fe78bSCy Schubert ret = setup_kdb_keytab();
478*7f2fe78bSCy Schubert if (ret)
479*7f2fe78bSCy Schubert fail_to_start(0, _("Cannot set up KDB keytab"));
480*7f2fe78bSCy Schubert
481*7f2fe78bSCy Schubert if (svcauth_gssapi_set_names(names, 2) == FALSE)
482*7f2fe78bSCy Schubert fail_to_start(0, _("Cannot set GSSAPI authentication names"));
483*7f2fe78bSCy Schubert
484*7f2fe78bSCy Schubert /* if set_names succeeded, this will too */
485*7f2fe78bSCy Schubert in_buf.value = names[1].name;
486*7f2fe78bSCy Schubert in_buf.length = strlen(names[1].name) + 1;
487*7f2fe78bSCy Schubert (void)gss_import_name(&minor_status, &in_buf, nt_krb5_name_oid,
488*7f2fe78bSCy Schubert &gss_changepw_name);
489*7f2fe78bSCy Schubert
490*7f2fe78bSCy Schubert svcauth_gssapi_set_log_badauth2_func(log_badauth, NULL);
491*7f2fe78bSCy Schubert svcauth_gssapi_set_log_badverf_func(log_badverf, NULL);
492*7f2fe78bSCy Schubert svcauth_gssapi_set_log_miscerr_func(log_miscerr, NULL);
493*7f2fe78bSCy Schubert
494*7f2fe78bSCy Schubert svcauth_gss_set_log_badauth2_func(log_badauth, NULL);
495*7f2fe78bSCy Schubert svcauth_gss_set_log_badverf_func(log_badverf, NULL);
496*7f2fe78bSCy Schubert svcauth_gss_set_log_miscerr_func(log_miscerr, NULL);
497*7f2fe78bSCy Schubert
498*7f2fe78bSCy Schubert if (svcauth_gss_set_svc_name(GSS_C_NO_NAME) != TRUE)
499*7f2fe78bSCy Schubert fail_to_start(0, _("Cannot initialize GSSAPI service name"));
500*7f2fe78bSCy Schubert
501*7f2fe78bSCy Schubert acl_file = (*params.acl_file != '\0') ? params.acl_file : NULL;
502*7f2fe78bSCy Schubert ret = auth_init(context, acl_file);
503*7f2fe78bSCy Schubert if (ret)
504*7f2fe78bSCy Schubert fail_to_start(ret, _("initializing ACL file"));
505*7f2fe78bSCy Schubert
506*7f2fe78bSCy Schubert /* Since some KDB modules are not fork-safe, we must reinitialize the
507*7f2fe78bSCy Schubert * server handle after daemonizing. */
508*7f2fe78bSCy Schubert kadm5_destroy(global_server_handle);
509*7f2fe78bSCy Schubert global_server_handle = NULL;
510*7f2fe78bSCy Schubert
511*7f2fe78bSCy Schubert if (!nofork && daemon(0, 0) != 0)
512*7f2fe78bSCy Schubert fail_to_start(errno, _("spawning daemon process"));
513*7f2fe78bSCy Schubert if (pid_file != NULL) {
514*7f2fe78bSCy Schubert ret = write_pid_file(pid_file);
515*7f2fe78bSCy Schubert if (ret)
516*7f2fe78bSCy Schubert fail_to_start(ret, _("creating PID file"));
517*7f2fe78bSCy Schubert }
518*7f2fe78bSCy Schubert
519*7f2fe78bSCy Schubert ret = kadm5_init(context, "kadmind", NULL, NULL, ¶ms,
520*7f2fe78bSCy Schubert KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, db_args,
521*7f2fe78bSCy Schubert &global_server_handle);
522*7f2fe78bSCy Schubert if (ret)
523*7f2fe78bSCy Schubert fail_to_start(ret, _("initializing"));
524*7f2fe78bSCy Schubert
525*7f2fe78bSCy Schubert if (params.iprop_enabled == TRUE) {
526*7f2fe78bSCy Schubert ulog_set_role(context, IPROP_PRIMARY);
527*7f2fe78bSCy Schubert
528*7f2fe78bSCy Schubert ret = ulog_map(context, params.iprop_logfile, params.iprop_ulogsize);
529*7f2fe78bSCy Schubert if (ret)
530*7f2fe78bSCy Schubert fail_to_start(ret, _("mapping update log"));
531*7f2fe78bSCy Schubert
532*7f2fe78bSCy Schubert if (nofork) {
533*7f2fe78bSCy Schubert fprintf(stderr,
534*7f2fe78bSCy Schubert _("%s: create IPROP svc (PROG=%d, VERS=%d)\n"),
535*7f2fe78bSCy Schubert progname, KRB5_IPROP_PROG, KRB5_IPROP_VERS);
536*7f2fe78bSCy Schubert }
537*7f2fe78bSCy Schubert }
538*7f2fe78bSCy Schubert
539*7f2fe78bSCy Schubert if (kprop_port == NULL)
540*7f2fe78bSCy Schubert kprop_port = getenv("KPROP_PORT");
541*7f2fe78bSCy Schubert
542*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_INFO, _("starting"));
543*7f2fe78bSCy Schubert if (nofork)
544*7f2fe78bSCy Schubert fprintf(stderr, _("%s: starting...\n"), progname);
545*7f2fe78bSCy Schubert
546*7f2fe78bSCy Schubert verto_run(vctx);
547*7f2fe78bSCy Schubert krb5_klog_syslog(LOG_INFO, _("finished, exiting"));
548*7f2fe78bSCy Schubert
549*7f2fe78bSCy Schubert /* Clean up memory, etc */
550*7f2fe78bSCy Schubert svcauth_gssapi_unset_names();
551*7f2fe78bSCy Schubert kadm5_destroy(global_server_handle);
552*7f2fe78bSCy Schubert loop_free(vctx);
553*7f2fe78bSCy Schubert auth_fini(context);
554*7f2fe78bSCy Schubert (void)gss_release_name(&minor_status, &gss_changepw_name);
555*7f2fe78bSCy Schubert (void)gss_release_name(&minor_status, &gss_oldchangepw_name);
556*7f2fe78bSCy Schubert for (i = 0; i < 4; i++)
557*7f2fe78bSCy Schubert free(names[i].name);
558*7f2fe78bSCy Schubert
559*7f2fe78bSCy Schubert krb5_klog_close(context);
560*7f2fe78bSCy Schubert krb5_free_context(context);
561*7f2fe78bSCy Schubert exit(0);
562*7f2fe78bSCy Schubert }
563