1   /*
   2    * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
   3    * Use is subject to license terms.
   4    */
   5   
   6 | #pragma ident        "@(#)ovsec_kadmd.c        1.9        04/09/08 SMI"
   6 | #pragma ident        "@(#)ovsec_kadmd.c        1.8        04/05/24 SMI"
   7   
   8   /*
   9    * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  10    *
  11    *        Openvision retains the copyright to derivative works of
  12    *        this source code.        Do *NOT* create a derivative of this
  13    *        source code before consulting with your legal department.
  14    *        Do *NOT* integrate *ANY* of this source code into another
  15    *        product before consulting with your legal department.
  16    *
  17    *        For further information, read the top-level Openvision
  18    *        copyright which is contained in the top-level MIT Kerberos
  19    *        copyright.
  20    *
  21    * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  22    *
  23    */
  24   
  25   
  26   /*
  27    * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
  28    */
  29   
  30   /*
  31    * SUNWresync121 XXX
  32    * Beware future resyncers, this file is much diff from MIT (1.0...)
  33    */
  34   
  35   #include <stdio.h>
  36   #include <signal.h>
  37   #include <syslog.h>
  38   #include <sys/types.h>
  39   #include <sys/time.h>
  40   #include <sys/socket.h>
  41   #include <unistd.h>
  42   #include <netinet/in.h>
  43   #include <arpa/inet.h>        /* inet_ntoa */
  44   #include <netdb.h>
  45   #include <gssapi/gssapi.h>
  46   #include <rpc/rpc.h>
  47   #include <kadm5/admin.h>
  48   #include <kadm5/kadm_rpc.h>
  49   #include <kadm5/server_internal.h>
  50   #include <server_acl.h>
  51   #include <krb5/adm_proto.h>
  52   #include <string.h>
  53   #include <gssapi_krb5.h>
  54   #include <libintl.h>
  55   #include <locale.h>
  56   #include <sys/resource.h>
  57 + #include <kdb/kdb_log.h>
  58   
  59 + #include <rpc/rpcsec_gss.h>
  60 + 
  61   #ifndef        FD_SETSIZE
  62   #define        FD_SETSIZE        256
  63   #endif
  64   
  65   #ifndef MAX
  66   #define        MAX(a, b)        (((a) > (b)) ? (a) : (b))
  67   #endif
  68   
  69   static int signal_request_exit = 0;
  70   static int schpw;
  71   kadm5_config_params chgpw_params;
  72   void kadm_svc_run(void);
  70 | void setup_signal_handlers();
  73 | void setup_signal_handlers(iprop_role iproprole);
  74   void sig_exit(int);
  75   void sig_pipe(int);
  76   
  77   #ifdef POSIX_SIGNALS
  78   static struct sigaction s_action;
  79   #endif /* POSIX_SIGNALS */
  80   
  81   #define        TIMEOUT        15
  82   
  83   typedef struct _auth_gssapi_name {
  84           char *name;
  85           gss_OID type;
  86   } auth_gssapi_name;
  87   
  88   gss_name_t gss_changepw_name = NULL, gss_oldchangepw_name = NULL;
  89   void *global_server_handle;
  90   
  91   /*
  92    * This is a kludge, but the server needs these constants to be
  93    * compatible with old clients.        They are defined in <kadm5/admin.h>,
  94    * but only if USE_KADM5_API_VERSION == 1.
  95    */
  96   #define        OVSEC_KADM_ADMIN_SERVICE_P        "ovsec_adm@admin"
  97   #define        OVSEC_KADM_CHANGEPW_SERVICE_P        "ovsec_adm@changepw"
  98   
  99   /*
 100    * This enables us to set the keytab that gss_acquire_cred uses, but
 101    * it also restricts us to linking against the Kv5 GSS-API library.
 102    * Since this is *k*admind, that shouldn't be a problem.
 103    */
 104   extern char *krb5_overridekeyname;
 105   
 106 + extern void krb5_iprop_prog_1();
 107 + extern kadm5_ret_t kiprop_get_adm_host_srv_name(
 108 +         krb5_context,
 109 +         const char *,
 110 +         char **);
 111   
 112   /*
 113    * Function: usage
 114    *
 115    * Purpose: print out the server usage message
 116    *
 117    * Arguments:
 118    * Requires:
 119    * Effects:
 120    * Modifies:
 121    */
 122   
 123   void
 124   usage()
 125   {
 126           fprintf(stderr, gettext("Usage: kadmind [-r realm] [-m] [-d] "
 127               "[-p port-number]\n"));
 128           exit(1);
 129   }

 ----Unchanged portion omitted----

 181   
 182   static krb5_context context;  /* XXX yuck.  the signal handlers need this */
 183   
 184   in_port_t l_port = 0;        /* global local port num, for BSM audits */
 185   
 186 + int nofork = 0; /* global; don't fork (debug mode) */
 187 + 
 188   int
 189   main(int argc, char *argv[])
 190   {
 191           void kadm_1(struct svc_req *, SVCXPRT *);
 192           SVCXPRT *transp;
 193           extern char *optarg;
 194           extern int optind, opterr;
 185 |         int ret, rlen, nofork, oldnames = 0;
 195 |         int ret, rlen, oldnames = 0;
 196           OM_uint32 OMret, major_status, minor_status;
 197           char *whoami;
 198           FILE *acl_file;
 199           gss_buffer_desc in_buf;
 200           struct servent *srv;
 201           struct sockaddr_in addr;
 202           struct sockaddr_in *sin;
 203           int s;
 204           int optchar;
 205           struct netconfig *nconf;
 206           void *handlep;
 207           int fd;
 208           struct t_info tinfo;
 209           struct t_bind tbindstr, *tres;
 210   
 211           struct t_optmgmt req, resp;
 212           struct opthdr *opt;
 213           char reqbuf[128];
 214           int *ip;
 215           struct rlimit rl;
 216   
 217 +         char *kiprop_name = NULL; /* IProp svc name */
 218 +         kdb_log_context *log_ctx;
 219           kadm5_server_handle_t handle;
 220           krb5_context ctx;
 221 + 
 222           kadm5_config_params params;
 223           auth_gssapi_name names[6];
 224                gss_buffer_desc gssbuf;
 225                gss_OID nt_krb5_name_oid;
 226   
 227           int allowed;
 228   
 229           /* This is OID value the Krb5_Name NameType */
 230                gssbuf.value = "{1 2 840 113554 1 2 2 1}";
 231                gssbuf.length = strlen(gssbuf.value);
 232                major_status = gss_str_to_oid(&minor_status, &gssbuf,
 233                                       &nt_krb5_name_oid);
 234                if (major_status != GSS_S_COMPLETE) {
 235                   fprintf(stderr,
 236                           gettext("Couldn't create KRB5 Name NameType OID\n"));
 237                   display_status("str_to_oid", major_status, minor_status);
 238                   exit(1);
 239                }
 240   
 241           names[0].name = names[1].name = names[2].name = 
 242                   names[3].name = names[4].name  = names[5].name =NULL;
 243           names[0].type = names[1].type = names[2].type = 
 244                   names[3].type = names[4].type = names[5].type =
 245                   (gss_OID) nt_krb5_name_oid;
 246   
 247           whoami = (strrchr(argv[0], '/') ? strrchr(argv[0], '/') + 1 : argv[0]);
 248   
 249           (void) setlocale(LC_ALL, "");
 250   
 251   #if !defined(TEXT_DOMAIN)  /* Should be defined by cc -D */
 252   #define        TEXT_DOMAIN        "SYS_TEST"        /* Use this only if it weren't */
 253   #endif
 254   
 255           (void) textdomain(TEXT_DOMAIN);
 256   
 257           nofork = 0;
 258   
 259           memset((char *) &params, 0, sizeof (params));
 260   
 261           while ((optchar = getopt(argc, argv, "r:mdp:")) != EOF) {
 262                   switch (optchar) {
 263                   case 'r':
 264                           if (!optarg)
 265                                   usage();
 266                           params.realm = optarg;
 267                           params.mask |= KADM5_CONFIG_REALM;
 268                           break;
 269                   case 'm':
 270                           params.mkey_from_kbd = 1;
 271                           params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
 272                           break;
 273                   case 'd':
 274                           nofork = 1;
 275                           break;
 276                   case 'p':
 277                           if (!optarg)
 278                                   usage();
 279                           params.kadmind_port = atoi(optarg);
 280                           params.mask |= KADM5_CONFIG_KADMIND_PORT;
 281                           break;
 282                   case '?':
 283                   default:
 284                           usage();
 285                   }
 286           }
 287   
 288   
 289           if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
 290                   rl.rlim_cur = rl.rlim_max = MAX(rl.rlim_max, FD_SETSIZE);
 291                   setrlimit(RLIMIT_NOFILE, &rl);
 292           }
 293   
 294           if (!nofork && (ret = daemon(0, 0))) {
 295                   ret = errno;
 296                   krb5_klog_syslog(LOG_ERR,
 297                       gettext("Cannot detach from tty: %s"),
 298                       error_message(ret));
 299                   fprintf(stderr, gettext("%s: Cannot detach from tty: %s\n"),
 300                       whoami, error_message(ret));
 301                   krb5_klog_close(context);
 302                   exit(1);
 303           }
 304   
 305           if (ret = krb5_init_context(&context)) {
 306                   fprintf(stderr,
 307                       gettext("%s: %s while initializing context, aborting\n"),
 308                       whoami, error_message(ret));
 309                   exit(1);
 310           }
 311   
 312           krb5_klog_init(context, "admin_server", whoami, 1);
 313   
 314   
 315           /*
 316            * When using the Horowitz/IETF protocol for
 317            * password changing, the default port is 464
 318            * (officially recognized by IANA)
 319            *
 320            * DEFAULT_KPASSWD_PORT -> 464
 321            */
 322           chgpw_params.kpasswd_port = DEFAULT_KPASSWD_PORT;
 323           chgpw_params.mask |= KADM5_CONFIG_KPASSWD_PORT;
 324           chgpw_params.kpasswd_protocol = KRB5_CHGPWD_CHANGEPW_V2;
 325           chgpw_params.mask |= KADM5_CONFIG_KPASSWD_PROTOCOL;
 326   
 327           if (ret = kadm5_get_config_params(context, NULL, NULL, &chgpw_params,
 328                   &chgpw_params)) {
 329                   krb5_klog_syslog(LOG_ERR, gettext("%s: %s while initializing,"
 330                                   " aborting"), whoami, error_message(ret));
 331                   fprintf(stderr,
 332                       gettext("%s: %s while initializing, aborting\n"),
 333                       whoami, error_message(ret));
 334                   krb5_klog_close(context);
 335                   exit(1);
 336           }
 337   
 338           /*
 339            * We now setup the socket and bind() to port 464, so that
 340            * kadmind can now listen to and process change-pwd requests
 341            * from non-Solaris Kerberos V5 clients such as Microsoft,
 342            * MIT, AIX, HP etc
 343            */
 344           if ((schpw = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
 345                   krb5_klog_syslog(LOG_ERR, gettext( "cannot create simple "
 346                                   "chpw socket: %s"), error_message(errno));
 347                   fprintf(stderr, gettext("Cannot create simple chpw "
 348                                           "socket: %s"), error_message(errno));
 349                   krb5_klog_close(context);
 350                   exit(1);
 351           }
 352   
 353           /*
 354            * Don't allow socket re-use.  This should prevent multiple
 355            * daemons from starting at the same time.
 356            */
 357           allowed = 0;
 358           if (setsockopt(schpw, SOL_SOCKET, SO_REUSEADDR,
 359                       (char *) &allowed, sizeof(allowed)) < 0) {
 360                   krb5_klog_syslog(LOG_ERR, gettext("cannot set SO_REUSEADDR "
 361                                   "on simple chpw socket: %s"),
 362                                   error_message(errno));
 363                   fprintf(stderr, gettext("Cannot set SO_REUSEADDR on "
 364                           "simple chpw socket: %s"), error_message(errno));
 365           }
 366   
 367           memset(&addr, 0, sizeof(addr));
 368           addr.sin_family = AF_INET;
 369           addr.sin_addr.s_addr = INADDR_ANY;
 370           addr.sin_port = htons(chgpw_params.kpasswd_port);
 371   
 372           if (bind(schpw, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 373                   char portbuf[32];
 374                   int oerrno = errno;
 375                   fprintf(stderr, gettext("%s: Cannot bind socket.\n"), whoami);
 376                   fprintf(stderr, gettext("bind: %s\n"), error_message(oerrno));
 377                   errno = oerrno;
 378                   (void) snprintf(portbuf, sizeof (portbuf), "%d",
 379                                   ntohs(addr.sin_port));
 380                   krb5_klog_syslog(LOG_ERR, gettext("cannot bind simple "
 381                                   "chpw socket: %s"), error_message(oerrno));
 382                   if(oerrno == EADDRINUSE) {
 383                           char *w = strrchr(whoami, '/');
 384                           if (w) {
 385                                   w++;
 386                           }
 387                           else {
 388                                   w = whoami;
 389                           }
 390                           fprintf(stderr, gettext(
 391                                   "This probably means that another %s process\n"
 392                                   "is already running, or that another program\n"
 393                                   "is using the server port (number %d).\n"
 394                                   "If another %s is already running, you should\n"
 395                                   "kill it before restarting the server.\n"),
 396                                   w, ntohs(addr.sin_port), w);
 397                   }
 398                   krb5_klog_close(context);
 399                   exit(1);
 400           }
 401   
 402           if (ret = kadm5_get_config_params(context, NULL, NULL, &params,
 403                   &params)) {
 404                   krb5_klog_syslog(LOG_ERR, gettext("%s: %s while initializing,"
 405                                   " aborting"), whoami, error_message(ret));
 406                   fprintf(stderr,
 407                       gettext("%s: %s while initializing, aborting\n"),
 408                       whoami, error_message(ret));
 409                   krb5_klog_close(context);
 410                   exit(1);
 411           }
 412   #define        REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_ACL_FILE | \
 413                           KADM5_CONFIG_ADMIN_KEYTAB)
 414   
 415           if ((params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
 416                   krb5_klog_syslog(LOG_ERR,
 417                       gettext("%s: Missing required configuration values "
 418                           "while initializing, aborting"), whoami,
 419                       (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS);
 420                   fprintf(stderr,
 421                       gettext("%s: Missing required configuration values "
 422                           "(%x) while initializing, aborting\n"), whoami,
 423                       (params.mask & REQUIRED_PARAMS) ^ REQUIRED_PARAMS);
 424                   krb5_klog_close(context);
 425                   exit(1);
 426           }
 427           memset((char *) &addr, 0, sizeof (struct sockaddr_in));
 428           addr.sin_family = AF_INET;
 429           addr.sin_addr.s_addr = INADDR_ANY;
 430           l_port = addr.sin_port = htons(params.kadmind_port);
 431           sin = &addr;
 432   
 433           if ((handlep = setnetconfig()) == (void *) NULL) {
 434                   (void) krb5_klog_syslog(LOG_ERR,
 435                       gettext("cannot get any transport information"));
 436                   krb5_klog_close(context);
 437                   exit(1);
 438           }
 439           while (nconf = getnetconfig(handlep)) {
 440                   if ((nconf->nc_semantics == NC_TPI_COTS_ORD) &&
 441                       (strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
 442                       (strcmp(nconf->nc_proto, NC_TCP) == 0))
 443                           break;
 444           }
 445   
 446           if (nconf == (struct netconfig *) NULL) {
 447                   (void) endnetconfig(handlep);
 448                   krb5_klog_close(context);
 449                   exit(1);
 450           }
 451           fd = t_open(nconf->nc_device, O_RDWR, &tinfo);
 452           if (fd == -1) {
 453                   krb5_klog_syslog(LOG_ERR,
 454                       gettext("unable to open connection for ADMIN server"));
 455                   krb5_klog_close(context);
 456                   exit(1);
 457           }
 458           /* LINTED */
 459           opt = (struct opthdr *) reqbuf;
 460           opt->level = SOL_SOCKET;
 461           opt->name = SO_REUSEADDR;
 462           opt->len = sizeof (int);
 463   
 464           /* LINTED */
 465           ip = (int *) &reqbuf[sizeof (struct opthdr)];
 466   
 467           /*
 468            * The option value is "0".  This is supposed to
 469            * Prevent socket reuse and thus prevent multiple
 470            * daemons from running on the same port.
 471            */
 472           *ip = 0;
 473   
 474           req.flags = T_NEGOTIATE;
 475           req.opt.len = sizeof (struct opthdr) + opt->len;
 476           req.opt.buf = (char *) opt;
 477   
 478           resp.flags = 0;
 479           resp.opt.buf = reqbuf;
 480           resp.opt.maxlen = sizeof (reqbuf);
 481   
 482           if (t_optmgmt(fd, &req, &resp) < 0 || resp.flags != T_SUCCESS) {
 483                   t_error("t_optmgmt");
 484                   exit(1);
 485           }
 486           /* Transform addr to netbuf */
 487   
 488           tres = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR);
 489           if (tres == NULL) {
 490                   (void) t_close(fd);
 491                   (void) krb5_klog_syslog(LOG_ERR,
 492                                           gettext("cannot allocate netbuf"));
 493                   krb5_klog_close(context);
 494                   exit(1);
 495           }
 496           tbindstr.qlen = 8;
 497           tbindstr.addr.buf = (char *) sin;
 498           tbindstr.addr.len = tbindstr.addr.maxlen = __rpc_get_a_size(tinfo.addr);
 499           sin = (struct sockaddr_in *) tbindstr.addr.buf;
 500           /* SUNWresync121 XXX (void) memset(&addr, 0, sizeof(addr)); */
 501   
 502           if (t_bind(fd, &tbindstr, tres) < 0) {
 503                   int oerrno = errno;
 504                   fprintf(stderr, gettext("%s: Cannot bind socket.\n"), whoami);
 505                   fprintf(stderr, gettext("bind: %s\n"), error_message(oerrno));
 506                   errno = oerrno;
 507                   krb5_klog_syslog(LOG_ERR, gettext("Cannot bind socket: %s"),
 508                       error_message(errno));
 509                   if (oerrno == EADDRINUSE) {
 510                           char *w = strrchr(whoami, '/');
 511   
 512                           if (w) {
 513                                   w++;
 514                           } else {
 515                                   w = whoami;
 516                           }
 517                           fprintf(stderr, gettext(
 518                                   "This probably means that another %s "
 519                                   "process is already\n"
 520                                   "running, or that another program is using "
 521                                   "the server port (number %d)\n"
 522                                   "after being assigned it by the RPC "
 523                                   "portmap deamon.        If another\n"
 524                                   "%s is already running, you should kill "
 525                                   "it before\n"
 526                                   "restarting the server. If, on the other hand, "
 527                                   "another program is\n"
 528                                   "using the server port, you should kill it "
 529                                   "before running\n"
 530                                   "%s, and ensure that the conflict does "
 531                                   "not occur in the\n"
 532                                   "future by making sure that %s is started "
 533                                   "on reboot\n"
 534                                   "before portmap.\n"),
 535                               w, ntohs(addr.sin_port), w, w, w);
 536                           krb5_klog_syslog(LOG_ERR,
 537                               gettext("Check for already-running %s or for "
 538                                   "another process using port %d"), w,
 539                               htons(addr.sin_port));
 540                   }
 541                   krb5_klog_close(context);
 542                   exit(1);
 543           }
 544           transp = svc_tli_create(fd, nconf, NULL, 0, 0);
 545           (void) t_free((char *) tres, T_BIND);
 546           if (transp == NULL) {
 547                   fprintf(stderr, gettext("%s: Cannot create RPC service.\n"),
 548                           whoami);
 549                   krb5_klog_syslog(LOG_ERR, gettext("Cannot create RPC service: %m"));
 550                   krb5_klog_close(context);
 551                   exit(1);
 552           }
 553           if (!svc_register(transp, KADM, KADMVERS, kadm_1, 0)) {
 554                   fprintf(stderr,
 555                       gettext("%s: Cannot register RPC service.\n"), whoami);
 556                   krb5_klog_syslog(LOG_ERR,
 557                       gettext("Cannot register RPC service, failing."));
 558                   krb5_klog_close(context);
 559                   exit(1);
 560           }
 561   
 562 +         /*
 563 +          * XXX krb5_defkeyname is an internal library global and should go
 564 +          * away
 565 +          */
 566 +         krb5_overridekeyname = params.admin_keytab;
 567 + 
 568           (void) kadm5_get_adm_host_srv_name(context,
 569                                              params.realm, &names[0].name);
 570           (void) kadm5_get_cpw_host_srv_name(context,
 571                                              params.realm, &names[1].name);
 572           names[2].name = KADM5_ADMIN_SERVICE_P;
 573           names[3].name = KADM5_CHANGEPW_SERVICE_P;
 574           names[4].name = OVSEC_KADM_ADMIN_SERVICE_P;
 575           names[5].name = OVSEC_KADM_CHANGEPW_SERVICE_P;
 576   
 577           if (names[0].name == NULL || names[1].name == NULL ||
 578               names[2].name == NULL || names[3].name == NULL ||
 579               names[4].name == NULL || names[5].name == NULL) {
 580                   krb5_klog_syslog(LOG_ERR,
 581                       gettext("Cannot initialize GSS-API authentication, "
 582                           "failing."));
 583                   fprintf(stderr,
 584                       gettext("%s: Cannot initialize "
 585                           "GSS-API authentication.\n"),
 586                       whoami);
 587                   krb5_klog_close(context);
 588                   exit(1);
 571 -         /*
 572 -          * XXX krb5_defkeyname is an internal library global and should go
 573 -          * away
 574 -          */
 575 -         krb5_overridekeyname = params.admin_keytab;
 589           }
 590   
 591           /*
 592            * Try to acquire creds for the old OV services as well as the new
 593            * names, but if that fails just fall back on the new names.
 594            */
 595           
 596           if (rpc_gss_set_svc_name(names[5].name,
 597                                   "kerberos_v5", 0, KADM, KADMVERS) &&
 598               rpc_gss_set_svc_name(names[4].name,
 599                                   "kerberos_v5", 0, KADM, KADMVERS))
 600                   oldnames++;
 601           if (rpc_gss_set_svc_name(names[3].name,
 602                                   "kerberos_v5", 0, KADM, KADMVERS))
 603                   oldnames++;
 604           if (rpc_gss_set_svc_name(names[2].name,
 605                                   "kerberos_v5", 0, KADM, KADMVERS))
 606                   oldnames++;
 607           if (rpc_gss_set_svc_name(names[0].name,
 608                                   "kerberos_v5", 0, KADM, KADMVERS))
 609                   oldnames++;
 610           if (rpc_gss_set_svc_name(names[1].name,
 611                                   "kerberos_v5", 0, KADM, KADMVERS))
 612                   oldnames++;
 613           if (!oldnames) {
 614                   krb5_klog_syslog(LOG_ERR,
 615                       gettext("Cannot initialize GSS-API authentication, "
 616                           "failing."));
 617                   fprintf(stderr,
 618                       gettext("%s:Cannot initialize GSS-API authentication.\n"),
 619                       whoami);
 620                   krb5_klog_close(context);
 621                   exit(1);
 622           }
 623   
 624           /* if set_names succeeded, this will too */
 625           in_buf.value = names[1].name;
 626           in_buf.length = strlen(names[1].name) + 1;
 627           (void) gss_import_name(&OMret, &in_buf, (gss_OID) nt_krb5_name_oid,
 628               &gss_changepw_name);
 629           if (oldnames) {
 630                   in_buf.value = names[3].name;
 631                   in_buf.length = strlen(names[3].name) + 1;
 632                   (void) gss_import_name(&OMret, &in_buf,
 633                                           (gss_OID) nt_krb5_name_oid,
 634                                           &gss_oldchangepw_name);
 635           }
 636           if (ret = acl_init(context, 0, params.acl_file)) {
 637                   krb5_klog_syslog(LOG_ERR, gettext("Cannot initialize acl file: %s"),
 638                       error_message(ret));
 639                   fprintf(stderr, gettext("%s: Cannot initialize acl file: %s\n"),
 640                       whoami, error_message(ret));
 641                   krb5_klog_close(context);
 642                   exit(1);
 643           }
 644           if ((ret = kadm5_init("kadmind", NULL,
 645                       NULL, &params,
 646                       KADM5_STRUCT_VERSION,
 647                       KADM5_API_VERSION_2,
 648                       &global_server_handle)) != KADM5_OK) {
 649                   krb5_klog_syslog(LOG_ERR,
 650                       gettext("%s while initializing, aborting"),
 651                       error_message(ret));
 652                   fprintf(stderr,
 653                       gettext("%s: %s while initializing, aborting\n"),
 654                       whoami, error_message(ret));
 655                   krb5_klog_close(context);
 656                   exit(1);
 657           }
 658   
 659           handle = global_server_handle;
 660           ctx = handle->context;
 661 +         if (params.iprop_enabled == TRUE)
 662 +                 ulog_set_role(ctx, IPROP_MASTER);
 663 +         else
 664 +                 ulog_set_role(ctx, IPROP_NULL);
 665   
 666 +         log_ctx = ctx->kdblog_context;
 667 + 
 668 +         if (log_ctx && (log_ctx->iproprole == IPROP_MASTER)) {
 669 +                 /*
 670 +                  * IProp is enabled, so let's map in the update log
 671 +                  * and setup the service.
 672 +                  */
 673 +                 if (ret = ulog_map(ctx, &params, FKADMIND)) {
 674 +                         fprintf(stderr,
 675 +                                 gettext("%s: %s while mapping update log "
 676 +                                 "(`%s.ulog')\n"), whoami, error_message(ret),
 677 +                                 params.dbname);
 678 +                         krb5_klog_syslog(LOG_ERR,
 679 +                                 gettext("%s while mapping update log "
 680 +                                 "(`%s.ulog')"), error_message(ret),
 681 +                                 params.dbname);
 682 +                         krb5_klog_close(ctx);
 683 +                         exit(1);
 684 +                 }
 685 + 
 686 + 
 687 +                 if (nofork)
 688 +                         fprintf(stderr,
 689 +                                 "%s: create IPROP svc (PROG=%d, VERS=%d)\n",
 690 +                                 whoami, KRB5_IPROP_PROG, KRB5_IPROP_VERS);
 691 + 
 692 +                 if (!svc_create(krb5_iprop_prog_1,
 693 +                                 KRB5_IPROP_PROG, KRB5_IPROP_VERS,
 694 +                                 "circuit_v")) {
 695 +                         fprintf(stderr,
 696 +     gettext("%s: Cannot create IProp RPC service (PROG=%d, VERS=%d)\n"),
 697 +                                 whoami,
 698 +                                 KRB5_IPROP_PROG, KRB5_IPROP_VERS);
 699 +                         krb5_klog_syslog(LOG_ERR,
 700 +     gettext("Cannot create IProp RPC service (PROG=%d, VERS=%d), failing."),
 701 +                                         KRB5_IPROP_PROG, KRB5_IPROP_VERS);
 702 +                         krb5_klog_close(ctx);
 703 +                         exit(1);
 704 +                 }
 705 + 
 706 +                 if (ret = kiprop_get_adm_host_srv_name(ctx,
 707 +                                                         params.realm,
 708 +                                                         &kiprop_name)) {
 709 +                         krb5_klog_syslog(LOG_ERR,
 710 +                         gettext("%s while getting IProp svc name, failing"),
 711 +                                         error_message(ret));
 712 +                         fprintf(stderr,
 713 +                 gettext("%s: %s while getting IProp svc name, failing\n"),
 714 +                                 whoami, error_message(ret));
 715 +                         krb5_klog_close(ctx);
 716 +                         exit(1);
 717 +                 }
 718 + 
 719 +                 if (!rpc_gss_set_svc_name(kiprop_name, "kerberos_v5", 0,
 720 +                                         KRB5_IPROP_PROG, KRB5_IPROP_VERS)) {
 721 +                         rpc_gss_error_t err;
 722 +                         (void) rpc_gss_get_error(&err);
 723 + 
 724 +                         krb5_klog_syslog(LOG_ERR,
 725 +     gettext("Unable to set RPCSEC_GSS service name (`%s'), failing."),
 726 +                                         kiprop_name ? kiprop_name : "<null>");
 727 + 
 728 +                         fprintf(stderr,
 729 +     gettext("%s: Unable to set RPCSEC_GSS service name (`%s'), failing.\n"),
 730 +                                 whoami,
 731 +                                 kiprop_name ? kiprop_name : "<null>");
 732 + 
 733 +                         if (nofork) {
 734 +                                 fprintf(stderr,
 735 +                         "%s: set svc name (rpcsec err=%d, sys err=%d)\n",
 736 +                                         whoami,
 737 +                                         err.rpc_gss_error,
 738 +                                         err.system_error);
 739 +                         }
 740 + 
 741 +                         exit(1);
 742 +                 }
 743 +                 free(kiprop_name);
 744 +         }
 745 + 
 746 +         setup_signal_handlers(log_ctx->iproprole);
 747           krb5_klog_syslog(LOG_INFO, gettext("starting"));
 748 +         if (nofork)
 749 +                 fprintf(stderr, "%s: starting...\n", whoami);
 750   
 751 + 
 752           /*
 753            * We now call our own customized async event processing
 754            * function kadm_svc_run(), as opposed to svc_run() earlier,
 755            * since this enables kadmind to also listen-to/process
 756            * non-RPCSEC_GSS based change-pwd requests apart from the
 757            * regular, RPCSEC_GSS kpasswd requests from Solaris Krb5 clients.
 758            */
 759           kadm_svc_run();
 760   
 761           krb5_klog_syslog(LOG_INFO, gettext("finished, exiting"));
 762           kadm5_destroy(global_server_handle);
 763           t_close(fd);
 764           krb5_klog_close(context);
 765           exit(0);
 766   }

 ----Unchanged portion omitted----

 837   
 838   
 839   /*
 840    * Function: setup_signal_handlers
 841    *
 842    * Purpose: Setup signal handling functions with System V's signal().
 843    */
 742 | void setup_signal_handlers() {
 844 | void setup_signal_handlers(iprop_role iproprole) {
 845           signal(SIGINT, sig_exit);
 846           signal(SIGTERM, sig_exit);
 847           signal(SIGQUIT, sig_exit);
 848           signal(SIGPIPE, sig_pipe);
 849 + 
 850 +         /*
 851 +          * IProp will fork for a full-resync, we don't want to
 852 +          * wait on it and we don't want the living dead procs either.
 853 +          */
 854 +         if (iproprole == IPROP_MASTER)
 855 +                 (void) signal(SIGCHLD, SIG_IGN);
 856 + 
 857           return;
 858   }

 ----Unchanged portion omitted----