1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate * 5*7c478bd9Sstevel@tonic-gate * All rights reserved. 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may require 8*7c478bd9Sstevel@tonic-gate * a specific license from the United States Government. It is the 9*7c478bd9Sstevel@tonic-gate * responsibility of any person or organization contemplating export to 10*7c478bd9Sstevel@tonic-gate * obtain such a license before exporting. 11*7c478bd9Sstevel@tonic-gate * 12*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 14*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 15*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 16*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 17*7c478bd9Sstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining 18*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 19*7c478bd9Sstevel@tonic-gate * permission. FundsXpress makes no representations about the suitability of 20*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 21*7c478bd9Sstevel@tonic-gate * or implied warranty. 22*7c478bd9Sstevel@tonic-gate * 23*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25*7c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26*7c478bd9Sstevel@tonic-gate */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate /* 31*7c478bd9Sstevel@tonic-gate * slave/kpropd.c 32*7c478bd9Sstevel@tonic-gate * 33*7c478bd9Sstevel@tonic-gate * Copyright 1990,1991 by the Massachusetts Institute of Technology. 34*7c478bd9Sstevel@tonic-gate * All Rights Reserved. 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 37*7c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 38*7c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 39*7c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 40*7c478bd9Sstevel@tonic-gate * 41*7c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 42*7c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 43*7c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 44*7c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 45*7c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 46*7c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 47*7c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 48*7c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 49*7c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 50*7c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 51*7c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 52*7c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 53*7c478bd9Sstevel@tonic-gate * or implied warranty. 54*7c478bd9Sstevel@tonic-gate * 55*7c478bd9Sstevel@tonic-gate * 56*7c478bd9Sstevel@tonic-gate * XXX We need to modify the protocol so that an acknowledge is set 57*7c478bd9Sstevel@tonic-gate * after each block, instead after the entire series is sent over. 58*7c478bd9Sstevel@tonic-gate * The reason for this is so that error packets can get interpreted 59*7c478bd9Sstevel@tonic-gate * right away. If you don't do this, the sender may never get the 60*7c478bd9Sstevel@tonic-gate * error packet, because it will die an EPIPE trying to complete the 61*7c478bd9Sstevel@tonic-gate * write... 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate #include <stdio.h> 65*7c478bd9Sstevel@tonic-gate #include <ctype.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 67*7c478bd9Sstevel@tonic-gate #include <signal.h> 68*7c478bd9Sstevel@tonic-gate #include <string.h> 69*7c478bd9Sstevel@tonic-gate #ifndef POSIX_TERMIOS 70*7c478bd9Sstevel@tonic-gate #include <sgtty.h> 71*7c478bd9Sstevel@tonic-gate #endif 72*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 73*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 74*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 75*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 76*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 77*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 78*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 79*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 80*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 81*7c478bd9Sstevel@tonic-gate #include <netdb.h> 82*7c478bd9Sstevel@tonic-gate #include <syslog.h> 83*7c478bd9Sstevel@tonic-gate #include <libintl.h> 84*7c478bd9Sstevel@tonic-gate #include <locale.h> 85*7c478bd9Sstevel@tonic-gate #include <k5-int.h> 86*7c478bd9Sstevel@tonic-gate #include <socket-utils.h> 87*7c478bd9Sstevel@tonic-gate #include "com_err.h" 88*7c478bd9Sstevel@tonic-gate #include <errno.h> 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate #include "kprop.h" 91*7c478bd9Sstevel@tonic-gate #include <iprop_hdr.h> 92*7c478bd9Sstevel@tonic-gate #include "iprop.h" 93*7c478bd9Sstevel@tonic-gate #include <kadm5/admin.h> 94*7c478bd9Sstevel@tonic-gate #include <kdb/kdb_log.h> 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate #define SYSLOG_CLASS LOG_DAEMON 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate char *poll_time = NULL; 99*7c478bd9Sstevel@tonic-gate char *def_realm = NULL; 100*7c478bd9Sstevel@tonic-gate boolean_t runonce = B_FALSE; 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate /* 103*7c478bd9Sstevel@tonic-gate * This struct simulates the use of _kadm5_server_handle_t 104*7c478bd9Sstevel@tonic-gate */ 105*7c478bd9Sstevel@tonic-gate typedef struct _kadm5_iprop_handle_t { 106*7c478bd9Sstevel@tonic-gate krb5_ui_4 magic_number; 107*7c478bd9Sstevel@tonic-gate krb5_ui_4 struct_version; 108*7c478bd9Sstevel@tonic-gate krb5_ui_4 api_version; 109*7c478bd9Sstevel@tonic-gate char *cache_name; 110*7c478bd9Sstevel@tonic-gate int destroy_cache; 111*7c478bd9Sstevel@tonic-gate CLIENT *clnt; 112*7c478bd9Sstevel@tonic-gate krb5_context context; 113*7c478bd9Sstevel@tonic-gate kadm5_config_params params; 114*7c478bd9Sstevel@tonic-gate struct _kadm5_iprop_handle_t *lhandle; 115*7c478bd9Sstevel@tonic-gate } *kadm5_iprop_handle_t; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate static char *kprop_version = KPROP_PROT_VERSION; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate char *progname; 120*7c478bd9Sstevel@tonic-gate int debug = 0; 121*7c478bd9Sstevel@tonic-gate char *srvtab = 0; 122*7c478bd9Sstevel@tonic-gate int standalone = 0; 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate krb5_principal server; /* This is our server principal name */ 125*7c478bd9Sstevel@tonic-gate krb5_principal client; /* This is who we're talking to */ 126*7c478bd9Sstevel@tonic-gate krb5_context kpropd_context; 127*7c478bd9Sstevel@tonic-gate krb5_auth_context auth_context; 128*7c478bd9Sstevel@tonic-gate char *realm = NULL; /* Our realm */ 129*7c478bd9Sstevel@tonic-gate char *file = KPROPD_DEFAULT_FILE; 130*7c478bd9Sstevel@tonic-gate char *temp_file_name; 131*7c478bd9Sstevel@tonic-gate char *kdb5_util = KPROPD_DEFAULT_KDB5_UTIL; 132*7c478bd9Sstevel@tonic-gate char *kerb_database = NULL; 133*7c478bd9Sstevel@tonic-gate char *acl_file_name = KPROPD_ACL_FILE; 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate int database_fd; 136*7c478bd9Sstevel@tonic-gate krb5_address sender_addr; 137*7c478bd9Sstevel@tonic-gate krb5_address receiver_addr; 138*7c478bd9Sstevel@tonic-gate short port = 0; 139*7c478bd9Sstevel@tonic-gate 140*7c478bd9Sstevel@tonic-gate void PRS 141*7c478bd9Sstevel@tonic-gate (int, char**); 142*7c478bd9Sstevel@tonic-gate int do_standalone 143*7c478bd9Sstevel@tonic-gate (iprop_role iproprole); 144*7c478bd9Sstevel@tonic-gate void doit 145*7c478bd9Sstevel@tonic-gate (int); 146*7c478bd9Sstevel@tonic-gate krb5_error_code do_iprop(kdb_log_context *log_ctx); 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate void kerberos_authenticate 149*7c478bd9Sstevel@tonic-gate (krb5_context, 150*7c478bd9Sstevel@tonic-gate int, 151*7c478bd9Sstevel@tonic-gate krb5_principal *, 152*7c478bd9Sstevel@tonic-gate krb5_enctype *, 153*7c478bd9Sstevel@tonic-gate struct sockaddr_storage); 154*7c478bd9Sstevel@tonic-gate 155*7c478bd9Sstevel@tonic-gate krb5_boolean authorized_principal 156*7c478bd9Sstevel@tonic-gate (krb5_context, 157*7c478bd9Sstevel@tonic-gate krb5_principal, 158*7c478bd9Sstevel@tonic-gate krb5_enctype); 159*7c478bd9Sstevel@tonic-gate void recv_database 160*7c478bd9Sstevel@tonic-gate (krb5_context, 161*7c478bd9Sstevel@tonic-gate int, 162*7c478bd9Sstevel@tonic-gate int, 163*7c478bd9Sstevel@tonic-gate krb5_data *); 164*7c478bd9Sstevel@tonic-gate void load_database 165*7c478bd9Sstevel@tonic-gate (krb5_context, 166*7c478bd9Sstevel@tonic-gate char *, 167*7c478bd9Sstevel@tonic-gate char *); 168*7c478bd9Sstevel@tonic-gate void send_error 169*7c478bd9Sstevel@tonic-gate (krb5_context, 170*7c478bd9Sstevel@tonic-gate int, 171*7c478bd9Sstevel@tonic-gate krb5_error_code, 172*7c478bd9Sstevel@tonic-gate char *); 173*7c478bd9Sstevel@tonic-gate void recv_error 174*7c478bd9Sstevel@tonic-gate (krb5_context, 175*7c478bd9Sstevel@tonic-gate krb5_data *); 176*7c478bd9Sstevel@tonic-gate int convert_polltime 177*7c478bd9Sstevel@tonic-gate (char *); 178*7c478bd9Sstevel@tonic-gate unsigned int backoff_from_master 179*7c478bd9Sstevel@tonic-gate (int *); 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate static void usage() 182*7c478bd9Sstevel@tonic-gate { 183*7c478bd9Sstevel@tonic-gate fprintf(stderr, 184*7c478bd9Sstevel@tonic-gate gettext("\nUsage: %s\n"), /* progname may be a long pathname */ 185*7c478bd9Sstevel@tonic-gate progname); 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate fprintf(stderr, 188*7c478bd9Sstevel@tonic-gate gettext("\t[-r realm] [-s srvtab] [-dS] [-f slave_file]\n")); 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate fprintf(stderr, 191*7c478bd9Sstevel@tonic-gate gettext("\t[-F kerberos_db_file ] [-p kdb5_util_pathname]\n")); 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("\t[-P port] [-a acl_file]\n")); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate exit(1); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate int 199*7c478bd9Sstevel@tonic-gate main(argc, argv) 200*7c478bd9Sstevel@tonic-gate int argc; 201*7c478bd9Sstevel@tonic-gate char **argv; 202*7c478bd9Sstevel@tonic-gate { 203*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 204*7c478bd9Sstevel@tonic-gate int ret = 0; 205*7c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate PRS(argc, argv); 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate log_ctx = kpropd_context->kdblog_context; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) { 212*7c478bd9Sstevel@tonic-gate /* 213*7c478bd9Sstevel@tonic-gate * We wanna do iprop ! 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate retval = do_iprop(log_ctx); 216*7c478bd9Sstevel@tonic-gate if (retval) { 217*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 218*7c478bd9Sstevel@tonic-gate gettext("do_iprop failed.\n")); 219*7c478bd9Sstevel@tonic-gate exit(1); 220*7c478bd9Sstevel@tonic-gate } 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate } else { 223*7c478bd9Sstevel@tonic-gate if (standalone) 224*7c478bd9Sstevel@tonic-gate ret = do_standalone(IPROP_NULL); 225*7c478bd9Sstevel@tonic-gate else 226*7c478bd9Sstevel@tonic-gate doit(0); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate exit(ret); 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate int do_standalone(iprop_role iproprole) 233*7c478bd9Sstevel@tonic-gate { 234*7c478bd9Sstevel@tonic-gate struct linger linger; 235*7c478bd9Sstevel@tonic-gate struct servent *sp; 236*7c478bd9Sstevel@tonic-gate int finet, fromlen, s; 237*7c478bd9Sstevel@tonic-gate int on = 1; 238*7c478bd9Sstevel@tonic-gate int ret, status = 0; 239*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 sin6 = { AF_INET6 }; 240*7c478bd9Sstevel@tonic-gate int sin6_size = sizeof (sin6); 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* listen for either ipv4 or ipv6 */ 243*7c478bd9Sstevel@tonic-gate finet = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); 244*7c478bd9Sstevel@tonic-gate if (finet < 0 ) { 245*7c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while obtaining socket")); 246*7c478bd9Sstevel@tonic-gate exit(1); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate if(!port) { 250*7c478bd9Sstevel@tonic-gate sp = getservbyname(KPROP_SERVICE, "tcp"); 251*7c478bd9Sstevel@tonic-gate if (sp == NULL) { 252*7c478bd9Sstevel@tonic-gate com_err(progname, 0, gettext("%s/tcp: unknown service"), 253*7c478bd9Sstevel@tonic-gate KPROP_SERVICE); 254*7c478bd9Sstevel@tonic-gate exit(1); 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate sin6.sin6_port = sp->s_port; 257*7c478bd9Sstevel@tonic-gate } else 258*7c478bd9Sstevel@tonic-gate sin6.sin6_port = port; 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate /* 261*7c478bd9Sstevel@tonic-gate * We need to close the socket immediately if iprop is enabled, 262*7c478bd9Sstevel@tonic-gate * since back-to-back full resyncs are possible, so we do not 263*7c478bd9Sstevel@tonic-gate * linger around for too long 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate if (iproprole == IPROP_SLAVE) { 266*7c478bd9Sstevel@tonic-gate if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR, 267*7c478bd9Sstevel@tonic-gate (char *)&on, sizeof(on)) < 0) 268*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 269*7c478bd9Sstevel@tonic-gate gettext("in setsockopt(SO_REUSEADDR)")); 270*7c478bd9Sstevel@tonic-gate linger.l_onoff = 1; 271*7c478bd9Sstevel@tonic-gate linger.l_linger = 2; 272*7c478bd9Sstevel@tonic-gate if (setsockopt(finet, SOL_SOCKET, SO_LINGER, 273*7c478bd9Sstevel@tonic-gate (void *)&linger, sizeof(linger)) < 0) 274*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 275*7c478bd9Sstevel@tonic-gate gettext("in setsockopt(SO_LINGER)")); 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate if ((ret = bind(finet, (struct sockaddr *)&sin6, sizeof(sin6))) < 0) { 278*7c478bd9Sstevel@tonic-gate if (debug) { 279*7c478bd9Sstevel@tonic-gate on = 1; 280*7c478bd9Sstevel@tonic-gate fprintf(stderr, 281*7c478bd9Sstevel@tonic-gate gettext("%s: attempting to rebind socket " 282*7c478bd9Sstevel@tonic-gate "with SO_REUSEADDR\n"), progname); 283*7c478bd9Sstevel@tonic-gate if (setsockopt(finet, SOL_SOCKET, SO_REUSEADDR, 284*7c478bd9Sstevel@tonic-gate (char *)&on, sizeof(on)) < 0) { 285*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 286*7c478bd9Sstevel@tonic-gate gettext("in setsockopt(SO_REUSEADDR)")); 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate ret = bind(finet, (struct sockaddr *) &sin6, sizeof(sin6)); 289*7c478bd9Sstevel@tonic-gate } 290*7c478bd9Sstevel@tonic-gate 291*7c478bd9Sstevel@tonic-gate if (ret < 0) { 292*7c478bd9Sstevel@tonic-gate perror(gettext("bind")); 293*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 294*7c478bd9Sstevel@tonic-gate gettext("while binding listener socket")); 295*7c478bd9Sstevel@tonic-gate exit(1); 296*7c478bd9Sstevel@tonic-gate } 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate if (!debug && (iproprole != IPROP_SLAVE)) 300*7c478bd9Sstevel@tonic-gate daemon(1, 0); 301*7c478bd9Sstevel@tonic-gate 302*7c478bd9Sstevel@tonic-gate #ifdef PID_FILE 303*7c478bd9Sstevel@tonic-gate if ((pidfile = fopen(PID_FILE, "w")) != NULL) { 304*7c478bd9Sstevel@tonic-gate fprintf(pidfile, gettext("%d\n"), getpid()); 305*7c478bd9Sstevel@tonic-gate fclose(pidfile); 306*7c478bd9Sstevel@tonic-gate } else 307*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 308*7c478bd9Sstevel@tonic-gate gettext("while opening pid file %s for writing"), 309*7c478bd9Sstevel@tonic-gate PID_FILE); 310*7c478bd9Sstevel@tonic-gate #endif 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate if (listen(finet, 5) < 0) { 313*7c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("in listen call")); 314*7c478bd9Sstevel@tonic-gate exit(1); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate while (1) { 318*7c478bd9Sstevel@tonic-gate int child_pid; 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate s = accept(finet, (struct sockaddr *) &sin6, &sin6_size); 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate if (s < 0) { 323*7c478bd9Sstevel@tonic-gate if (errno != EINTR) 324*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 325*7c478bd9Sstevel@tonic-gate gettext("from accept system call")); 326*7c478bd9Sstevel@tonic-gate continue; 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate if (debug && (iproprole != IPROP_SLAVE)) 330*7c478bd9Sstevel@tonic-gate child_pid = 0; 331*7c478bd9Sstevel@tonic-gate else 332*7c478bd9Sstevel@tonic-gate child_pid = fork(); 333*7c478bd9Sstevel@tonic-gate 334*7c478bd9Sstevel@tonic-gate switch (child_pid) { 335*7c478bd9Sstevel@tonic-gate case -1: 336*7c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while forking")); 337*7c478bd9Sstevel@tonic-gate exit(1); 338*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 339*7c478bd9Sstevel@tonic-gate case 0: 340*7c478bd9Sstevel@tonic-gate /* child */ 341*7c478bd9Sstevel@tonic-gate (void) close(finet); 342*7c478bd9Sstevel@tonic-gate doit(s); 343*7c478bd9Sstevel@tonic-gate close(s); 344*7c478bd9Sstevel@tonic-gate _exit(0); 345*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 346*7c478bd9Sstevel@tonic-gate default: 347*7c478bd9Sstevel@tonic-gate /* parent */ 348*7c478bd9Sstevel@tonic-gate if (wait(&status) < 0) { 349*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 350*7c478bd9Sstevel@tonic-gate gettext("while waiting to receive database")); 351*7c478bd9Sstevel@tonic-gate exit(1); 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate close(s); 355*7c478bd9Sstevel@tonic-gate if (iproprole == IPROP_SLAVE) 356*7c478bd9Sstevel@tonic-gate close(finet); 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate if ((ret = WEXITSTATUS(status)) != 0) 359*7c478bd9Sstevel@tonic-gate return (ret); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate if (iproprole == IPROP_SLAVE) 363*7c478bd9Sstevel@tonic-gate break; 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate 366*7c478bd9Sstevel@tonic-gate return (0); 367*7c478bd9Sstevel@tonic-gate } 368*7c478bd9Sstevel@tonic-gate 369*7c478bd9Sstevel@tonic-gate void doit(fd) 370*7c478bd9Sstevel@tonic-gate int fd; 371*7c478bd9Sstevel@tonic-gate { 372*7c478bd9Sstevel@tonic-gate struct sockaddr_storage from; 373*7c478bd9Sstevel@tonic-gate socklen_t fromlen; 374*7c478bd9Sstevel@tonic-gate int on = 1; 375*7c478bd9Sstevel@tonic-gate struct hostent *hp; 376*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 377*7c478bd9Sstevel@tonic-gate krb5_data confmsg; 378*7c478bd9Sstevel@tonic-gate int lock_fd; 379*7c478bd9Sstevel@tonic-gate int omask; 380*7c478bd9Sstevel@tonic-gate krb5_enctype etype; 381*7c478bd9Sstevel@tonic-gate char ntop[NI_MAXHOST] = ""; 382*7c478bd9Sstevel@tonic-gate krb5_context doit_context; 383*7c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate retval = krb5_init_context(&doit_context); 386*7c478bd9Sstevel@tonic-gate if (retval) { 387*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while initializing krb5")); 388*7c478bd9Sstevel@tonic-gate exit(1); 389*7c478bd9Sstevel@tonic-gate } 390*7c478bd9Sstevel@tonic-gate log_ctx = kpropd_context->kdblog_context; 391*7c478bd9Sstevel@tonic-gate if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) 392*7c478bd9Sstevel@tonic-gate ulog_set_role(doit_context, IPROP_SLAVE); 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate fromlen = (socklen_t)sizeof (from); 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate if (getpeername(fd, (struct sockaddr *) &from, &fromlen) < 0) { 397*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: ", progname); 398*7c478bd9Sstevel@tonic-gate perror(gettext("getpeername")); 399*7c478bd9Sstevel@tonic-gate exit(1); 400*7c478bd9Sstevel@tonic-gate } 401*7c478bd9Sstevel@tonic-gate if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (caddr_t) &on, 402*7c478bd9Sstevel@tonic-gate sizeof (on)) < 0) { 403*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 404*7c478bd9Sstevel@tonic-gate gettext("while attempting setsockopt (SO_KEEPALIVE)")); 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), 408*7c478bd9Sstevel@tonic-gate NULL, 0, NI_NUMERICHOST) != 0) { 409*7c478bd9Sstevel@tonic-gate 410*7c478bd9Sstevel@tonic-gate /* getnameifo failed so use inet_ntop() to get printable addresses */ 411*7c478bd9Sstevel@tonic-gate if (from.ss_family == AF_INET) { 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate inet_ntop(AF_INET, 414*7c478bd9Sstevel@tonic-gate (const void *)&ss2sin(&from)->sin_addr, 415*7c478bd9Sstevel@tonic-gate ntop, sizeof(ntop)); 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate } else if (from.ss_family == AF_INET6 && 418*7c478bd9Sstevel@tonic-gate ! IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) { 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate ipaddr_t v4addr; 421*7c478bd9Sstevel@tonic-gate 422*7c478bd9Sstevel@tonic-gate inet_ntop(AF_INET6, 423*7c478bd9Sstevel@tonic-gate (const void *)&ss2sin6(&from)->sin6_addr, ntop, 424*7c478bd9Sstevel@tonic-gate sizeof(ntop)); 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate /* ipv4 mapped ipv6 addrs handled later */ 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate if (from.ss_family == AF_INET || from.ss_family == AF_INET6) { 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate if (from.ss_family == AF_INET6 && 432*7c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&ss2sin6(&from)->sin6_addr)) { 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate ipaddr_t v4addr; 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate /* coerce ipv4 mapped ipv6 addr to normal ipv4 addr */ 437*7c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_IPADDR(&(ss2sin6(&from)->sin6_addr), 438*7c478bd9Sstevel@tonic-gate v4addr); 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate inet_ntop(AF_INET, (const void *) &v4addr, 441*7c478bd9Sstevel@tonic-gate ntop, sizeof(ntop)); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, gettext("Connection from %s"), ntop); 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate if (debug) 447*7c478bd9Sstevel@tonic-gate printf("Connection from %s\n", ntop); 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate } else { 450*7c478bd9Sstevel@tonic-gate /* address family isn't either AF_INET || AF_INET6 */ 451*7c478bd9Sstevel@tonic-gate syslog(LOG_INFO, 452*7c478bd9Sstevel@tonic-gate gettext("Connection from unknown address family:%d"), 453*7c478bd9Sstevel@tonic-gate from.ss_family); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate if (debug) { 456*7c478bd9Sstevel@tonic-gate printf(gettext("Connection from unknown address family:%d"), 457*7c478bd9Sstevel@tonic-gate from.ss_family); 458*7c478bd9Sstevel@tonic-gate } 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate /* 462*7c478bd9Sstevel@tonic-gate * Now do the authentication 463*7c478bd9Sstevel@tonic-gate */ 464*7c478bd9Sstevel@tonic-gate kerberos_authenticate(doit_context, fd, &client, &etype, from); 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate if (!authorized_principal(doit_context, client, etype)) { 467*7c478bd9Sstevel@tonic-gate char *name; 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if (retval = krb5_unparse_name(doit_context, client, &name)) { 470*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 471*7c478bd9Sstevel@tonic-gate gettext("While unparsing client name")); 472*7c478bd9Sstevel@tonic-gate exit(1); 473*7c478bd9Sstevel@tonic-gate } 474*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 475*7c478bd9Sstevel@tonic-gate gettext("Rejected connection from unauthorized principal %s"), 476*7c478bd9Sstevel@tonic-gate name); 477*7c478bd9Sstevel@tonic-gate free(name); 478*7c478bd9Sstevel@tonic-gate exit(1); 479*7c478bd9Sstevel@tonic-gate } 480*7c478bd9Sstevel@tonic-gate omask = umask(077); 481*7c478bd9Sstevel@tonic-gate lock_fd = open(temp_file_name, O_RDWR|O_CREAT, 0600); 482*7c478bd9Sstevel@tonic-gate (void) umask(omask); 483*7c478bd9Sstevel@tonic-gate retval = krb5_lock_file(doit_context, lock_fd, 484*7c478bd9Sstevel@tonic-gate KRB5_LOCKMODE_EXCLUSIVE|KRB5_LOCKMODE_DONTBLOCK); 485*7c478bd9Sstevel@tonic-gate if (retval) { 486*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 487*7c478bd9Sstevel@tonic-gate gettext("while trying to lock '%s'"), 488*7c478bd9Sstevel@tonic-gate temp_file_name); 489*7c478bd9Sstevel@tonic-gate exit(1); 490*7c478bd9Sstevel@tonic-gate } 491*7c478bd9Sstevel@tonic-gate if ((database_fd = open(temp_file_name, 492*7c478bd9Sstevel@tonic-gate O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) { 493*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 494*7c478bd9Sstevel@tonic-gate gettext("while opening database file, '%s'"), 495*7c478bd9Sstevel@tonic-gate temp_file_name); 496*7c478bd9Sstevel@tonic-gate exit(1); 497*7c478bd9Sstevel@tonic-gate } 498*7c478bd9Sstevel@tonic-gate recv_database(doit_context, fd, database_fd, &confmsg); 499*7c478bd9Sstevel@tonic-gate if (rename(temp_file_name, file)) { 500*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 501*7c478bd9Sstevel@tonic-gate gettext("While renaming %s to %s"), 502*7c478bd9Sstevel@tonic-gate temp_file_name, file); 503*7c478bd9Sstevel@tonic-gate exit(1); 504*7c478bd9Sstevel@tonic-gate } 505*7c478bd9Sstevel@tonic-gate retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_SHARED); 506*7c478bd9Sstevel@tonic-gate if (retval) { 507*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 508*7c478bd9Sstevel@tonic-gate gettext("while downgrading lock on '%s'"), 509*7c478bd9Sstevel@tonic-gate temp_file_name); 510*7c478bd9Sstevel@tonic-gate exit(1); 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate load_database(doit_context, kdb5_util, file); 513*7c478bd9Sstevel@tonic-gate retval = krb5_lock_file(doit_context, lock_fd, KRB5_LOCKMODE_UNLOCK); 514*7c478bd9Sstevel@tonic-gate if (retval) { 515*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 516*7c478bd9Sstevel@tonic-gate gettext("while unlocking '%s'"), temp_file_name); 517*7c478bd9Sstevel@tonic-gate exit(1); 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate (void)close(lock_fd); 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate /* 522*7c478bd9Sstevel@tonic-gate * Send the acknowledgement message generated in 523*7c478bd9Sstevel@tonic-gate * recv_database, then close the socket. 524*7c478bd9Sstevel@tonic-gate */ 525*7c478bd9Sstevel@tonic-gate if (retval = krb5_write_message(doit_context, (void *) &fd, 526*7c478bd9Sstevel@tonic-gate &confmsg)) { 527*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(doit_context, &confmsg); 528*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 529*7c478bd9Sstevel@tonic-gate gettext("while sending # of received bytes")); 530*7c478bd9Sstevel@tonic-gate exit(1); 531*7c478bd9Sstevel@tonic-gate } 532*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(doit_context, &confmsg); 533*7c478bd9Sstevel@tonic-gate if (close(fd) < 0) { 534*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 535*7c478bd9Sstevel@tonic-gate gettext("while trying to close database file")); 536*7c478bd9Sstevel@tonic-gate exit(1); 537*7c478bd9Sstevel@tonic-gate } 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate exit(0); 540*7c478bd9Sstevel@tonic-gate } 541*7c478bd9Sstevel@tonic-gate 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate /* 544*7c478bd9Sstevel@tonic-gate * Routine to handle incremental update transfer(s) from master KDC 545*7c478bd9Sstevel@tonic-gate */ 546*7c478bd9Sstevel@tonic-gate krb5_error_code do_iprop(kdb_log_context *log_ctx) { 547*7c478bd9Sstevel@tonic-gate CLIENT *cl; 548*7c478bd9Sstevel@tonic-gate kadm5_ret_t retval; 549*7c478bd9Sstevel@tonic-gate kadm5_config_params params; 550*7c478bd9Sstevel@tonic-gate krb5_ccache cc; 551*7c478bd9Sstevel@tonic-gate krb5_principal iprop_svc_principal; 552*7c478bd9Sstevel@tonic-gate void *server_handle = NULL; 553*7c478bd9Sstevel@tonic-gate char *iprop_svc_princstr = NULL; 554*7c478bd9Sstevel@tonic-gate char *master_svc_princstr = NULL; 555*7c478bd9Sstevel@tonic-gate char *admin_server = NULL; 556*7c478bd9Sstevel@tonic-gate char *keytab_name = NULL; 557*7c478bd9Sstevel@tonic-gate unsigned int pollin, backoff_time; 558*7c478bd9Sstevel@tonic-gate int backoff_cnt = 0; 559*7c478bd9Sstevel@tonic-gate int reinit_cnt = 0; 560*7c478bd9Sstevel@tonic-gate int ret; 561*7c478bd9Sstevel@tonic-gate boolean_t frdone = B_FALSE; 562*7c478bd9Sstevel@tonic-gate 563*7c478bd9Sstevel@tonic-gate kdb_incr_result_t *incr_ret; 564*7c478bd9Sstevel@tonic-gate static kdb_last_t mylast; 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate kdb_fullresync_result_t *full_ret; 567*7c478bd9Sstevel@tonic-gate char *full_resync_arg = NULL; 568*7c478bd9Sstevel@tonic-gate 569*7c478bd9Sstevel@tonic-gate kadm5_iprop_handle_t handle; 570*7c478bd9Sstevel@tonic-gate kdb_hlog_t *ulog; 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate if (!debug) 573*7c478bd9Sstevel@tonic-gate daemon(0, 0); 574*7c478bd9Sstevel@tonic-gate 575*7c478bd9Sstevel@tonic-gate pollin = (unsigned int)0; 576*7c478bd9Sstevel@tonic-gate (void) memset((char *)¶ms, 0, sizeof (params)); 577*7c478bd9Sstevel@tonic-gate ulog = log_ctx->ulog; 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_REALM; 580*7c478bd9Sstevel@tonic-gate params.realm = def_realm; 581*7c478bd9Sstevel@tonic-gate 582*7c478bd9Sstevel@tonic-gate if (master_svc_princstr == NULL) { 583*7c478bd9Sstevel@tonic-gate if (retval = kadm5_get_kiprop_host_srv_name(kpropd_context, 584*7c478bd9Sstevel@tonic-gate def_realm, &master_svc_princstr)) { 585*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 586*7c478bd9Sstevel@tonic-gate gettext("%s: unable to get kiprop host based " 587*7c478bd9Sstevel@tonic-gate "service name for realm %s\n"), 588*7c478bd9Sstevel@tonic-gate progname, def_realm); 589*7c478bd9Sstevel@tonic-gate exit(1); 590*7c478bd9Sstevel@tonic-gate } 591*7c478bd9Sstevel@tonic-gate } 592*7c478bd9Sstevel@tonic-gate 593*7c478bd9Sstevel@tonic-gate /* 594*7c478bd9Sstevel@tonic-gate * Set cc to the default credentials cache 595*7c478bd9Sstevel@tonic-gate */ 596*7c478bd9Sstevel@tonic-gate if (retval = krb5_cc_default(kpropd_context, &cc)) { 597*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 598*7c478bd9Sstevel@tonic-gate gettext("while opening default " 599*7c478bd9Sstevel@tonic-gate "credentials cache")); 600*7c478bd9Sstevel@tonic-gate exit(1); 601*7c478bd9Sstevel@tonic-gate } 602*7c478bd9Sstevel@tonic-gate 603*7c478bd9Sstevel@tonic-gate retval = krb5_sname_to_principal(kpropd_context, NULL, KIPROP_SVC_NAME, 604*7c478bd9Sstevel@tonic-gate KRB5_NT_SRV_HST, &iprop_svc_principal); 605*7c478bd9Sstevel@tonic-gate if (retval) { 606*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while trying to construct " 607*7c478bd9Sstevel@tonic-gate "host service principal")); 608*7c478bd9Sstevel@tonic-gate exit(1); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate if (retval = krb5_unparse_name(kpropd_context, iprop_svc_principal, 612*7c478bd9Sstevel@tonic-gate &iprop_svc_princstr)) { 613*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 614*7c478bd9Sstevel@tonic-gate gettext("while canonicalizing " 615*7c478bd9Sstevel@tonic-gate "principal name")); 616*7c478bd9Sstevel@tonic-gate krb5_free_principal(kpropd_context, iprop_svc_principal); 617*7c478bd9Sstevel@tonic-gate exit(1); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate krb5_free_principal(kpropd_context, iprop_svc_principal); 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate reinit: 622*7c478bd9Sstevel@tonic-gate /* 623*7c478bd9Sstevel@tonic-gate * Authentication, initialize rpcsec_gss handle etc. 624*7c478bd9Sstevel@tonic-gate */ 625*7c478bd9Sstevel@tonic-gate retval = kadm5_init_with_skey(iprop_svc_princstr, keytab_name, 626*7c478bd9Sstevel@tonic-gate master_svc_princstr, 627*7c478bd9Sstevel@tonic-gate ¶ms, 628*7c478bd9Sstevel@tonic-gate KADM5_STRUCT_VERSION, 629*7c478bd9Sstevel@tonic-gate KADM5_API_VERSION_2, 630*7c478bd9Sstevel@tonic-gate &server_handle); 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate if (retval) { 633*7c478bd9Sstevel@tonic-gate if (retval == KADM5_RPC_ERROR) { 634*7c478bd9Sstevel@tonic-gate reinit_cnt++; 635*7c478bd9Sstevel@tonic-gate if (server_handle) 636*7c478bd9Sstevel@tonic-gate kadm5_destroy((void *) server_handle); 637*7c478bd9Sstevel@tonic-gate server_handle = (void *)NULL; 638*7c478bd9Sstevel@tonic-gate handle = (kadm5_iprop_handle_t)NULL; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext( 641*7c478bd9Sstevel@tonic-gate "while attempting to connect" 642*7c478bd9Sstevel@tonic-gate " to master KDC ... retrying")); 643*7c478bd9Sstevel@tonic-gate backoff_time = backoff_from_master(&reinit_cnt); 644*7c478bd9Sstevel@tonic-gate (void) sleep(backoff_time); 645*7c478bd9Sstevel@tonic-gate goto reinit; 646*7c478bd9Sstevel@tonic-gate } else { 647*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 648*7c478bd9Sstevel@tonic-gate gettext("while initializing %s interface"), 649*7c478bd9Sstevel@tonic-gate progname); 650*7c478bd9Sstevel@tonic-gate if (retval == KADM5_BAD_CLIENT_PARAMS || 651*7c478bd9Sstevel@tonic-gate retval == KADM5_BAD_SERVER_PARAMS) 652*7c478bd9Sstevel@tonic-gate usage(); 653*7c478bd9Sstevel@tonic-gate exit(1); 654*7c478bd9Sstevel@tonic-gate } 655*7c478bd9Sstevel@tonic-gate } 656*7c478bd9Sstevel@tonic-gate 657*7c478bd9Sstevel@tonic-gate /* 658*7c478bd9Sstevel@tonic-gate * Reset re-initialization count to zero now. 659*7c478bd9Sstevel@tonic-gate */ 660*7c478bd9Sstevel@tonic-gate reinit_cnt = backoff_time = 0; 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate /* 663*7c478bd9Sstevel@tonic-gate * Reset the handle to the correct type for the RPC call 664*7c478bd9Sstevel@tonic-gate */ 665*7c478bd9Sstevel@tonic-gate handle = server_handle; 666*7c478bd9Sstevel@tonic-gate 667*7c478bd9Sstevel@tonic-gate /* 668*7c478bd9Sstevel@tonic-gate * If we have reached this far, we have succesfully established 669*7c478bd9Sstevel@tonic-gate * a RPCSEC_GSS connection; we now start polling for updates 670*7c478bd9Sstevel@tonic-gate */ 671*7c478bd9Sstevel@tonic-gate if (poll_time == NULL) { 672*7c478bd9Sstevel@tonic-gate if ((poll_time = (char *)strdup("2m")) == NULL) { 673*7c478bd9Sstevel@tonic-gate com_err(progname, ENOMEM, 674*7c478bd9Sstevel@tonic-gate gettext("Unable to allocate poll_time")); 675*7c478bd9Sstevel@tonic-gate exit(1); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate } 678*7c478bd9Sstevel@tonic-gate 679*7c478bd9Sstevel@tonic-gate if (pollin == (unsigned int)0) 680*7c478bd9Sstevel@tonic-gate pollin = convert_polltime(poll_time); 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate for (;;) { 683*7c478bd9Sstevel@tonic-gate incr_ret = NULL; 684*7c478bd9Sstevel@tonic-gate full_ret = NULL; 685*7c478bd9Sstevel@tonic-gate 686*7c478bd9Sstevel@tonic-gate /* 687*7c478bd9Sstevel@tonic-gate * Get the most recent ulog entry sno + ts, which 688*7c478bd9Sstevel@tonic-gate * we package in the request to the master KDC 689*7c478bd9Sstevel@tonic-gate */ 690*7c478bd9Sstevel@tonic-gate mylast.last_sno = ulog->kdb_last_sno; 691*7c478bd9Sstevel@tonic-gate mylast.last_time = ulog->kdb_last_time; 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate /* 694*7c478bd9Sstevel@tonic-gate * Loop continuously on an iprop_get_updates_1(), 695*7c478bd9Sstevel@tonic-gate * so that we can keep probing the master for updates 696*7c478bd9Sstevel@tonic-gate * or (if needed) do a full resync of the krb5 db. 697*7c478bd9Sstevel@tonic-gate */ 698*7c478bd9Sstevel@tonic-gate 699*7c478bd9Sstevel@tonic-gate incr_ret = iprop_get_updates_1(&mylast, handle->clnt); 700*7c478bd9Sstevel@tonic-gate if (incr_ret == (kdb_incr_result_t *)NULL) { 701*7c478bd9Sstevel@tonic-gate clnt_perror(handle->clnt, 702*7c478bd9Sstevel@tonic-gate "iprop_get_updates call failed"); 703*7c478bd9Sstevel@tonic-gate if (server_handle) 704*7c478bd9Sstevel@tonic-gate kadm5_destroy((void *)server_handle); 705*7c478bd9Sstevel@tonic-gate server_handle = (void *)NULL; 706*7c478bd9Sstevel@tonic-gate handle = (kadm5_iprop_handle_t)NULL; 707*7c478bd9Sstevel@tonic-gate goto reinit; 708*7c478bd9Sstevel@tonic-gate } 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate switch (incr_ret->ret) { 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate case UPDATE_FULL_RESYNC_NEEDED: 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * We dont do a full resync again, if the last 715*7c478bd9Sstevel@tonic-gate * X'fer was a resync and if the master sno is 716*7c478bd9Sstevel@tonic-gate * still "0", i.e. no updates so far. 717*7c478bd9Sstevel@tonic-gate */ 718*7c478bd9Sstevel@tonic-gate if ((frdone == B_TRUE) && (incr_ret->lastentry.last_sno 719*7c478bd9Sstevel@tonic-gate == 0)) { 720*7c478bd9Sstevel@tonic-gate break; 721*7c478bd9Sstevel@tonic-gate } else { 722*7c478bd9Sstevel@tonic-gate 723*7c478bd9Sstevel@tonic-gate full_ret = iprop_full_resync_1((void *) 724*7c478bd9Sstevel@tonic-gate &full_resync_arg, handle->clnt); 725*7c478bd9Sstevel@tonic-gate 726*7c478bd9Sstevel@tonic-gate if (full_ret == (kdb_fullresync_result_t *) 727*7c478bd9Sstevel@tonic-gate NULL) { 728*7c478bd9Sstevel@tonic-gate clnt_perror(handle->clnt, 729*7c478bd9Sstevel@tonic-gate "iprop_full_resync call failed"); 730*7c478bd9Sstevel@tonic-gate if (server_handle) 731*7c478bd9Sstevel@tonic-gate kadm5_destroy((void *) 732*7c478bd9Sstevel@tonic-gate server_handle); 733*7c478bd9Sstevel@tonic-gate server_handle = (void *)NULL; 734*7c478bd9Sstevel@tonic-gate handle = (kadm5_iprop_handle_t)NULL; 735*7c478bd9Sstevel@tonic-gate goto reinit; 736*7c478bd9Sstevel@tonic-gate } 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate 739*7c478bd9Sstevel@tonic-gate switch (full_ret->ret) { 740*7c478bd9Sstevel@tonic-gate case UPDATE_OK: 741*7c478bd9Sstevel@tonic-gate backoff_cnt = 0; 742*7c478bd9Sstevel@tonic-gate /* 743*7c478bd9Sstevel@tonic-gate * We now listen on the kprop port for 744*7c478bd9Sstevel@tonic-gate * the full dump 745*7c478bd9Sstevel@tonic-gate */ 746*7c478bd9Sstevel@tonic-gate ret = do_standalone(log_ctx->iproprole); 747*7c478bd9Sstevel@tonic-gate if (ret) 748*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 749*7c478bd9Sstevel@tonic-gate gettext("kpropd: Full resync, " 750*7c478bd9Sstevel@tonic-gate "invalid return.")); 751*7c478bd9Sstevel@tonic-gate if (debug) 752*7c478bd9Sstevel@tonic-gate if (ret) 753*7c478bd9Sstevel@tonic-gate fprintf(stderr, 754*7c478bd9Sstevel@tonic-gate gettext("Full resync " 755*7c478bd9Sstevel@tonic-gate "was unsuccessful\n")); 756*7c478bd9Sstevel@tonic-gate else 757*7c478bd9Sstevel@tonic-gate fprintf(stderr, 758*7c478bd9Sstevel@tonic-gate gettext("Full resync " 759*7c478bd9Sstevel@tonic-gate "was successful\n")); 760*7c478bd9Sstevel@tonic-gate frdone = B_TRUE; 761*7c478bd9Sstevel@tonic-gate break; 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate case UPDATE_BUSY: 764*7c478bd9Sstevel@tonic-gate /* 765*7c478bd9Sstevel@tonic-gate * Exponential backoff 766*7c478bd9Sstevel@tonic-gate */ 767*7c478bd9Sstevel@tonic-gate backoff_cnt++; 768*7c478bd9Sstevel@tonic-gate break; 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate case UPDATE_FULL_RESYNC_NEEDED: 771*7c478bd9Sstevel@tonic-gate case UPDATE_NIL: 772*7c478bd9Sstevel@tonic-gate default: 773*7c478bd9Sstevel@tonic-gate backoff_cnt = 0; 774*7c478bd9Sstevel@tonic-gate frdone = B_FALSE; 775*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: Full resync," 776*7c478bd9Sstevel@tonic-gate " invalid return from master KDC.")); 777*7c478bd9Sstevel@tonic-gate break; 778*7c478bd9Sstevel@tonic-gate 779*7c478bd9Sstevel@tonic-gate case UPDATE_PERM_DENIED: 780*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: Full resync," 781*7c478bd9Sstevel@tonic-gate " permission denied.")); 782*7c478bd9Sstevel@tonic-gate goto error; 783*7c478bd9Sstevel@tonic-gate 784*7c478bd9Sstevel@tonic-gate case UPDATE_ERROR: 785*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: Full resync," 786*7c478bd9Sstevel@tonic-gate " error returned from master KDC.")); 787*7c478bd9Sstevel@tonic-gate goto error; 788*7c478bd9Sstevel@tonic-gate } 789*7c478bd9Sstevel@tonic-gate break; 790*7c478bd9Sstevel@tonic-gate 791*7c478bd9Sstevel@tonic-gate case UPDATE_OK: 792*7c478bd9Sstevel@tonic-gate backoff_cnt = 0; 793*7c478bd9Sstevel@tonic-gate frdone = B_FALSE; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate /* 796*7c478bd9Sstevel@tonic-gate * ulog_replay() will convert the ulog updates to db 797*7c478bd9Sstevel@tonic-gate * entries using the kdb conv api and will commit 798*7c478bd9Sstevel@tonic-gate * the entries to the slave kdc database 799*7c478bd9Sstevel@tonic-gate */ 800*7c478bd9Sstevel@tonic-gate retval = ulog_replay(kpropd_context, incr_ret); 801*7c478bd9Sstevel@tonic-gate 802*7c478bd9Sstevel@tonic-gate if (retval) { 803*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: ulog_replay" 804*7c478bd9Sstevel@tonic-gate " failed, updates not registered.")); 805*7c478bd9Sstevel@tonic-gate break; 806*7c478bd9Sstevel@tonic-gate } 807*7c478bd9Sstevel@tonic-gate 808*7c478bd9Sstevel@tonic-gate if (debug) 809*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Update transfer " 810*7c478bd9Sstevel@tonic-gate "from master was OK\n")); 811*7c478bd9Sstevel@tonic-gate break; 812*7c478bd9Sstevel@tonic-gate 813*7c478bd9Sstevel@tonic-gate case UPDATE_PERM_DENIED: 814*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: get_updates," 815*7c478bd9Sstevel@tonic-gate " permission denied.")); 816*7c478bd9Sstevel@tonic-gate goto error; 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate case UPDATE_ERROR: 819*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: get_updates, error " 820*7c478bd9Sstevel@tonic-gate "returned from master KDC.")); 821*7c478bd9Sstevel@tonic-gate goto error; 822*7c478bd9Sstevel@tonic-gate 823*7c478bd9Sstevel@tonic-gate case UPDATE_BUSY: 824*7c478bd9Sstevel@tonic-gate /* 825*7c478bd9Sstevel@tonic-gate * Exponential backoff 826*7c478bd9Sstevel@tonic-gate */ 827*7c478bd9Sstevel@tonic-gate backoff_cnt++; 828*7c478bd9Sstevel@tonic-gate break; 829*7c478bd9Sstevel@tonic-gate 830*7c478bd9Sstevel@tonic-gate case UPDATE_NIL: 831*7c478bd9Sstevel@tonic-gate /* 832*7c478bd9Sstevel@tonic-gate * Master-slave are in sync 833*7c478bd9Sstevel@tonic-gate */ 834*7c478bd9Sstevel@tonic-gate if (debug) 835*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Master, slave KDC's " 836*7c478bd9Sstevel@tonic-gate "are in-sync, no updates\n")); 837*7c478bd9Sstevel@tonic-gate backoff_cnt = 0; 838*7c478bd9Sstevel@tonic-gate frdone = B_FALSE; 839*7c478bd9Sstevel@tonic-gate break; 840*7c478bd9Sstevel@tonic-gate 841*7c478bd9Sstevel@tonic-gate default: 842*7c478bd9Sstevel@tonic-gate backoff_cnt = 0; 843*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: get_updates," 844*7c478bd9Sstevel@tonic-gate " invalid return from master KDC.")); 845*7c478bd9Sstevel@tonic-gate break; 846*7c478bd9Sstevel@tonic-gate } 847*7c478bd9Sstevel@tonic-gate 848*7c478bd9Sstevel@tonic-gate if (runonce == B_TRUE) 849*7c478bd9Sstevel@tonic-gate goto done; 850*7c478bd9Sstevel@tonic-gate 851*7c478bd9Sstevel@tonic-gate /* 852*7c478bd9Sstevel@tonic-gate * Sleep for the specified poll interval (Default is 2 mts), 853*7c478bd9Sstevel@tonic-gate * or do a binary exponential backoff if we get an 854*7c478bd9Sstevel@tonic-gate * UPDATE_BUSY signal 855*7c478bd9Sstevel@tonic-gate */ 856*7c478bd9Sstevel@tonic-gate if (backoff_cnt > 0) { 857*7c478bd9Sstevel@tonic-gate backoff_time = backoff_from_master(&backoff_cnt); 858*7c478bd9Sstevel@tonic-gate if (debug) 859*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("Busy signal received " 860*7c478bd9Sstevel@tonic-gate "from master, backoff for %d secs\n"), 861*7c478bd9Sstevel@tonic-gate backoff_time); 862*7c478bd9Sstevel@tonic-gate (void) sleep(backoff_time); 863*7c478bd9Sstevel@tonic-gate } 864*7c478bd9Sstevel@tonic-gate else 865*7c478bd9Sstevel@tonic-gate (void) sleep(pollin); 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate error: 871*7c478bd9Sstevel@tonic-gate if (debug) 872*7c478bd9Sstevel@tonic-gate fprintf(stderr, gettext("ERROR returned by master, bailing\n")); 873*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("kpropd: ERROR returned by master KDC," 874*7c478bd9Sstevel@tonic-gate " bailing.\n")); 875*7c478bd9Sstevel@tonic-gate done: 876*7c478bd9Sstevel@tonic-gate if (poll_time) 877*7c478bd9Sstevel@tonic-gate free(poll_time); 878*7c478bd9Sstevel@tonic-gate if(iprop_svc_princstr) 879*7c478bd9Sstevel@tonic-gate free(iprop_svc_princstr); 880*7c478bd9Sstevel@tonic-gate if (master_svc_princstr) 881*7c478bd9Sstevel@tonic-gate free(master_svc_princstr); 882*7c478bd9Sstevel@tonic-gate if (retval = krb5_cc_close(kpropd_context, cc)) { 883*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 884*7c478bd9Sstevel@tonic-gate gettext("while closing default ccache")); 885*7c478bd9Sstevel@tonic-gate exit(1); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate if (def_realm) 888*7c478bd9Sstevel@tonic-gate free(def_realm); 889*7c478bd9Sstevel@tonic-gate if (server_handle) 890*7c478bd9Sstevel@tonic-gate kadm5_destroy((void *)server_handle); 891*7c478bd9Sstevel@tonic-gate if (kpropd_context) 892*7c478bd9Sstevel@tonic-gate krb5_free_context(kpropd_context); 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate if (runonce == B_TRUE) 895*7c478bd9Sstevel@tonic-gate return (0); 896*7c478bd9Sstevel@tonic-gate else 897*7c478bd9Sstevel@tonic-gate exit(1); 898*7c478bd9Sstevel@tonic-gate } 899*7c478bd9Sstevel@tonic-gate 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate /* 902*7c478bd9Sstevel@tonic-gate * Do exponential backoff, since master KDC is BUSY or down 903*7c478bd9Sstevel@tonic-gate */ 904*7c478bd9Sstevel@tonic-gate unsigned int backoff_from_master(int *cnt) { 905*7c478bd9Sstevel@tonic-gate unsigned int btime; 906*7c478bd9Sstevel@tonic-gate 907*7c478bd9Sstevel@tonic-gate btime = (unsigned int)(2<<(*cnt)); 908*7c478bd9Sstevel@tonic-gate if (btime > MAX_BACKOFF) { 909*7c478bd9Sstevel@tonic-gate btime = MAX_BACKOFF; 910*7c478bd9Sstevel@tonic-gate *cnt--; 911*7c478bd9Sstevel@tonic-gate } 912*7c478bd9Sstevel@tonic-gate 913*7c478bd9Sstevel@tonic-gate return (btime); 914*7c478bd9Sstevel@tonic-gate } 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate 917*7c478bd9Sstevel@tonic-gate /* 918*7c478bd9Sstevel@tonic-gate * Routine to convert the `pollstr' string to seconds 919*7c478bd9Sstevel@tonic-gate */ 920*7c478bd9Sstevel@tonic-gate int convert_polltime(char *pollstr) { 921*7c478bd9Sstevel@tonic-gate char *tokenptr = NULL; 922*7c478bd9Sstevel@tonic-gate int len, polltime; 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate len = polltime = 0; 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate if ((len = strcspn(pollstr, "s")) < strlen(pollstr)) { 927*7c478bd9Sstevel@tonic-gate tokenptr = malloc((len + 1) * sizeof(char)); 928*7c478bd9Sstevel@tonic-gate (void) strlcpy(tokenptr, pollstr, len + 1); 929*7c478bd9Sstevel@tonic-gate polltime = atoi(tokenptr); 930*7c478bd9Sstevel@tonic-gate } 931*7c478bd9Sstevel@tonic-gate 932*7c478bd9Sstevel@tonic-gate if ((len = strcspn(pollstr, "m")) < strlen(pollstr)) { 933*7c478bd9Sstevel@tonic-gate tokenptr = malloc((len + 1) * sizeof(char)); 934*7c478bd9Sstevel@tonic-gate (void) strlcpy(tokenptr, pollstr, len + 1); 935*7c478bd9Sstevel@tonic-gate polltime = atoi(tokenptr) * 60; 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate if ((len = strcspn(pollstr, "h")) < strlen(pollstr)) { 939*7c478bd9Sstevel@tonic-gate tokenptr = malloc((len + 1) * sizeof(char)); 940*7c478bd9Sstevel@tonic-gate (void) strlcpy(tokenptr, pollstr, len + 1); 941*7c478bd9Sstevel@tonic-gate polltime = atoi(tokenptr) * 3600; 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate 944*7c478bd9Sstevel@tonic-gate if (tokenptr != NULL) 945*7c478bd9Sstevel@tonic-gate free(tokenptr); 946*7c478bd9Sstevel@tonic-gate /* 947*7c478bd9Sstevel@tonic-gate * If we have a bogus pollstr value, set polltime to the 948*7c478bd9Sstevel@tonic-gate * default of 2 mts (120 seconds). 949*7c478bd9Sstevel@tonic-gate */ 950*7c478bd9Sstevel@tonic-gate if (polltime == 0) 951*7c478bd9Sstevel@tonic-gate polltime = 120; 952*7c478bd9Sstevel@tonic-gate return (polltime); 953*7c478bd9Sstevel@tonic-gate } 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate static void 956*7c478bd9Sstevel@tonic-gate kpropd_com_err_proc(whoami, code, fmt, args) 957*7c478bd9Sstevel@tonic-gate const char *whoami; 958*7c478bd9Sstevel@tonic-gate long code; 959*7c478bd9Sstevel@tonic-gate const char *fmt; 960*7c478bd9Sstevel@tonic-gate va_list args; 961*7c478bd9Sstevel@tonic-gate { 962*7c478bd9Sstevel@tonic-gate char error_buf[8096]; 963*7c478bd9Sstevel@tonic-gate 964*7c478bd9Sstevel@tonic-gate error_buf[0] = '\0'; 965*7c478bd9Sstevel@tonic-gate if (fmt) 966*7c478bd9Sstevel@tonic-gate vsprintf(error_buf, fmt, args); 967*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "%s%s%s%s%s", whoami ? whoami : "", whoami ? ": " : "", 968*7c478bd9Sstevel@tonic-gate code ? error_message(code) : "", code ? " " : "", error_buf); 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate 971*7c478bd9Sstevel@tonic-gate void PRS(argc,argv) 972*7c478bd9Sstevel@tonic-gate int argc; 973*7c478bd9Sstevel@tonic-gate char **argv; 974*7c478bd9Sstevel@tonic-gate { 975*7c478bd9Sstevel@tonic-gate register char *word, ch; 976*7c478bd9Sstevel@tonic-gate char *cp; 977*7c478bd9Sstevel@tonic-gate int c; 978*7c478bd9Sstevel@tonic-gate struct hostent *hp; 979*7c478bd9Sstevel@tonic-gate char my_host_name[MAXHOSTNAMELEN], buf[BUFSIZ]; 980*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 981*7c478bd9Sstevel@tonic-gate static const char tmp[] = ".temp"; 982*7c478bd9Sstevel@tonic-gate kadm5_config_params params; 983*7c478bd9Sstevel@tonic-gate 984*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 985*7c478bd9Sstevel@tonic-gate 986*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 987*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "KPROPD_TEST" /* Use this only if it weren't */ 988*7c478bd9Sstevel@tonic-gate #endif 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 991*7c478bd9Sstevel@tonic-gate 992*7c478bd9Sstevel@tonic-gate (void) memset((char *) ¶ms, 0, sizeof (params)); 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate retval = krb5_init_context(&kpropd_context); 995*7c478bd9Sstevel@tonic-gate if (retval) { 996*7c478bd9Sstevel@tonic-gate com_err(argv[0], retval, 997*7c478bd9Sstevel@tonic-gate gettext("while initializing krb5")); 998*7c478bd9Sstevel@tonic-gate exit(1); 999*7c478bd9Sstevel@tonic-gate } 1000*7c478bd9Sstevel@tonic-gate progname = argv[0]; 1001*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "dtf:F:p:P:r:s:Sa:")) != EOF){ 1002*7c478bd9Sstevel@tonic-gate switch (c) { 1003*7c478bd9Sstevel@tonic-gate case 'd': 1004*7c478bd9Sstevel@tonic-gate debug++; 1005*7c478bd9Sstevel@tonic-gate break; 1006*7c478bd9Sstevel@tonic-gate case 't': 1007*7c478bd9Sstevel@tonic-gate /* 1008*7c478bd9Sstevel@tonic-gate * Undocumented option - for testing only. 1009*7c478bd9Sstevel@tonic-gate * 1010*7c478bd9Sstevel@tonic-gate * Option to run the kpropd server exactly 1011*7c478bd9Sstevel@tonic-gate * once (this is true only if iprop is enabled). 1012*7c478bd9Sstevel@tonic-gate */ 1013*7c478bd9Sstevel@tonic-gate runonce = B_TRUE; 1014*7c478bd9Sstevel@tonic-gate break; 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate case 'f': 1017*7c478bd9Sstevel@tonic-gate file = optarg; 1018*7c478bd9Sstevel@tonic-gate if (!file) 1019*7c478bd9Sstevel@tonic-gate usage(); 1020*7c478bd9Sstevel@tonic-gate break; 1021*7c478bd9Sstevel@tonic-gate case 'F': 1022*7c478bd9Sstevel@tonic-gate kerb_database = optarg; 1023*7c478bd9Sstevel@tonic-gate if (!kerb_database) 1024*7c478bd9Sstevel@tonic-gate usage(); 1025*7c478bd9Sstevel@tonic-gate break; 1026*7c478bd9Sstevel@tonic-gate case 'p': 1027*7c478bd9Sstevel@tonic-gate kdb5_util = optarg; 1028*7c478bd9Sstevel@tonic-gate if (!kdb5_util) 1029*7c478bd9Sstevel@tonic-gate usage(); 1030*7c478bd9Sstevel@tonic-gate break; 1031*7c478bd9Sstevel@tonic-gate case 'P': 1032*7c478bd9Sstevel@tonic-gate port = htons(atoi(optarg)); 1033*7c478bd9Sstevel@tonic-gate if (!port) 1034*7c478bd9Sstevel@tonic-gate usage(); 1035*7c478bd9Sstevel@tonic-gate break; 1036*7c478bd9Sstevel@tonic-gate case 'r': 1037*7c478bd9Sstevel@tonic-gate realm = optarg; 1038*7c478bd9Sstevel@tonic-gate if (!realm) 1039*7c478bd9Sstevel@tonic-gate usage(); 1040*7c478bd9Sstevel@tonic-gate params.realm = realm; 1041*7c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_REALM; 1042*7c478bd9Sstevel@tonic-gate break; 1043*7c478bd9Sstevel@tonic-gate case 's': 1044*7c478bd9Sstevel@tonic-gate srvtab = optarg; 1045*7c478bd9Sstevel@tonic-gate if (!srvtab) 1046*7c478bd9Sstevel@tonic-gate usage(); 1047*7c478bd9Sstevel@tonic-gate break; 1048*7c478bd9Sstevel@tonic-gate case 'S': 1049*7c478bd9Sstevel@tonic-gate standalone++; 1050*7c478bd9Sstevel@tonic-gate break; 1051*7c478bd9Sstevel@tonic-gate case 'a': 1052*7c478bd9Sstevel@tonic-gate acl_file_name = optarg; 1053*7c478bd9Sstevel@tonic-gate if (!acl_file_name) 1054*7c478bd9Sstevel@tonic-gate usage(); 1055*7c478bd9Sstevel@tonic-gate break; 1056*7c478bd9Sstevel@tonic-gate case '?': 1057*7c478bd9Sstevel@tonic-gate default: 1058*7c478bd9Sstevel@tonic-gate usage(); 1059*7c478bd9Sstevel@tonic-gate } 1060*7c478bd9Sstevel@tonic-gate 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate /* 1063*7c478bd9Sstevel@tonic-gate * If not in debug mode, switch com_err reporting to syslog 1064*7c478bd9Sstevel@tonic-gate */ 1065*7c478bd9Sstevel@tonic-gate if (! debug) { 1066*7c478bd9Sstevel@tonic-gate openlog("kpropd", LOG_PID | LOG_ODELAY, SYSLOG_CLASS); 1067*7c478bd9Sstevel@tonic-gate set_com_err_hook(kpropd_com_err_proc); 1068*7c478bd9Sstevel@tonic-gate } 1069*7c478bd9Sstevel@tonic-gate /* 1070*7c478bd9Sstevel@tonic-gate * Get my hostname, so we can construct my service name 1071*7c478bd9Sstevel@tonic-gate */ 1072*7c478bd9Sstevel@tonic-gate retval = krb5_sname_to_principal(kpropd_context, 1073*7c478bd9Sstevel@tonic-gate NULL, KPROP_SERVICE_NAME, 1074*7c478bd9Sstevel@tonic-gate KRB5_NT_SRV_HST, &server); 1075*7c478bd9Sstevel@tonic-gate if (retval) { 1076*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 1077*7c478bd9Sstevel@tonic-gate gettext("While trying to construct my service name")); 1078*7c478bd9Sstevel@tonic-gate exit(1); 1079*7c478bd9Sstevel@tonic-gate } 1080*7c478bd9Sstevel@tonic-gate if (realm) { 1081*7c478bd9Sstevel@tonic-gate (void) krb5_xfree(krb5_princ_realm(context, server)->data); 1082*7c478bd9Sstevel@tonic-gate krb5_princ_set_realm_length(context, server, strlen(realm)); 1083*7c478bd9Sstevel@tonic-gate krb5_princ_set_realm_data(context, server, strdup(realm)); 1084*7c478bd9Sstevel@tonic-gate } 1085*7c478bd9Sstevel@tonic-gate /* 1086*7c478bd9Sstevel@tonic-gate * Construct the name of the temporary file. 1087*7c478bd9Sstevel@tonic-gate */ 1088*7c478bd9Sstevel@tonic-gate if ((temp_file_name = (char *) malloc(strlen(file) + 1089*7c478bd9Sstevel@tonic-gate strlen(tmp) + 1)) == NULL) { 1090*7c478bd9Sstevel@tonic-gate com_err(progname, ENOMEM, 1091*7c478bd9Sstevel@tonic-gate gettext("while allocating filename for temp file")); 1092*7c478bd9Sstevel@tonic-gate exit(1); 1093*7c478bd9Sstevel@tonic-gate } 1094*7c478bd9Sstevel@tonic-gate strcpy(temp_file_name, file); 1095*7c478bd9Sstevel@tonic-gate strcat(temp_file_name, tmp); 1096*7c478bd9Sstevel@tonic-gate 1097*7c478bd9Sstevel@tonic-gate retval = kadm5_get_config_params(kpropd_context, NULL, NULL, ¶ms, 1098*7c478bd9Sstevel@tonic-gate ¶ms); 1099*7c478bd9Sstevel@tonic-gate if (retval) { 1100*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while initializing")); 1101*7c478bd9Sstevel@tonic-gate exit(1); 1102*7c478bd9Sstevel@tonic-gate } 1103*7c478bd9Sstevel@tonic-gate if (params.iprop_enabled == TRUE) { 1104*7c478bd9Sstevel@tonic-gate ulog_set_role(kpropd_context, IPROP_SLAVE); 1105*7c478bd9Sstevel@tonic-gate poll_time = params.iprop_polltime; 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate if (ulog_map(kpropd_context, ¶ms, FKPROPD)) { 1108*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 1109*7c478bd9Sstevel@tonic-gate gettext("Unable to map log!\n")); 1110*7c478bd9Sstevel@tonic-gate exit(1); 1111*7c478bd9Sstevel@tonic-gate } 1112*7c478bd9Sstevel@tonic-gate } 1113*7c478bd9Sstevel@tonic-gate 1114*7c478bd9Sstevel@tonic-gate /* 1115*7c478bd9Sstevel@tonic-gate * Grab the realm info and check if iprop is enabled. 1116*7c478bd9Sstevel@tonic-gate */ 1117*7c478bd9Sstevel@tonic-gate if (def_realm == NULL) { 1118*7c478bd9Sstevel@tonic-gate retval = krb5_get_default_realm(kpropd_context, &def_realm); 1119*7c478bd9Sstevel@tonic-gate if (retval) { 1120*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 1121*7c478bd9Sstevel@tonic-gate gettext("Unable to get default realm")); 1122*7c478bd9Sstevel@tonic-gate exit(1); 1123*7c478bd9Sstevel@tonic-gate } 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate } 1126*7c478bd9Sstevel@tonic-gate 1127*7c478bd9Sstevel@tonic-gate /* 1128*7c478bd9Sstevel@tonic-gate * Figure out who's calling on the other end of the connection.... 1129*7c478bd9Sstevel@tonic-gate */ 1130*7c478bd9Sstevel@tonic-gate void 1131*7c478bd9Sstevel@tonic-gate kerberos_authenticate(context, fd, clientp, etype, ss) 1132*7c478bd9Sstevel@tonic-gate krb5_context context; 1133*7c478bd9Sstevel@tonic-gate int fd; 1134*7c478bd9Sstevel@tonic-gate krb5_principal * clientp; 1135*7c478bd9Sstevel@tonic-gate krb5_enctype * etype; 1136*7c478bd9Sstevel@tonic-gate struct sockaddr_storage ss; 1137*7c478bd9Sstevel@tonic-gate { 1138*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 1139*7c478bd9Sstevel@tonic-gate krb5_ticket * ticket; 1140*7c478bd9Sstevel@tonic-gate struct sockaddr_storage r_ss; 1141*7c478bd9Sstevel@tonic-gate int ss_length; 1142*7c478bd9Sstevel@tonic-gate krb5_keytab keytab = NULL; 1143*7c478bd9Sstevel@tonic-gate 1144*7c478bd9Sstevel@tonic-gate /* 1145*7c478bd9Sstevel@tonic-gate * Set recv_addr and send_addr 1146*7c478bd9Sstevel@tonic-gate */ 1147*7c478bd9Sstevel@tonic-gate if (cvtkaddr(&ss, &sender_addr) == NULL) { 1148*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 1149*7c478bd9Sstevel@tonic-gate gettext("while converting socket address")); 1150*7c478bd9Sstevel@tonic-gate exit(1); 1151*7c478bd9Sstevel@tonic-gate } 1152*7c478bd9Sstevel@tonic-gate 1153*7c478bd9Sstevel@tonic-gate ss_length = sizeof (r_ss); 1154*7c478bd9Sstevel@tonic-gate if (getsockname(fd, (struct sockaddr *) &r_ss, &ss_length)) { 1155*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 1156*7c478bd9Sstevel@tonic-gate gettext("while getting local socket address")); 1157*7c478bd9Sstevel@tonic-gate exit(1); 1158*7c478bd9Sstevel@tonic-gate } 1159*7c478bd9Sstevel@tonic-gate 1160*7c478bd9Sstevel@tonic-gate if (cvtkaddr(&r_ss, &receiver_addr) == NULL) { 1161*7c478bd9Sstevel@tonic-gate com_err(progname, errno, 1162*7c478bd9Sstevel@tonic-gate gettext("while converting socket address")); 1163*7c478bd9Sstevel@tonic-gate exit(1); 1164*7c478bd9Sstevel@tonic-gate } 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate if (debug) { 1167*7c478bd9Sstevel@tonic-gate char *name; 1168*7c478bd9Sstevel@tonic-gate if (retval = krb5_unparse_name(context, server, &name)) { 1169*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("While unparsing server name")); 1170*7c478bd9Sstevel@tonic-gate exit(1); 1171*7c478bd9Sstevel@tonic-gate } 1172*7c478bd9Sstevel@tonic-gate printf(gettext("krb5_recvauth(%d, %s, %s, ...)\n"), fd, kprop_version, 1173*7c478bd9Sstevel@tonic-gate name); 1174*7c478bd9Sstevel@tonic-gate free(name); 1175*7c478bd9Sstevel@tonic-gate } 1176*7c478bd9Sstevel@tonic-gate 1177*7c478bd9Sstevel@tonic-gate if (retval = krb5_auth_con_init(context, &auth_context)) { 1178*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_auth_con_init: %s"), 1179*7c478bd9Sstevel@tonic-gate error_message(retval)); 1180*7c478bd9Sstevel@tonic-gate exit(1); 1181*7c478bd9Sstevel@tonic-gate } 1182*7c478bd9Sstevel@tonic-gate 1183*7c478bd9Sstevel@tonic-gate if (retval = krb5_auth_con_setflags(context, auth_context, 1184*7c478bd9Sstevel@tonic-gate KRB5_AUTH_CONTEXT_DO_SEQUENCE)) { 1185*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_auth_con_setflags: %s"), 1186*7c478bd9Sstevel@tonic-gate error_message(retval)); 1187*7c478bd9Sstevel@tonic-gate exit(1); 1188*7c478bd9Sstevel@tonic-gate } 1189*7c478bd9Sstevel@tonic-gate 1190*7c478bd9Sstevel@tonic-gate if (retval = krb5_auth_con_setaddrs(context, auth_context, &receiver_addr, 1191*7c478bd9Sstevel@tonic-gate &sender_addr)) { 1192*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_auth_con_setaddrs: %s"), 1193*7c478bd9Sstevel@tonic-gate error_message(retval)); 1194*7c478bd9Sstevel@tonic-gate exit(1); 1195*7c478bd9Sstevel@tonic-gate } 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate if (srvtab) { 1198*7c478bd9Sstevel@tonic-gate if (retval = krb5_kt_resolve(context, srvtab, &keytab)) { 1199*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_kt_resolve: %s"), error_message(retval)); 1200*7c478bd9Sstevel@tonic-gate exit(1); 1201*7c478bd9Sstevel@tonic-gate } 1202*7c478bd9Sstevel@tonic-gate } 1203*7c478bd9Sstevel@tonic-gate 1204*7c478bd9Sstevel@tonic-gate if (retval = krb5_recvauth(context, &auth_context, (void *) &fd, 1205*7c478bd9Sstevel@tonic-gate kprop_version, server, 0, keytab, &ticket)){ 1206*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_recvauth: %s"), 1207*7c478bd9Sstevel@tonic-gate error_message(retval)); 1208*7c478bd9Sstevel@tonic-gate exit(1); 1209*7c478bd9Sstevel@tonic-gate } 1210*7c478bd9Sstevel@tonic-gate 1211*7c478bd9Sstevel@tonic-gate if (retval = krb5_copy_principal(context, 1212*7c478bd9Sstevel@tonic-gate ticket->enc_part2->client, clientp)) { 1213*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, gettext("Error in krb5_copy_prinicpal: %s"), 1214*7c478bd9Sstevel@tonic-gate error_message(retval)); 1215*7c478bd9Sstevel@tonic-gate exit(1); 1216*7c478bd9Sstevel@tonic-gate } 1217*7c478bd9Sstevel@tonic-gate 1218*7c478bd9Sstevel@tonic-gate *etype = ticket->enc_part.enctype; 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate if (debug) { 1221*7c478bd9Sstevel@tonic-gate char * name; 1222*7c478bd9Sstevel@tonic-gate char etypebuf[100]; 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate if (retval = krb5_unparse_name(context, *clientp, &name)) { 1225*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 1226*7c478bd9Sstevel@tonic-gate gettext("While unparsing client name")); 1227*7c478bd9Sstevel@tonic-gate exit(1); 1228*7c478bd9Sstevel@tonic-gate } 1229*7c478bd9Sstevel@tonic-gate 1230*7c478bd9Sstevel@tonic-gate if (retval = krb5_enctype_to_string(*etype, etypebuf, 1231*7c478bd9Sstevel@tonic-gate sizeof(etypebuf))) { 1232*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("While unparsing ticket etype")); 1233*7c478bd9Sstevel@tonic-gate exit(1); 1234*7c478bd9Sstevel@tonic-gate } 1235*7c478bd9Sstevel@tonic-gate 1236*7c478bd9Sstevel@tonic-gate printf("authenticated client: %s (etype == %s)\n", name, etypebuf); 1237*7c478bd9Sstevel@tonic-gate free(name); 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate krb5_free_ticket(context, ticket); 1241*7c478bd9Sstevel@tonic-gate } 1242*7c478bd9Sstevel@tonic-gate 1243*7c478bd9Sstevel@tonic-gate krb5_boolean 1244*7c478bd9Sstevel@tonic-gate authorized_principal(context, p, auth_etype) 1245*7c478bd9Sstevel@tonic-gate krb5_context context; 1246*7c478bd9Sstevel@tonic-gate krb5_principal p; 1247*7c478bd9Sstevel@tonic-gate krb5_enctype auth_etype; 1248*7c478bd9Sstevel@tonic-gate { 1249*7c478bd9Sstevel@tonic-gate char *name, *ptr; 1250*7c478bd9Sstevel@tonic-gate char buf[1024]; 1251*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 1252*7c478bd9Sstevel@tonic-gate FILE *acl_file; 1253*7c478bd9Sstevel@tonic-gate int end; 1254*7c478bd9Sstevel@tonic-gate krb5_enctype acl_etype; 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate retval = krb5_unparse_name(context, p, &name); 1257*7c478bd9Sstevel@tonic-gate if (retval) 1258*7c478bd9Sstevel@tonic-gate return FALSE; 1259*7c478bd9Sstevel@tonic-gate 1260*7c478bd9Sstevel@tonic-gate acl_file = fopen(acl_file_name, "r"); 1261*7c478bd9Sstevel@tonic-gate if (!acl_file) 1262*7c478bd9Sstevel@tonic-gate return FALSE; 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate while (!feof(acl_file)) { 1265*7c478bd9Sstevel@tonic-gate if (!fgets(buf, sizeof(buf), acl_file)) 1266*7c478bd9Sstevel@tonic-gate break; 1267*7c478bd9Sstevel@tonic-gate end = strlen(buf) - 1; 1268*7c478bd9Sstevel@tonic-gate if (buf[end] == '\n') 1269*7c478bd9Sstevel@tonic-gate buf[end] = '\0'; 1270*7c478bd9Sstevel@tonic-gate if (!strncmp(name, buf, strlen(name))) { 1271*7c478bd9Sstevel@tonic-gate ptr = buf+strlen(name); 1272*7c478bd9Sstevel@tonic-gate 1273*7c478bd9Sstevel@tonic-gate /* if the next character is not whitespace or nul, then 1274*7c478bd9Sstevel@tonic-gate the match is only partial. continue on to new lines. */ 1275*7c478bd9Sstevel@tonic-gate if (*ptr && !isspace(*ptr)) 1276*7c478bd9Sstevel@tonic-gate continue; 1277*7c478bd9Sstevel@tonic-gate 1278*7c478bd9Sstevel@tonic-gate /* otherwise, skip trailing whitespace */ 1279*7c478bd9Sstevel@tonic-gate for (; *ptr && isspace(*ptr); ptr++) ; 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate /* now, look for an etype string. if there isn't one, 1282*7c478bd9Sstevel@tonic-gate return true. if there is an invalid string, continue. 1283*7c478bd9Sstevel@tonic-gate If there is a valid string, return true only if it 1284*7c478bd9Sstevel@tonic-gate matches the etype passed in, otherwise continue */ 1285*7c478bd9Sstevel@tonic-gate 1286*7c478bd9Sstevel@tonic-gate if ((*ptr) && 1287*7c478bd9Sstevel@tonic-gate ((retval = krb5_string_to_enctype(ptr, &acl_etype)) || 1288*7c478bd9Sstevel@tonic-gate (acl_etype != auth_etype))) 1289*7c478bd9Sstevel@tonic-gate continue; 1290*7c478bd9Sstevel@tonic-gate 1291*7c478bd9Sstevel@tonic-gate free(name); 1292*7c478bd9Sstevel@tonic-gate fclose(acl_file); 1293*7c478bd9Sstevel@tonic-gate return TRUE; 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate } 1296*7c478bd9Sstevel@tonic-gate free(name); 1297*7c478bd9Sstevel@tonic-gate fclose(acl_file); 1298*7c478bd9Sstevel@tonic-gate return FALSE; 1299*7c478bd9Sstevel@tonic-gate } 1300*7c478bd9Sstevel@tonic-gate 1301*7c478bd9Sstevel@tonic-gate void 1302*7c478bd9Sstevel@tonic-gate recv_database(context, fd, database_fd, confmsg) 1303*7c478bd9Sstevel@tonic-gate krb5_context context; 1304*7c478bd9Sstevel@tonic-gate int fd; 1305*7c478bd9Sstevel@tonic-gate int database_fd; 1306*7c478bd9Sstevel@tonic-gate krb5_data *confmsg; 1307*7c478bd9Sstevel@tonic-gate { 1308*7c478bd9Sstevel@tonic-gate int database_size; 1309*7c478bd9Sstevel@tonic-gate int received_size, n; 1310*7c478bd9Sstevel@tonic-gate char buf[1024]; 1311*7c478bd9Sstevel@tonic-gate krb5_data inbuf, outbuf; 1312*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 1313*7c478bd9Sstevel@tonic-gate 1314*7c478bd9Sstevel@tonic-gate /* 1315*7c478bd9Sstevel@tonic-gate * Receive and decode size from client 1316*7c478bd9Sstevel@tonic-gate */ 1317*7c478bd9Sstevel@tonic-gate if (retval = krb5_read_message(context, (void *) &fd, &inbuf)) { 1318*7c478bd9Sstevel@tonic-gate send_error(context, fd, retval, gettext("while reading database size")); 1319*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 1320*7c478bd9Sstevel@tonic-gate gettext("while reading size of database from client")); 1321*7c478bd9Sstevel@tonic-gate exit(1); 1322*7c478bd9Sstevel@tonic-gate } 1323*7c478bd9Sstevel@tonic-gate if (krb5_is_krb_error(&inbuf)) 1324*7c478bd9Sstevel@tonic-gate recv_error(context, &inbuf); 1325*7c478bd9Sstevel@tonic-gate if (retval = krb5_rd_safe(context,auth_context,&inbuf,&outbuf,NULL)) { 1326*7c478bd9Sstevel@tonic-gate send_error(context, fd, retval, gettext("while decoding database size")); 1327*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf); 1328*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 1329*7c478bd9Sstevel@tonic-gate gettext("while decoding database size from client")); 1330*7c478bd9Sstevel@tonic-gate exit(1); 1331*7c478bd9Sstevel@tonic-gate } 1332*7c478bd9Sstevel@tonic-gate memcpy((char *) &database_size, outbuf.data, sizeof(database_size)); 1333*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf); 1334*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &outbuf); 1335*7c478bd9Sstevel@tonic-gate database_size = ntohl(database_size); 1336*7c478bd9Sstevel@tonic-gate 1337*7c478bd9Sstevel@tonic-gate /* 1338*7c478bd9Sstevel@tonic-gate * Initialize the initial vector. 1339*7c478bd9Sstevel@tonic-gate */ 1340*7c478bd9Sstevel@tonic-gate if (retval = krb5_auth_con_initivector(context, auth_context)) { 1341*7c478bd9Sstevel@tonic-gate send_error(context, fd, retval, gettext("failed while initializing i_vector")); 1342*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while initializing i_vector")); 1343*7c478bd9Sstevel@tonic-gate exit(1); 1344*7c478bd9Sstevel@tonic-gate } 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate /* 1347*7c478bd9Sstevel@tonic-gate * Now start receiving the database from the net 1348*7c478bd9Sstevel@tonic-gate */ 1349*7c478bd9Sstevel@tonic-gate received_size = 0; 1350*7c478bd9Sstevel@tonic-gate while (received_size < database_size) { 1351*7c478bd9Sstevel@tonic-gate if (retval = krb5_read_message(context, (void *) &fd, &inbuf)) { 1352*7c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf), 1353*7c478bd9Sstevel@tonic-gate gettext("while reading database block starting at offset %d"), 1354*7c478bd9Sstevel@tonic-gate received_size); 1355*7c478bd9Sstevel@tonic-gate com_err(progname, retval, buf); 1356*7c478bd9Sstevel@tonic-gate send_error(context, fd, retval, buf); 1357*7c478bd9Sstevel@tonic-gate exit(1); 1358*7c478bd9Sstevel@tonic-gate } 1359*7c478bd9Sstevel@tonic-gate if (krb5_is_krb_error(&inbuf)) 1360*7c478bd9Sstevel@tonic-gate recv_error(context, &inbuf); 1361*7c478bd9Sstevel@tonic-gate if (retval = krb5_rd_priv(context, auth_context, &inbuf, 1362*7c478bd9Sstevel@tonic-gate &outbuf, NULL)) { 1363*7c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf), 1364*7c478bd9Sstevel@tonic-gate gettext("while decoding database block starting at offset %d"), 1365*7c478bd9Sstevel@tonic-gate received_size); 1366*7c478bd9Sstevel@tonic-gate com_err(progname, retval, buf); 1367*7c478bd9Sstevel@tonic-gate send_error(context, fd, retval, buf); 1368*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf); 1369*7c478bd9Sstevel@tonic-gate exit(1); 1370*7c478bd9Sstevel@tonic-gate } 1371*7c478bd9Sstevel@tonic-gate n = write(database_fd, outbuf.data, outbuf.length); 1372*7c478bd9Sstevel@tonic-gate if (n < 0) { 1373*7c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf), 1374*7c478bd9Sstevel@tonic-gate gettext( 1375*7c478bd9Sstevel@tonic-gate "while writing database block starting at offset %d"), 1376*7c478bd9Sstevel@tonic-gate received_size); 1377*7c478bd9Sstevel@tonic-gate send_error(context, fd, errno, buf); 1378*7c478bd9Sstevel@tonic-gate } else if (n != outbuf.length) { 1379*7c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf), 1380*7c478bd9Sstevel@tonic-gate gettext( 1381*7c478bd9Sstevel@tonic-gate "incomplete write while writing database block starting at\n" 1382*7c478bd9Sstevel@tonic-gate "offset %d (%d written, %d expected)"), 1383*7c478bd9Sstevel@tonic-gate received_size, n, outbuf.length); 1384*7c478bd9Sstevel@tonic-gate send_error(context, fd, KRB5KRB_ERR_GENERIC, buf); 1385*7c478bd9Sstevel@tonic-gate } 1386*7c478bd9Sstevel@tonic-gate received_size += outbuf.length; 1387*7c478bd9Sstevel@tonic-gate /* SUNWresync121: our krb5...contents sets length to 0 */ 1388*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &inbuf); 1389*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &outbuf); 1390*7c478bd9Sstevel@tonic-gate } 1391*7c478bd9Sstevel@tonic-gate /* 1392*7c478bd9Sstevel@tonic-gate * OK, we've seen the entire file. Did we get too many bytes? 1393*7c478bd9Sstevel@tonic-gate */ 1394*7c478bd9Sstevel@tonic-gate if (received_size > database_size) { 1395*7c478bd9Sstevel@tonic-gate snprintf(buf, sizeof (buf), 1396*7c478bd9Sstevel@tonic-gate gettext("Received %d bytes, expected %d bytes for database file"), 1397*7c478bd9Sstevel@tonic-gate received_size, database_size); 1398*7c478bd9Sstevel@tonic-gate send_error(context, fd, KRB5KRB_ERR_GENERIC, buf); 1399*7c478bd9Sstevel@tonic-gate } 1400*7c478bd9Sstevel@tonic-gate /* 1401*7c478bd9Sstevel@tonic-gate * Create message acknowledging number of bytes received, but 1402*7c478bd9Sstevel@tonic-gate * don't send it until kdb5_util returns successfully. 1403*7c478bd9Sstevel@tonic-gate */ 1404*7c478bd9Sstevel@tonic-gate database_size = htonl(database_size); 1405*7c478bd9Sstevel@tonic-gate inbuf.data = (char *) &database_size; 1406*7c478bd9Sstevel@tonic-gate inbuf.length = sizeof(database_size); 1407*7c478bd9Sstevel@tonic-gate if (retval = krb5_mk_safe(context,auth_context,&inbuf,confmsg,NULL)) { 1408*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 1409*7c478bd9Sstevel@tonic-gate gettext("while encoding # of receieved bytes")); 1410*7c478bd9Sstevel@tonic-gate send_error(context, fd, retval, 1411*7c478bd9Sstevel@tonic-gate gettext("while encoding # of received bytes")); 1412*7c478bd9Sstevel@tonic-gate exit(1); 1413*7c478bd9Sstevel@tonic-gate } 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate void 1418*7c478bd9Sstevel@tonic-gate send_error(context, fd, err_code, err_text) 1419*7c478bd9Sstevel@tonic-gate krb5_context context; 1420*7c478bd9Sstevel@tonic-gate int fd; 1421*7c478bd9Sstevel@tonic-gate krb5_error_code err_code; 1422*7c478bd9Sstevel@tonic-gate char *err_text; 1423*7c478bd9Sstevel@tonic-gate { 1424*7c478bd9Sstevel@tonic-gate krb5_error error; 1425*7c478bd9Sstevel@tonic-gate const char *text; 1426*7c478bd9Sstevel@tonic-gate krb5_data outbuf; 1427*7c478bd9Sstevel@tonic-gate char buf[1024]; 1428*7c478bd9Sstevel@tonic-gate 1429*7c478bd9Sstevel@tonic-gate memset((char *)&error, 0, sizeof(error)); 1430*7c478bd9Sstevel@tonic-gate krb5_us_timeofday(context, &error.stime, &error.susec); 1431*7c478bd9Sstevel@tonic-gate error.server = server; 1432*7c478bd9Sstevel@tonic-gate error.client = client; 1433*7c478bd9Sstevel@tonic-gate 1434*7c478bd9Sstevel@tonic-gate if (err_text) 1435*7c478bd9Sstevel@tonic-gate text = err_text; 1436*7c478bd9Sstevel@tonic-gate else 1437*7c478bd9Sstevel@tonic-gate text = error_message(err_code); 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate error.error = err_code - ERROR_TABLE_BASE_krb5; 1440*7c478bd9Sstevel@tonic-gate if (error.error > 127) { 1441*7c478bd9Sstevel@tonic-gate error.error = KRB_ERR_GENERIC; 1442*7c478bd9Sstevel@tonic-gate if (err_text) { 1443*7c478bd9Sstevel@tonic-gate sprintf(buf, "%s %s", error_message(err_code), 1444*7c478bd9Sstevel@tonic-gate err_text); 1445*7c478bd9Sstevel@tonic-gate text = buf; 1446*7c478bd9Sstevel@tonic-gate } 1447*7c478bd9Sstevel@tonic-gate } 1448*7c478bd9Sstevel@tonic-gate error.text.length = strlen(text) + 1; 1449*7c478bd9Sstevel@tonic-gate if (error.text.data = malloc(error.text.length)) { 1450*7c478bd9Sstevel@tonic-gate strcpy(error.text.data, text); 1451*7c478bd9Sstevel@tonic-gate if (!krb5_mk_error(context, &error, &outbuf)) { 1452*7c478bd9Sstevel@tonic-gate (void) krb5_write_message(context, (void *)&fd,&outbuf); 1453*7c478bd9Sstevel@tonic-gate krb5_free_data_contents(context, &outbuf); 1454*7c478bd9Sstevel@tonic-gate } 1455*7c478bd9Sstevel@tonic-gate free(error.text.data); 1456*7c478bd9Sstevel@tonic-gate } 1457*7c478bd9Sstevel@tonic-gate } 1458*7c478bd9Sstevel@tonic-gate 1459*7c478bd9Sstevel@tonic-gate void 1460*7c478bd9Sstevel@tonic-gate recv_error(context, inbuf) 1461*7c478bd9Sstevel@tonic-gate krb5_context context; 1462*7c478bd9Sstevel@tonic-gate krb5_data *inbuf; 1463*7c478bd9Sstevel@tonic-gate { 1464*7c478bd9Sstevel@tonic-gate krb5_error *error; 1465*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 1466*7c478bd9Sstevel@tonic-gate 1467*7c478bd9Sstevel@tonic-gate if (retval = krb5_rd_error(context, inbuf, &error)) { 1468*7c478bd9Sstevel@tonic-gate com_err(progname, retval, 1469*7c478bd9Sstevel@tonic-gate gettext("while decoding error packet from client")); 1470*7c478bd9Sstevel@tonic-gate exit(1); 1471*7c478bd9Sstevel@tonic-gate } 1472*7c478bd9Sstevel@tonic-gate if (error->error == KRB_ERR_GENERIC) { 1473*7c478bd9Sstevel@tonic-gate if (error->text.data) 1474*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1475*7c478bd9Sstevel@tonic-gate gettext("Generic remote error: %s\n"), 1476*7c478bd9Sstevel@tonic-gate error->text.data); 1477*7c478bd9Sstevel@tonic-gate } else if (error->error) { 1478*7c478bd9Sstevel@tonic-gate com_err(progname, error->error + ERROR_TABLE_BASE_krb5, 1479*7c478bd9Sstevel@tonic-gate gettext("signalled from server")); 1480*7c478bd9Sstevel@tonic-gate if (error->text.data) 1481*7c478bd9Sstevel@tonic-gate fprintf(stderr, 1482*7c478bd9Sstevel@tonic-gate gettext("Error text from client: %s\n"), 1483*7c478bd9Sstevel@tonic-gate error->text.data); 1484*7c478bd9Sstevel@tonic-gate } 1485*7c478bd9Sstevel@tonic-gate krb5_free_error(context, error); 1486*7c478bd9Sstevel@tonic-gate exit(1); 1487*7c478bd9Sstevel@tonic-gate } 1488*7c478bd9Sstevel@tonic-gate 1489*7c478bd9Sstevel@tonic-gate void 1490*7c478bd9Sstevel@tonic-gate load_database(context, kdb5_util, database_file_name) 1491*7c478bd9Sstevel@tonic-gate krb5_context context; 1492*7c478bd9Sstevel@tonic-gate char *kdb5_util; 1493*7c478bd9Sstevel@tonic-gate char *database_file_name; 1494*7c478bd9Sstevel@tonic-gate { 1495*7c478bd9Sstevel@tonic-gate static char *edit_av[10]; 1496*7c478bd9Sstevel@tonic-gate int error_ret, save_stderr; 1497*7c478bd9Sstevel@tonic-gate int child_pid; 1498*7c478bd9Sstevel@tonic-gate int count; 1499*7c478bd9Sstevel@tonic-gate int waitb; 1500*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 1501*7c478bd9Sstevel@tonic-gate kdb_log_context *log_ctx; 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate if (debug) 1504*7c478bd9Sstevel@tonic-gate printf(gettext("calling kdb5_util to load database\n")); 1505*7c478bd9Sstevel@tonic-gate 1506*7c478bd9Sstevel@tonic-gate log_ctx = context->kdblog_context; 1507*7c478bd9Sstevel@tonic-gate 1508*7c478bd9Sstevel@tonic-gate edit_av[0] = kdb5_util; 1509*7c478bd9Sstevel@tonic-gate count = 1; 1510*7c478bd9Sstevel@tonic-gate if (realm) { 1511*7c478bd9Sstevel@tonic-gate edit_av[count++] = "-r"; 1512*7c478bd9Sstevel@tonic-gate edit_av[count++] = realm; 1513*7c478bd9Sstevel@tonic-gate } 1514*7c478bd9Sstevel@tonic-gate edit_av[count++] = "load"; 1515*7c478bd9Sstevel@tonic-gate if (kerb_database) { 1516*7c478bd9Sstevel@tonic-gate edit_av[count++] = "-d"; 1517*7c478bd9Sstevel@tonic-gate edit_av[count++] = kerb_database; 1518*7c478bd9Sstevel@tonic-gate } 1519*7c478bd9Sstevel@tonic-gate 1520*7c478bd9Sstevel@tonic-gate if (log_ctx && (log_ctx->iproprole == IPROP_SLAVE)) { 1521*7c478bd9Sstevel@tonic-gate edit_av[count++] = "-i"; 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate edit_av[count++] = database_file_name; 1524*7c478bd9Sstevel@tonic-gate edit_av[count++] = NULL; 1525*7c478bd9Sstevel@tonic-gate 1526*7c478bd9Sstevel@tonic-gate switch(child_pid = fork()) { 1527*7c478bd9Sstevel@tonic-gate case -1: 1528*7c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while trying to fork %s"), 1529*7c478bd9Sstevel@tonic-gate kdb5_util); 1530*7c478bd9Sstevel@tonic-gate exit(1); 1531*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1532*7c478bd9Sstevel@tonic-gate case 0: 1533*7c478bd9Sstevel@tonic-gate if (!debug) { 1534*7c478bd9Sstevel@tonic-gate save_stderr = dup(2); 1535*7c478bd9Sstevel@tonic-gate close(0); 1536*7c478bd9Sstevel@tonic-gate close(1); 1537*7c478bd9Sstevel@tonic-gate close(2); 1538*7c478bd9Sstevel@tonic-gate open("/dev/null", O_RDWR); 1539*7c478bd9Sstevel@tonic-gate dup(0); 1540*7c478bd9Sstevel@tonic-gate dup(0); 1541*7c478bd9Sstevel@tonic-gate } 1542*7c478bd9Sstevel@tonic-gate 1543*7c478bd9Sstevel@tonic-gate execv(kdb5_util, edit_av); 1544*7c478bd9Sstevel@tonic-gate retval = errno; 1545*7c478bd9Sstevel@tonic-gate if (!debug) 1546*7c478bd9Sstevel@tonic-gate dup2(save_stderr, 2); 1547*7c478bd9Sstevel@tonic-gate com_err(progname, retval, gettext("while trying to exec %s"), 1548*7c478bd9Sstevel@tonic-gate kdb5_util); 1549*7c478bd9Sstevel@tonic-gate _exit(1); 1550*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1551*7c478bd9Sstevel@tonic-gate default: 1552*7c478bd9Sstevel@tonic-gate if (debug) 1553*7c478bd9Sstevel@tonic-gate printf(gettext("Child PID is %d\n"), child_pid); 1554*7c478bd9Sstevel@tonic-gate if (wait(&waitb) < 0) { 1555*7c478bd9Sstevel@tonic-gate com_err(progname, errno, gettext("while waiting for %s"), 1556*7c478bd9Sstevel@tonic-gate kdb5_util); 1557*7c478bd9Sstevel@tonic-gate exit(1); 1558*7c478bd9Sstevel@tonic-gate } 1559*7c478bd9Sstevel@tonic-gate } 1560*7c478bd9Sstevel@tonic-gate 1561*7c478bd9Sstevel@tonic-gate if ((error_ret = WEXITSTATUS(waitb)) != 0) { 1562*7c478bd9Sstevel@tonic-gate com_err(progname, 0, 1563*7c478bd9Sstevel@tonic-gate gettext("%s returned a bad exit status (%d)"), kdb5_util, 1564*7c478bd9Sstevel@tonic-gate error_ret); 1565*7c478bd9Sstevel@tonic-gate exit(1); 1566*7c478bd9Sstevel@tonic-gate } 1567*7c478bd9Sstevel@tonic-gate return; 1568*7c478bd9Sstevel@tonic-gate } 1569