17c478bd9Sstevel@tonic-gate /*
2f5918cfdS * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate * All rights reserved.
67c478bd9Sstevel@tonic-gate *
77c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may require
87c478bd9Sstevel@tonic-gate * a specific license from the United States Government. It is the
97c478bd9Sstevel@tonic-gate * responsibility of any person or organization contemplating export to
107c478bd9Sstevel@tonic-gate * obtain such a license before exporting.
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
137c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
147c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
157c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
167c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
177c478bd9Sstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining
187c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
197c478bd9Sstevel@tonic-gate * permission. FundsXpress makes no representations about the suitability of
207c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
217c478bd9Sstevel@tonic-gate * or implied warranty.
227c478bd9Sstevel@tonic-gate *
237c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
247c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
257c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate * slave/kpropd.c
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate * Copyright 1990,1991 by the Massachusetts Institute of Technology.
327c478bd9Sstevel@tonic-gate * All Rights Reserved.
337c478bd9Sstevel@tonic-gate *
347c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may
357c478bd9Sstevel@tonic-gate * require a specific license from the United States Government.
367c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
377c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting.
387c478bd9Sstevel@tonic-gate *
397c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
407c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
417c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
427c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
437c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
447c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
457c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
467c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
477c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a
487c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
497c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
507c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
517c478bd9Sstevel@tonic-gate * or implied warranty.
527c478bd9Sstevel@tonic-gate *
537c478bd9Sstevel@tonic-gate *
547c478bd9Sstevel@tonic-gate * XXX We need to modify the protocol so that an acknowledge is set
557c478bd9Sstevel@tonic-gate * after each block, instead after the entire series is sent over.
567c478bd9Sstevel@tonic-gate * The reason for this is so that error packets can get interpreted
577c478bd9Sstevel@tonic-gate * right away. If you don't do this, the sender may never get the
587c478bd9Sstevel@tonic-gate * error packet, because it will die an EPIPE trying to complete the
597c478bd9Sstevel@tonic-gate * write...
607c478bd9Sstevel@tonic-gate */
617c478bd9Sstevel@tonic-gate
6256a424ccSmp153739
637c478bd9Sstevel@tonic-gate #include <stdio.h>
647c478bd9Sstevel@tonic-gate #include <ctype.h>
657c478bd9Sstevel@tonic-gate #include <sys/file.h>
667c478bd9Sstevel@tonic-gate #include <signal.h>
677c478bd9Sstevel@tonic-gate #include <string.h>
687c478bd9Sstevel@tonic-gate #include <fcntl.h>
697c478bd9Sstevel@tonic-gate #include <sys/types.h>
707c478bd9Sstevel@tonic-gate #include <sys/time.h>
717c478bd9Sstevel@tonic-gate #include <sys/stat.h>
727c478bd9Sstevel@tonic-gate #include <sys/socket.h>
737c478bd9Sstevel@tonic-gate #include <sys/wait.h>
747c478bd9Sstevel@tonic-gate #include <netinet/in.h>
757c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
767c478bd9Sstevel@tonic-gate #include <sys/param.h>
777c478bd9Sstevel@tonic-gate #include <netdb.h>
787c478bd9Sstevel@tonic-gate #include <syslog.h>
797c478bd9Sstevel@tonic-gate #include <libintl.h>
807c478bd9Sstevel@tonic-gate #include <locale.h>
817c478bd9Sstevel@tonic-gate #include <k5-int.h>
827c478bd9Sstevel@tonic-gate #include <socket-utils.h>
837c478bd9Sstevel@tonic-gate #include "com_err.h"
847c478bd9Sstevel@tonic-gate #include <errno.h>
857c478bd9Sstevel@tonic-gate
867c478bd9Sstevel@tonic-gate #include "kprop.h"
877c478bd9Sstevel@tonic-gate #include <iprop_hdr.h>
887c478bd9Sstevel@tonic-gate #include "iprop.h"
897c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
907c478bd9Sstevel@tonic-gate #include <kdb/kdb_log.h>
917c478bd9Sstevel@tonic-gate
927c64d375Smp153739 /* Solaris Kerberos */
937c64d375Smp153739 #include <libgen.h>
947c64d375Smp153739
957c478bd9Sstevel@tonic-gate #define SYSLOG_CLASS LOG_DAEMON
96*83cba5f6SPeter Shoults #define INITIAL_TIMER 10
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate char *poll_time = NULL;
997c478bd9Sstevel@tonic-gate char *def_realm = NULL;
1007c478bd9Sstevel@tonic-gate boolean_t runonce = B_FALSE;
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate /*
103*83cba5f6SPeter Shoults * Global fd to close upon alarm time-out.
104*83cba5f6SPeter Shoults */
105*83cba5f6SPeter Shoults volatile int gfd = -1;
106*83cba5f6SPeter Shoults
107*83cba5f6SPeter Shoults /*
1087c478bd9Sstevel@tonic-gate * This struct simulates the use of _kadm5_server_handle_t
1097c478bd9Sstevel@tonic-gate */
1107c478bd9Sstevel@tonic-gate typedef struct _kadm5_iprop_handle_t {
1117c478bd9Sstevel@tonic-gate krb5_ui_4 magic_number;
1127c478bd9Sstevel@tonic-gate krb5_ui_4 struct_version;
1137c478bd9Sstevel@tonic-gate krb5_ui_4 api_version;
1147c478bd9Sstevel@tonic-gate char *cache_name;
1157c478bd9Sstevel@tonic-gate int destroy_cache;
1167c478bd9Sstevel@tonic-gate CLIENT *clnt;
1177c478bd9Sstevel@tonic-gate krb5_context context;
1187c478bd9Sstevel@tonic-gate kadm5_config_params params;
1197c478bd9Sstevel@tonic-gate struct _kadm5_iprop_handle_t *lhandle;
1207c478bd9Sstevel@tonic-gate } *kadm5_iprop_handle_t;
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate static char *kprop_version = KPROP_PROT_VERSION;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate char *progname;
1257c478bd9Sstevel@tonic-gate int debug = 0;
1267c478bd9Sstevel@tonic-gate char *srvtab = 0;
1277c478bd9Sstevel@tonic-gate int standalone = 0;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate krb5_principal server; /* This is our server principal name */
1307c478bd9Sstevel@tonic-gate krb5_principal client; /* This is who we're talking to */
1317c478bd9Sstevel@tonic-gate krb5_context kpropd_context;
1327c478bd9Sstevel@tonic-gate krb5_auth_context auth_context;
1337c478bd9Sstevel@tonic-gate char *realm = NULL; /* Our realm */
1347c478bd9Sstevel@tonic-gate char *file = KPROPD_DEFAULT_FILE;
1357c478bd9Sstevel@tonic-gate char *temp_file_name;
1367c478bd9Sstevel@tonic-gate char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL;
1377c478bd9Sstevel@tonic-gate char *kerb_database = NULL;
1387c478bd9Sstevel@tonic-gate char *acl_file_name = KPROPD_ACL_FILE;
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate krb5_address sender_addr;
1417c478bd9Sstevel@tonic-gate krb5_address receiver_addr;
1427c478bd9Sstevel@tonic-gate short port = 0;
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate void PRS
1457c478bd9Sstevel@tonic-gate (int, char**);
1467c478bd9Sstevel@tonic-gate int do_standalone
1477c478bd9Sstevel@tonic-gate (iprop_role iproprole);
1487c478bd9Sstevel@tonic-gate void doit
1497c478bd9Sstevel@tonic-gate (int);
1507c478bd9Sstevel@tonic-gate krb5_error_code do_iprop(kdb_log_context *log_ctx);
1517c478bd9Sstevel@tonic-gate
152f5918cfdS /* Solaris Kerberos */
1537c478bd9Sstevel@tonic-gate void kerberos_authenticate
1547c478bd9Sstevel@tonic-gate (krb5_context,
1557c478bd9Sstevel@tonic-gate int,
1567c478bd9Sstevel@tonic-gate krb5_principal *,
1577c478bd9Sstevel@tonic-gate krb5_enctype *,
158f5918cfdS struct sockaddr_storage *);
1597c478bd9Sstevel@tonic-gate krb5_boolean authorized_principal
1607c478bd9Sstevel@tonic-gate (krb5_context,
1617c478bd9Sstevel@tonic-gate krb5_principal,
1627c478bd9Sstevel@tonic-gate krb5_enctype);
1637c478bd9Sstevel@tonic-gate void recv_database
1647c478bd9Sstevel@tonic-gate (krb5_context,
1657c478bd9Sstevel@tonic-gate int,
1667c478bd9Sstevel@tonic-gate int,
1677c478bd9Sstevel@tonic-gate krb5_data *);
1687c478bd9Sstevel@tonic-gate void load_database
1697c478bd9Sstevel@tonic-gate (krb5_context,
1707c478bd9Sstevel@tonic-gate char *,
1717c478bd9Sstevel@tonic-gate char *);
1727c478bd9Sstevel@tonic-gate void send_error
1737c478bd9Sstevel@tonic-gate (krb5_context,
1747c478bd9Sstevel@tonic-gate int,
1757c478bd9Sstevel@tonic-gate krb5_error_code,
1767c478bd9Sstevel@tonic-gate char *);
1777c478bd9Sstevel@tonic-gate void recv_error
1787c478bd9Sstevel@tonic-gate (krb5_context,
1797c478bd9Sstevel@tonic-gate krb5_data *);
1807c478bd9Sstevel@tonic-gate int convert_polltime
1817c478bd9Sstevel@tonic-gate (char *);
1827c478bd9Sstevel@tonic-gate unsigned int backoff_from_master
1837c478bd9Sstevel@tonic-gate (int *);
1847c478bd9Sstevel@tonic-gate
usage()1857c478bd9Sstevel@tonic-gate static void usage()
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate fprintf(stderr,
1887c478bd9Sstevel@tonic-gate gettext("\nUsage: %s\n"), /* progname may be a long pathname */
1897c478bd9Sstevel@tonic-gate progname);
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate fprintf(stderr,
1927c478bd9Sstevel@tonic-gate gettext("\t[-r realm] [-s srvtab] [-dS] [-f slave_file]\n"));
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate fprintf(stderr,
1957c478bd9Sstevel@tonic-gate gettext("\t[-F kerberos_db_file ] [-p kdb5_util_pathname]\n"));
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\t[-P port] [-a acl_file]\n"));
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate exit(1);
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate int
main(argc,argv)2037c478bd9Sstevel@tonic-gate main(argc, argv)
2047c478bd9Sstevel@tonic-gate int argc;
2057c478bd9Sstevel@tonic-gate char **argv;
2067c478bd9Sstevel@tonic-gate {
2077c478bd9Sstevel@tonic-gate krb5_error_code retval;
2087c478bd9Sstevel@tonic-gate int ret = 0;
2097c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx;
21054925bf6Swillf int iprop_supported;
2117c64d375Smp153739 krb5_boolean is_master = FALSE;
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate PRS(argc, argv);
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate log_ctx = kpropd_context->kdblog_context;
2167c478bd9Sstevel@tonic-gate
2177c478bd9Sstevel@tonic-gate if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
2187c478bd9Sstevel@tonic-gate /*
2197c478bd9Sstevel@tonic-gate * We wanna do iprop !
2207c478bd9Sstevel@tonic-gate */
22154925bf6Swillf retval = krb5_db_supports_iprop(kpropd_context,
22254925bf6Swillf &iprop_supported);
22354925bf6Swillf if (retval) {
2247c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
22554925bf6Swillf com_err(progname, retval,
2267c64d375Smp153739 gettext("while determining if dbmodule plugin "
2277c64d375Smp153739 "supports iprop"));
22854925bf6Swillf exit(1);
22954925bf6Swillf }
23054925bf6Swillf if (!iprop_supported) {
2317c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
2327c64d375Smp153739 com_err(progname, 0,
23354925bf6Swillf gettext("Current dbmodule plugin does not support "
2347c64d375Smp153739 "iprop"));
2357c64d375Smp153739 exit(1);
2367c64d375Smp153739 }
2377c64d375Smp153739
2387c64d375Smp153739 /*
2397c64d375Smp153739 * Solaris Kerberos:
2407c64d375Smp153739 * Ensure that kpropd is only run on a slave
2417c64d375Smp153739 */
2427c64d375Smp153739 if (retval = kadm5_is_master(kpropd_context, def_realm,
2437c64d375Smp153739 &is_master)) {
2447c64d375Smp153739 com_err(progname, retval,
2457c64d375Smp153739 gettext("while trying to determine whether host is "
2467c64d375Smp153739 "master KDC for realm %s"), def_realm);
2477c64d375Smp153739 exit(1);
2487c64d375Smp153739 }
2497c64d375Smp153739
2507c64d375Smp153739 if (is_master == TRUE) {
2517c64d375Smp153739 char *master = NULL;
2527c64d375Smp153739 kadm5_get_master(kpropd_context, def_realm, &master);
2537c64d375Smp153739
2547c64d375Smp153739 com_err(progname, 0,
2557c64d375Smp153739 gettext("%s is the master KDC for the realm %s. "
2567c64d375Smp153739 "%s can only be run on a slave KDC"),
2577c64d375Smp153739 master ? master : "unknown", def_realm, progname);
25854925bf6Swillf exit(1);
25954925bf6Swillf }
26054925bf6Swillf
2617c478bd9Sstevel@tonic-gate retval = do_iprop(log_ctx);
2627c478bd9Sstevel@tonic-gate if (retval) {
2637c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
2647c478bd9Sstevel@tonic-gate com_err(progname, retval,
2657c64d375Smp153739 gettext("while doing iprop"));
2667c478bd9Sstevel@tonic-gate exit(1);
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate
2697c478bd9Sstevel@tonic-gate } else {
2707c64d375Smp153739
2717c64d375Smp153739 /*
2727c64d375Smp153739 * Solaris Kerberos:
2737c64d375Smp153739 * Ensure that the kpropd.acl file exists and contains at least
2747c64d375Smp153739 * 1 entry.
2757c64d375Smp153739 */
2767c64d375Smp153739 FILE *tmp_acl_file;
2777c64d375Smp153739 int seen_file = 0;
2787c64d375Smp153739 char buf[1024];
2797c64d375Smp153739
2807c64d375Smp153739 tmp_acl_file = fopen(acl_file_name, "r");
2817c64d375Smp153739 if (!tmp_acl_file) {
2827c64d375Smp153739 com_err(progname, errno,
2837c64d375Smp153739 gettext("while opening acl file %s"),
2847c64d375Smp153739 acl_file_name);
2857c64d375Smp153739 exit(1);
2867c64d375Smp153739 }
2877c64d375Smp153739
2887c64d375Smp153739 while (!feof(tmp_acl_file) && !seen_file ) {
2897c64d375Smp153739 if (!fgets(buf, sizeof(buf), tmp_acl_file))
2907c64d375Smp153739 break;
2917c64d375Smp153739
2927c64d375Smp153739 if (buf[0] != '#' && !isspace(buf[0]))
2937c64d375Smp153739 seen_file = 1;
2947c64d375Smp153739 }
2957c64d375Smp153739 if (!seen_file) {
2967c64d375Smp153739 com_err(progname, 0,
2977c64d375Smp153739 gettext("No entries found in %s. Can't "
2987c64d375Smp153739 "authorize propagation requests"), acl_file_name);
2997c64d375Smp153739 exit(1);
3007c64d375Smp153739 }
3017c64d375Smp153739 fclose(tmp_acl_file);
3027c64d375Smp153739
3037c478bd9Sstevel@tonic-gate if (standalone)
3047c478bd9Sstevel@tonic-gate ret = do_standalone(IPROP_NULL);
3057c478bd9Sstevel@tonic-gate else
3067c478bd9Sstevel@tonic-gate doit(0);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate
3097c478bd9Sstevel@tonic-gate exit(ret);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate
resync_alarm(int sn)312*83cba5f6SPeter Shoults void resync_alarm(int sn)
313*83cba5f6SPeter Shoults {
314*83cba5f6SPeter Shoults close(gfd);
315*83cba5f6SPeter Shoults if (debug)
316*83cba5f6SPeter Shoults fprintf(stderr, gettext("resync_alarm: closing fd: %d\n"), gfd);
317*83cba5f6SPeter Shoults gfd = -1;
318*83cba5f6SPeter Shoults }
319*83cba5f6SPeter Shoults
do_standalone(iprop_role iproprole)3207c478bd9Sstevel@tonic-gate int do_standalone(iprop_role iproprole)
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate struct linger linger;
3237c478bd9Sstevel@tonic-gate struct servent *sp;
3247c478bd9Sstevel@tonic-gate int finet, fromlen, s;
3257c478bd9Sstevel@tonic-gate int on = 1;
3267c478bd9Sstevel@tonic-gate int ret, status = 0;
3277c478bd9Sstevel@tonic-gate struct sockaddr_in6 sin6 = { AF_INET6 };
3287c478bd9Sstevel@tonic-gate int sin6_size = sizeof (sin6);
329*83cba5f6SPeter Shoults /*
330*83cba5f6SPeter Shoults * Timer for accept/read calls, in case of network type errors.
331*83cba5f6SPeter Shoults */
332*83cba5f6SPeter Shoults int backoff_timer = INITIAL_TIMER;
333*83cba5f6SPeter Shoults
334*83cba5f6SPeter Shoults retry:
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate /* listen for either ipv4 or ipv6 */
3377c478bd9Sstevel@tonic-gate finet = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
3387c478bd9Sstevel@tonic-gate if (finet < 0 ) {
3397c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while obtaining socket"));
3407c478bd9Sstevel@tonic-gate exit(1);
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate
3437c478bd9Sstevel@tonic-gate if(!port) {
3447c478bd9Sstevel@tonic-gate sp = getservbyname(KPROP_SERVICE, "tcp");
3457c478bd9Sstevel@tonic-gate if (sp == NULL) {
3467c478bd9Sstevel@tonic-gate com_err(progname, 0, gettext("%s/tcp: unknown service"),
3477c478bd9Sstevel@tonic-gate KPROP_SERVICE);
3487c478bd9Sstevel@tonic-gate exit(1);
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate sin6.sin6_port = sp->s_port;
3517c478bd9Sstevel@tonic-gate } else
3527c478bd9Sstevel@tonic-gate sin6.sin6_port = port;
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate /*
3557c478bd9Sstevel@tonic-gate * We need to close the socket immediately if iprop is enabled,
3567c478bd9Sstevel@tonic-gate * since back-to-back full resyncs are possible, so we do not
3577c478bd9Sstevel@tonic-gate * linger around for too long
3587c478bd9Sstevel@tonic-gate */
3597c478bd9Sstevel@tonic-gate if (iproprole == IPROP_SLAVE) {
3607c478bd9Sstevel@tonic-gate if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
3617c478bd9Sstevel@tonic-gate (char *)&on, sizeof(on)) < 0)
3627c478bd9Sstevel@tonic-gate com_err(progname, errno,
3637c64d375Smp153739 gettext("while setting socket option (SO_REUSEADDR)"));
3647c478bd9Sstevel@tonic-gate linger.l_onoff = 1;
3657c478bd9Sstevel@tonic-gate linger.l_linger = 2;
3667c478bd9Sstevel@tonic-gate if (setsockopt(finet, SOL_SOCKET, SO_LINGER,
3677c478bd9Sstevel@tonic-gate (void *)&linger, sizeof(linger)) < 0)
3687c478bd9Sstevel@tonic-gate com_err(progname, errno,
3697c64d375Smp153739 gettext("while setting socket option (SO_LINGER)"));
370*83cba5f6SPeter Shoults /*
371*83cba5f6SPeter Shoults * We also want to set a timer so that the slave is not waiting
372*83cba5f6SPeter Shoults * until infinity for an update from the master.
373*83cba5f6SPeter Shoults */
374*83cba5f6SPeter Shoults gfd = finet;
375*83cba5f6SPeter Shoults signal(SIGALRM, resync_alarm);
376*83cba5f6SPeter Shoults if (debug) {
377*83cba5f6SPeter Shoults fprintf(stderr, "do_standalone: setting resync alarm to %d\n",
378*83cba5f6SPeter Shoults backoff_timer);
379*83cba5f6SPeter Shoults }
380*83cba5f6SPeter Shoults if (alarm(backoff_timer) != 0) {
381*83cba5f6SPeter Shoults if (debug) {
382*83cba5f6SPeter Shoults fprintf(stderr,
383*83cba5f6SPeter Shoults gettext("%s: alarm already set\n"), progname);
384*83cba5f6SPeter Shoults }
385*83cba5f6SPeter Shoults }
386*83cba5f6SPeter Shoults backoff_timer *= 2;
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate if ((ret = bind(finet, (struct sockaddr *)&sin6, sizeof(sin6))) < 0) {
3897c478bd9Sstevel@tonic-gate if (debug) {
3907c478bd9Sstevel@tonic-gate on = 1;
3917c478bd9Sstevel@tonic-gate fprintf(stderr,
3927c478bd9Sstevel@tonic-gate gettext("%s: attempting to rebind socket "
3937c478bd9Sstevel@tonic-gate "with SO_REUSEADDR\n"), progname);
3947c478bd9Sstevel@tonic-gate if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR,
3957c478bd9Sstevel@tonic-gate (char *)&on, sizeof(on)) < 0) {
3967c478bd9Sstevel@tonic-gate com_err(progname, errno,
3977c64d375Smp153739 gettext("while setting socket option (SO_REUSEADDR)"));
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate ret = bind(finet, (struct sockaddr *) &sin6, sizeof(sin6));
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate if (ret < 0) {
4037c64d375Smp153739 /*
4047c64d375Smp153739 * Solaris Kerberos:
4057c64d375Smp153739 * com_err will print the err msg associated with errno
4067c64d375Smp153739 */
4077c64d375Smp153739 #if 0
4087c478bd9Sstevel@tonic-gate perror(gettext("bind"));
4097c64d375Smp153739 #endif
4107c478bd9Sstevel@tonic-gate com_err(progname, errno,
4117c478bd9Sstevel@tonic-gate gettext("while binding listener socket"));
4127c478bd9Sstevel@tonic-gate exit(1);
4137c478bd9Sstevel@tonic-gate }
4147c478bd9Sstevel@tonic-gate }
4157c64d375Smp153739 if (!debug && (iproprole != IPROP_SLAVE)) {
4167c64d375Smp153739 /* Solaris Kerberos: Indicate where further messages will be sent */
4177c64d375Smp153739 fprintf(stderr,
4187c64d375Smp153739 gettext("%s: Logging to SYSLOG with LOG_DAEMON facility\n"),
4197c64d375Smp153739 progname);
4207c64d375Smp153739 if (daemon(1, 0)) {
4217c64d375Smp153739 com_err(progname, errno, gettext("while daemonizing"));
4227c64d375Smp153739 exit(1);
4237c64d375Smp153739 }
4247c64d375Smp153739 rem_default_com_err_hook();
4257c64d375Smp153739 }
4267c64d375Smp153739
4277c478bd9Sstevel@tonic-gate #ifdef PID_FILE
4287c478bd9Sstevel@tonic-gate if ((pidfile = fopen(PID_FILE, "w")) != NULL) {
4297c478bd9Sstevel@tonic-gate fprintf(pidfile, gettext("%d\n"), getpid());
4307c478bd9Sstevel@tonic-gate fclose(pidfile);
4317c478bd9Sstevel@tonic-gate } else
4327c478bd9Sstevel@tonic-gate com_err(progname, errno,
4337c478bd9Sstevel@tonic-gate gettext("while opening pid file %s for writing"),
4347c478bd9Sstevel@tonic-gate PID_FILE);
4357c478bd9Sstevel@tonic-gate #endif
4367c478bd9Sstevel@tonic-gate if (listen(finet, 5) < 0) {
4377c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
4387c64d375Smp153739 com_err(progname, errno, gettext("while listening on socket"));
4397c478bd9Sstevel@tonic-gate exit(1);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate while (1) {
4427c478bd9Sstevel@tonic-gate int child_pid;
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate s = accept(finet, (struct sockaddr *) &sin6, &sin6_size);
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate if (s < 0) {
447*83cba5f6SPeter Shoults int e = errno;
448*83cba5f6SPeter Shoults if (e != EINTR) {
449*83cba5f6SPeter Shoults /*
450*83cba5f6SPeter Shoults * Solaris Kerberos: Keep error messages
451*83cba5f6SPeter Shoults * consistent
452*83cba5f6SPeter Shoults */
453*83cba5f6SPeter Shoults com_err(progname, e,
4547c64d375Smp153739 gettext("while accepting connection"));
455*83cba5f6SPeter Shoults backoff_timer = INITIAL_TIMER;
4567c64d375Smp153739 }
457*83cba5f6SPeter Shoults /*
458*83cba5f6SPeter Shoults * If we got EBADF, an alarm signal handler closed
459*83cba5f6SPeter Shoults * the file descriptor on us.
460*83cba5f6SPeter Shoults */
461*83cba5f6SPeter Shoults if (e != EBADF)
462*83cba5f6SPeter Shoults close(finet);
463*83cba5f6SPeter Shoults /*
464*83cba5f6SPeter Shoults * An alarm could have been set and the fd closed, we
465*83cba5f6SPeter Shoults * should retry in case of transient network error for
466*83cba5f6SPeter Shoults * up to a couple of minutes.
467*83cba5f6SPeter Shoults */
468*83cba5f6SPeter Shoults if (backoff_timer > 120)
469*83cba5f6SPeter Shoults return (EINTR);
470*83cba5f6SPeter Shoults goto retry;
4717c478bd9Sstevel@tonic-gate }
472*83cba5f6SPeter Shoults alarm(0);
473*83cba5f6SPeter Shoults gfd = -1;
4747c478bd9Sstevel@tonic-gate if (debug && (iproprole != IPROP_SLAVE))
4757c478bd9Sstevel@tonic-gate child_pid = 0;
4767c478bd9Sstevel@tonic-gate else
4777c478bd9Sstevel@tonic-gate child_pid = fork();
4787c478bd9Sstevel@tonic-gate switch (child_pid) {
4797c478bd9Sstevel@tonic-gate case -1:
4807c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while forking"));
4817c478bd9Sstevel@tonic-gate exit(1);
4827c478bd9Sstevel@tonic-gate /*NOTREACHED*/
4837c478bd9Sstevel@tonic-gate case 0:
4847c478bd9Sstevel@tonic-gate /* child */
4857c478bd9Sstevel@tonic-gate (void) close(finet);
48656a424ccSmp153739
4877c478bd9Sstevel@tonic-gate doit(s);
4887c478bd9Sstevel@tonic-gate close(s);
4897c478bd9Sstevel@tonic-gate _exit(0);
4907c478bd9Sstevel@tonic-gate /*NOTREACHED*/
4917c478bd9Sstevel@tonic-gate default:
4927c478bd9Sstevel@tonic-gate /* parent */
493*83cba5f6SPeter Shoults /*
494*83cba5f6SPeter Shoults * Errors should not be considered fatal in the iprop case as we
495*83cba5f6SPeter Shoults * could have transient type errors, such as network outage, etc.
496*83cba5f6SPeter Shoults * Sleeping 3s for 2s linger interval.
497*83cba5f6SPeter Shoults */
4987c478bd9Sstevel@tonic-gate if (wait(&status) < 0) {
4997c478bd9Sstevel@tonic-gate com_err(progname, errno,
5007c478bd9Sstevel@tonic-gate gettext("while waiting to receive database"));
501*83cba5f6SPeter Shoults if (iproprole != IPROP_SLAVE)
5027c478bd9Sstevel@tonic-gate exit(1);
503*83cba5f6SPeter Shoults sleep(3);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate close(s);
5077c478bd9Sstevel@tonic-gate if (iproprole == IPROP_SLAVE)
5087c478bd9Sstevel@tonic-gate close(finet);
5097c478bd9Sstevel@tonic-gate
5107c478bd9Sstevel@tonic-gate if ((ret = WEXITSTATUS(status)) != 0)
5117c478bd9Sstevel@tonic-gate return (ret);
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate if (iproprole == IPROP_SLAVE)
5157c478bd9Sstevel@tonic-gate break;
5167c478bd9Sstevel@tonic-gate }
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate return (0);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
doit(fd)5217c478bd9Sstevel@tonic-gate void doit(fd)
5227c478bd9Sstevel@tonic-gate int fd;
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate struct sockaddr_storage from;
5257c478bd9Sstevel@tonic-gate socklen_t fromlen;
5267c478bd9Sstevel@tonic-gate int on = 1;
5277c478bd9Sstevel@tonic-gate struct hostent *hp;
5287c478bd9Sstevel@tonic-gate krb5_error_code retval;
5297c478bd9Sstevel@tonic-gate krb5_data confmsg;
5307c478bd9Sstevel@tonic-gate int lock_fd;
53156a424ccSmp153739 mode_t omask;
5327c478bd9Sstevel@tonic-gate krb5_enctype etype;
53356a424ccSmp153739 int database_fd;
5347c478bd9Sstevel@tonic-gate char ntop[NI_MAXHOST] = "";
5357c478bd9Sstevel@tonic-gate krb5_context doit_context;
5367c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx;
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate retval = krb5_init_context(&doit_context);
5397c478bd9Sstevel@tonic-gate if (retval) {
5407c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while initializing krb5"));
5417c478bd9Sstevel@tonic-gate exit(1);
5427c478bd9Sstevel@tonic-gate }
5437c478bd9Sstevel@tonic-gate log_ctx = kpropd_context->kdblog_context;
544*83cba5f6SPeter Shoults if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
5457c478bd9Sstevel@tonic-gate ulog_set_role(doit_context, IPROP_SLAVE);
546*83cba5f6SPeter Shoults /*
547*83cba5f6SPeter Shoults * We also want to set a timer so that the slave is not waiting
548*83cba5f6SPeter Shoults * until infinity for an update from the master.
549*83cba5f6SPeter Shoults */
550*83cba5f6SPeter Shoults if (debug)
551*83cba5f6SPeter Shoults fprintf(stderr, "doit: setting resync alarm to %ds\n",
552*83cba5f6SPeter Shoults INITIAL_TIMER);
553*83cba5f6SPeter Shoults signal(SIGALRM, resync_alarm);
554*83cba5f6SPeter Shoults gfd = fd;
555*83cba5f6SPeter Shoults if (alarm(INITIAL_TIMER) != 0) {
556*83cba5f6SPeter Shoults if (debug) {
557*83cba5f6SPeter Shoults fprintf(stderr,
558*83cba5f6SPeter Shoults gettext("%s: alarm already set\n"), progname);
559*83cba5f6SPeter Shoults }
560*83cba5f6SPeter Shoults }
561*83cba5f6SPeter Shoults }
5627c478bd9Sstevel@tonic-gate
5637c478bd9Sstevel@tonic-gate fromlen = (socklen_t)sizeof (from);
5647c478bd9Sstevel@tonic-gate if (getpeername(fd, (struct sockaddr *) &from, &fromlen) < 0) {
5657c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ", progname);
5667c478bd9Sstevel@tonic-gate perror(gettext("getpeername"));
5677c478bd9Sstevel@tonic-gate exit(1);
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (caddr_t) &on,
5707c478bd9Sstevel@tonic-gate sizeof (on)) < 0) {
5717c478bd9Sstevel@tonic-gate com_err(progname, errno,
5727c478bd9Sstevel@tonic-gate gettext("while attempting setsockopt (SO_KEEPALIVE)"));
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
5767c478bd9Sstevel@tonic-gate NULL, 0, NI_NUMERICHOST) != 0) {
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate /* getnameifo failed so use inet_ntop() to get printable addresses */
5797c478bd9Sstevel@tonic-gate if (from.ss_family == AF_INET) {
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate inet_ntop(AF_INET,
5827c478bd9Sstevel@tonic-gate (const void *)&ss2sin(&from)->sin_addr,
5837c478bd9Sstevel@tonic-gate ntop, sizeof(ntop));
5847c478bd9Sstevel@tonic-gate
5857c478bd9Sstevel@tonic-gate } else if (from.ss_family == AF_INET6 &&
5867c478bd9Sstevel@tonic-gate ! IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) {
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate ipaddr_t v4addr;
5897c478bd9Sstevel@tonic-gate
5907c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6,
5917c478bd9Sstevel@tonic-gate (const void *)&ss2sin6(&from)->sin6_addr, ntop,
5927c478bd9Sstevel@tonic-gate sizeof(ntop));
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate /* ipv4 mapped ipv6 addrs handled later */
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate
5977c478bd9Sstevel@tonic-gate if (from.ss_family == AF_INET || from.ss_family == AF_INET6) {
5987c478bd9Sstevel@tonic-gate
5997c478bd9Sstevel@tonic-gate if (from.ss_family == AF_INET6 &&
6007c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) {
6017c478bd9Sstevel@tonic-gate
6027c478bd9Sstevel@tonic-gate ipaddr_t v4addr;
6037c478bd9Sstevel@tonic-gate
6047c478bd9Sstevel@tonic-gate /* coerce ipv4 mapped ipv6 addr to normal ipv4 addr */
6057c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&(ss2sin6(&from)->sin6_addr),
6067c478bd9Sstevel@tonic-gate v4addr);
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate inet_ntop(AF_INET, (const void *) &v4addr,
6097c478bd9Sstevel@tonic-gate ntop, sizeof(ntop));
6107c478bd9Sstevel@tonic-gate }
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate syslog(LOG_INFO, gettext("Connection from %s"), ntop);
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate if (debug)
6157c478bd9Sstevel@tonic-gate printf("Connection from %s\n", ntop);
6167c478bd9Sstevel@tonic-gate
6177c478bd9Sstevel@tonic-gate } else {
6187c478bd9Sstevel@tonic-gate /* address family isn't either AF_INET || AF_INET6 */
6197c478bd9Sstevel@tonic-gate syslog(LOG_INFO,
6207c478bd9Sstevel@tonic-gate gettext("Connection from unknown address family:%d"),
6217c478bd9Sstevel@tonic-gate from.ss_family);
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate if (debug) {
6247c478bd9Sstevel@tonic-gate printf(gettext("Connection from unknown address family:%d"),
6257c478bd9Sstevel@tonic-gate from.ss_family);
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate /*
6307c478bd9Sstevel@tonic-gate * Now do the authentication
6317c478bd9Sstevel@tonic-gate */
632f5918cfdS /* Solaris Kerberos */
633f5918cfdS kerberos_authenticate(doit_context, fd, &client, &etype, &from);
6347c478bd9Sstevel@tonic-gate
635*83cba5f6SPeter Shoults /*
636*83cba5f6SPeter Shoults * Turn off alarm upon successful authentication from master.
637*83cba5f6SPeter Shoults */
638*83cba5f6SPeter Shoults alarm(0);
639*83cba5f6SPeter Shoults gfd = -1;
640*83cba5f6SPeter Shoults
6417c478bd9Sstevel@tonic-gate if (!authorized_principal(doit_context, client, etype)) {
6427c478bd9Sstevel@tonic-gate char *name;
6437c478bd9Sstevel@tonic-gate
64456a424ccSmp153739 retval = krb5_unparse_name(doit_context, client, &name);
64556a424ccSmp153739 if (retval) {
6467c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
6477c478bd9Sstevel@tonic-gate com_err(progname, retval,
6487c64d375Smp153739 gettext("while unparsing client name"));
6497c478bd9Sstevel@tonic-gate exit(1);
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
6527c478bd9Sstevel@tonic-gate gettext("Rejected connection from unauthorized principal %s"),
6537c478bd9Sstevel@tonic-gate name);
6547c478bd9Sstevel@tonic-gate free(name);
6557c478bd9Sstevel@tonic-gate exit(1);
6567c478bd9Sstevel@tonic-gate }
6577c478bd9Sstevel@tonic-gate omask = umask(077);
6587c478bd9Sstevel@tonic-gate lock_fd = open(temp_file_name, O_RDWR|O_CREAT, 0600);
6597c478bd9Sstevel@tonic-gate (void) umask(omask);
6607c478bd9Sstevel@tonic-gate retval = krb5_lock_file(doit_context, lock_fd,
6617c478bd9Sstevel@tonic-gate KRB5_LOCKMODE_EXCLUSIVE|KRB5_LOCKMODE_DONTBLOCK);
6627c478bd9Sstevel@tonic-gate if (retval) {
6637c478bd9Sstevel@tonic-gate com_err(progname, retval,
6647c478bd9Sstevel@tonic-gate gettext("while trying to lock '%s'"),
6657c478bd9Sstevel@tonic-gate temp_file_name);
6667c478bd9Sstevel@tonic-gate exit(1);
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate if ((database_fd = open(temp_file_name,
6697c478bd9Sstevel@tonic-gate O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
6707c478bd9Sstevel@tonic-gate com_err(progname, errno,
6717c478bd9Sstevel@tonic-gate gettext("while opening database file, '%s'"),
6727c478bd9Sstevel@tonic-gate temp_file_name);
6737c478bd9Sstevel@tonic-gate exit(1);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate recv_database(doit_context, fd, database_fd, &confmsg);
6767c478bd9Sstevel@tonic-gate if (rename(temp_file_name, file)) {
6777c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
6787c478bd9Sstevel@tonic-gate com_err(progname, errno,
6797c64d375Smp153739 gettext("while renaming %s to %s"),
6807c478bd9Sstevel@tonic-gate temp_file_name, file);
6817c478bd9Sstevel@tonic-gate exit(1);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_SHARED);
6847c478bd9Sstevel@tonic-gate if (retval) {
6857c478bd9Sstevel@tonic-gate com_err(progname, retval,
6867c478bd9Sstevel@tonic-gate gettext("while downgrading lock on '%s'"),
6877c478bd9Sstevel@tonic-gate temp_file_name);
6887c478bd9Sstevel@tonic-gate exit(1);
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate load_database(doit_context, kdb5_util, file);
6917c478bd9Sstevel@tonic-gate retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_UNLOCK);
6927c478bd9Sstevel@tonic-gate if (retval) {
6937c478bd9Sstevel@tonic-gate com_err(progname, retval,
6947c478bd9Sstevel@tonic-gate gettext("while unlocking '%s'"), temp_file_name);
6957c478bd9Sstevel@tonic-gate exit(1);
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate (void)close(lock_fd);
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate * Send the acknowledgement message generated in
7017c478bd9Sstevel@tonic-gate * recv_database, then close the socket.
7027c478bd9Sstevel@tonic-gate */
70356a424ccSmp153739 retval = krb5_write_message(doit_context, (void *) &fd, &confmsg);
70456a424ccSmp153739 if (retval) {
7057c478bd9Sstevel@tonic-gate krb5_free_data_contents(doit_context, &confmsg);
7067c478bd9Sstevel@tonic-gate com_err(progname, retval,
7077c478bd9Sstevel@tonic-gate gettext("while sending # of received bytes"));
7087c478bd9Sstevel@tonic-gate exit(1);
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate krb5_free_data_contents(doit_context, &confmsg);
7117c478bd9Sstevel@tonic-gate if (close(fd) < 0) {
7127c478bd9Sstevel@tonic-gate com_err(progname, errno,
7137c478bd9Sstevel@tonic-gate gettext("while trying to close database file"));
7147c478bd9Sstevel@tonic-gate exit(1);
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate exit(0);
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate /*
7227c478bd9Sstevel@tonic-gate * Routine to handle incremental update transfer(s) from master KDC
7237c478bd9Sstevel@tonic-gate */
do_iprop(kdb_log_context * log_ctx)7247c478bd9Sstevel@tonic-gate krb5_error_code do_iprop(kdb_log_context *log_ctx) {
7257c478bd9Sstevel@tonic-gate CLIENT *cl;
7267c478bd9Sstevel@tonic-gate kadm5_ret_t retval;
7277c478bd9Sstevel@tonic-gate kadm5_config_params params;
7287c478bd9Sstevel@tonic-gate krb5_ccache cc;
7297c478bd9Sstevel@tonic-gate krb5_principal iprop_svc_principal;
7307c478bd9Sstevel@tonic-gate void *server_handle = NULL;
7317c478bd9Sstevel@tonic-gate char *iprop_svc_princstr = NULL;
7327c478bd9Sstevel@tonic-gate char *master_svc_princstr = NULL;
7337c478bd9Sstevel@tonic-gate char *admin_server = NULL;
7347c478bd9Sstevel@tonic-gate char *keytab_name = NULL;
7357c478bd9Sstevel@tonic-gate unsigned int pollin, backoff_time;
7367c478bd9Sstevel@tonic-gate int backoff_cnt = 0;
7377c478bd9Sstevel@tonic-gate int reinit_cnt = 0;
7387c478bd9Sstevel@tonic-gate int ret;
7397c478bd9Sstevel@tonic-gate boolean_t frdone = B_FALSE;
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate kdb_incr_result_t *incr_ret;
7427c478bd9Sstevel@tonic-gate static kdb_last_t mylast;
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate kdb_fullresync_result_t *full_ret;
7457c478bd9Sstevel@tonic-gate char *full_resync_arg = NULL;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate kadm5_iprop_handle_t handle;
7487c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog;
7497c478bd9Sstevel@tonic-gate
7507c64d375Smp153739 krb5_keytab kt;
7517c64d375Smp153739 krb5_keytab_entry entry;
7527c64d375Smp153739 char kt_name[MAX_KEYTAB_NAME_LEN];
7537c64d375Smp153739
7547c64d375Smp153739 /*
7557c64d375Smp153739 * Solaris Kerberos:
7567c64d375Smp153739 * Delay daemonizing until some basic configuration checks have been
7577c64d375Smp153739 * performed
7587c64d375Smp153739 */
7597c64d375Smp153739 #if 0
7607c478bd9Sstevel@tonic-gate if (!debug)
7617c478bd9Sstevel@tonic-gate daemon(0, 0);
7627c64d375Smp153739 #endif
7637c478bd9Sstevel@tonic-gate pollin = (unsigned int)0;
7647c478bd9Sstevel@tonic-gate (void) memset((char *)¶ms, 0, sizeof (params));
7657c478bd9Sstevel@tonic-gate ulog = log_ctx->ulog;
7667c478bd9Sstevel@tonic-gate
7677c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_REALM;
7687c478bd9Sstevel@tonic-gate params.realm = def_realm;
7697c478bd9Sstevel@tonic-gate
7707c478bd9Sstevel@tonic-gate if (master_svc_princstr == NULL) {
7717c478bd9Sstevel@tonic-gate if (retval = kadm5_get_kiprop_host_srv_name(kpropd_context,
7727c478bd9Sstevel@tonic-gate def_realm, &master_svc_princstr)) {
7737c64d375Smp153739 /* Solaris Kerberos: keep error messages consistent */
7747c478bd9Sstevel@tonic-gate com_err(progname, retval,
7757c64d375Smp153739 gettext("while getting kiprop host based "
7767c64d375Smp153739 "service name for realm %s"), def_realm);
7777c478bd9Sstevel@tonic-gate exit(1);
7787c478bd9Sstevel@tonic-gate }
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate
7817c478bd9Sstevel@tonic-gate /*
7827c478bd9Sstevel@tonic-gate * Set cc to the default credentials cache
7837c478bd9Sstevel@tonic-gate */
7847c478bd9Sstevel@tonic-gate if (retval = krb5_cc_default(kpropd_context, &cc)) {
7857c478bd9Sstevel@tonic-gate com_err(progname, retval,
7867c478bd9Sstevel@tonic-gate gettext("while opening default "
7877c478bd9Sstevel@tonic-gate "credentials cache"));
7887c478bd9Sstevel@tonic-gate exit(1);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate
7917c478bd9Sstevel@tonic-gate retval = krb5_sname_to_principal(kpropd_context, NULL, KIPROP_SVC_NAME,
7927c478bd9Sstevel@tonic-gate KRB5_NT_SRV_HST, &iprop_svc_principal);
7937c478bd9Sstevel@tonic-gate if (retval) {
7947c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while trying to construct "
7957c478bd9Sstevel@tonic-gate "host service principal"));
7967c478bd9Sstevel@tonic-gate exit(1);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate
799159d09a2SMark Phalan /* Solaris Kerberos */
800159d09a2SMark Phalan if (krb5_is_referral_realm(krb5_princ_realm(kpropd_context,
801159d09a2SMark Phalan iprop_svc_principal))) {
802159d09a2SMark Phalan krb5_data *r = krb5_princ_realm(kpropd_context,
803159d09a2SMark Phalan iprop_svc_principal);
804159d09a2SMark Phalan assert(def_realm != NULL);
805159d09a2SMark Phalan r->length = strlen(def_realm);
806159d09a2SMark Phalan r->data = strdup(def_realm);
807159d09a2SMark Phalan if (r->data == NULL) {
808159d09a2SMark Phalan com_err(progname, retval,
809159d09a2SMark Phalan ("while determining local service principal name"));
810159d09a2SMark Phalan exit(1);
811159d09a2SMark Phalan }
812159d09a2SMark Phalan }
813159d09a2SMark Phalan
8147c478bd9Sstevel@tonic-gate if (retval = krb5_unparse_name(kpropd_context, iprop_svc_principal,
8157c478bd9Sstevel@tonic-gate &iprop_svc_princstr)) {
8167c478bd9Sstevel@tonic-gate com_err(progname, retval,
8177c478bd9Sstevel@tonic-gate gettext("while canonicalizing "
8187c478bd9Sstevel@tonic-gate "principal name"));
8197c478bd9Sstevel@tonic-gate krb5_free_principal(kpropd_context, iprop_svc_principal);
8207c478bd9Sstevel@tonic-gate exit(1);
8217c478bd9Sstevel@tonic-gate }
8227c64d375Smp153739
8237c64d375Smp153739 /*
8247c64d375Smp153739 * Solaris Kerberos:
8257c64d375Smp153739 * Check to see if kiprop/<fqdn>@REALM is in the keytab
8267c64d375Smp153739 */
8277c64d375Smp153739 kt_name[0] = '\0';
8287c64d375Smp153739 if (retval = krb5_kt_default_name(kpropd_context, kt_name,
8297c64d375Smp153739 MAX_KEYTAB_NAME_LEN)){
8307c64d375Smp153739 com_err(progname, retval, gettext ("while resolving the "
8317c64d375Smp153739 "name of the default keytab"));
8327c64d375Smp153739 }
8337c64d375Smp153739
8347c64d375Smp153739 if (retval = krb5_kt_default(kpropd_context, &kt)) {
8357c64d375Smp153739 com_err(progname, retval, gettext ("while resolving default "
8367c64d375Smp153739 "keytab"));
8377c478bd9Sstevel@tonic-gate krb5_free_principal(kpropd_context, iprop_svc_principal);
8387c64d375Smp153739 exit(1);
8397c64d375Smp153739 }
8407c64d375Smp153739
8417c64d375Smp153739 if (retval = krb5_kt_get_entry(kpropd_context, kt, iprop_svc_principal,
8427c64d375Smp153739 0, 0, &entry)) {
8437c64d375Smp153739 com_err(progname, retval, gettext("while retrieving entry %s "
8447c64d375Smp153739 "from %s"), iprop_svc_princstr,
8457c64d375Smp153739 kt_name[0] ? kt_name : "default keytab");
8467c64d375Smp153739 krb5_kt_close(kpropd_context,kt);
8477c64d375Smp153739 krb5_free_principal(kpropd_context, iprop_svc_principal);
8487c64d375Smp153739 exit(1);
8497c64d375Smp153739 }
8507c64d375Smp153739
8517c64d375Smp153739 krb5_kt_close(kpropd_context,kt);
8527c64d375Smp153739 krb5_free_principal(kpropd_context, iprop_svc_principal);
8537c64d375Smp153739
8547c64d375Smp153739 if (!debug) {
8557c64d375Smp153739 /* Solaris Kerberos: Indicate where further messages will be sent */
8567c64d375Smp153739 fprintf(stderr, gettext("%s: Logging to SYSLOG\n"), progname);
8577c64d375Smp153739 if (daemon(0, 0)) {
8587c64d375Smp153739 com_err(progname, errno, gettext("while daemonizing"));
8597c64d375Smp153739 exit(1);
8607c64d375Smp153739 }
8617c64d375Smp153739 rem_default_com_err_hook();
8627c64d375Smp153739 }
8637c478bd9Sstevel@tonic-gate
8647c478bd9Sstevel@tonic-gate reinit:
8657c478bd9Sstevel@tonic-gate /*
8667c478bd9Sstevel@tonic-gate * Authentication, initialize rpcsec_gss handle etc.
8677c478bd9Sstevel@tonic-gate */
8687c478bd9Sstevel@tonic-gate retval = kadm5_init_with_skey(iprop_svc_princstr, keytab_name,
8697c478bd9Sstevel@tonic-gate master_svc_princstr,
8707c478bd9Sstevel@tonic-gate ¶ms,
8717c478bd9Sstevel@tonic-gate KADM5_STRUCT_VERSION,
8727c478bd9Sstevel@tonic-gate KADM5_API_VERSION_2,
87354925bf6Swillf NULL,
8747c478bd9Sstevel@tonic-gate &server_handle);
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate if (retval) {
8777c478bd9Sstevel@tonic-gate if (retval == KADM5_RPC_ERROR) {
8787c478bd9Sstevel@tonic-gate reinit_cnt++;
8797c478bd9Sstevel@tonic-gate if (server_handle)
8807c478bd9Sstevel@tonic-gate kadm5_destroy((void *) server_handle);
8817c478bd9Sstevel@tonic-gate server_handle = (void *)NULL;
8827c478bd9Sstevel@tonic-gate handle = (kadm5_iprop_handle_t)NULL;
8837c478bd9Sstevel@tonic-gate
8847c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext(
8857c478bd9Sstevel@tonic-gate "while attempting to connect"
8867c478bd9Sstevel@tonic-gate " to master KDC ... retrying"));
8877c478bd9Sstevel@tonic-gate backoff_time = backoff_from_master(&reinit_cnt);
8887c478bd9Sstevel@tonic-gate (void) sleep(backoff_time);
8897c478bd9Sstevel@tonic-gate goto reinit;
8907c478bd9Sstevel@tonic-gate } else {
8917c64d375Smp153739 /* Solaris Kerberos: Be more verbose */
8927c478bd9Sstevel@tonic-gate com_err(progname, retval,
8937c64d375Smp153739 gettext("while initializing %s interface for "
8947c64d375Smp153739 "%s"), progname, iprop_svc_princstr);
8957c478bd9Sstevel@tonic-gate if (retval == KADM5_BAD_CLIENT_PARAMS ||
8967c478bd9Sstevel@tonic-gate retval == KADM5_BAD_SERVER_PARAMS)
8977c478bd9Sstevel@tonic-gate usage();
8987c478bd9Sstevel@tonic-gate exit(1);
8997c478bd9Sstevel@tonic-gate }
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate
9027c478bd9Sstevel@tonic-gate /*
9037c478bd9Sstevel@tonic-gate * Reset re-initialization count to zero now.
9047c478bd9Sstevel@tonic-gate */
9057c478bd9Sstevel@tonic-gate reinit_cnt = backoff_time = 0;
9067c478bd9Sstevel@tonic-gate
9077c478bd9Sstevel@tonic-gate /*
9087c478bd9Sstevel@tonic-gate * Reset the handle to the correct type for the RPC call
9097c478bd9Sstevel@tonic-gate */
9107c478bd9Sstevel@tonic-gate handle = server_handle;
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate /*
9137c478bd9Sstevel@tonic-gate * If we have reached this far, we have succesfully established
9147c478bd9Sstevel@tonic-gate * a RPCSEC_GSS connection; we now start polling for updates
9157c478bd9Sstevel@tonic-gate */
9167c478bd9Sstevel@tonic-gate if (poll_time == NULL) {
9177c478bd9Sstevel@tonic-gate if ((poll_time = (char *)strdup("2m")) == NULL) {
9187c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
9197c478bd9Sstevel@tonic-gate com_err(progname, ENOMEM,
9207c64d375Smp153739 gettext("while allocating poll_time"));
9217c478bd9Sstevel@tonic-gate exit(1);
9227c478bd9Sstevel@tonic-gate }
9237c478bd9Sstevel@tonic-gate }
9247c478bd9Sstevel@tonic-gate
9257c478bd9Sstevel@tonic-gate if (pollin == (unsigned int)0)
9267c478bd9Sstevel@tonic-gate pollin = convert_polltime(poll_time);
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate for (;;) {
9297c478bd9Sstevel@tonic-gate incr_ret = NULL;
9307c478bd9Sstevel@tonic-gate full_ret = NULL;
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate /*
9337c478bd9Sstevel@tonic-gate * Get the most recent ulog entry sno + ts, which
9347c478bd9Sstevel@tonic-gate * we package in the request to the master KDC
9357c478bd9Sstevel@tonic-gate */
9367c478bd9Sstevel@tonic-gate mylast.last_sno = ulog->kdb_last_sno;
9377c478bd9Sstevel@tonic-gate mylast.last_time = ulog->kdb_last_time;
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate /*
9407c478bd9Sstevel@tonic-gate * Loop continuously on an iprop_get_updates_1(),
9417c478bd9Sstevel@tonic-gate * so that we can keep probing the master for updates
9427c478bd9Sstevel@tonic-gate * or (if needed) do a full resync of the krb5 db.
9437c478bd9Sstevel@tonic-gate */
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate incr_ret = iprop_get_updates_1(&mylast, handle->clnt);
9467c478bd9Sstevel@tonic-gate if (incr_ret == (kdb_incr_result_t *)NULL) {
9477c478bd9Sstevel@tonic-gate clnt_perror(handle->clnt,
9487c478bd9Sstevel@tonic-gate "iprop_get_updates call failed");
9497c478bd9Sstevel@tonic-gate if (server_handle)
9507c478bd9Sstevel@tonic-gate kadm5_destroy((void *)server_handle);
9517c478bd9Sstevel@tonic-gate server_handle = (void *)NULL;
9527c478bd9Sstevel@tonic-gate handle = (kadm5_iprop_handle_t)NULL;
9537c478bd9Sstevel@tonic-gate goto reinit;
9547c478bd9Sstevel@tonic-gate }
9557c478bd9Sstevel@tonic-gate
9567c478bd9Sstevel@tonic-gate switch (incr_ret->ret) {
9577c478bd9Sstevel@tonic-gate
9587c478bd9Sstevel@tonic-gate case UPDATE_FULL_RESYNC_NEEDED:
9597c478bd9Sstevel@tonic-gate /*
9607c478bd9Sstevel@tonic-gate * We dont do a full resync again, if the last
9617c478bd9Sstevel@tonic-gate * X'fer was a resync and if the master sno is
9627c478bd9Sstevel@tonic-gate * still "0", i.e. no updates so far.
9637c478bd9Sstevel@tonic-gate */
9647c478bd9Sstevel@tonic-gate if ((frdone == B_TRUE) && (incr_ret->lastentry.last_sno
9657c478bd9Sstevel@tonic-gate == 0)) {
9667c478bd9Sstevel@tonic-gate break;
9677c478bd9Sstevel@tonic-gate } else {
9687c478bd9Sstevel@tonic-gate
9697c478bd9Sstevel@tonic-gate full_ret = iprop_full_resync_1((void *)
9707c478bd9Sstevel@tonic-gate &full_resync_arg, handle->clnt);
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate if (full_ret == (kdb_fullresync_result_t *)
9737c478bd9Sstevel@tonic-gate NULL) {
9747c478bd9Sstevel@tonic-gate clnt_perror(handle->clnt,
9757c478bd9Sstevel@tonic-gate "iprop_full_resync call failed");
9767c478bd9Sstevel@tonic-gate if (server_handle)
9777c478bd9Sstevel@tonic-gate kadm5_destroy((void *)
9787c478bd9Sstevel@tonic-gate server_handle);
9797c478bd9Sstevel@tonic-gate server_handle = (void *)NULL;
9807c478bd9Sstevel@tonic-gate handle = (kadm5_iprop_handle_t)NULL;
9817c478bd9Sstevel@tonic-gate goto reinit;
9827c478bd9Sstevel@tonic-gate }
9837c478bd9Sstevel@tonic-gate }
9847c478bd9Sstevel@tonic-gate
9857c478bd9Sstevel@tonic-gate switch (full_ret->ret) {
9867c478bd9Sstevel@tonic-gate case UPDATE_OK:
9877c478bd9Sstevel@tonic-gate backoff_cnt = 0;
9887c478bd9Sstevel@tonic-gate /*
9897c478bd9Sstevel@tonic-gate * We now listen on the kprop port for
9907c478bd9Sstevel@tonic-gate * the full dump
9917c478bd9Sstevel@tonic-gate */
9927c478bd9Sstevel@tonic-gate ret = do_standalone(log_ctx->iproprole);
9937c478bd9Sstevel@tonic-gate if (debug)
9947c478bd9Sstevel@tonic-gate if (ret)
9957c478bd9Sstevel@tonic-gate fprintf(stderr,
9967c478bd9Sstevel@tonic-gate gettext("Full resync "
9977c478bd9Sstevel@tonic-gate "was unsuccessful\n"));
9987c478bd9Sstevel@tonic-gate else
9997c478bd9Sstevel@tonic-gate fprintf(stderr,
10007c478bd9Sstevel@tonic-gate gettext("Full resync "
10017c478bd9Sstevel@tonic-gate "was successful\n"));
1002*83cba5f6SPeter Shoults if (ret) {
1003*83cba5f6SPeter Shoults syslog(LOG_WARNING,
1004*83cba5f6SPeter Shoults gettext("kpropd: Full resync, "
1005*83cba5f6SPeter Shoults "invalid return."));
1006*83cba5f6SPeter Shoults /*
1007*83cba5f6SPeter Shoults * Start backing-off immediately after
1008*83cba5f6SPeter Shoults * failure.
1009*83cba5f6SPeter Shoults */
1010*83cba5f6SPeter Shoults backoff_cnt++;
1011*83cba5f6SPeter Shoults frdone = B_FALSE;
1012*83cba5f6SPeter Shoults } else
10137c478bd9Sstevel@tonic-gate frdone = B_TRUE;
10147c478bd9Sstevel@tonic-gate break;
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate case UPDATE_BUSY:
10177c478bd9Sstevel@tonic-gate /*
10187c478bd9Sstevel@tonic-gate * Exponential backoff
10197c478bd9Sstevel@tonic-gate */
10207c478bd9Sstevel@tonic-gate backoff_cnt++;
10217c478bd9Sstevel@tonic-gate break;
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate case UPDATE_FULL_RESYNC_NEEDED:
10247c478bd9Sstevel@tonic-gate case UPDATE_NIL:
10257c478bd9Sstevel@tonic-gate default:
10267c478bd9Sstevel@tonic-gate backoff_cnt = 0;
10277c478bd9Sstevel@tonic-gate frdone = B_FALSE;
10287c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: Full resync,"
10297c478bd9Sstevel@tonic-gate " invalid return from master KDC."));
10307c478bd9Sstevel@tonic-gate break;
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate case UPDATE_PERM_DENIED:
10337c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: Full resync,"
10347c478bd9Sstevel@tonic-gate " permission denied."));
10357c478bd9Sstevel@tonic-gate goto error;
10367c478bd9Sstevel@tonic-gate
10377c478bd9Sstevel@tonic-gate case UPDATE_ERROR:
10387c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: Full resync,"
10397c478bd9Sstevel@tonic-gate " error returned from master KDC."));
10407c478bd9Sstevel@tonic-gate goto error;
10417c478bd9Sstevel@tonic-gate }
10427c478bd9Sstevel@tonic-gate break;
10437c478bd9Sstevel@tonic-gate
10447c478bd9Sstevel@tonic-gate case UPDATE_OK:
10457c478bd9Sstevel@tonic-gate backoff_cnt = 0;
10467c478bd9Sstevel@tonic-gate frdone = B_FALSE;
10477c478bd9Sstevel@tonic-gate
10487c478bd9Sstevel@tonic-gate /*
10497c478bd9Sstevel@tonic-gate * ulog_replay() will convert the ulog updates to db
10507c478bd9Sstevel@tonic-gate * entries using the kdb conv api and will commit
10517c478bd9Sstevel@tonic-gate * the entries to the slave kdc database
10527c478bd9Sstevel@tonic-gate */
10537c478bd9Sstevel@tonic-gate retval = ulog_replay(kpropd_context, incr_ret);
10547c478bd9Sstevel@tonic-gate
10557c478bd9Sstevel@tonic-gate if (retval) {
10567c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: ulog_replay"
10577c478bd9Sstevel@tonic-gate " failed, updates not registered."));
10587c478bd9Sstevel@tonic-gate break;
10597c478bd9Sstevel@tonic-gate }
10607c478bd9Sstevel@tonic-gate
10617c478bd9Sstevel@tonic-gate if (debug)
10627c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Update transfer "
10637c478bd9Sstevel@tonic-gate "from master was OK\n"));
10647c478bd9Sstevel@tonic-gate break;
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate case UPDATE_PERM_DENIED:
10677c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: get_updates,"
10687c478bd9Sstevel@tonic-gate " permission denied."));
10697c478bd9Sstevel@tonic-gate goto error;
10707c478bd9Sstevel@tonic-gate
10717c478bd9Sstevel@tonic-gate case UPDATE_ERROR:
10727c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: get_updates, error "
10737c478bd9Sstevel@tonic-gate "returned from master KDC."));
10747c478bd9Sstevel@tonic-gate goto error;
10757c478bd9Sstevel@tonic-gate
10767c478bd9Sstevel@tonic-gate case UPDATE_BUSY:
10777c478bd9Sstevel@tonic-gate /*
10787c478bd9Sstevel@tonic-gate * Exponential backoff
10797c478bd9Sstevel@tonic-gate */
10807c478bd9Sstevel@tonic-gate backoff_cnt++;
10817c478bd9Sstevel@tonic-gate break;
10827c478bd9Sstevel@tonic-gate
10837c478bd9Sstevel@tonic-gate case UPDATE_NIL:
10847c478bd9Sstevel@tonic-gate /*
10857c478bd9Sstevel@tonic-gate * Master-slave are in sync
10867c478bd9Sstevel@tonic-gate */
10877c478bd9Sstevel@tonic-gate if (debug)
10887c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Master, slave KDC's "
10897c478bd9Sstevel@tonic-gate "are in-sync, no updates\n"));
10907c478bd9Sstevel@tonic-gate backoff_cnt = 0;
10917c478bd9Sstevel@tonic-gate frdone = B_FALSE;
10927c478bd9Sstevel@tonic-gate break;
10937c478bd9Sstevel@tonic-gate
10947c478bd9Sstevel@tonic-gate default:
10957c478bd9Sstevel@tonic-gate backoff_cnt = 0;
10967c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: get_updates,"
10977c478bd9Sstevel@tonic-gate " invalid return from master KDC."));
10987c478bd9Sstevel@tonic-gate break;
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate
11017c478bd9Sstevel@tonic-gate if (runonce == B_TRUE)
11027c478bd9Sstevel@tonic-gate goto done;
11037c478bd9Sstevel@tonic-gate
11047c478bd9Sstevel@tonic-gate /*
11057c478bd9Sstevel@tonic-gate * Sleep for the specified poll interval (Default is 2 mts),
11067c478bd9Sstevel@tonic-gate * or do a binary exponential backoff if we get an
11077c478bd9Sstevel@tonic-gate * UPDATE_BUSY signal
11087c478bd9Sstevel@tonic-gate */
11097c478bd9Sstevel@tonic-gate if (backoff_cnt > 0) {
11107c478bd9Sstevel@tonic-gate backoff_time = backoff_from_master(&backoff_cnt);
11117c478bd9Sstevel@tonic-gate if (debug)
11127c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Busy signal received "
11137c478bd9Sstevel@tonic-gate "from master, backoff for %d secs\n"),
11147c478bd9Sstevel@tonic-gate backoff_time);
11157c478bd9Sstevel@tonic-gate (void) sleep(backoff_time);
11167c478bd9Sstevel@tonic-gate }
11177c478bd9Sstevel@tonic-gate else
11187c478bd9Sstevel@tonic-gate (void) sleep(pollin);
11197c478bd9Sstevel@tonic-gate
11207c478bd9Sstevel@tonic-gate }
11217c478bd9Sstevel@tonic-gate
11227c478bd9Sstevel@tonic-gate
11237c478bd9Sstevel@tonic-gate error:
11247c478bd9Sstevel@tonic-gate if (debug)
11257c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("ERROR returned by master, bailing\n"));
11267c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: ERROR returned by master KDC,"
11277c478bd9Sstevel@tonic-gate " bailing.\n"));
11287c478bd9Sstevel@tonic-gate done:
11297c478bd9Sstevel@tonic-gate if (poll_time)
11307c478bd9Sstevel@tonic-gate free(poll_time);
11317c478bd9Sstevel@tonic-gate if(iprop_svc_princstr)
11327c478bd9Sstevel@tonic-gate free(iprop_svc_princstr);
11337c478bd9Sstevel@tonic-gate if (master_svc_princstr)
11347c478bd9Sstevel@tonic-gate free(master_svc_princstr);
11357c478bd9Sstevel@tonic-gate if (retval = krb5_cc_close(kpropd_context, cc)) {
11367c478bd9Sstevel@tonic-gate com_err(progname, retval,
11377c478bd9Sstevel@tonic-gate gettext("while closing default ccache"));
11387c478bd9Sstevel@tonic-gate exit(1);
11397c478bd9Sstevel@tonic-gate }
11407c478bd9Sstevel@tonic-gate if (def_realm)
11417c478bd9Sstevel@tonic-gate free(def_realm);
11427c478bd9Sstevel@tonic-gate if (server_handle)
11437c478bd9Sstevel@tonic-gate kadm5_destroy((void *)server_handle);
11447c478bd9Sstevel@tonic-gate if (kpropd_context)
11457c478bd9Sstevel@tonic-gate krb5_free_context(kpropd_context);
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate if (runonce == B_TRUE)
11487c478bd9Sstevel@tonic-gate return (0);
11497c478bd9Sstevel@tonic-gate else
11507c478bd9Sstevel@tonic-gate exit(1);
11517c478bd9Sstevel@tonic-gate }
11527c478bd9Sstevel@tonic-gate
11537c478bd9Sstevel@tonic-gate
11547c478bd9Sstevel@tonic-gate /*
11557c478bd9Sstevel@tonic-gate * Do exponential backoff, since master KDC is BUSY or down
11567c478bd9Sstevel@tonic-gate */
backoff_from_master(int * cnt)11577c478bd9Sstevel@tonic-gate unsigned int backoff_from_master(int *cnt) {
11587c478bd9Sstevel@tonic-gate unsigned int btime;
11597c478bd9Sstevel@tonic-gate
11607c478bd9Sstevel@tonic-gate btime = (unsigned int)(2<<(*cnt));
11617c478bd9Sstevel@tonic-gate if (btime > MAX_BACKOFF) {
11627c478bd9Sstevel@tonic-gate btime = MAX_BACKOFF;
11637c478bd9Sstevel@tonic-gate *cnt--;
11647c478bd9Sstevel@tonic-gate }
11657c478bd9Sstevel@tonic-gate
11667c478bd9Sstevel@tonic-gate return (btime);
11677c478bd9Sstevel@tonic-gate }
11687c478bd9Sstevel@tonic-gate
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate /*
11717c478bd9Sstevel@tonic-gate * Routine to convert the `pollstr' string to seconds
11727c478bd9Sstevel@tonic-gate */
convert_polltime(char * pollstr)11737c478bd9Sstevel@tonic-gate int convert_polltime(char *pollstr) {
11747c478bd9Sstevel@tonic-gate char *tokenptr = NULL;
11757c478bd9Sstevel@tonic-gate int len, polltime;
11767c478bd9Sstevel@tonic-gate
11777c478bd9Sstevel@tonic-gate len = polltime = 0;
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate if ((len = strcspn(pollstr, "s")) < strlen(pollstr)) {
11807c478bd9Sstevel@tonic-gate tokenptr = malloc((len + 1) * sizeof(char));
11817c478bd9Sstevel@tonic-gate (void) strlcpy(tokenptr, pollstr, len + 1);
11827c478bd9Sstevel@tonic-gate polltime = atoi(tokenptr);
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate
11857c478bd9Sstevel@tonic-gate if ((len = strcspn(pollstr, "m")) < strlen(pollstr)) {
11867c478bd9Sstevel@tonic-gate tokenptr = malloc((len + 1) * sizeof(char));
11877c478bd9Sstevel@tonic-gate (void) strlcpy(tokenptr, pollstr, len + 1);
11887c478bd9Sstevel@tonic-gate polltime = atoi(tokenptr) * 60;
11897c478bd9Sstevel@tonic-gate }
11907c478bd9Sstevel@tonic-gate
11917c478bd9Sstevel@tonic-gate if ((len = strcspn(pollstr, "h")) < strlen(pollstr)) {
11927c478bd9Sstevel@tonic-gate tokenptr = malloc((len + 1) * sizeof(char));
11937c478bd9Sstevel@tonic-gate (void) strlcpy(tokenptr, pollstr, len + 1);
11947c478bd9Sstevel@tonic-gate polltime = atoi(tokenptr) * 3600;
11957c478bd9Sstevel@tonic-gate }
11967c478bd9Sstevel@tonic-gate
11977c478bd9Sstevel@tonic-gate if (tokenptr != NULL)
11987c478bd9Sstevel@tonic-gate free(tokenptr);
11997c478bd9Sstevel@tonic-gate /*
12007c478bd9Sstevel@tonic-gate * If we have a bogus pollstr value, set polltime to the
12017c478bd9Sstevel@tonic-gate * default of 2 mts (120 seconds).
12027c478bd9Sstevel@tonic-gate */
12037c478bd9Sstevel@tonic-gate if (polltime == 0)
12047c478bd9Sstevel@tonic-gate polltime = 120;
12057c478bd9Sstevel@tonic-gate return (polltime);
12067c478bd9Sstevel@tonic-gate }
12077c478bd9Sstevel@tonic-gate
12087c478bd9Sstevel@tonic-gate static void
kpropd_com_err_proc(whoami,code,fmt,args)12097c478bd9Sstevel@tonic-gate kpropd_com_err_proc(whoami, code, fmt, args)
12107c478bd9Sstevel@tonic-gate const char *whoami;
12117c478bd9Sstevel@tonic-gate long code;
12127c478bd9Sstevel@tonic-gate const char *fmt;
12137c478bd9Sstevel@tonic-gate va_list args;
12147c478bd9Sstevel@tonic-gate {
12157c478bd9Sstevel@tonic-gate char error_buf[8096];
12167c478bd9Sstevel@tonic-gate
12177c478bd9Sstevel@tonic-gate error_buf[0] = '\0';
12187c478bd9Sstevel@tonic-gate if (fmt)
12197c478bd9Sstevel@tonic-gate vsprintf(error_buf, fmt, args);
12207c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "%s%s%s%s%s", whoami ? whoami : "", whoami ? ": " : "",
12217c478bd9Sstevel@tonic-gate code ? error_message(code) : "", code ? " " : "", error_buf);
12227c478bd9Sstevel@tonic-gate }
12237c478bd9Sstevel@tonic-gate
PRS(argc,argv)12247c478bd9Sstevel@tonic-gate void PRS(argc,argv)
12257c478bd9Sstevel@tonic-gate int argc;
12267c478bd9Sstevel@tonic-gate char **argv;
12277c478bd9Sstevel@tonic-gate {
12287c478bd9Sstevel@tonic-gate register char *word, ch;
12297c478bd9Sstevel@tonic-gate char *cp;
12307c478bd9Sstevel@tonic-gate int c;
12317c478bd9Sstevel@tonic-gate struct hostent *hp;
12327c478bd9Sstevel@tonic-gate char my_host_name[MAXHOSTNAMELEN], buf[BUFSIZ];
12337c478bd9Sstevel@tonic-gate krb5_error_code retval;
12347c478bd9Sstevel@tonic-gate static const char tmp[] = ".temp";
12357c478bd9Sstevel@tonic-gate kadm5_config_params params;
12367c478bd9Sstevel@tonic-gate
12377c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
12387c478bd9Sstevel@tonic-gate
12397c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
12407c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "KPROPD_TEST" /* Use this only if it weren't */
12417c478bd9Sstevel@tonic-gate #endif
12427c478bd9Sstevel@tonic-gate
12437c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
12447c478bd9Sstevel@tonic-gate
12457c478bd9Sstevel@tonic-gate (void) memset((char *) ¶ms, 0, sizeof (params));
12467c478bd9Sstevel@tonic-gate
12477c478bd9Sstevel@tonic-gate retval = krb5_init_context(&kpropd_context);
12487c478bd9Sstevel@tonic-gate if (retval) {
12497c478bd9Sstevel@tonic-gate com_err(argv[0], retval,
12507c478bd9Sstevel@tonic-gate gettext("while initializing krb5"));
12517c478bd9Sstevel@tonic-gate exit(1);
12527c478bd9Sstevel@tonic-gate }
12537c64d375Smp153739
12547c64d375Smp153739 /* Solaris Kerberos: Sanitize progname */
12557c64d375Smp153739 progname = basename(argv[0]);
12567c64d375Smp153739
12577c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "dtf:F:p:P:r:s:Sa:")) != EOF){
12587c478bd9Sstevel@tonic-gate switch (c) {
12597c478bd9Sstevel@tonic-gate case 'd':
12607c478bd9Sstevel@tonic-gate debug++;
12617c478bd9Sstevel@tonic-gate break;
12627c478bd9Sstevel@tonic-gate case 't':
12637c478bd9Sstevel@tonic-gate /*
12647c478bd9Sstevel@tonic-gate * Undocumented option - for testing only.
12657c478bd9Sstevel@tonic-gate *
12667c478bd9Sstevel@tonic-gate * Option to run the kpropd server exactly
12677c478bd9Sstevel@tonic-gate * once (this is true only if iprop is enabled).
12687c478bd9Sstevel@tonic-gate */
12697c478bd9Sstevel@tonic-gate runonce = B_TRUE;
12707c478bd9Sstevel@tonic-gate break;
12717c478bd9Sstevel@tonic-gate
12727c478bd9Sstevel@tonic-gate case 'f':
12737c478bd9Sstevel@tonic-gate file = optarg;
12747c478bd9Sstevel@tonic-gate if (!file)
12757c478bd9Sstevel@tonic-gate usage();
12767c478bd9Sstevel@tonic-gate break;
12777c478bd9Sstevel@tonic-gate case 'F':
12787c478bd9Sstevel@tonic-gate kerb_database = optarg;
12797c478bd9Sstevel@tonic-gate if (!kerb_database)
12807c478bd9Sstevel@tonic-gate usage();
12817c478bd9Sstevel@tonic-gate break;
12827c478bd9Sstevel@tonic-gate case 'p':
12837c478bd9Sstevel@tonic-gate kdb5_util = optarg;
12847c478bd9Sstevel@tonic-gate if (!kdb5_util)
12857c478bd9Sstevel@tonic-gate usage();
12867c478bd9Sstevel@tonic-gate break;
12877c478bd9Sstevel@tonic-gate case 'P':
12887c478bd9Sstevel@tonic-gate port = htons(atoi(optarg));
12897c478bd9Sstevel@tonic-gate if (!port)
12907c478bd9Sstevel@tonic-gate usage();
12917c478bd9Sstevel@tonic-gate break;
12927c478bd9Sstevel@tonic-gate case 'r':
12937c478bd9Sstevel@tonic-gate realm = optarg;
12947c478bd9Sstevel@tonic-gate if (!realm)
12957c478bd9Sstevel@tonic-gate usage();
12967c478bd9Sstevel@tonic-gate params.realm = realm;
12977c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_REALM;
12987c478bd9Sstevel@tonic-gate break;
12997c478bd9Sstevel@tonic-gate case 's':
13007c478bd9Sstevel@tonic-gate srvtab = optarg;
13017c478bd9Sstevel@tonic-gate if (!srvtab)
13027c478bd9Sstevel@tonic-gate usage();
13037c478bd9Sstevel@tonic-gate break;
13047c478bd9Sstevel@tonic-gate case 'S':
13057c478bd9Sstevel@tonic-gate standalone++;
13067c478bd9Sstevel@tonic-gate break;
13077c478bd9Sstevel@tonic-gate case 'a':
13087c478bd9Sstevel@tonic-gate acl_file_name = optarg;
13097c478bd9Sstevel@tonic-gate if (!acl_file_name)
13107c478bd9Sstevel@tonic-gate usage();
13117c478bd9Sstevel@tonic-gate break;
13127c478bd9Sstevel@tonic-gate case '?':
13137c478bd9Sstevel@tonic-gate default:
13147c478bd9Sstevel@tonic-gate usage();
13157c478bd9Sstevel@tonic-gate }
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate }
13187c478bd9Sstevel@tonic-gate /*
13197c478bd9Sstevel@tonic-gate * If not in debug mode, switch com_err reporting to syslog
13207c478bd9Sstevel@tonic-gate */
13217c478bd9Sstevel@tonic-gate if (! debug) {
13227c478bd9Sstevel@tonic-gate openlog("kpropd", LOG_PID | LOG_ODELAY, SYSLOG_CLASS);
13237c64d375Smp153739 /*
13247c64d375Smp153739 * Solaris Kerberos:
13257c64d375Smp153739 * Don't replace default logging. Add a new logging channel.
13267c64d375Smp153739 * Stop logging to stderr when daemonizing
13277c64d375Smp153739 */
13287c64d375Smp153739 add_com_err_hook(kpropd_com_err_proc);
13297c478bd9Sstevel@tonic-gate }
13307c478bd9Sstevel@tonic-gate /*
13317c478bd9Sstevel@tonic-gate * Get my hostname, so we can construct my service name
13327c478bd9Sstevel@tonic-gate */
13337c478bd9Sstevel@tonic-gate retval = krb5_sname_to_principal(kpropd_context,
13347c478bd9Sstevel@tonic-gate NULL, KPROP_SERVICE_NAME,
13357c478bd9Sstevel@tonic-gate KRB5_NT_SRV_HST, &server);
13367c478bd9Sstevel@tonic-gate if (retval) {
13377c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
13387c478bd9Sstevel@tonic-gate com_err(progname, retval,
13397c64d375Smp153739 gettext("while trying to construct my service name"));
13407c478bd9Sstevel@tonic-gate exit(1);
13417c478bd9Sstevel@tonic-gate }
13427c478bd9Sstevel@tonic-gate if (realm) {
134356a424ccSmp153739 retval = krb5_set_principal_realm(kpropd_context, server, realm);
134456a424ccSmp153739 if (retval) {
134556a424ccSmp153739 com_err(progname, errno,
134656a424ccSmp153739 gettext("while constructing my service realm"));
134756a424ccSmp153739 exit(1);
134856a424ccSmp153739 }
13497c478bd9Sstevel@tonic-gate }
13507c478bd9Sstevel@tonic-gate /*
13517c478bd9Sstevel@tonic-gate * Construct the name of the temporary file.
13527c478bd9Sstevel@tonic-gate */
13537c478bd9Sstevel@tonic-gate if ((temp_file_name = (char *) malloc(strlen(file) +
13547c478bd9Sstevel@tonic-gate strlen(tmp) + 1)) == NULL) {
13557c478bd9Sstevel@tonic-gate com_err(progname, ENOMEM,
13567c478bd9Sstevel@tonic-gate gettext("while allocating filename for temp file"));
13577c478bd9Sstevel@tonic-gate exit(1);
13587c478bd9Sstevel@tonic-gate }
13597c478bd9Sstevel@tonic-gate strcpy(temp_file_name, file);
13607c478bd9Sstevel@tonic-gate strcat(temp_file_name, tmp);
13617c478bd9Sstevel@tonic-gate
1362159d09a2SMark Phalan retval = kadm5_get_config_params(kpropd_context, 1, NULL, ¶ms,
13637c478bd9Sstevel@tonic-gate ¶ms);
13647c478bd9Sstevel@tonic-gate if (retval) {
13657c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while initializing"));
13667c478bd9Sstevel@tonic-gate exit(1);
13677c478bd9Sstevel@tonic-gate }
13687c478bd9Sstevel@tonic-gate if (params.iprop_enabled == TRUE) {
13697c478bd9Sstevel@tonic-gate ulog_set_role(kpropd_context, IPROP_SLAVE);
13707c478bd9Sstevel@tonic-gate poll_time = params.iprop_polltime;
13717c478bd9Sstevel@tonic-gate
13727c478bd9Sstevel@tonic-gate if (ulog_map(kpropd_context, ¶ms, FKPROPD)) {
13737c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
13747c478bd9Sstevel@tonic-gate com_err(progname, errno,
13757c64d375Smp153739 gettext("while mapping log"));
13767c478bd9Sstevel@tonic-gate exit(1);
13777c478bd9Sstevel@tonic-gate }
13787c478bd9Sstevel@tonic-gate }
13797c478bd9Sstevel@tonic-gate
13807c478bd9Sstevel@tonic-gate /*
13817c478bd9Sstevel@tonic-gate * Grab the realm info and check if iprop is enabled.
13827c478bd9Sstevel@tonic-gate */
13837c478bd9Sstevel@tonic-gate if (def_realm == NULL) {
13847c478bd9Sstevel@tonic-gate retval = krb5_get_default_realm(kpropd_context, &def_realm);
13857c478bd9Sstevel@tonic-gate if (retval) {
13867c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
13877c478bd9Sstevel@tonic-gate com_err(progname, retval,
13887c64d375Smp153739 gettext("while retrieving default realm"));
13897c478bd9Sstevel@tonic-gate exit(1);
13907c478bd9Sstevel@tonic-gate }
13917c478bd9Sstevel@tonic-gate }
13927c478bd9Sstevel@tonic-gate }
13937c478bd9Sstevel@tonic-gate
13947c478bd9Sstevel@tonic-gate /*
13957c478bd9Sstevel@tonic-gate * Figure out who's calling on the other end of the connection....
13967c478bd9Sstevel@tonic-gate */
1397f5918cfdS /* Solaris Kerberos */
13987c478bd9Sstevel@tonic-gate void
kerberos_authenticate(context,fd,clientp,etype,ss)13997c478bd9Sstevel@tonic-gate kerberos_authenticate(context, fd, clientp, etype, ss)
14007c478bd9Sstevel@tonic-gate krb5_context context;
14017c478bd9Sstevel@tonic-gate int fd;
14027c478bd9Sstevel@tonic-gate krb5_principal * clientp;
14037c478bd9Sstevel@tonic-gate krb5_enctype * etype;
1404f5918cfdS struct sockaddr_storage * ss;
14057c478bd9Sstevel@tonic-gate {
14067c478bd9Sstevel@tonic-gate krb5_error_code retval;
14077c478bd9Sstevel@tonic-gate krb5_ticket * ticket;
14087c478bd9Sstevel@tonic-gate struct sockaddr_storage r_ss;
14097c478bd9Sstevel@tonic-gate int ss_length;
14107c478bd9Sstevel@tonic-gate krb5_keytab keytab = NULL;
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate /*
14137c478bd9Sstevel@tonic-gate * Set recv_addr and send_addr
14147c478bd9Sstevel@tonic-gate */
1415f5918cfdS /* Solaris Kerberos */
1416f5918cfdS if (cvtkaddr(ss, &sender_addr) == NULL) {
14177c478bd9Sstevel@tonic-gate com_err(progname, errno,
14187c478bd9Sstevel@tonic-gate gettext("while converting socket address"));
14197c478bd9Sstevel@tonic-gate exit(1);
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate ss_length = sizeof (r_ss);
14237c478bd9Sstevel@tonic-gate if (getsockname(fd, (struct sockaddr *) &r_ss, &ss_length)) {
14247c478bd9Sstevel@tonic-gate com_err(progname, errno,
14257c478bd9Sstevel@tonic-gate gettext("while getting local socket address"));
14267c478bd9Sstevel@tonic-gate exit(1);
14277c478bd9Sstevel@tonic-gate }
14287c478bd9Sstevel@tonic-gate
14297c478bd9Sstevel@tonic-gate if (cvtkaddr(&r_ss, &receiver_addr) == NULL) {
14307c478bd9Sstevel@tonic-gate com_err(progname, errno,
14317c478bd9Sstevel@tonic-gate gettext("while converting socket address"));
14327c478bd9Sstevel@tonic-gate exit(1);
14337c478bd9Sstevel@tonic-gate }
14347c478bd9Sstevel@tonic-gate
14357c478bd9Sstevel@tonic-gate if (debug) {
14367c478bd9Sstevel@tonic-gate char *name;
143756a424ccSmp153739
143856a424ccSmp153739 retval = krb5_unparse_name(context, server, &name);
143956a424ccSmp153739 if (retval) {
14407c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
14417c64d375Smp153739 com_err(progname, retval, gettext("while unparsing server name"));
14427c478bd9Sstevel@tonic-gate exit(1);
14437c478bd9Sstevel@tonic-gate }
14447c478bd9Sstevel@tonic-gate printf(gettext("krb5_recvauth(%d, %s, %s, ...)\n"), fd, kprop_version,
14457c478bd9Sstevel@tonic-gate name);
14467c478bd9Sstevel@tonic-gate free(name);
14477c478bd9Sstevel@tonic-gate }
14487c478bd9Sstevel@tonic-gate
144956a424ccSmp153739 retval = krb5_auth_con_init(context, &auth_context);
145056a424ccSmp153739 if (retval) {
14517c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_auth_con_init: %s"),
14527c478bd9Sstevel@tonic-gate error_message(retval));
14537c478bd9Sstevel@tonic-gate exit(1);
14547c478bd9Sstevel@tonic-gate }
14557c478bd9Sstevel@tonic-gate
145656a424ccSmp153739 retval = krb5_auth_con_setflags(context, auth_context,
145756a424ccSmp153739 KRB5_AUTH_CONTEXT_DO_SEQUENCE);
145856a424ccSmp153739 if (retval) {
14597c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_auth_con_setflags: %s"),
14607c478bd9Sstevel@tonic-gate error_message(retval));
14617c478bd9Sstevel@tonic-gate exit(1);
14627c478bd9Sstevel@tonic-gate }
14637c478bd9Sstevel@tonic-gate
146456a424ccSmp153739 retval = krb5_auth_con_setaddrs(context, auth_context, &receiver_addr,
146556a424ccSmp153739 &sender_addr);
146656a424ccSmp153739 if (retval) {
14677c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_auth_con_setaddrs: %s"),
14687c478bd9Sstevel@tonic-gate error_message(retval));
14697c478bd9Sstevel@tonic-gate exit(1);
14707c478bd9Sstevel@tonic-gate }
14717c478bd9Sstevel@tonic-gate
14727c478bd9Sstevel@tonic-gate if (srvtab) {
147356a424ccSmp153739 retval = krb5_kt_resolve(context, srvtab, &keytab);
147456a424ccSmp153739 if (retval) {
14757c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_kt_resolve: %s"), error_message(retval));
14767c478bd9Sstevel@tonic-gate exit(1);
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate }
14797c478bd9Sstevel@tonic-gate
148056a424ccSmp153739 retval = krb5_recvauth(context, &auth_context, (void *) &fd,
148156a424ccSmp153739 kprop_version, server, 0, keytab, &ticket);
148256a424ccSmp153739 if (retval) {
148356a424ccSmp153739 syslog(LOG_ERR, gettext("Error in krb5_recvauth: %s"), error_message(retval));
14847c478bd9Sstevel@tonic-gate exit(1);
14857c478bd9Sstevel@tonic-gate }
14867c478bd9Sstevel@tonic-gate
148756a424ccSmp153739 retval = krb5_copy_principal(context, ticket->enc_part2->client, clientp);
148856a424ccSmp153739 if (retval) {
14897c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_copy_prinicpal: %s"),
14907c478bd9Sstevel@tonic-gate error_message(retval));
14917c478bd9Sstevel@tonic-gate exit(1);
14927c478bd9Sstevel@tonic-gate }
14937c478bd9Sstevel@tonic-gate
14947c478bd9Sstevel@tonic-gate *etype = ticket->enc_part.enctype;
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate if (debug) {
14977c478bd9Sstevel@tonic-gate char * name;
14987c478bd9Sstevel@tonic-gate char etypebuf[100];
14997c478bd9Sstevel@tonic-gate
150056a424ccSmp153739 retval = krb5_unparse_name(context, *clientp, &name);
150156a424ccSmp153739 if (retval) {
15027c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
15037c478bd9Sstevel@tonic-gate com_err(progname, retval,
15047c64d375Smp153739 gettext("while unparsing client name"));
15057c478bd9Sstevel@tonic-gate exit(1);
15067c478bd9Sstevel@tonic-gate }
15077c478bd9Sstevel@tonic-gate
150856a424ccSmp153739 retval = krb5_enctype_to_string(*etype, etypebuf, sizeof(etypebuf));
150956a424ccSmp153739 if (retval) {
15107c64d375Smp153739 /* Solaris Kerberos: Keep error messages consistent */
15117c64d375Smp153739 com_err(progname, retval, gettext("while unparsing ticket etype"));
15127c478bd9Sstevel@tonic-gate exit(1);
15137c478bd9Sstevel@tonic-gate }
15147c478bd9Sstevel@tonic-gate
15157c478bd9Sstevel@tonic-gate printf("authenticated client: %s (etype == %s)\n", name, etypebuf);
15167c478bd9Sstevel@tonic-gate free(name);
15177c478bd9Sstevel@tonic-gate }
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate krb5_free_ticket(context, ticket);
15207c478bd9Sstevel@tonic-gate }
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate krb5_boolean
authorized_principal(context,p,auth_etype)15237c478bd9Sstevel@tonic-gate authorized_principal(context, p, auth_etype)
15247c478bd9Sstevel@tonic-gate krb5_context context;
15257c478bd9Sstevel@tonic-gate krb5_principal p;
15267c478bd9Sstevel@tonic-gate krb5_enctype auth_etype;
15277c478bd9Sstevel@tonic-gate {
15287c478bd9Sstevel@tonic-gate char *name, *ptr;
15297c478bd9Sstevel@tonic-gate char buf[1024];
15307c478bd9Sstevel@tonic-gate krb5_error_code retval;
15317c478bd9Sstevel@tonic-gate FILE *acl_file;
15327c478bd9Sstevel@tonic-gate int end;
15337c478bd9Sstevel@tonic-gate krb5_enctype acl_etype;
15347c478bd9Sstevel@tonic-gate
15357c478bd9Sstevel@tonic-gate retval = krb5_unparse_name(context, p, &name);
15367c478bd9Sstevel@tonic-gate if (retval)
15377c478bd9Sstevel@tonic-gate return FALSE;
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate acl_file = fopen(acl_file_name, "r");
15407c478bd9Sstevel@tonic-gate if (!acl_file)
15417c478bd9Sstevel@tonic-gate return FALSE;
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate while (!feof(acl_file)) {
15447c478bd9Sstevel@tonic-gate if (!fgets(buf, sizeof(buf), acl_file))
15457c478bd9Sstevel@tonic-gate break;
15467c478bd9Sstevel@tonic-gate end = strlen(buf) - 1;
15477c478bd9Sstevel@tonic-gate if (buf[end] == '\n')
15487c478bd9Sstevel@tonic-gate buf[end] = '\0';
15497c478bd9Sstevel@tonic-gate if (!strncmp(name, buf, strlen(name))) {
15507c478bd9Sstevel@tonic-gate ptr = buf+strlen(name);
15517c478bd9Sstevel@tonic-gate
15527c478bd9Sstevel@tonic-gate /* if the next character is not whitespace or nul, then
15537c478bd9Sstevel@tonic-gate the match is only partial. continue on to new lines. */
155456a424ccSmp153739 if (*ptr && !isspace((int) *ptr))
15557c478bd9Sstevel@tonic-gate continue;
15567c478bd9Sstevel@tonic-gate
15577c478bd9Sstevel@tonic-gate /* otherwise, skip trailing whitespace */
155856a424ccSmp153739 for (; *ptr && isspace((int) *ptr); ptr++) ;
15597c478bd9Sstevel@tonic-gate
15607c478bd9Sstevel@tonic-gate /* now, look for an etype string. if there isn't one,
15617c478bd9Sstevel@tonic-gate return true. if there is an invalid string, continue.
15627c478bd9Sstevel@tonic-gate If there is a valid string, return true only if it
15637c478bd9Sstevel@tonic-gate matches the etype passed in, otherwise continue */
15647c478bd9Sstevel@tonic-gate
15657c478bd9Sstevel@tonic-gate if ((*ptr) &&
15667c478bd9Sstevel@tonic-gate ((retval = krb5_string_to_enctype(ptr, &acl_etype)) ||
15677c478bd9Sstevel@tonic-gate (acl_etype != auth_etype)))
15687c478bd9Sstevel@tonic-gate continue;
15697c478bd9Sstevel@tonic-gate
15707c478bd9Sstevel@tonic-gate free(name);
15717c478bd9Sstevel@tonic-gate fclose(acl_file);
15727c478bd9Sstevel@tonic-gate return TRUE;
15737c478bd9Sstevel@tonic-gate }
15747c478bd9Sstevel@tonic-gate }
15757c478bd9Sstevel@tonic-gate free(name);
15767c478bd9Sstevel@tonic-gate fclose(acl_file);
15777c478bd9Sstevel@tonic-gate return FALSE;
15787c478bd9Sstevel@tonic-gate }
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate void
recv_database(context,fd,database_fd,confmsg)15817c478bd9Sstevel@tonic-gate recv_database(context, fd, database_fd, confmsg)
15827c478bd9Sstevel@tonic-gate krb5_context context;
15837c478bd9Sstevel@tonic-gate int fd;
15847c478bd9Sstevel@tonic-gate int database_fd;
15857c478bd9Sstevel@tonic-gate krb5_data *confmsg;
15867c478bd9Sstevel@tonic-gate {
158756a424ccSmp153739 krb5_ui_4 database_size; /* This must be 4 bytes */
15887c478bd9Sstevel@tonic-gate int received_size, n;
15897c478bd9Sstevel@tonic-gate char buf[1024];
15907c478bd9Sstevel@tonic-gate krb5_data inbuf, outbuf;
15917c478bd9Sstevel@tonic-gate krb5_error_code retval;
15927c478bd9Sstevel@tonic-gate
15937c478bd9Sstevel@tonic-gate /*
15947c478bd9Sstevel@tonic-gate * Receive and decode size from client
15957c478bd9Sstevel@tonic-gate */
159656a424ccSmp153739 retval = krb5_read_message(context, (void *) &fd, &inbuf);
159756a424ccSmp153739 if (retval) {
15987c478bd9Sstevel@tonic-gate send_error(context, fd, retval, gettext("while reading database size"));
15997c478bd9Sstevel@tonic-gate com_err(progname, retval,
16007c478bd9Sstevel@tonic-gate gettext("while reading size of database from client"));
16017c478bd9Sstevel@tonic-gate exit(1);
16027c478bd9Sstevel@tonic-gate }
16037c478bd9Sstevel@tonic-gate if (krb5_is_krb_error(&inbuf))
16047c478bd9Sstevel@tonic-gate recv_error(context, &inbuf);
160556a424ccSmp153739 retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL);
160656a424ccSmp153739 if (retval) {
160756a424ccSmp153739 send_error(context, fd, retval, gettext(
160856a424ccSmp153739 "while decoding database size"));
16097c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf);
16107c478bd9Sstevel@tonic-gate com_err(progname, retval,
16117c478bd9Sstevel@tonic-gate gettext("while decoding database size from client"));
16127c478bd9Sstevel@tonic-gate exit(1);
16137c478bd9Sstevel@tonic-gate }
16147c478bd9Sstevel@tonic-gate memcpy((char *) &database_size, outbuf.data, sizeof(database_size));
16157c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf);
16167c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &outbuf);
16177c478bd9Sstevel@tonic-gate database_size = ntohl(database_size);
16187c478bd9Sstevel@tonic-gate
16197c478bd9Sstevel@tonic-gate /*
16207c478bd9Sstevel@tonic-gate * Initialize the initial vector.
16217c478bd9Sstevel@tonic-gate */
162256a424ccSmp153739 retval = krb5_auth_con_initivector(context, auth_context);
162356a424ccSmp153739 if (retval) {
162456a424ccSmp153739 send_error(context, fd, retval, gettext(
162556a424ccSmp153739 "failed while initializing i_vector"));
16267c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while initializing i_vector"));
16277c478bd9Sstevel@tonic-gate exit(1);
16287c478bd9Sstevel@tonic-gate }
16297c478bd9Sstevel@tonic-gate
16307c478bd9Sstevel@tonic-gate /*
16317c478bd9Sstevel@tonic-gate * Now start receiving the database from the net
16327c478bd9Sstevel@tonic-gate */
16337c478bd9Sstevel@tonic-gate received_size = 0;
16347c478bd9Sstevel@tonic-gate while (received_size < database_size) {
163556a424ccSmp153739 retval = krb5_read_message(context, (void *) &fd, &inbuf);
163656a424ccSmp153739 if (retval) {
16377c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf),
16387c478bd9Sstevel@tonic-gate gettext("while reading database block starting at offset %d"),
16397c478bd9Sstevel@tonic-gate received_size);
16407c478bd9Sstevel@tonic-gate com_err(progname, retval, buf);
16417c478bd9Sstevel@tonic-gate send_error(context, fd, retval, buf);
16427c478bd9Sstevel@tonic-gate exit(1);
16437c478bd9Sstevel@tonic-gate }
16447c478bd9Sstevel@tonic-gate if (krb5_is_krb_error(&inbuf))
16457c478bd9Sstevel@tonic-gate recv_error(context, &inbuf);
164656a424ccSmp153739 retval = krb5_rd_priv(context, auth_context, &inbuf,
164756a424ccSmp153739 &outbuf, NULL);
164856a424ccSmp153739 if (retval) {
16497c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf),
16507c478bd9Sstevel@tonic-gate gettext("while decoding database block starting at offset %d"),
16517c478bd9Sstevel@tonic-gate received_size);
16527c478bd9Sstevel@tonic-gate com_err(progname, retval, buf);
16537c478bd9Sstevel@tonic-gate send_error(context, fd, retval, buf);
16547c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf);
16557c478bd9Sstevel@tonic-gate exit(1);
16567c478bd9Sstevel@tonic-gate }
16577c478bd9Sstevel@tonic-gate n = write(database_fd, outbuf.data, outbuf.length);
16587c478bd9Sstevel@tonic-gate if (n < 0) {
16597c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf),
16607c478bd9Sstevel@tonic-gate gettext(
16617c478bd9Sstevel@tonic-gate "while writing database block starting at offset %d"),
16627c478bd9Sstevel@tonic-gate received_size);
16637c478bd9Sstevel@tonic-gate send_error(context, fd, errno, buf);
16647c478bd9Sstevel@tonic-gate } else if (n != outbuf.length) {
16657c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf),
16667c478bd9Sstevel@tonic-gate gettext(
16677c478bd9Sstevel@tonic-gate "incomplete write while writing database block starting at\n"
16687c478bd9Sstevel@tonic-gate "offset %d (%d written, %d expected)"),
16697c478bd9Sstevel@tonic-gate received_size, n, outbuf.length);
16707c478bd9Sstevel@tonic-gate send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
16717c478bd9Sstevel@tonic-gate }
16727c478bd9Sstevel@tonic-gate received_size += outbuf.length;
16737c478bd9Sstevel@tonic-gate /* SUNWresync121: our krb5...contents sets length to 0 */
16747c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf);
16757c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &outbuf);
167656a424ccSmp153739
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate /*
16797c478bd9Sstevel@tonic-gate * OK, we've seen the entire file. Did we get too many bytes?
16807c478bd9Sstevel@tonic-gate */
16817c478bd9Sstevel@tonic-gate if (received_size > database_size) {
16827c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf),
16837c478bd9Sstevel@tonic-gate gettext("Received %d bytes, expected %d bytes for database file"),
16847c478bd9Sstevel@tonic-gate received_size, database_size);
16857c478bd9Sstevel@tonic-gate send_error(context, fd, KRB5KRB_ERR_GENERIC, buf);
16867c478bd9Sstevel@tonic-gate }
16877c478bd9Sstevel@tonic-gate /*
16887c478bd9Sstevel@tonic-gate * Create message acknowledging number of bytes received, but
16897c478bd9Sstevel@tonic-gate * don't send it until kdb5_util returns successfully.
16907c478bd9Sstevel@tonic-gate */
16917c478bd9Sstevel@tonic-gate database_size = htonl(database_size);
16927c478bd9Sstevel@tonic-gate inbuf.data = (char *) &database_size;
16937c478bd9Sstevel@tonic-gate inbuf.length = sizeof(database_size);
169456a424ccSmp153739 retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL);
169556a424ccSmp153739 if (retval) {
16967c478bd9Sstevel@tonic-gate com_err(progname, retval,
16977c478bd9Sstevel@tonic-gate gettext("while encoding # of receieved bytes"));
16987c478bd9Sstevel@tonic-gate send_error(context, fd, retval,
16997c478bd9Sstevel@tonic-gate gettext("while encoding # of received bytes"));
17007c478bd9Sstevel@tonic-gate exit(1);
17017c478bd9Sstevel@tonic-gate }
17027c478bd9Sstevel@tonic-gate }
17037c478bd9Sstevel@tonic-gate
17047c478bd9Sstevel@tonic-gate
17057c478bd9Sstevel@tonic-gate void
send_error(context,fd,err_code,err_text)17067c478bd9Sstevel@tonic-gate send_error(context, fd, err_code, err_text)
17077c478bd9Sstevel@tonic-gate krb5_context context;
17087c478bd9Sstevel@tonic-gate int fd;
17097c478bd9Sstevel@tonic-gate krb5_error_code err_code;
17107c478bd9Sstevel@tonic-gate char *err_text;
17117c478bd9Sstevel@tonic-gate {
17127c478bd9Sstevel@tonic-gate krb5_error error;
17137c478bd9Sstevel@tonic-gate const char *text;
17147c478bd9Sstevel@tonic-gate krb5_data outbuf;
17157c478bd9Sstevel@tonic-gate char buf[1024];
17167c478bd9Sstevel@tonic-gate
17177c478bd9Sstevel@tonic-gate memset((char *)&error, 0, sizeof(error));
17187c478bd9Sstevel@tonic-gate krb5_us_timeofday(context, &error.stime, &error.susec);
17197c478bd9Sstevel@tonic-gate error.server = server;
17207c478bd9Sstevel@tonic-gate error.client = client;
17217c478bd9Sstevel@tonic-gate
17227c478bd9Sstevel@tonic-gate if (err_text)
17237c478bd9Sstevel@tonic-gate text = err_text;
17247c478bd9Sstevel@tonic-gate else
17257c478bd9Sstevel@tonic-gate text = error_message(err_code);
17267c478bd9Sstevel@tonic-gate
17277c478bd9Sstevel@tonic-gate error.error = err_code - ERROR_TABLE_BASE_krb5;
17287c478bd9Sstevel@tonic-gate if (error.error > 127) {
17297c478bd9Sstevel@tonic-gate error.error = KRB_ERR_GENERIC;
17307c478bd9Sstevel@tonic-gate if (err_text) {
17317c478bd9Sstevel@tonic-gate sprintf(buf, "%s %s", error_message(err_code),
17327c478bd9Sstevel@tonic-gate err_text);
17337c478bd9Sstevel@tonic-gate text = buf;
17347c478bd9Sstevel@tonic-gate }
17357c478bd9Sstevel@tonic-gate }
17367c478bd9Sstevel@tonic-gate error.text.length = strlen(text) + 1;
173756a424ccSmp153739 error.text.data = malloc(error.text.length);
173856a424ccSmp153739 if (error.text.data) {
17397c478bd9Sstevel@tonic-gate strcpy(error.text.data, text);
17407c478bd9Sstevel@tonic-gate if (!krb5_mk_error(context, &error, &outbuf)) {
17417c478bd9Sstevel@tonic-gate (void) krb5_write_message(context, (void *)&fd,&outbuf);
17427c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &outbuf);
17437c478bd9Sstevel@tonic-gate }
17447c478bd9Sstevel@tonic-gate free(error.text.data);
17457c478bd9Sstevel@tonic-gate }
17467c478bd9Sstevel@tonic-gate }
17477c478bd9Sstevel@tonic-gate
17487c478bd9Sstevel@tonic-gate void
recv_error(context,inbuf)17497c478bd9Sstevel@tonic-gate recv_error(context, inbuf)
17507c478bd9Sstevel@tonic-gate krb5_context context;
17517c478bd9Sstevel@tonic-gate krb5_data *inbuf;
17527c478bd9Sstevel@tonic-gate {
17537c478bd9Sstevel@tonic-gate krb5_error *error;
17547c478bd9Sstevel@tonic-gate krb5_error_code retval;
17557c478bd9Sstevel@tonic-gate
175656a424ccSmp153739 retval = krb5_rd_error(context, inbuf, &error);
175756a424ccSmp153739 if (retval) {
17587c478bd9Sstevel@tonic-gate com_err(progname, retval,
17597c478bd9Sstevel@tonic-gate gettext("while decoding error packet from client"));
17607c478bd9Sstevel@tonic-gate exit(1);
17617c478bd9Sstevel@tonic-gate }
17627c478bd9Sstevel@tonic-gate if (error->error == KRB_ERR_GENERIC) {
17637c478bd9Sstevel@tonic-gate if (error->text.data)
17647c478bd9Sstevel@tonic-gate fprintf(stderr,
17657c478bd9Sstevel@tonic-gate gettext("Generic remote error: %s\n"),
17667c478bd9Sstevel@tonic-gate error->text.data);
17677c478bd9Sstevel@tonic-gate } else if (error->error) {
17687c478bd9Sstevel@tonic-gate com_err(progname, error->error + ERROR_TABLE_BASE_krb5,
1769*83cba5f6SPeter Shoults gettext("signaled from server"));
17707c478bd9Sstevel@tonic-gate if (error->text.data)
17717c478bd9Sstevel@tonic-gate fprintf(stderr,
17727c478bd9Sstevel@tonic-gate gettext("Error text from client: %s\n"),
17737c478bd9Sstevel@tonic-gate error->text.data);
17747c478bd9Sstevel@tonic-gate }
17757c478bd9Sstevel@tonic-gate krb5_free_error(context, error);
17767c478bd9Sstevel@tonic-gate exit(1);
17777c478bd9Sstevel@tonic-gate }
17787c478bd9Sstevel@tonic-gate
17797c478bd9Sstevel@tonic-gate void
load_database(context,kdb_util,database_file_name)178056a424ccSmp153739 load_database(context, kdb_util, database_file_name)
17817c478bd9Sstevel@tonic-gate krb5_context context;
178256a424ccSmp153739 char *kdb_util;
17837c478bd9Sstevel@tonic-gate char *database_file_name;
17847c478bd9Sstevel@tonic-gate {
17857c478bd9Sstevel@tonic-gate static char *edit_av[10];
178656a424ccSmp153739 int error_ret, save_stderr = -1;
17877c478bd9Sstevel@tonic-gate int child_pid;
17887c478bd9Sstevel@tonic-gate int count;
178956a424ccSmp153739
179056a424ccSmp153739 /* <sys/param.h> has been included, so BSD will be defined on
179156a424ccSmp153739 BSD systems */
179256a424ccSmp153739 #if BSD > 0 && BSD <= 43
179356a424ccSmp153739 #ifndef WEXITSTATUS
179456a424ccSmp153739 #define WEXITSTATUS(w) (w).w_retcode
179556a424ccSmp153739 #endif
179656a424ccSmp153739 union wait waitb;
179756a424ccSmp153739 #else
17987c478bd9Sstevel@tonic-gate int waitb;
179956a424ccSmp153739 #endif
18007c478bd9Sstevel@tonic-gate krb5_error_code retval;
18017c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx;
18027c478bd9Sstevel@tonic-gate
18037c478bd9Sstevel@tonic-gate if (debug)
180456a424ccSmp153739 printf(gettext("calling kdb_util to load database\n"));
18057c478bd9Sstevel@tonic-gate
18067c478bd9Sstevel@tonic-gate log_ctx = context->kdblog_context;
18077c478bd9Sstevel@tonic-gate
180856a424ccSmp153739 edit_av[0] = kdb_util;
18097c478bd9Sstevel@tonic-gate count = 1;
18107c478bd9Sstevel@tonic-gate if (realm) {
18117c478bd9Sstevel@tonic-gate edit_av[count++] = "-r";
18127c478bd9Sstevel@tonic-gate edit_av[count++] = realm;
18137c478bd9Sstevel@tonic-gate }
18147c478bd9Sstevel@tonic-gate edit_av[count++] = "load";
18157c478bd9Sstevel@tonic-gate if (kerb_database) {
18167c478bd9Sstevel@tonic-gate edit_av[count++] = "-d";
18177c478bd9Sstevel@tonic-gate edit_av[count++] = kerb_database;
18187c478bd9Sstevel@tonic-gate }
18197c478bd9Sstevel@tonic-gate
18207c478bd9Sstevel@tonic-gate if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) {
18217c478bd9Sstevel@tonic-gate edit_av[count++] = "-i";
18227c478bd9Sstevel@tonic-gate }
18237c478bd9Sstevel@tonic-gate edit_av[count++] = database_file_name;
18247c478bd9Sstevel@tonic-gate edit_av[count++] = NULL;
18257c478bd9Sstevel@tonic-gate
18267c478bd9Sstevel@tonic-gate switch(child_pid = fork()) {
18277c478bd9Sstevel@tonic-gate case -1:
18287c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while trying to fork %s"),
182956a424ccSmp153739 kdb_util);
18307c478bd9Sstevel@tonic-gate exit(1);
18317c478bd9Sstevel@tonic-gate /*NOTREACHED*/
18327c478bd9Sstevel@tonic-gate case 0:
18337c478bd9Sstevel@tonic-gate if (!debug) {
18347c478bd9Sstevel@tonic-gate save_stderr = dup(2);
18357c478bd9Sstevel@tonic-gate close(0);
18367c478bd9Sstevel@tonic-gate close(1);
18377c478bd9Sstevel@tonic-gate close(2);
18387c478bd9Sstevel@tonic-gate open("/dev/null", O_RDWR);
18397c478bd9Sstevel@tonic-gate dup(0);
18407c478bd9Sstevel@tonic-gate dup(0);
18417c478bd9Sstevel@tonic-gate }
18427c478bd9Sstevel@tonic-gate
184356a424ccSmp153739 execv(kdb_util, edit_av);
18447c478bd9Sstevel@tonic-gate retval = errno;
18457c478bd9Sstevel@tonic-gate if (!debug)
18467c478bd9Sstevel@tonic-gate dup2(save_stderr, 2);
18477c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while trying to exec %s"),
184856a424ccSmp153739 kdb_util);
18497c478bd9Sstevel@tonic-gate _exit(1);
18507c478bd9Sstevel@tonic-gate /*NOTREACHED*/
18517c478bd9Sstevel@tonic-gate default:
18527c478bd9Sstevel@tonic-gate if (debug)
18537c478bd9Sstevel@tonic-gate printf(gettext("Child PID is %d\n"), child_pid);
18547c478bd9Sstevel@tonic-gate if (wait(&waitb) < 0) {
18557c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while waiting for %s"),
185656a424ccSmp153739 kdb_util);
18577c478bd9Sstevel@tonic-gate exit(1);
18587c478bd9Sstevel@tonic-gate }
18597c478bd9Sstevel@tonic-gate }
18607c478bd9Sstevel@tonic-gate
186156a424ccSmp153739 error_ret = WEXITSTATUS(waitb);
186256a424ccSmp153739 if (error_ret) {
18637c478bd9Sstevel@tonic-gate com_err(progname, 0,
186456a424ccSmp153739 gettext("%s returned a bad exit status (%d)"),
186556a424ccSmp153739 kdb_util, error_ret);
18667c478bd9Sstevel@tonic-gate exit(1);
18677c478bd9Sstevel@tonic-gate }
18687c478bd9Sstevel@tonic-gate return;
18697c478bd9Sstevel@tonic-gate }
1870