17c478bd9Sstevel@tonic-gate /*
2d15b0992SMark Phalan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate
77c478bd9Sstevel@tonic-gate /*
87c478bd9Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
97c478bd9Sstevel@tonic-gate *
107c478bd9Sstevel@tonic-gate * Openvision retains the copyright to derivative works of
117c478bd9Sstevel@tonic-gate * this source code. Do *NOT* create a derivative of this
127c478bd9Sstevel@tonic-gate * source code before consulting with your legal department.
137c478bd9Sstevel@tonic-gate * Do *NOT* integrate *ANY* of this source code into another
147c478bd9Sstevel@tonic-gate * product before consulting with your legal department.
157c478bd9Sstevel@tonic-gate *
167c478bd9Sstevel@tonic-gate * For further information, read the top-level Openvision
177c478bd9Sstevel@tonic-gate * copyright which is contained in the top-level MIT Kerberos
187c478bd9Sstevel@tonic-gate * copyright.
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
217c478bd9Sstevel@tonic-gate *
227c478bd9Sstevel@tonic-gate */
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
26159d09a2SMark Phalan *
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
3056a424ccSmp153739 * Copyright (C) 1998 by the FundsXpress, INC.
3156a424ccSmp153739 *
3256a424ccSmp153739 * All rights reserved.
3356a424ccSmp153739 *
3456a424ccSmp153739 * Export of this software from the United States of America may require
3556a424ccSmp153739 * a specific license from the United States Government. It is the
3656a424ccSmp153739 * responsibility of any person or organization contemplating export to
3756a424ccSmp153739 * obtain such a license before exporting.
3856a424ccSmp153739 *
3956a424ccSmp153739 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
4056a424ccSmp153739 * distribute this software and its documentation for any purpose and
4156a424ccSmp153739 * without fee is hereby granted, provided that the above copyright
4256a424ccSmp153739 * notice appear in all copies and that both that copyright notice and
4356a424ccSmp153739 * this permission notice appear in supporting documentation, and that
4456a424ccSmp153739 * the name of FundsXpress. not be used in advertising or publicity pertaining
4556a424ccSmp153739 * to distribution of the software without specific, written prior
4656a424ccSmp153739 * permission. FundsXpress makes no representations about the suitability of
4756a424ccSmp153739 * this software for any purpose. It is provided "as is" without express
4856a424ccSmp153739 * or implied warranty.
4956a424ccSmp153739 *
5056a424ccSmp153739 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
5156a424ccSmp153739 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
5256a424ccSmp153739 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5356a424ccSmp153739 */
5456a424ccSmp153739
5556a424ccSmp153739
5656a424ccSmp153739 /*
577c478bd9Sstevel@tonic-gate * SUNWresync121 XXX
587c478bd9Sstevel@tonic-gate * Beware future resyncers, this file is much diff from MIT (1.0...)
597c478bd9Sstevel@tonic-gate */
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate #include <stdio.h>
62004388ebScasper #include <stdio_ext.h>
637c478bd9Sstevel@tonic-gate #include <signal.h>
647c478bd9Sstevel@tonic-gate #include <syslog.h>
657c478bd9Sstevel@tonic-gate #include <sys/types.h>
6656a424ccSmp153739 #ifdef _AIX
6756a424ccSmp153739 #include <sys/select.h>
6856a424ccSmp153739 #endif
697c478bd9Sstevel@tonic-gate #include <sys/time.h>
707c478bd9Sstevel@tonic-gate #include <sys/socket.h>
717c478bd9Sstevel@tonic-gate #include <unistd.h>
727c478bd9Sstevel@tonic-gate #include <netinet/in.h>
737c478bd9Sstevel@tonic-gate #include <arpa/inet.h> /* inet_ntoa */
747c478bd9Sstevel@tonic-gate #include <gssapi/gssapi.h>
75159d09a2SMark Phalan #include "gssapiP_krb5.h" /* for kg_get_context */
767c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
777c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
787c478bd9Sstevel@tonic-gate #include <kadm5/kadm_rpc.h>
797c478bd9Sstevel@tonic-gate #include <server_acl.h>
807c478bd9Sstevel@tonic-gate #include <krb5/adm_proto.h>
81159d09a2SMark Phalan #include "kdb_kt.h" /* for krb5_ktkdb_set_context */
827c478bd9Sstevel@tonic-gate #include <string.h>
8356a424ccSmp153739 #include <kadm5/server_internal.h>
847c478bd9Sstevel@tonic-gate #include <gssapi_krb5.h>
857c478bd9Sstevel@tonic-gate #include <libintl.h>
867c478bd9Sstevel@tonic-gate #include <locale.h>
877c478bd9Sstevel@tonic-gate #include <sys/resource.h>
887c478bd9Sstevel@tonic-gate #include <kdb/kdb_log.h>
8954925bf6Swillf #include <kdb_kt.h>
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
9256a424ccSmp153739 #include "misc.h"
937c478bd9Sstevel@tonic-gate
94159d09a2SMark Phalan #ifdef PURIFY
95159d09a2SMark Phalan #include "purify.h"
96159d09a2SMark Phalan
97159d09a2SMark Phalan int signal_pure_report = 0;
98159d09a2SMark Phalan int signal_pure_clear = 0;
99159d09a2SMark Phalan void request_pure_report(int);
100159d09a2SMark Phalan void request_pure_clear(int);
101159d09a2SMark Phalan #endif /* PURIFY */
102159d09a2SMark Phalan
103159d09a2SMark Phalan
1047c478bd9Sstevel@tonic-gate #ifndef FD_SETSIZE
1057c478bd9Sstevel@tonic-gate #define FD_SETSIZE 256
1067c478bd9Sstevel@tonic-gate #endif
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate #ifndef MAX
1097c478bd9Sstevel@tonic-gate #define MAX(a, b) (((a) > (b)) ? (a) : (b))
1107c478bd9Sstevel@tonic-gate #endif
1117c478bd9Sstevel@tonic-gate
11256a424ccSmp153739 #if defined(NEED_DAEMON_PROTO)
11356a424ccSmp153739 extern int daemon(int, int);
11456a424ccSmp153739 #endif
11556a424ccSmp153739
1167c478bd9Sstevel@tonic-gate static int signal_request_exit = 0;
1177c478bd9Sstevel@tonic-gate kadm5_config_params chgpw_params;
1187c478bd9Sstevel@tonic-gate void setup_signal_handlers(iprop_role iproprole);
119159d09a2SMark Phalan void request_exit(int);
1207c478bd9Sstevel@tonic-gate void sig_pipe(int);
121159d09a2SMark Phalan void kadm_svc_run(void);
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate #ifdef POSIX_SIGNALS
1247c478bd9Sstevel@tonic-gate static struct sigaction s_action;
1257c478bd9Sstevel@tonic-gate #endif /* POSIX_SIGNALS */
1267c478bd9Sstevel@tonic-gate
12756a424ccSmp153739
1287c478bd9Sstevel@tonic-gate #define TIMEOUT 15
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate typedef struct _auth_gssapi_name {
1317c478bd9Sstevel@tonic-gate char *name;
1327c478bd9Sstevel@tonic-gate gss_OID type;
1337c478bd9Sstevel@tonic-gate } auth_gssapi_name;
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate gss_name_t gss_changepw_name = NULL, gss_oldchangepw_name = NULL;
1367c478bd9Sstevel@tonic-gate void *global_server_handle;
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate * This is a kludge, but the server needs these constants to be
1407c478bd9Sstevel@tonic-gate * compatible with old clients. They are defined in <kadm5/admin.h>,
1417c478bd9Sstevel@tonic-gate * but only if USE_KADM5_API_VERSION == 1.
1427c478bd9Sstevel@tonic-gate */
1437c478bd9Sstevel@tonic-gate #define OVSEC_KADM_ADMIN_SERVICE_P "ovsec_adm@admin"
1447c478bd9Sstevel@tonic-gate #define OVSEC_KADM_CHANGEPW_SERVICE_P "ovsec_adm@changepw"
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate extern void krb5_iprop_prog_1();
1487c478bd9Sstevel@tonic-gate extern kadm5_ret_t kiprop_get_adm_host_srv_name(
1497c478bd9Sstevel@tonic-gate krb5_context,
1507c478bd9Sstevel@tonic-gate const char *,
1517c478bd9Sstevel@tonic-gate char **);
1527c478bd9Sstevel@tonic-gate
153159d09a2SMark Phalan static int schpw;
1547c478bd9Sstevel@tonic-gate
15556a424ccSmp153739
1567c478bd9Sstevel@tonic-gate in_port_t l_port = 0; /* global local port num, for BSM audits */
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate int nofork = 0; /* global; don't fork (debug mode) */
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /*
1627c478bd9Sstevel@tonic-gate * Function: usage
1637c478bd9Sstevel@tonic-gate *
1647c478bd9Sstevel@tonic-gate * Purpose: print out the server usage message
1657c478bd9Sstevel@tonic-gate *
1667c478bd9Sstevel@tonic-gate * Arguments:
1677c478bd9Sstevel@tonic-gate * Requires:
1687c478bd9Sstevel@tonic-gate * Effects:
1697c478bd9Sstevel@tonic-gate * Modifies:
1707c478bd9Sstevel@tonic-gate */
1717c478bd9Sstevel@tonic-gate
usage()17256a424ccSmp153739 static void usage()
1737c478bd9Sstevel@tonic-gate {
17454925bf6Swillf fprintf(stderr, gettext("Usage: kadmind [-x db_args]* [-r realm] [-m] [-d] "
1757c478bd9Sstevel@tonic-gate "[-p port-number]\n"));
1767c478bd9Sstevel@tonic-gate exit(1);
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * Function: display_status
1817c478bd9Sstevel@tonic-gate *
1827c478bd9Sstevel@tonic-gate * Purpose: displays GSS-API messages
1837c478bd9Sstevel@tonic-gate *
1847c478bd9Sstevel@tonic-gate * Arguments:
1857c478bd9Sstevel@tonic-gate *
1867c478bd9Sstevel@tonic-gate * msg a string to be displayed with the message
1877c478bd9Sstevel@tonic-gate * maj_stat the GSS-API major status code
1887c478bd9Sstevel@tonic-gate * min_stat the GSS-API minor status code
1897c478bd9Sstevel@tonic-gate *
1907c478bd9Sstevel@tonic-gate * Effects:
1917c478bd9Sstevel@tonic-gate *
1927c478bd9Sstevel@tonic-gate * The GSS-API messages associated with maj_stat and min_stat are
1937c478bd9Sstevel@tonic-gate * displayed on stderr, each preceeded by "GSS-API error <msg>: " and
1947c478bd9Sstevel@tonic-gate * followed by a newline.
1957c478bd9Sstevel@tonic-gate */
19656a424ccSmp153739 static void display_status_1(char *, OM_uint32, int);
1977c478bd9Sstevel@tonic-gate
display_status(msg,maj_stat,min_stat)19856a424ccSmp153739 static void display_status(msg, maj_stat, min_stat)
1997c478bd9Sstevel@tonic-gate char *msg;
2007c478bd9Sstevel@tonic-gate OM_uint32 maj_stat;
2017c478bd9Sstevel@tonic-gate OM_uint32 min_stat;
2027c478bd9Sstevel@tonic-gate {
2037c478bd9Sstevel@tonic-gate display_status_1(msg, maj_stat, GSS_C_GSS_CODE);
2047c478bd9Sstevel@tonic-gate display_status_1(msg, min_stat, GSS_C_MECH_CODE);
2057c478bd9Sstevel@tonic-gate }
2067c478bd9Sstevel@tonic-gate
display_status_1(m,code,type)2077c478bd9Sstevel@tonic-gate static void display_status_1(m, code, type)
2087c478bd9Sstevel@tonic-gate char *m;
2097c478bd9Sstevel@tonic-gate OM_uint32 code;
2107c478bd9Sstevel@tonic-gate int type;
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate OM_uint32 maj_stat, min_stat;
2137c478bd9Sstevel@tonic-gate gss_buffer_desc msg;
2147c478bd9Sstevel@tonic-gate OM_uint32 msg_ctx;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate msg_ctx = 0;
2177c478bd9Sstevel@tonic-gate while (1) {
2187c478bd9Sstevel@tonic-gate maj_stat = gss_display_status(&min_stat, code,
2197c478bd9Sstevel@tonic-gate type, GSS_C_NULL_OID,
2207c478bd9Sstevel@tonic-gate &msg_ctx, &msg);
2217c478bd9Sstevel@tonic-gate fprintf(stderr, "GSS-API error %s: %s\n", m,
2227c478bd9Sstevel@tonic-gate (char *)msg.value);
2237c478bd9Sstevel@tonic-gate (void) gss_release_buffer(&min_stat, &msg);
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate if (!msg_ctx)
2267c478bd9Sstevel@tonic-gate break;
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate /*
2327c478bd9Sstevel@tonic-gate * Solaris Kerberos: the following prototypes are needed because these are
2337c478bd9Sstevel@tonic-gate * private interfaces that do not have prototypes in any .h
2347c478bd9Sstevel@tonic-gate */
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate extern struct hostent *res_getipnodebyaddr(const void *, size_t, int, int *);
2377c478bd9Sstevel@tonic-gate extern void res_freehostent(struct hostent *);
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate static void
freedomnames(char ** npp)2407c478bd9Sstevel@tonic-gate freedomnames(char **npp)
2417c478bd9Sstevel@tonic-gate {
2427c478bd9Sstevel@tonic-gate char **tpp;
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate if (npp) {
2457c478bd9Sstevel@tonic-gate tpp = npp;
2467c478bd9Sstevel@tonic-gate while (*tpp++) {
2477c478bd9Sstevel@tonic-gate free(*(tpp-1));
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate free(npp);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate * Construct a list of uniq FQDNs of all the net interfaces (except
2557c478bd9Sstevel@tonic-gate * krb5.conf master dups) and return it in arg 'dnames'.
2567c478bd9Sstevel@tonic-gate *
2577c478bd9Sstevel@tonic-gate * On successful return (0), caller must call freedomnames()
2587c478bd9Sstevel@tonic-gate * to free memory.
2597c478bd9Sstevel@tonic-gate */
2607c478bd9Sstevel@tonic-gate static int
getdomnames(krb5_context ctx,char * realm,char *** dnames)2617c478bd9Sstevel@tonic-gate getdomnames(krb5_context ctx, char *realm, char ***dnames)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate krb5_address **addresses = NULL;
2647c478bd9Sstevel@tonic-gate krb5_address *a = NULL;
2657c478bd9Sstevel@tonic-gate struct hostent *hp = NULL;
2667c478bd9Sstevel@tonic-gate int ret, i, result=0, error;
2677c478bd9Sstevel@tonic-gate char **npp = NULL, **tpp=NULL;
2687c478bd9Sstevel@tonic-gate int dup=0, n = 0;
2697c478bd9Sstevel@tonic-gate char *cfhost = NULL; /* krb5 conf file master hostname */
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate if (ret = kadm5_get_master(ctx, realm, &cfhost)) {
2727c478bd9Sstevel@tonic-gate return (ret);
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate ret = krb5_os_localaddr(ctx, &addresses);
2767c478bd9Sstevel@tonic-gate if (ret != 0) {
2777c478bd9Sstevel@tonic-gate if (nofork)
2787c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
2797c478bd9Sstevel@tonic-gate "kadmind: get localaddrs failed: %s",
2807c478bd9Sstevel@tonic-gate error_message(ret));
2817c478bd9Sstevel@tonic-gate result = ret;
2827c478bd9Sstevel@tonic-gate goto err;
2837c478bd9Sstevel@tonic-gate }
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate
2867c478bd9Sstevel@tonic-gate for (i=0; addresses[i]; i++) {
2877c478bd9Sstevel@tonic-gate a = addresses[i];
2887c478bd9Sstevel@tonic-gate hp = res_getipnodebyaddr(a->contents, a->length,
2897c478bd9Sstevel@tonic-gate a->addrtype == ADDRTYPE_INET
2907c478bd9Sstevel@tonic-gate ? AF_INET : AF_INET6,
2917c478bd9Sstevel@tonic-gate &error);
2927c478bd9Sstevel@tonic-gate if (hp != NULL) {
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /* skip master host in krb5.conf */
2957c478bd9Sstevel@tonic-gate if (strcasecmp(cfhost, hp->h_name) == 0) {
2967c478bd9Sstevel@tonic-gate res_freehostent(hp);
2977c478bd9Sstevel@tonic-gate hp = NULL;
2987c478bd9Sstevel@tonic-gate continue;
2997c478bd9Sstevel@tonic-gate }
3007c478bd9Sstevel@tonic-gate
3017c478bd9Sstevel@tonic-gate dup = 0;
3027c478bd9Sstevel@tonic-gate tpp = npp;
3037c478bd9Sstevel@tonic-gate /* skip if hostname already exists in list */
3047c478bd9Sstevel@tonic-gate while (tpp && *tpp++) {
3057c478bd9Sstevel@tonic-gate if (strcasecmp(*(tpp-1), hp->h_name) == 0) {
3067c478bd9Sstevel@tonic-gate dup++;
3077c478bd9Sstevel@tonic-gate break;
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate if (dup) {
3127c478bd9Sstevel@tonic-gate res_freehostent(hp);
3137c478bd9Sstevel@tonic-gate hp = NULL;
3147c478bd9Sstevel@tonic-gate continue;
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate npp = realloc(npp, sizeof(char *) * (n + 2));
3187c478bd9Sstevel@tonic-gate if (!npp) {
3197c478bd9Sstevel@tonic-gate result = ENOMEM;
3207c478bd9Sstevel@tonic-gate goto err;
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate npp[n] = strdup(hp->h_name);
3237c478bd9Sstevel@tonic-gate if (!npp[n]) {
3247c478bd9Sstevel@tonic-gate result = ENOMEM;
3257c478bd9Sstevel@tonic-gate goto err;
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate npp[n+1] = NULL;
3287c478bd9Sstevel@tonic-gate n++;
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate res_freehostent(hp);
3317c478bd9Sstevel@tonic-gate hp = NULL;
3327c478bd9Sstevel@tonic-gate result = 0;
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate #ifdef DEBUG
3387c478bd9Sstevel@tonic-gate printf("getdomnames: n=%d, i=%d, npp=%p\n", n, i, npp);
3397c478bd9Sstevel@tonic-gate tpp = npp;
3407c478bd9Sstevel@tonic-gate while (tpp && *tpp++) {
3417c478bd9Sstevel@tonic-gate printf("tpp=%s\n", *(tpp-1));
3427c478bd9Sstevel@tonic-gate }
3437c478bd9Sstevel@tonic-gate #endif
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate goto out;
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate err:
3487c478bd9Sstevel@tonic-gate if (npp) {
3497c478bd9Sstevel@tonic-gate freedomnames(npp);
3507c478bd9Sstevel@tonic-gate npp = NULL;
3517c478bd9Sstevel@tonic-gate }
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate if (hp) {
3547c478bd9Sstevel@tonic-gate res_freehostent(hp);
3557c478bd9Sstevel@tonic-gate hp = NULL;
3567c478bd9Sstevel@tonic-gate }
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate out:
3597c478bd9Sstevel@tonic-gate if (cfhost) {
3607c478bd9Sstevel@tonic-gate free (cfhost);
3617c478bd9Sstevel@tonic-gate cfhost = NULL;
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate if (addresses) {
3647c478bd9Sstevel@tonic-gate krb5_free_addresses(ctx, addresses);
3657c478bd9Sstevel@tonic-gate addresses = NULL;
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate if (result == 0)
3697c478bd9Sstevel@tonic-gate *dnames = npp;
3707c478bd9Sstevel@tonic-gate
3717c478bd9Sstevel@tonic-gate return (result);
3727c478bd9Sstevel@tonic-gate }
3737c478bd9Sstevel@tonic-gate
3747c478bd9Sstevel@tonic-gate /*
3757c478bd9Sstevel@tonic-gate * Set the rpcsec_gss svc names for all net interfaces.
3767c478bd9Sstevel@tonic-gate */
3777c478bd9Sstevel@tonic-gate static void
set_svc_domnames(char * svcname,char ** dnames,u_int program,u_int version)3787c478bd9Sstevel@tonic-gate set_svc_domnames(char *svcname, char **dnames,
3797c478bd9Sstevel@tonic-gate u_int program, u_int version)
3807c478bd9Sstevel@tonic-gate {
3817c478bd9Sstevel@tonic-gate bool_t ret;
3827c478bd9Sstevel@tonic-gate char **tpp = dnames;
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate if (!tpp)
3857c478bd9Sstevel@tonic-gate return;
3867c478bd9Sstevel@tonic-gate
3877c478bd9Sstevel@tonic-gate while (*tpp++) {
3887c478bd9Sstevel@tonic-gate /* MAX_NAME_LEN from rpc/rpcsec_gss.h */
3897c478bd9Sstevel@tonic-gate char name[MAXHOSTNAMELEN+MAX_NAME_LEN+2] = {0};
3907c478bd9Sstevel@tonic-gate (void) snprintf(name, sizeof(name), "%s@%s",
3917c478bd9Sstevel@tonic-gate svcname, *(tpp-1));
3927c478bd9Sstevel@tonic-gate ret = rpc_gss_set_svc_name(name,
3937c478bd9Sstevel@tonic-gate "kerberos_v5", 0,
3947c478bd9Sstevel@tonic-gate program, version);
3957c478bd9Sstevel@tonic-gate if (nofork && ret)
3967c478bd9Sstevel@tonic-gate (void) fprintf(stderr,
3977c478bd9Sstevel@tonic-gate "rpc_gss_set_svc_name success: %s\n",
3987c478bd9Sstevel@tonic-gate name);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate }
4017c478bd9Sstevel@tonic-gate
402159d09a2SMark Phalan /* XXX yuck. the signal handlers need this */
403159d09a2SMark Phalan static krb5_context context;
4047c478bd9Sstevel@tonic-gate
405159d09a2SMark Phalan static krb5_context hctx;
4067c478bd9Sstevel@tonic-gate
main(int argc,char * argv[])407159d09a2SMark Phalan int main(int argc, char *argv[])
4087c478bd9Sstevel@tonic-gate {
409159d09a2SMark Phalan register SVCXPRT *transp;
4107c478bd9Sstevel@tonic-gate extern char *optarg;
4117c478bd9Sstevel@tonic-gate extern int optind, opterr;
4127c478bd9Sstevel@tonic-gate int ret, rlen, oldnames = 0;
4137c478bd9Sstevel@tonic-gate OM_uint32 OMret, major_status, minor_status;
4147c478bd9Sstevel@tonic-gate char *whoami;
4157c478bd9Sstevel@tonic-gate FILE *acl_file;
4167c478bd9Sstevel@tonic-gate gss_buffer_desc in_buf;
4177c478bd9Sstevel@tonic-gate struct servent *srv;
4187c478bd9Sstevel@tonic-gate struct sockaddr_in addr;
4197c478bd9Sstevel@tonic-gate struct sockaddr_in *sin;
4207c478bd9Sstevel@tonic-gate int s;
421159d09a2SMark Phalan auth_gssapi_name names[6];
422159d09a2SMark Phalan gss_buffer_desc gssbuf;
423159d09a2SMark Phalan gss_OID nt_krb5_name_oid;
4247c478bd9Sstevel@tonic-gate int optchar;
4257c478bd9Sstevel@tonic-gate struct netconfig *nconf;
4267c478bd9Sstevel@tonic-gate void *handlep;
4277c478bd9Sstevel@tonic-gate int fd;
4287c478bd9Sstevel@tonic-gate struct t_info tinfo;
4297c478bd9Sstevel@tonic-gate struct t_bind tbindstr, *tres;
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate struct t_optmgmt req, resp;
4327c478bd9Sstevel@tonic-gate struct opthdr *opt;
4337c478bd9Sstevel@tonic-gate char reqbuf[128];
4347c478bd9Sstevel@tonic-gate struct rlimit rl;
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate char *kiprop_name = NULL; /* IProp svc name */
4377c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx;
4387c478bd9Sstevel@tonic-gate kadm5_server_handle_t handle;
4397c478bd9Sstevel@tonic-gate krb5_context ctx;
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate kadm5_config_params params;
44254925bf6Swillf char **db_args = NULL;
44354925bf6Swillf int db_args_size = 0;
444159d09a2SMark Phalan const char *errmsg;
4457c478bd9Sstevel@tonic-gate char **dnames = NULL;
4467c478bd9Sstevel@tonic-gate int retdn;
44754925bf6Swillf int iprop_supported;
4487c478bd9Sstevel@tonic-gate
4497c64d375Smp153739 /* Solaris Kerberos: Stores additional error messages */
4507c64d375Smp153739 char *emsg = NULL;
4517c64d375Smp153739
4527c64d375Smp153739 /* Solaris Kerberos: Indicates whether loalhost is master or not */
4537c64d375Smp153739 krb5_boolean is_master;
4547c64d375Smp153739
4557c64d375Smp153739 /* Solaris Kerberos: Used for checking acl file */
4567c64d375Smp153739 gss_name_t name;
4577c64d375Smp153739
4587c478bd9Sstevel@tonic-gate /* This is OID value the Krb5_Name NameType */
4597c478bd9Sstevel@tonic-gate gssbuf.value = "{1 2 840 113554 1 2 2 1}";
4607c478bd9Sstevel@tonic-gate gssbuf.length = strlen(gssbuf.value);
461159d09a2SMark Phalan major_status = gss_str_to_oid(&minor_status, &gssbuf, &nt_krb5_name_oid);
4627c478bd9Sstevel@tonic-gate if (major_status != GSS_S_COMPLETE) {
4637c478bd9Sstevel@tonic-gate fprintf(stderr,
4647c478bd9Sstevel@tonic-gate gettext("Couldn't create KRB5 Name NameType OID\n"));
4657c478bd9Sstevel@tonic-gate display_status("str_to_oid", major_status, minor_status);
4667c478bd9Sstevel@tonic-gate exit(1);
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate
469159d09a2SMark Phalan names[0].name = names[1].name = names[2].name = names[3].name = NULL;
470159d09a2SMark Phalan names[4].name = names[5].name =NULL;
471159d09a2SMark Phalan names[0].type = names[1].type = names[2].type = names[3].type =
4727c478bd9Sstevel@tonic-gate (gss_OID) nt_krb5_name_oid;
473159d09a2SMark Phalan names[4].type = names[5].type = (gss_OID) nt_krb5_name_oid;
4747c478bd9Sstevel@tonic-gate
475159d09a2SMark Phalan #ifdef PURIFY
476159d09a2SMark Phalan purify_start_batch();
477159d09a2SMark Phalan #endif /* PURIFY */
4787c478bd9Sstevel@tonic-gate whoami = (strrchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
4837c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
4847c478bd9Sstevel@tonic-gate #endif
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
4877c478bd9Sstevel@tonic-gate
4887c478bd9Sstevel@tonic-gate nofork = 0;
4897c478bd9Sstevel@tonic-gate
4907c478bd9Sstevel@tonic-gate memset((char *) ¶ms, 0, sizeof(params));
4917c478bd9Sstevel@tonic-gate
49254925bf6Swillf while ((optchar = getopt(argc, argv, "r:mdp:x:")) != EOF) {
4937c478bd9Sstevel@tonic-gate switch (optchar) {
4947c478bd9Sstevel@tonic-gate case 'r':
4957c478bd9Sstevel@tonic-gate if (!optarg)
4967c478bd9Sstevel@tonic-gate usage();
4977c478bd9Sstevel@tonic-gate params.realm = optarg;
4987c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_REALM;
4997c478bd9Sstevel@tonic-gate break;
5007c478bd9Sstevel@tonic-gate case 'm':
5017c478bd9Sstevel@tonic-gate params.mkey_from_kbd = 1;
5027c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
5037c478bd9Sstevel@tonic-gate break;
5047c478bd9Sstevel@tonic-gate case 'd':
5057c478bd9Sstevel@tonic-gate nofork = 1;
5067c478bd9Sstevel@tonic-gate break;
5077c478bd9Sstevel@tonic-gate case 'p':
5087c478bd9Sstevel@tonic-gate if (!optarg)
5097c478bd9Sstevel@tonic-gate usage();
5107c478bd9Sstevel@tonic-gate params.kadmind_port = atoi(optarg);
5117c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_KADMIND_PORT;
5127c478bd9Sstevel@tonic-gate break;
51354925bf6Swillf case 'x':
51454925bf6Swillf if (!optarg)
51554925bf6Swillf usage();
51654925bf6Swillf db_args_size++;
51754925bf6Swillf {
51854925bf6Swillf char **temp = realloc( db_args,
51954925bf6Swillf sizeof(char*) * (db_args_size+1)); /* one for NULL */
52054925bf6Swillf if( temp == NULL )
52154925bf6Swillf {
52254925bf6Swillf fprintf(stderr, gettext("%s: cannot initialize. Not enough memory\n"),
52354925bf6Swillf whoami);
52454925bf6Swillf exit(1);
52554925bf6Swillf }
52654925bf6Swillf db_args = temp;
52754925bf6Swillf }
52854925bf6Swillf db_args[db_args_size-1] = optarg;
52954925bf6Swillf db_args[db_args_size] = NULL;
53054925bf6Swillf break;
5317c478bd9Sstevel@tonic-gate case '?':
5327c478bd9Sstevel@tonic-gate default:
5337c478bd9Sstevel@tonic-gate usage();
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
5397c478bd9Sstevel@tonic-gate rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, FD_SETSIZE);
540004388ebScasper (void) setrlimit(RLIMIT_NOFILE, &rl);
541004388ebScasper (void) enable_extended_FILE_stdio(-1, -1);
5427c478bd9Sstevel@tonic-gate }
5437c478bd9Sstevel@tonic-gate
544159d09a2SMark Phalan if ((ret = kadm5_init_krb5_context(&context))) {
5457c478bd9Sstevel@tonic-gate fprintf(stderr,
5467c478bd9Sstevel@tonic-gate gettext("%s: %s while initializing context, aborting\n"),
5477c478bd9Sstevel@tonic-gate whoami, error_message(ret));
5487c478bd9Sstevel@tonic-gate exit(1);
5497c478bd9Sstevel@tonic-gate }
5507c478bd9Sstevel@tonic-gate
5517c478bd9Sstevel@tonic-gate krb5_klog_init(context, "admin_server", whoami, 1);
552159d09a2SMark Phalan
553159d09a2SMark Phalan /* Solaris Kerberos */
554159d09a2SMark Phalan if((ret = kadm5_init2("kadmind", NULL,
555159d09a2SMark Phalan NULL, ¶ms,
556159d09a2SMark Phalan KADM5_STRUCT_VERSION,
557159d09a2SMark Phalan KADM5_API_VERSION_2,
558159d09a2SMark Phalan db_args,
559159d09a2SMark Phalan &global_server_handle,
560159d09a2SMark Phalan &emsg)) != KADM5_OK) {
561159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR,
562159d09a2SMark Phalan gettext("%s while initializing, aborting"),
563159d09a2SMark Phalan (emsg ? emsg : error_message(ret)));
564159d09a2SMark Phalan fprintf(stderr,
565159d09a2SMark Phalan gettext("%s: %s while initializing, aborting\n"),
566159d09a2SMark Phalan whoami, (emsg ? emsg : error_message(ret)));
567159d09a2SMark Phalan if (emsg)
568159d09a2SMark Phalan free(emsg);
569159d09a2SMark Phalan krb5_klog_close(context);
57056a424ccSmp153739 exit(1);
57156a424ccSmp153739 }
572159d09a2SMark Phalan
573159d09a2SMark Phalan if( db_args )
574159d09a2SMark Phalan {
575159d09a2SMark Phalan free(db_args), db_args=NULL;
576159d09a2SMark Phalan }
577159d09a2SMark Phalan
578159d09a2SMark Phalan if ((ret = kadm5_get_config_params(context, 1, ¶ms,
579159d09a2SMark Phalan ¶ms))) {
580159d09a2SMark Phalan const char *e_txt = krb5_get_error_message (context, ret);
581159d09a2SMark Phalan /* Solaris Kerberos: Remove double "whoami" */
582159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, gettext("%s while initializing, aborting"),
583159d09a2SMark Phalan e_txt);
584159d09a2SMark Phalan fprintf(stderr,
585159d09a2SMark Phalan gettext("%s: %s while initializing, aborting\n"),
586159d09a2SMark Phalan whoami, e_txt);
587159d09a2SMark Phalan kadm5_destroy(global_server_handle);
588159d09a2SMark Phalan krb5_klog_close(context);
589159d09a2SMark Phalan exit(1);
590159d09a2SMark Phalan }
591159d09a2SMark Phalan
592159d09a2SMark Phalan #define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_ACL_FILE)
593159d09a2SMark Phalan
594159d09a2SMark Phalan if ((params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
595159d09a2SMark Phalan /* Solaris Kerberos: Keep error messages consistent */
596159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR,
597159d09a2SMark Phalan gettext("Missing required configuration values (%lx)"
598159d09a2SMark Phalan "while initializing, aborting"),
599159d09a2SMark Phalan (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS);
600159d09a2SMark Phalan fprintf(stderr,
601159d09a2SMark Phalan gettext("%s: Missing required configuration values "
602159d09a2SMark Phalan "(%lx) while initializing, aborting\n"), whoami,
603159d09a2SMark Phalan (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS);
604159d09a2SMark Phalan krb5_klog_close(context);
605159d09a2SMark Phalan kadm5_destroy(global_server_handle);
606159d09a2SMark Phalan exit(1);
607159d09a2SMark Phalan }
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate /*
6107c478bd9Sstevel@tonic-gate * When using the Horowitz/IETF protocol for
6117c478bd9Sstevel@tonic-gate * password changing, the default port is 464
6127c478bd9Sstevel@tonic-gate * (officially recognized by IANA)
6137c478bd9Sstevel@tonic-gate *
6147c478bd9Sstevel@tonic-gate * DEFAULT_KPASSWD_PORT -> 464
6157c478bd9Sstevel@tonic-gate */
6167c478bd9Sstevel@tonic-gate chgpw_params.kpasswd_port = DEFAULT_KPASSWD_PORT;
6177c478bd9Sstevel@tonic-gate chgpw_params.mask |= KADM5_CONFIG_KPASSWD_PORT;
6187c478bd9Sstevel@tonic-gate chgpw_params.kpasswd_protocol = KRB5_CHGPWD_CHANGEPW_V2;
6197c478bd9Sstevel@tonic-gate chgpw_params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL;
6207c478bd9Sstevel@tonic-gate
621159d09a2SMark Phalan if (ret = kadm5_get_config_params(context, 1, &chgpw_params,
6227c478bd9Sstevel@tonic-gate &chgpw_params)) {
6237c64d375Smp153739 /* Solaris Kerberos: Remove double "whoami" */
6247c64d375Smp153739 krb5_klog_syslog(LOG_ERR, gettext("%s while initializing,"
6257c64d375Smp153739 " aborting"), error_message(ret));
6267c478bd9Sstevel@tonic-gate fprintf(stderr,
6277c478bd9Sstevel@tonic-gate gettext("%s: %s while initializing, aborting\n"),
6287c478bd9Sstevel@tonic-gate whoami, error_message(ret));
6297c478bd9Sstevel@tonic-gate krb5_klog_close(context);
6307c478bd9Sstevel@tonic-gate exit(1);
6317c478bd9Sstevel@tonic-gate }
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate /*
6347c478bd9Sstevel@tonic-gate * We now setup the socket and bind() to port 464, so that
6357c478bd9Sstevel@tonic-gate * kadmind can now listen to and process change-pwd requests
6367c478bd9Sstevel@tonic-gate * from non-Solaris Kerberos V5 clients such as Microsoft,
6377c478bd9Sstevel@tonic-gate * MIT, AIX, HP etc
6387c478bd9Sstevel@tonic-gate */
6397c478bd9Sstevel@tonic-gate if ((schpw = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
640159d09a2SMark Phalan const char *e_txt = krb5_get_error_message (context, ret);
6417c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR,
642159d09a2SMark Phalan gettext( "Cannot create simple " "chpw socket: %s"),
643159d09a2SMark Phalan e_txt);
644159d09a2SMark Phalan fprintf(stderr, gettext("Cannot create simple chpw socket: %s"),
645159d09a2SMark Phalan e_txt);
646159d09a2SMark Phalan kadm5_destroy(global_server_handle);
6477c478bd9Sstevel@tonic-gate krb5_klog_close(context);
6487c478bd9Sstevel@tonic-gate exit(1);
6497c478bd9Sstevel@tonic-gate }
6507c64d375Smp153739
6517c64d375Smp153739 /* Solaris Kerberos: Ensure that kadmind is only run on a master kdc */
6527c64d375Smp153739 if (ret = kadm5_is_master(context, params.realm, &is_master)){
6537c64d375Smp153739 krb5_klog_syslog(LOG_ERR,
6547c64d375Smp153739 gettext("Failed to determine whether host is master "
6557c64d375Smp153739 "KDC for realm %s: %s"), params.realm,
6567c64d375Smp153739 error_message(ret));
6577c64d375Smp153739 fprintf(stderr,
6587c64d375Smp153739 gettext("%s: Failed to determine whether host is master "
6597c64d375Smp153739 "KDC for realm %s: %s\n"), whoami, params.realm,
6607c64d375Smp153739 error_message(ret));
6617c64d375Smp153739 krb5_klog_close(context);
6627c64d375Smp153739 exit(1);
6637c64d375Smp153739 }
6647c64d375Smp153739
6657c64d375Smp153739 if (is_master == FALSE) {
6667c64d375Smp153739 char *master = NULL;
6677c64d375Smp153739 kadm5_get_master(context, params.realm, &master);
6687c64d375Smp153739
6697c64d375Smp153739 krb5_klog_syslog(LOG_ERR,
6707c64d375Smp153739 gettext("%s can only be run on the master KDC, %s, for "
6717c64d375Smp153739 "realm %s"), whoami, master ? master : "unknown",
6727c64d375Smp153739 params.realm);
6737c64d375Smp153739 fprintf(stderr,
6747c64d375Smp153739 gettext("%s: %s can only be run on the master KDC, %s, for "
6757c64d375Smp153739 "realm %s\n"), whoami, whoami, master ? master: "unknown",
6767c64d375Smp153739 params.realm);
6777c64d375Smp153739 krb5_klog_close(context);
6787c64d375Smp153739 exit(1);
6797c64d375Smp153739 }
6807c64d375Smp153739
6817c478bd9Sstevel@tonic-gate memset((char *) &addr, 0, sizeof (struct sockaddr_in));
6827c478bd9Sstevel@tonic-gate addr.sin_family = AF_INET;
6837c478bd9Sstevel@tonic-gate addr.sin_addr.s_addr = INADDR_ANY;
6847c478bd9Sstevel@tonic-gate l_port = addr.sin_port = htons(params.kadmind_port);
6857c478bd9Sstevel@tonic-gate sin = &addr;
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate if ((handlep = setnetconfig()) == (void *) NULL) {
6887c478bd9Sstevel@tonic-gate (void) krb5_klog_syslog(LOG_ERR,
6897c478bd9Sstevel@tonic-gate gettext("cannot get any transport information"));
6907c478bd9Sstevel@tonic-gate krb5_klog_close(context);
6917c478bd9Sstevel@tonic-gate exit(1);
6927c478bd9Sstevel@tonic-gate }
693159d09a2SMark Phalan
6947c478bd9Sstevel@tonic-gate while (nconf = getnetconfig(handlep)) {
6957c478bd9Sstevel@tonic-gate if ((nconf->nc_semantics == NC_TPI_COTS_ORD) &&
6967c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
6977c478bd9Sstevel@tonic-gate (strcmp(nconf->nc_proto, NC_TCP) == 0))
6987c478bd9Sstevel@tonic-gate break;
6997c478bd9Sstevel@tonic-gate }
7007c478bd9Sstevel@tonic-gate
7017c478bd9Sstevel@tonic-gate if (nconf == (struct netconfig *) NULL) {
7027c478bd9Sstevel@tonic-gate (void) endnetconfig(handlep);
7037c478bd9Sstevel@tonic-gate krb5_klog_close(context);
7047c478bd9Sstevel@tonic-gate exit(1);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
7077c478bd9Sstevel@tonic-gate if (fd == -1) {
7087c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR,
7097c478bd9Sstevel@tonic-gate gettext("unable to open connection for ADMIN server"));
7107c478bd9Sstevel@tonic-gate krb5_klog_close(context);
7117c478bd9Sstevel@tonic-gate exit(1);
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate /* LINTED */
7147c478bd9Sstevel@tonic-gate opt = (struct opthdr *) reqbuf;
7157c478bd9Sstevel@tonic-gate opt->level = SOL_SOCKET;
7167c478bd9Sstevel@tonic-gate opt->name = SO_REUSEADDR;
7177c478bd9Sstevel@tonic-gate opt->len = sizeof (int);
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate /*
7207c478bd9Sstevel@tonic-gate * The option value is "1". This will allow the server to restart
7217c478bd9Sstevel@tonic-gate * whilst the previous process is cleaning up after itself in a
7227c478bd9Sstevel@tonic-gate * FIN_WAIT_2 or TIME_WAIT state. If another process is started
7237c478bd9Sstevel@tonic-gate * outside of smf(5) then bind will fail anyway, which is what we want.
7247c478bd9Sstevel@tonic-gate */
7257c478bd9Sstevel@tonic-gate reqbuf[sizeof (struct opthdr)] = 1;
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate req.flags = T_NEGOTIATE;
7287c478bd9Sstevel@tonic-gate req.opt.len = sizeof (struct opthdr) + opt->len;
7297c478bd9Sstevel@tonic-gate req.opt.buf = (char *) opt;
7307c478bd9Sstevel@tonic-gate
7317c478bd9Sstevel@tonic-gate resp.flags = 0;
7327c478bd9Sstevel@tonic-gate resp.opt.buf = reqbuf;
7337c478bd9Sstevel@tonic-gate resp.opt.maxlen = sizeof (reqbuf);
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) {
7367c478bd9Sstevel@tonic-gate t_error("t_optmgmt");
7377c478bd9Sstevel@tonic-gate exit(1);
7387c478bd9Sstevel@tonic-gate }
7397c478bd9Sstevel@tonic-gate /* Transform addr to netbuf */
7407c478bd9Sstevel@tonic-gate
7417c478bd9Sstevel@tonic-gate tres = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR);
7427c478bd9Sstevel@tonic-gate if (tres == NULL) {
7437c478bd9Sstevel@tonic-gate (void) t_close(fd);
7447c478bd9Sstevel@tonic-gate (void) krb5_klog_syslog(LOG_ERR,
7457c478bd9Sstevel@tonic-gate gettext("cannot allocate netbuf"));
7467c478bd9Sstevel@tonic-gate krb5_klog_close(context);
7477c478bd9Sstevel@tonic-gate exit(1);
7487c478bd9Sstevel@tonic-gate }
7497c478bd9Sstevel@tonic-gate tbindstr.qlen = 8;
7507c478bd9Sstevel@tonic-gate tbindstr.addr.buf = (char *) sin;
7517c478bd9Sstevel@tonic-gate tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr);
7527c478bd9Sstevel@tonic-gate sin = (struct sockaddr_in *) tbindstr.addr.buf;
7537c478bd9Sstevel@tonic-gate /* SUNWresync121 XXX (void) memset(&addr, 0, sizeof(addr)); */
7547c478bd9Sstevel@tonic-gate
7557c478bd9Sstevel@tonic-gate if (t_bind(fd, &tbindstr, tres) < 0) {
7567c478bd9Sstevel@tonic-gate int oerrno = errno;
757159d09a2SMark Phalan const char *e_txt = krb5_get_error_message (context, errno);
7587c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot bind socket.\n"), whoami);
759159d09a2SMark Phalan fprintf(stderr, gettext("bind: %s\n"), e_txt);
7607c478bd9Sstevel@tonic-gate errno = oerrno;
761159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, gettext("Cannot bind socket: %s"), e_txt);
7627c478bd9Sstevel@tonic-gate if(oerrno == EADDRINUSE) {
7637c478bd9Sstevel@tonic-gate char *w = strrchr(whoami, '/');
7647c478bd9Sstevel@tonic-gate if (w) {
7657c478bd9Sstevel@tonic-gate w++;
766159d09a2SMark Phalan }
767159d09a2SMark Phalan else {
7687c478bd9Sstevel@tonic-gate w = whoami;
7697c478bd9Sstevel@tonic-gate }
7707c478bd9Sstevel@tonic-gate fprintf(stderr, gettext(
771159d09a2SMark Phalan "This probably means that another %s process is already\n"
772159d09a2SMark Phalan "running, or that another program is using the server port (number %d)\n"
773159d09a2SMark Phalan "after being assigned it by the RPC portmap daemon. If another\n"
774159d09a2SMark Phalan "%s is already running, you should kill it before\n"
775159d09a2SMark Phalan "restarting the server. If, on the other hand, another program is\n"
776159d09a2SMark Phalan "using the server port, you should kill it before running\n"
777159d09a2SMark Phalan "%s, and ensure that the conflict does not occur in the\n"
778159d09a2SMark Phalan "future by making sure that %s is started on reboot\n"
779159d09a2SMark Phalan "before portmap.\n"), w, ntohs(addr.sin_port), w, w, w);
780159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, gettext("Check for already-running %s or for "
7817c478bd9Sstevel@tonic-gate "another process using port %d"), w,
7827c478bd9Sstevel@tonic-gate htons(addr.sin_port));
7837c478bd9Sstevel@tonic-gate }
784159d09a2SMark Phalan kadm5_destroy(global_server_handle);
785159d09a2SMark Phalan krb5_klog_close(context);
786159d09a2SMark Phalan exit(1);
787159d09a2SMark Phalan }
788159d09a2SMark Phalan memset(&addr, 0, sizeof(addr));
789159d09a2SMark Phalan addr.sin_family = AF_INET;
790159d09a2SMark Phalan addr.sin_addr.s_addr = INADDR_ANY;
791159d09a2SMark Phalan
792159d09a2SMark Phalan addr.sin_port = htons(chgpw_params.kpasswd_port);
793159d09a2SMark Phalan
794159d09a2SMark Phalan if (bind(schpw, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
795159d09a2SMark Phalan char portbuf[32];
796159d09a2SMark Phalan int oerrno = errno;
797159d09a2SMark Phalan const char *e_txt = krb5_get_error_message (context, errno);
798159d09a2SMark Phalan fprintf(stderr, gettext("%s: Cannot bind socket.\n"), whoami);
799159d09a2SMark Phalan fprintf(stderr, gettext("bind: %s\n"), e_txt);
800159d09a2SMark Phalan errno = oerrno;
801159d09a2SMark Phalan (void) snprintf(portbuf, sizeof (portbuf), "%d", ntohs(addr.sin_port));
802159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, gettext("cannot bind simple chpw socket: %s"),
803159d09a2SMark Phalan e_txt);
804159d09a2SMark Phalan if(oerrno == EADDRINUSE) {
805159d09a2SMark Phalan char *w = strrchr(whoami, '/');
806159d09a2SMark Phalan if (w) {
807159d09a2SMark Phalan w++;
808159d09a2SMark Phalan }
809159d09a2SMark Phalan else {
810159d09a2SMark Phalan w = whoami;
811159d09a2SMark Phalan }
812159d09a2SMark Phalan fprintf(stderr, gettext(
813159d09a2SMark Phalan "This probably means that another %s process is already\n"
814159d09a2SMark Phalan "running, or that another program is using the server port (number %d).\n"
815159d09a2SMark Phalan "If another %s is already running, you should kill it before\n"
816159d09a2SMark Phalan "restarting the server.\n"),
817159d09a2SMark Phalan w, ntohs(addr.sin_port), w);
818159d09a2SMark Phalan }
8197c478bd9Sstevel@tonic-gate krb5_klog_close(context);
8207c478bd9Sstevel@tonic-gate exit(1);
8217c478bd9Sstevel@tonic-gate }
822159d09a2SMark Phalan
8237c478bd9Sstevel@tonic-gate transp = svc_tli_create(fd, nconf, NULL, 0, 0);
8247c478bd9Sstevel@tonic-gate (void) t_free((char *) tres, T_BIND);
825159d09a2SMark Phalan (void) endnetconfig(handlep);
8267c478bd9Sstevel@tonic-gate if(transp == NULL) {
827159d09a2SMark Phalan fprintf(stderr, gettext("%s: Cannot create RPC service.\n"), whoami);
8287c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR, gettext("Cannot create RPC service: %m"));
829159d09a2SMark Phalan kadm5_destroy(global_server_handle);
8307c478bd9Sstevel@tonic-gate krb5_klog_close(context);
8317c478bd9Sstevel@tonic-gate exit(1);
8327c478bd9Sstevel@tonic-gate }
8337c478bd9Sstevel@tonic-gate if(!svc_register(transp, KADM, KADMVERS, kadm_1, 0)) {
834159d09a2SMark Phalan fprintf(stderr, gettext("%s: Cannot register RPC service.\n"), whoami);
835159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, gettext("Cannot register RPC service, failing."));
836159d09a2SMark Phalan kadm5_destroy(global_server_handle);
8377c478bd9Sstevel@tonic-gate krb5_klog_close(context);
8387c478bd9Sstevel@tonic-gate exit(1);
8397c478bd9Sstevel@tonic-gate }
8407c478bd9Sstevel@tonic-gate
8417c478bd9Sstevel@tonic-gate
842a0709436Smp153739 /* Solaris Kerberos:
843a0709436Smp153739 * The only service principals which matter here are
844a0709436Smp153739 * -> names[0].name (kadmin/<fqdn>)
845a0709436Smp153739 * -> names[1].name (changepw/<fqdn>)
846a0709436Smp153739 * KADM5_ADMIN_SERVICE_P, KADM5_CHANGEPW_SERVICE_P,
847a0709436Smp153739 * OVSEC_KADM_ADMIN_SERVICE_P, OVSEC_KADM_CHANGEPW_SERVICE_P
848a0709436Smp153739 * are all legacy service princs and calls to rpc_gss_set_svc_name()
849a0709436Smp153739 * using these principals will always fail as they are not host
850a0709436Smp153739 * based principals.
851a0709436Smp153739 */
852a0709436Smp153739
8537c64d375Smp153739 if (ret = kadm5_get_adm_host_srv_name(context, params.realm,
8547c64d375Smp153739 &names[0].name)) {
8557c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR,
8567c64d375Smp153739 gettext("Cannot get host based service name for admin "
8577c64d375Smp153739 "principal in realm %s: %s"), params.realm,
8587c64d375Smp153739 error_message(ret));
8597c478bd9Sstevel@tonic-gate fprintf(stderr,
8607c64d375Smp153739 gettext("%s: Cannot get host based service name for admin "
8617c64d375Smp153739 "principal in realm %s: %s\n"), whoami, params.realm,
8627c64d375Smp153739 error_message(ret));
8637c478bd9Sstevel@tonic-gate krb5_klog_close(context);
8647c478bd9Sstevel@tonic-gate exit(1);
8657c478bd9Sstevel@tonic-gate }
8667c478bd9Sstevel@tonic-gate
8677c64d375Smp153739 if (ret = kadm5_get_cpw_host_srv_name(context, params.realm,
8687c64d375Smp153739 &names[1].name)) {
8697c64d375Smp153739 krb5_klog_syslog(LOG_ERR,
8707c64d375Smp153739 gettext("Cannot get host based service name for changepw "
8717c64d375Smp153739 "principal in realm %s: %s"), params.realm,
8727c64d375Smp153739 error_message(ret));
8737c64d375Smp153739 fprintf(stderr,
8747c64d375Smp153739 gettext("%s: Cannot get host based service name for "
8757c64d375Smp153739 "changepw principal in realm %s: %s\n"), whoami, params.realm,
8767c64d375Smp153739 error_message(ret));
8777c64d375Smp153739 krb5_klog_close(context);
8787c64d375Smp153739 exit(1);
8797c64d375Smp153739 }
8807c64d375Smp153739 names[2].name = KADM5_ADMIN_SERVICE_P;
8817c64d375Smp153739 names[3].name = KADM5_CHANGEPW_SERVICE_P;
8827c64d375Smp153739 names[4].name = OVSEC_KADM_ADMIN_SERVICE_P;
8837c64d375Smp153739 names[5].name = OVSEC_KADM_CHANGEPW_SERVICE_P;
8847c478bd9Sstevel@tonic-gate
885159d09a2SMark Phalan if (names[0].name == NULL || names[1].name == NULL ||
886159d09a2SMark Phalan names[2].name == NULL || names[3].name == NULL ||
887159d09a2SMark Phalan names[4].name == NULL || names[5].name == NULL) {
888159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR,
889159d09a2SMark Phalan gettext("Cannot initialize GSS-API authentication, "
890159d09a2SMark Phalan "failing."));
891159d09a2SMark Phalan fprintf(stderr,
892159d09a2SMark Phalan gettext("%s: Cannot initialize "
893159d09a2SMark Phalan "GSS-API authentication.\n"),
894159d09a2SMark Phalan whoami);
895159d09a2SMark Phalan krb5_klog_close(context);
896159d09a2SMark Phalan exit(1);
897159d09a2SMark Phalan }
898159d09a2SMark Phalan
8997c478bd9Sstevel@tonic-gate /*
900159d09a2SMark Phalan * Go through some contortions to point gssapi at a kdb keytab.
901159d09a2SMark Phalan * This prevents kadmind from needing to use an actual file-based
902159d09a2SMark Phalan * keytab.
903159d09a2SMark Phalan */
904159d09a2SMark Phalan /* XXX extract kadm5's krb5_context */
905159d09a2SMark Phalan hctx = ((kadm5_server_handle_t)global_server_handle)->context;
906159d09a2SMark Phalan /* Set ktkdb's internal krb5_context. */
907159d09a2SMark Phalan ret = krb5_ktkdb_set_context(hctx);
908159d09a2SMark Phalan if (ret) {
909159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, "Can't set kdb keytab's internal context.");
910159d09a2SMark Phalan goto kterr;
911159d09a2SMark Phalan }
912159d09a2SMark Phalan /* Solaris Kerberos */
913159d09a2SMark Phalan ret = krb5_db_set_mkey(hctx, &((kadm5_server_handle_t)global_server_handle)->master_keyblock);
914159d09a2SMark Phalan if (ret) {
915159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, "Can't set master key for kdb keytab.");
916159d09a2SMark Phalan goto kterr;
917159d09a2SMark Phalan }
918159d09a2SMark Phalan ret = krb5_kt_register(context, &krb5_kt_kdb_ops);
919159d09a2SMark Phalan if (ret) {
920159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, "Can't register kdb keytab.");
921159d09a2SMark Phalan goto kterr;
922159d09a2SMark Phalan }
923159d09a2SMark Phalan /* Tell gssapi about the kdb keytab. */
924159d09a2SMark Phalan ret = krb5_gss_register_acceptor_identity("KDB:");
925159d09a2SMark Phalan if (ret) {
926159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, "Can't register acceptor keytab.");
927159d09a2SMark Phalan goto kterr;
928159d09a2SMark Phalan }
929159d09a2SMark Phalan kterr:
930159d09a2SMark Phalan if (ret) {
931159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, "%s", krb5_get_error_message (context, ret));
932159d09a2SMark Phalan fprintf(stderr, "%s: Can't set up keytab for RPC.\n", whoami);
933159d09a2SMark Phalan kadm5_destroy(global_server_handle);
934159d09a2SMark Phalan krb5_klog_close(context);
935159d09a2SMark Phalan exit(1);
936159d09a2SMark Phalan }
937159d09a2SMark Phalan
938159d09a2SMark Phalan /*
939159d09a2SMark Phalan * Try to acquire creds for the old OV services as well as the
940159d09a2SMark Phalan * new names, but if that fails just fall back on the new names.
9417c478bd9Sstevel@tonic-gate */
9427c478bd9Sstevel@tonic-gate
9437c478bd9Sstevel@tonic-gate if (rpc_gss_set_svc_name(names[5].name,
9447c478bd9Sstevel@tonic-gate "kerberos_v5", 0, KADM, KADMVERS) &&
9457c478bd9Sstevel@tonic-gate rpc_gss_set_svc_name(names[4].name,
9467c478bd9Sstevel@tonic-gate "kerberos_v5", 0, KADM, KADMVERS))
9477c478bd9Sstevel@tonic-gate oldnames++;
9487c478bd9Sstevel@tonic-gate if (rpc_gss_set_svc_name(names[3].name,
9497c478bd9Sstevel@tonic-gate "kerberos_v5", 0, KADM, KADMVERS))
9507c478bd9Sstevel@tonic-gate oldnames++;
9517c478bd9Sstevel@tonic-gate if (rpc_gss_set_svc_name(names[2].name,
9527c478bd9Sstevel@tonic-gate "kerberos_v5", 0, KADM, KADMVERS))
9537c478bd9Sstevel@tonic-gate oldnames++;
954a0709436Smp153739
955a0709436Smp153739 /* If rpc_gss_set_svc_name() fails for either kadmin/<fqdn> or
956a0709436Smp153739 * for changepw/<fqdn> then try to determine if this is caused
957a0709436Smp153739 * by a missing keytab file or entry. If so, log it and continue.
958a0709436Smp153739 */
9597c478bd9Sstevel@tonic-gate if (rpc_gss_set_svc_name(names[0].name,
9607c478bd9Sstevel@tonic-gate "kerberos_v5", 0, KADM, KADMVERS))
9617c478bd9Sstevel@tonic-gate oldnames++;
962159d09a2SMark Phalan
9637c478bd9Sstevel@tonic-gate if (rpc_gss_set_svc_name(names[1].name,
9647c478bd9Sstevel@tonic-gate "kerberos_v5", 0, KADM, KADMVERS))
9657c478bd9Sstevel@tonic-gate oldnames++;
9667c478bd9Sstevel@tonic-gate
9677c478bd9Sstevel@tonic-gate retdn = getdomnames(context, params.realm, &dnames);
9687c478bd9Sstevel@tonic-gate if (retdn == 0 && dnames) {
9697c478bd9Sstevel@tonic-gate /*
9707c478bd9Sstevel@tonic-gate * Multi-homed KDCs sometimes may need to set svc names
9717c478bd9Sstevel@tonic-gate * for multiple net interfaces so we set them for
9727c478bd9Sstevel@tonic-gate * all interfaces just in case.
9737c478bd9Sstevel@tonic-gate */
9747c478bd9Sstevel@tonic-gate set_svc_domnames(KADM5_ADMIN_HOST_SERVICE,
9757c478bd9Sstevel@tonic-gate dnames, KADM, KADMVERS);
9767c478bd9Sstevel@tonic-gate set_svc_domnames(KADM5_CHANGEPW_HOST_SERVICE,
9777c478bd9Sstevel@tonic-gate dnames, KADM, KADMVERS);
9787c478bd9Sstevel@tonic-gate }
9797c478bd9Sstevel@tonic-gate
9807c478bd9Sstevel@tonic-gate /* if set_names succeeded, this will too */
9817c478bd9Sstevel@tonic-gate in_buf.value = names[1].name;
9827c478bd9Sstevel@tonic-gate in_buf.length = strlen(names[1].name) + 1;
9837c478bd9Sstevel@tonic-gate (void) gss_import_name(&OMret, &in_buf, (gss_OID) nt_krb5_name_oid,
9847c478bd9Sstevel@tonic-gate &gss_changepw_name);
9857c478bd9Sstevel@tonic-gate if (oldnames) {
9867c478bd9Sstevel@tonic-gate in_buf.value = names[3].name;
9877c478bd9Sstevel@tonic-gate in_buf.length = strlen(names[3].name) + 1;
988159d09a2SMark Phalan (void) gss_import_name(&OMret, &in_buf, (gss_OID) nt_krb5_name_oid,
9897c478bd9Sstevel@tonic-gate &gss_oldchangepw_name);
9907c478bd9Sstevel@tonic-gate }
991159d09a2SMark Phalan
992159d09a2SMark Phalan if ((ret = kadm5int_acl_init(context, 0, params.acl_file))) {
993159d09a2SMark Phalan errmsg = krb5_get_error_message (context, ret);
9947c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR, gettext("Cannot initialize acl file: %s"),
995159d09a2SMark Phalan errmsg);
9967c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("%s: Cannot initialize acl file: %s\n"),
997159d09a2SMark Phalan whoami, errmsg);
998159d09a2SMark Phalan kadm5_destroy(global_server_handle);
9997c478bd9Sstevel@tonic-gate krb5_klog_close(context);
10007c478bd9Sstevel@tonic-gate exit(1);
10017c478bd9Sstevel@tonic-gate }
10027c64d375Smp153739
10037c64d375Smp153739 /*
10047c64d375Smp153739 * Solaris Kerberos:
1005d15b0992SMark Phalan * Warn if the acl file contains an entry for a principal matching the
1006d15b0992SMark Phalan * default (unconfigured) acl rule.
10077c64d375Smp153739 */
1008d15b0992SMark Phalan gssbuf.length = strlen("x/admin@___default_realm___");
1009d15b0992SMark Phalan gssbuf.value = "x/admin@___default_realm___";
1010d15b0992SMark Phalan /* Use any value as the first component - 'x' in this case */
1011d15b0992SMark Phalan if (gss_import_name(&minor_status, &gssbuf, GSS_C_NT_USER_NAME, &name)
1012d15b0992SMark Phalan == GSS_S_COMPLETE) {
1013d15b0992SMark Phalan if (kadm5int_acl_check(context, name, ACL_MODIFY, NULL, NULL)) {
10147c64d375Smp153739 krb5_klog_syslog(LOG_WARNING,
1015d15b0992SMark Phalan gettext("acls may not be properly configured: "
1016d15b0992SMark Phalan "found an acl matching \"___default_realm___\" in "
1017d15b0992SMark Phalan " %s"), params.acl_file);
10187c64d375Smp153739 (void) fprintf(stderr, gettext("%s: Warning: "
1019d15b0992SMark Phalan "acls may not be properly configured: found an acl "
1020d15b0992SMark Phalan "matching \"___default_realm___\" in %s\n"),
1021d15b0992SMark Phalan whoami, params.acl_file);
10227c64d375Smp153739 }
10237c64d375Smp153739 (void) gss_release_name(&minor_status, &name);
10247c64d375Smp153739 }
10257c64d375Smp153739 gssbuf.value = NULL;
10267c64d375Smp153739 gssbuf.length = 0;
10277c64d375Smp153739
10287c64d375Smp153739 /*
10297c64d375Smp153739 * Solaris Kerberos:
10307c64d375Smp153739 * List the logs (FILE, STDERR, etc) which are currently being
10317c64d375Smp153739 * logged to and print to stderr. Useful when trying to
10327c64d375Smp153739 * track down a failure via SMF.
10337c64d375Smp153739 */
10347c64d375Smp153739 if (ret = krb5_klog_list_logs(whoami)) {
10357c64d375Smp153739 fprintf(stderr, gettext("%s: %s while listing logs\n"),
10367c64d375Smp153739 whoami, error_message(ret));
10377c64d375Smp153739 krb5_klog_syslog(LOG_ERR, gettext("%s while listing logs"),
10387c64d375Smp153739 error_message(ret));
10397c64d375Smp153739 }
10407c64d375Smp153739
10413441f6a1Ssemery if (!nofork && (ret = daemon(0, 0))) {
10423441f6a1Ssemery ret = errno;
1043159d09a2SMark Phalan errmsg = krb5_get_error_message (context, ret);
10443441f6a1Ssemery krb5_klog_syslog(LOG_ERR,
1045159d09a2SMark Phalan gettext("Cannot detach from tty: %s"), errmsg);
10463441f6a1Ssemery fprintf(stderr, gettext("%s: Cannot detach from tty: %s\n"),
1047159d09a2SMark Phalan whoami, errmsg);
1048159d09a2SMark Phalan kadm5_destroy(global_server_handle);
10493441f6a1Ssemery krb5_klog_close(context);
10503441f6a1Ssemery exit(1);
10513441f6a1Ssemery }
10523441f6a1Ssemery
1053159d09a2SMark Phalan /* SUNW14resync */
1054159d09a2SMark Phalan #if 0
1055159d09a2SMark Phalan krb5_klog_syslog(LOG_INFO, "Seeding random number generator");
1056159d09a2SMark Phalan ret = krb5_c_random_os_entropy(context, 1, NULL);
1057159d09a2SMark Phalan if (ret) {
1058159d09a2SMark Phalan krb5_klog_syslog(LOG_ERR, "Error getting random seed: %s, aborting",
1059159d09a2SMark Phalan krb5_get_error_message(context, ret));
1060159d09a2SMark Phalan kadm5_destroy(global_server_handle);
1061159d09a2SMark Phalan krb5_klog_close(context);
1062159d09a2SMark Phalan exit(1);
106354925bf6Swillf }
1064159d09a2SMark Phalan #endif
1065159d09a2SMark Phalan
106654925bf6Swillf
10677c478bd9Sstevel@tonic-gate handle = global_server_handle;
10687c478bd9Sstevel@tonic-gate ctx = handle->context;
106954925bf6Swillf if (params.iprop_enabled == TRUE) {
107054925bf6Swillf if (ret = krb5_db_supports_iprop(ctx, &iprop_supported)) {
107154925bf6Swillf fprintf(stderr,
107254925bf6Swillf gettext("%s: %s while trying to determine if KDB "
107354925bf6Swillf "plugin supports iprop\n"), whoami,
107454925bf6Swillf error_message(ret));
107554925bf6Swillf krb5_klog_syslog(LOG_ERR,
107654925bf6Swillf gettext("%s while trying to determine if KDB "
107754925bf6Swillf "plugin supports iprop"), error_message(ret));
107854925bf6Swillf krb5_klog_close(ctx);
107954925bf6Swillf exit(1);
108054925bf6Swillf }
108154925bf6Swillf
108254925bf6Swillf if (!iprop_supported) {
108354925bf6Swillf fprintf(stderr,
108454925bf6Swillf gettext("%s: Warning, current KDB "
108554925bf6Swillf "plugin does not support iprop, continuing "
108654925bf6Swillf "with iprop disabled\n"), whoami);
108754925bf6Swillf krb5_klog_syslog(LOG_WARNING,
108878894ffcSmp153739 gettext("Warning, current KDB "
108954925bf6Swillf "plugin does not support iprop, continuing "
109054925bf6Swillf "with iprop disabled"));
109154925bf6Swillf
109254925bf6Swillf ulog_set_role(ctx, IPROP_NULL);
109354925bf6Swillf } else
10947c478bd9Sstevel@tonic-gate ulog_set_role(ctx, IPROP_MASTER);
109554925bf6Swillf } else
10967c478bd9Sstevel@tonic-gate ulog_set_role(ctx, IPROP_NULL);
10977c478bd9Sstevel@tonic-gate
10987c478bd9Sstevel@tonic-gate log_ctx = ctx->kdblog_context;
10997c478bd9Sstevel@tonic-gate
11007c478bd9Sstevel@tonic-gate if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) {
11017c478bd9Sstevel@tonic-gate /*
11027c478bd9Sstevel@tonic-gate * IProp is enabled, so let's map in the update log
11037c478bd9Sstevel@tonic-gate * and setup the service.
11047c478bd9Sstevel@tonic-gate */
11057c478bd9Sstevel@tonic-gate if (ret = ulog_map(ctx, ¶ms, FKADMIND)) {
11067c478bd9Sstevel@tonic-gate fprintf(stderr,
11077c478bd9Sstevel@tonic-gate gettext("%s: %s while mapping update log "
11087c478bd9Sstevel@tonic-gate "(`%s.ulog')\n"), whoami, error_message(ret),
11097c478bd9Sstevel@tonic-gate params.dbname);
11107c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR,
11117c478bd9Sstevel@tonic-gate gettext("%s while mapping update log "
11127c478bd9Sstevel@tonic-gate "(`%s.ulog')"), error_message(ret),
11137c478bd9Sstevel@tonic-gate params.dbname);
11147c478bd9Sstevel@tonic-gate krb5_klog_close(ctx);
11157c478bd9Sstevel@tonic-gate exit(1);
11167c478bd9Sstevel@tonic-gate }
11177c478bd9Sstevel@tonic-gate
11187c478bd9Sstevel@tonic-gate
11197c478bd9Sstevel@tonic-gate if (nofork)
11207c478bd9Sstevel@tonic-gate fprintf(stderr,
11217c478bd9Sstevel@tonic-gate "%s: create IPROP svc (PROG=%d, VERS=%d)\n",
11227c478bd9Sstevel@tonic-gate whoami, KRB5_IPROP_PROG, KRB5_IPROP_VERS);
11237c478bd9Sstevel@tonic-gate
11247c478bd9Sstevel@tonic-gate if (!svc_create(krb5_iprop_prog_1,
11257c478bd9Sstevel@tonic-gate KRB5_IPROP_PROG, KRB5_IPROP_VERS,
11267c478bd9Sstevel@tonic-gate "circuit_v")) {
11277c478bd9Sstevel@tonic-gate fprintf(stderr,
11287c478bd9Sstevel@tonic-gate gettext("%s: Cannot create IProp RPC service (PROG=%d, VERS=%d)\n"),
11297c478bd9Sstevel@tonic-gate whoami,
11307c478bd9Sstevel@tonic-gate KRB5_IPROP_PROG, KRB5_IPROP_VERS);
11317c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR,
11327c478bd9Sstevel@tonic-gate gettext("Cannot create IProp RPC service (PROG=%d, VERS=%d), failing."),
11337c478bd9Sstevel@tonic-gate KRB5_IPROP_PROG, KRB5_IPROP_VERS);
11347c478bd9Sstevel@tonic-gate krb5_klog_close(ctx);
11357c478bd9Sstevel@tonic-gate exit(1);
11367c478bd9Sstevel@tonic-gate }
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate if (ret = kiprop_get_adm_host_srv_name(ctx,
11397c478bd9Sstevel@tonic-gate params.realm,
11407c478bd9Sstevel@tonic-gate &kiprop_name)) {
11417c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR,
11427c478bd9Sstevel@tonic-gate gettext("%s while getting IProp svc name, failing"),
11437c478bd9Sstevel@tonic-gate error_message(ret));
11447c478bd9Sstevel@tonic-gate fprintf(stderr,
11457c478bd9Sstevel@tonic-gate gettext("%s: %s while getting IProp svc name, failing\n"),
11467c478bd9Sstevel@tonic-gate whoami, error_message(ret));
11477c478bd9Sstevel@tonic-gate krb5_klog_close(ctx);
11487c478bd9Sstevel@tonic-gate exit(1);
11497c478bd9Sstevel@tonic-gate }
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate if (!rpc_gss_set_svc_name(kiprop_name, "kerberos_v5", 0,
11527c478bd9Sstevel@tonic-gate KRB5_IPROP_PROG, KRB5_IPROP_VERS)) {
11537c478bd9Sstevel@tonic-gate rpc_gss_error_t err;
11547c478bd9Sstevel@tonic-gate (void) rpc_gss_get_error(&err);
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_ERR,
11577c478bd9Sstevel@tonic-gate gettext("Unable to set RPCSEC_GSS service name (`%s'), failing."),
11587c478bd9Sstevel@tonic-gate kiprop_name ? kiprop_name : "<null>");
11597c478bd9Sstevel@tonic-gate fprintf(stderr,
11607c478bd9Sstevel@tonic-gate gettext("%s: Unable to set RPCSEC_GSS service name (`%s'), failing.\n"),
11617c478bd9Sstevel@tonic-gate whoami,
11627c478bd9Sstevel@tonic-gate kiprop_name ? kiprop_name : "<null>");
11637c478bd9Sstevel@tonic-gate
11647c478bd9Sstevel@tonic-gate if (nofork) {
11657c478bd9Sstevel@tonic-gate fprintf(stderr,
11667c478bd9Sstevel@tonic-gate "%s: set svc name (rpcsec err=%d, sys err=%d)\n",
11677c478bd9Sstevel@tonic-gate whoami,
11687c478bd9Sstevel@tonic-gate err.rpc_gss_error,
11697c478bd9Sstevel@tonic-gate err.system_error);
11707c478bd9Sstevel@tonic-gate }
11717c478bd9Sstevel@tonic-gate
11727c478bd9Sstevel@tonic-gate exit(1);
11737c478bd9Sstevel@tonic-gate }
11747c478bd9Sstevel@tonic-gate free(kiprop_name);
11757c478bd9Sstevel@tonic-gate
11767c478bd9Sstevel@tonic-gate if (retdn == 0 && dnames) {
11777c478bd9Sstevel@tonic-gate set_svc_domnames(KADM5_KIPROP_HOST_SERVICE,
11787c478bd9Sstevel@tonic-gate dnames,
11797c478bd9Sstevel@tonic-gate KRB5_IPROP_PROG, KRB5_IPROP_VERS);
11807c478bd9Sstevel@tonic-gate }
11817c478bd9Sstevel@tonic-gate
11827c8de920Smp153739 } else {
11837c8de920Smp153739 if (!oldnames) {
11847c8de920Smp153739 /* rpc_gss_set_svc_name failed for both kadmin/<fqdn> and
11857c8de920Smp153739 * changepw/<fqdn>.
11867c8de920Smp153739 */
11877c8de920Smp153739 krb5_klog_syslog(LOG_ERR,
11887c8de920Smp153739 gettext("Unable to set RPCSEC_GSS service names "
11897c8de920Smp153739 "('%s, %s')"),
11907c8de920Smp153739 names[0].name, names[1].name);
11917c8de920Smp153739 fprintf(stderr,
11927c8de920Smp153739 gettext("%s: Unable to set RPCSEC_GSS service names "
11937c8de920Smp153739 "('%s, %s')\n"),
11947c8de920Smp153739 whoami,
11957c8de920Smp153739 names[0].name, names[1].name);
11967c8de920Smp153739 krb5_klog_close(context);
11977c8de920Smp153739 exit(1);
11987c8de920Smp153739 }
11997c478bd9Sstevel@tonic-gate }
12007c478bd9Sstevel@tonic-gate
12017c478bd9Sstevel@tonic-gate if (dnames)
12027c478bd9Sstevel@tonic-gate freedomnames(dnames);
12037c478bd9Sstevel@tonic-gate
12047c478bd9Sstevel@tonic-gate setup_signal_handlers(log_ctx->iproprole);
12057c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_INFO, gettext("starting"));
12067c478bd9Sstevel@tonic-gate if (nofork)
12077c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: starting...\n", whoami);
12087c478bd9Sstevel@tonic-gate
12097c478bd9Sstevel@tonic-gate
12107c478bd9Sstevel@tonic-gate /*
12117c478bd9Sstevel@tonic-gate * We now call our own customized async event processing
12127c478bd9Sstevel@tonic-gate * function kadm_svc_run(), as opposed to svc_run() earlier,
12137c478bd9Sstevel@tonic-gate * since this enables kadmind to also listen-to/process
12147c478bd9Sstevel@tonic-gate * non-RPCSEC_GSS based change-pwd requests apart from the
12157c478bd9Sstevel@tonic-gate * regular, RPCSEC_GSS kpasswd requests from Solaris Krb5 clients.
12167c478bd9Sstevel@tonic-gate */
12177c478bd9Sstevel@tonic-gate kadm_svc_run();
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_INFO, gettext("finished, exiting"));
12207c478bd9Sstevel@tonic-gate kadm5_destroy(global_server_handle);
12217c478bd9Sstevel@tonic-gate t_close(fd);
12227c478bd9Sstevel@tonic-gate krb5_klog_close(context);
12237c478bd9Sstevel@tonic-gate exit(0);
12247c478bd9Sstevel@tonic-gate }
12257c478bd9Sstevel@tonic-gate
12267c478bd9Sstevel@tonic-gate /*
12277c478bd9Sstevel@tonic-gate * Function: kadm_svc_run
12287c478bd9Sstevel@tonic-gate *
12297c478bd9Sstevel@tonic-gate * Purpose: modified version of sunrpc svc_run.
12307c478bd9Sstevel@tonic-gate * which closes the database every TIMEOUT seconds.
12317c478bd9Sstevel@tonic-gate *
12327c478bd9Sstevel@tonic-gate * Arguments:
12337c478bd9Sstevel@tonic-gate * Requires:
12347c478bd9Sstevel@tonic-gate * Effects:
12357c478bd9Sstevel@tonic-gate * Modifies:
12367c478bd9Sstevel@tonic-gate */
1237159d09a2SMark Phalan
kadm_svc_run(void)1238159d09a2SMark Phalan void kadm_svc_run(void)
12397c478bd9Sstevel@tonic-gate {
12407c478bd9Sstevel@tonic-gate struct pollfd *rfd = 0;
12417c478bd9Sstevel@tonic-gate struct timeval timeout;
12427c478bd9Sstevel@tonic-gate int pollret;
12437c478bd9Sstevel@tonic-gate int nfds = 0;
12447c478bd9Sstevel@tonic-gate int i;
12457c478bd9Sstevel@tonic-gate
12467c478bd9Sstevel@tonic-gate while(signal_request_exit == 0) {
12477c478bd9Sstevel@tonic-gate timeout.tv_sec = TIMEOUT;
12487c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
12497c478bd9Sstevel@tonic-gate
12507c478bd9Sstevel@tonic-gate if (nfds != svc_max_pollfd) {
12517c478bd9Sstevel@tonic-gate rfd = realloc(rfd, sizeof (pollfd_t) * svc_max_pollfd);
12527c478bd9Sstevel@tonic-gate nfds = svc_max_pollfd;
12537c478bd9Sstevel@tonic-gate }
12547c478bd9Sstevel@tonic-gate
12557c478bd9Sstevel@tonic-gate (void) memcpy(rfd, svc_pollfd,
12567c478bd9Sstevel@tonic-gate sizeof (pollfd_t) * svc_max_pollfd);
12577c478bd9Sstevel@tonic-gate
12587c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) {
12597c478bd9Sstevel@tonic-gate if (rfd[i].fd == -1) {
12607c478bd9Sstevel@tonic-gate rfd[i].fd = schpw;
12617c478bd9Sstevel@tonic-gate rfd[i].events = POLLIN;
12627c478bd9Sstevel@tonic-gate break;
12637c478bd9Sstevel@tonic-gate }
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate
12667c478bd9Sstevel@tonic-gate switch(pollret = poll(rfd, nfds,
12677c478bd9Sstevel@tonic-gate __rpc_timeval_to_msec(&timeout))) {
12687c478bd9Sstevel@tonic-gate case -1:
12697c478bd9Sstevel@tonic-gate if(errno == EINTR)
12707c478bd9Sstevel@tonic-gate continue;
12717c478bd9Sstevel@tonic-gate perror("poll");
12727c478bd9Sstevel@tonic-gate return;
12737c478bd9Sstevel@tonic-gate case 0:
12747c478bd9Sstevel@tonic-gate continue;
12757c478bd9Sstevel@tonic-gate default:
12767c478bd9Sstevel@tonic-gate for (i = 0; i < nfds; i++) {
12777c478bd9Sstevel@tonic-gate if (rfd[i].revents & POLLIN) {
12787c478bd9Sstevel@tonic-gate if (rfd[i].fd == schpw)
12797c478bd9Sstevel@tonic-gate handle_chpw(context, schpw,
12807c478bd9Sstevel@tonic-gate global_server_handle,
12817c478bd9Sstevel@tonic-gate &chgpw_params);
12827c478bd9Sstevel@tonic-gate else
12837c478bd9Sstevel@tonic-gate svc_getreq_poll(rfd, pollret);
12847c478bd9Sstevel@tonic-gate break;
12857c478bd9Sstevel@tonic-gate } else {
12867c478bd9Sstevel@tonic-gate if (i == (nfds - 1))
12877c478bd9Sstevel@tonic-gate perror("poll");
12887c478bd9Sstevel@tonic-gate }
12897c478bd9Sstevel@tonic-gate }
12907c478bd9Sstevel@tonic-gate break;
12917c478bd9Sstevel@tonic-gate }
12927c478bd9Sstevel@tonic-gate }
12937c478bd9Sstevel@tonic-gate }
12947c478bd9Sstevel@tonic-gate
12957c478bd9Sstevel@tonic-gate
12967c478bd9Sstevel@tonic-gate /*
12977c478bd9Sstevel@tonic-gate * Function: setup_signal_handlers
12987c478bd9Sstevel@tonic-gate *
1299*4e2a441bSPeter Shoults * Purpose: Setup signal handling functions with either
1300*4e2a441bSPeter Shoults * System V's signal() or POSIX_SIGNALS.
13017c478bd9Sstevel@tonic-gate */
setup_signal_handlers(iprop_role iproprole)13027c478bd9Sstevel@tonic-gate void setup_signal_handlers(iprop_role iproprole) {
1303*4e2a441bSPeter Shoults #ifdef POSIX_SIGNALS
1304*4e2a441bSPeter Shoults (void) sigemptyset(&s_action.sa_mask);
1305*4e2a441bSPeter Shoults s_action.sa_handler = request_exit;
1306*4e2a441bSPeter Shoults (void) sigaction(SIGINT, &s_action, (struct sigaction *) NULL);
1307*4e2a441bSPeter Shoults (void) sigaction(SIGTERM, &s_action, (struct sigaction *) NULL);
1308*4e2a441bSPeter Shoults (void) sigaction(SIGQUIT, &s_action, (struct sigaction *) NULL);
1309*4e2a441bSPeter Shoults s_action.sa_handler = sig_pipe;
1310*4e2a441bSPeter Shoults (void) sigaction(SIGPIPE, &s_action, (struct sigaction *) NULL);
1311*4e2a441bSPeter Shoults
1312*4e2a441bSPeter Shoults /*
1313*4e2a441bSPeter Shoults * IProp will fork for a full-resync, we don't want to
1314*4e2a441bSPeter Shoults * wait on it and we don't want the living dead procs either.
1315*4e2a441bSPeter Shoults */
1316*4e2a441bSPeter Shoults if (iproprole == IPROP_MASTER) {
1317*4e2a441bSPeter Shoults s_action.sa_handler = SIG_IGN;
1318*4e2a441bSPeter Shoults (void) sigaction(SIGCHLD, &s_action, (struct sigaction *) NULL);
1319*4e2a441bSPeter Shoults }
1320*4e2a441bSPeter Shoults #else
1321159d09a2SMark Phalan signal(SIGINT, request_exit);
1322159d09a2SMark Phalan signal(SIGTERM, request_exit);
1323159d09a2SMark Phalan signal(SIGQUIT, request_exit);
13247c478bd9Sstevel@tonic-gate signal(SIGPIPE, sig_pipe);
13257c478bd9Sstevel@tonic-gate
13267c478bd9Sstevel@tonic-gate /*
13277c478bd9Sstevel@tonic-gate * IProp will fork for a full-resync, we don't want to
13287c478bd9Sstevel@tonic-gate * wait on it and we don't want the living dead procs either.
13297c478bd9Sstevel@tonic-gate */
13307c478bd9Sstevel@tonic-gate if (iproprole == IPROP_MASTER)
13317c478bd9Sstevel@tonic-gate (void) signal(SIGCHLD, SIG_IGN);
13327c478bd9Sstevel@tonic-gate
1333*4e2a441bSPeter Shoults #endif /* POSIX_SIGNALS */
13347c478bd9Sstevel@tonic-gate return;
13357c478bd9Sstevel@tonic-gate }
13367c478bd9Sstevel@tonic-gate
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate /*
1339159d09a2SMark Phalan * Function: request_exit
13407c478bd9Sstevel@tonic-gate *
13417c478bd9Sstevel@tonic-gate * Purpose: sets flags saying the server got a signal and that it
1342159d09a2SMark Phalan * should exit when convient.
13437c478bd9Sstevel@tonic-gate *
1344159d09a2SMark Phalan * Arguments:
1345159d09a2SMark Phalan * Requires:
13467c478bd9Sstevel@tonic-gate * Effects:
1347159d09a2SMark Phalan * modifies signal_request_exit which ideally makes the server exit
13487c478bd9Sstevel@tonic-gate * at some point.
13497c478bd9Sstevel@tonic-gate *
13507c478bd9Sstevel@tonic-gate * Modifies:
1351159d09a2SMark Phalan * signal_request_exit
13527c478bd9Sstevel@tonic-gate */
1353159d09a2SMark Phalan
request_exit(int signum)1354159d09a2SMark Phalan void request_exit(int signum)
13557c478bd9Sstevel@tonic-gate {
13567c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_NOTICE, gettext("Got signal to request exit"));
13577c478bd9Sstevel@tonic-gate signal_request_exit = 1;
13587c478bd9Sstevel@tonic-gate return;
13597c478bd9Sstevel@tonic-gate }
13607c478bd9Sstevel@tonic-gate
13617c478bd9Sstevel@tonic-gate /*
13627c478bd9Sstevel@tonic-gate * Function: sig_pipe
13637c478bd9Sstevel@tonic-gate *
13647c478bd9Sstevel@tonic-gate * Purpose: SIGPIPE handler
13657c478bd9Sstevel@tonic-gate *
1366159d09a2SMark Phalan * Effects: krb5_klog_syslogs a message that a SIGPIPE occurred and returns,
13677c478bd9Sstevel@tonic-gate * thus causing the read() or write() to fail and, presumable, the RPC
13687c478bd9Sstevel@tonic-gate * to recover. Otherwise, the process aborts.
13697c478bd9Sstevel@tonic-gate */
sig_pipe(int unused)1370159d09a2SMark Phalan void sig_pipe(int unused)
13717c478bd9Sstevel@tonic-gate {
1372*4e2a441bSPeter Shoults #ifndef POSIX_SIGNALS
1373*4e2a441bSPeter Shoults signal(SIGPIPE, sig_pipe);
1374*4e2a441bSPeter Shoults #endif /* POSIX_SIGNALS */
13757c478bd9Sstevel@tonic-gate krb5_klog_syslog(LOG_NOTICE, gettext("Warning: Received a SIGPIPE; "
13767c478bd9Sstevel@tonic-gate "probably a client aborted. Continuing."));
1377159d09a2SMark Phalan return;
1378a0709436Smp153739 }
1379a0709436Smp153739
1380