static void initialize_realms(krb5_context kcontext, int argc, char **argv) { int c; char *db_name = (char *) NULL; char *lrealm = (char *) NULL; char *mkey_name = (char *) NULL; krb5_error_code retval; krb5_enctype menctype = ENCTYPE_UNKNOWN; kdc_realm_t *rdatap = NULL; krb5_boolean manual = FALSE; krb5_boolean def_restrict_anon; char *default_udp_ports = 0; char *default_tcp_ports = 0; krb5_pointer aprof; const char *hierarchy[3]; char *no_refrls = NULL; char *host_based_srvcs = NULL; int db_args_size = 0; char **db_args = NULL; extern char *optarg; if (!krb5_aprof_init(DEFAULT_KDC_PROFILE, KDC_PROFILE_ENV, &aprof)) { hierarchy[0] = KRB5_CONF_KDCDEFAULTS; hierarchy[1] = KRB5_CONF_KDC_PORTS; hierarchy[2] = (char *) NULL; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_udp_ports)) default_udp_ports = 0; hierarchy[1] = KRB5_CONF_KDC_TCP_PORTS; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &default_tcp_ports)) default_tcp_ports = 0; hierarchy[1] = KRB5_CONF_MAX_DGRAM_REPLY_SIZE; if (krb5_aprof_get_int32(aprof, hierarchy, TRUE, &max_dgram_reply_size)) max_dgram_reply_size = MAX_DGRAM_SIZE; hierarchy[1] = KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT; if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &def_restrict_anon)) def_restrict_anon = FALSE; hierarchy[1] = KRB5_CONF_NO_HOST_REFERRAL; if (krb5_aprof_get_string_all(aprof, hierarchy, &no_refrls)) no_refrls = 0; if (!no_refrls || krb5_match_config_pattern(no_refrls, KRB5_CONF_ASTERISK) == FALSE) { hierarchy[1] = KRB5_CONF_HOST_BASED_SERVICES; if (krb5_aprof_get_string_all(aprof, hierarchy, &host_based_srvcs)) host_based_srvcs = 0; } krb5_aprof_finish(aprof); } if (default_udp_ports == 0) { default_udp_ports = strdup(DEFAULT_KDC_UDP_PORTLIST); if (default_udp_ports == 0) { fprintf(stderr, _(" KDC cannot initialize. Not enough memory\n")); exit(1); } } if (default_tcp_ports == 0) { default_tcp_ports = strdup(DEFAULT_KDC_TCP_PORTLIST); if (default_tcp_ports == 0) { fprintf(stderr, _(" KDC cannot initialize. Not enough memory\n")); exit(1); } } /* * Loop through the option list. Each time we encounter a realm name, * use the previously scanned options to fill in for defaults. */ while ((c = getopt(argc, argv, "x:r:d:mM:k:R:e:P:p:s:nw:4:X3")) != -1) { switch(c) { case 'x': db_args_size++; { char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ if( temp == NULL ) { fprintf(stderr, _("%s: KDC cannot initialize. Not enough " "memory\n"), argv[0]); exit(1); } db_args = temp; } db_args[db_args_size-1] = optarg; db_args[db_args_size] = NULL; break; case 'r': /* realm name for db */ if (!find_realm_data(optarg, (krb5_ui_4) strlen(optarg))) { if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { if ((retval = init_realm(rdatap, optarg, mkey_name, menctype, default_udp_ports, default_tcp_ports, manual, def_restrict_anon, db_args, no_refrls, host_based_srvcs))) { fprintf(stderr, _("%s: cannot initialize realm %s - " "see log file for details\n"), argv[0], optarg); exit(1); } kdc_realmlist[kdc_numrealms] = rdatap; kdc_numrealms++; free(db_args), db_args=NULL, db_args_size = 0; } else { fprintf(stderr, _("%s: cannot initialize realm %s. Not " "enough memory\n"), argv[0], optarg); exit(1); } } break; case 'd': /* pathname for db */ /* now db_name is not a seperate argument. * It has to be passed as part of the db_args */ if( db_name == NULL ) { if (asprintf(&db_name, "dbname=%s", optarg) < 0) { fprintf(stderr, _("%s: KDC cannot initialize. Not enough " "memory\n"), argv[0]); exit(1); } } db_args_size++; { char **temp = realloc( db_args, sizeof(char*) * (db_args_size+1)); /* one for NULL */ if( temp == NULL ) { fprintf(stderr, _("%s: KDC cannot initialize. Not enough " "memory\n"), argv[0]); exit(1); } db_args = temp; } db_args[db_args_size-1] = db_name; db_args[db_args_size] = NULL; break; case 'm': /* manual type-in of master key */ manual = TRUE; if (menctype == ENCTYPE_UNKNOWN) menctype = ENCTYPE_DES_CBC_CRC; break; case 'M': /* master key name in DB */ mkey_name = optarg; break; case 'n': nofork++; /* don't detach from terminal */ break; case 'w': /* create multiple worker processes */ workers = atoi(optarg); if (workers <= 0) usage(argv[0]); break; case 'k': /* enctype for master key */ if (krb5_string_to_enctype(optarg, &menctype)) com_err(argv[0], 0, _("invalid enctype %s"), optarg); break; case 'R': /* Replay cache name; defunct since we don't use a replay cache. */ break; case 'P': pid_file = optarg; break; case 'p': if (default_udp_ports) free(default_udp_ports); default_udp_ports = strdup(optarg); if (!default_udp_ports) { fprintf(stderr, _(" KDC cannot initialize. Not enough " "memory\n")); exit(1); } #if 0 /* not yet */ if (default_tcp_ports) free(default_tcp_ports); default_tcp_ports = strdup(optarg); #endif break; case '4': break; case 'X': break; case '?': default: usage(argv[0]); } } /* * Check to see if we processed any realms. */ if (kdc_numrealms == 0) { /* no realm specified, use default realm */ if ((retval = krb5_get_default_realm(kcontext, &lrealm))) { com_err(argv[0], retval, _("while attempting to retrieve default realm")); fprintf (stderr, _("%s: %s, attempting to retrieve default realm\n"), argv[0], krb5_get_error_message(kcontext, retval)); exit(1); } if ((rdatap = (kdc_realm_t *) malloc(sizeof(kdc_realm_t)))) { if ((retval = init_realm(rdatap, lrealm, mkey_name, menctype, default_udp_ports, default_tcp_ports, manual, def_restrict_anon, db_args, no_refrls, host_based_srvcs))) { fprintf(stderr, _("%s: cannot initialize realm %s - see log " "file for details\n"), argv[0], lrealm); exit(1); } kdc_realmlist[0] = rdatap; kdc_numrealms++; } krb5_free_default_realm(kcontext, lrealm); } /* Ensure that this is set for our first request. */ kdc_active_realm = kdc_realmlist[0]; if (default_udp_ports) free(default_udp_ports); if (default_tcp_ports) free(default_tcp_ports); if (db_args) free(db_args); if (db_name) free(db_name); if (host_based_srvcs) free(host_based_srvcs); if (no_refrls) free(no_refrls); return; }
/* * Initialize a realm control structure from the alternate profile or from * the specified defaults. * * After we're complete here, the essence of the realm is embodied in the * realm data and we should be all set to begin operation for that realm. */ static krb5_error_code init_realm(kdc_realm_t * rdp, krb5_pointer aprof, char *realm, char *def_mpname, krb5_enctype def_enctype, char *def_udp_listen, char *def_tcp_listen, krb5_boolean def_manual, krb5_boolean def_restrict_anon, char **db_args, char *no_referral, char *hostbased) { krb5_error_code kret; krb5_boolean manual; int kdb_open_flags; char *svalue = NULL; const char *hierarchy[4]; krb5_kvno mkvno = IGNORE_VNO; memset(rdp, 0, sizeof(kdc_realm_t)); if (!realm) { kret = EINVAL; goto whoops; } hierarchy[0] = KRB5_CONF_REALMS; hierarchy[1] = realm; hierarchy[3] = NULL; rdp->realm_name = strdup(realm); if (rdp->realm_name == NULL) { kret = ENOMEM; goto whoops; } kret = krb5int_init_context_kdc(&rdp->realm_context); if (kret) { kdc_err(NULL, kret, _("while getting context for realm %s"), realm); goto whoops; } if (time_offset != 0) (void)krb5_set_time_offsets(rdp->realm_context, time_offset, 0); /* Handle master key name */ hierarchy[2] = KRB5_CONF_MASTER_KEY_NAME; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_mpname)) { rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) : strdup(KRB5_KDB_M_NAME); } if (!rdp->realm_mpname) { kret = ENOMEM; goto whoops; } /* Handle KDC addresses/ports */ hierarchy[2] = KRB5_CONF_KDC_LISTEN; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_listen)) { /* Try the old kdc_ports configuration option. */ hierarchy[2] = KRB5_CONF_KDC_PORTS; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_listen)) rdp->realm_listen = strdup(def_udp_listen); } if (!rdp->realm_listen) { kret = ENOMEM; goto whoops; } hierarchy[2] = KRB5_CONF_KDC_TCP_LISTEN; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_tcp_listen)) { /* Try the old kdc_tcp_ports configuration option. */ hierarchy[2] = KRB5_CONF_KDC_TCP_PORTS; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_tcp_listen)) rdp->realm_tcp_listen = strdup(def_tcp_listen); } if (!rdp->realm_tcp_listen) { kret = ENOMEM; goto whoops; } /* Handle stash file */ hierarchy[2] = KRB5_CONF_KEY_STASH_FILE; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &rdp->realm_stash)) manual = def_manual; else manual = FALSE; hierarchy[2] = KRB5_CONF_RESTRICT_ANONYMOUS_TO_TGT; if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &rdp->realm_restrict_anon)) rdp->realm_restrict_anon = def_restrict_anon; /* Handle master key type */ hierarchy[2] = KRB5_CONF_MASTER_KEY_TYPE; if (krb5_aprof_get_string(aprof, hierarchy, TRUE, &svalue) || krb5_string_to_enctype(svalue, &rdp->realm_mkey.enctype)) rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN; free(svalue); svalue = NULL; /* Handle reject-bad-transit flag */ hierarchy[2] = KRB5_CONF_REJECT_BAD_TRANSIT; if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &rdp->realm_reject_bad_transit)) rdp->realm_reject_bad_transit = TRUE; /* Handle assume des-cbc-crc is supported for session keys */ hierarchy[2] = KRB5_CONF_DES_CRC_SESSION_SUPPORTED; if (krb5_aprof_get_boolean(aprof, hierarchy, TRUE, &rdp->realm_assume_des_crc_sess)) rdp->realm_assume_des_crc_sess = TRUE; /* Handle ticket maximum life */ hierarchy[2] = KRB5_CONF_MAX_LIFE; if (krb5_aprof_get_deltat(aprof, hierarchy, TRUE, &rdp->realm_maxlife)) rdp->realm_maxlife = KRB5_KDB_MAX_LIFE; /* Handle ticket renewable maximum life */ hierarchy[2] = KRB5_CONF_MAX_RENEWABLE_LIFE; if (krb5_aprof_get_deltat(aprof, hierarchy, TRUE, &rdp->realm_maxrlife)) rdp->realm_maxrlife = KRB5_KDB_MAX_RLIFE; /* Handle KDC referrals */ hierarchy[2] = KRB5_CONF_NO_HOST_REFERRAL; (void)krb5_aprof_get_string_all(aprof, hierarchy, &svalue); kret = combine(no_referral, svalue, &rdp->realm_no_referral); if (kret) goto whoops; free(svalue); svalue = NULL; hierarchy[2] = KRB5_CONF_HOST_BASED_SERVICES; (void)krb5_aprof_get_string_all(aprof, hierarchy, &svalue); kret = combine(hostbased, svalue, &rdp->realm_hostbased); if (kret) goto whoops; free(svalue); svalue = NULL; /* * We've got our parameters, now go and setup our realm context. */ /* Set the default realm of this context */ if ((kret = krb5_set_default_realm(rdp->realm_context, realm))) { kdc_err(rdp->realm_context, kret, _("while setting default realm to %s"), realm); goto whoops; } /* first open the database before doing anything */ kdb_open_flags = KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC; if ((kret = krb5_db_open(rdp->realm_context, db_args, kdb_open_flags))) { kdc_err(rdp->realm_context, kret, _("while initializing database for realm %s"), realm); goto whoops; } /* Assemble and parse the master key name */ if ((kret = krb5_db_setup_mkey_name(rdp->realm_context, rdp->realm_mpname, rdp->realm_name, (char **) NULL, &rdp->realm_mprinc))) { kdc_err(rdp->realm_context, kret, _("while setting up master key name %s for realm %s"), rdp->realm_mpname, realm); goto whoops; } /* * Get the master key (note, may not be the most current mkey). */ if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, rdp->realm_mkey.enctype, manual, FALSE, rdp->realm_stash, &mkvno, NULL, &rdp->realm_mkey))) { kdc_err(rdp->realm_context, kret, _("while fetching master key %s for realm %s"), rdp->realm_mpname, realm); goto whoops; } if ((kret = krb5_db_fetch_mkey_list(rdp->realm_context, rdp->realm_mprinc, &rdp->realm_mkey))) { kdc_err(rdp->realm_context, kret, _("while fetching master keys list for realm %s"), realm); goto whoops; } /* Set up the keytab */ if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, &rdp->realm_keytab))) { kdc_err(rdp->realm_context, kret, _("while resolving kdb keytab for realm %s"), realm); goto whoops; } /* Preformat the TGS name */ if ((kret = krb5_build_principal(rdp->realm_context, &rdp->realm_tgsprinc, strlen(realm), realm, KRB5_TGS_NAME, realm, (char *) NULL))) { kdc_err(rdp->realm_context, kret, _("while building TGS name for realm %s"), realm); goto whoops; } if (!rkey_init_done) { krb5_data seed; /* * If all that worked, then initialize the random key * generators. */ seed.length = rdp->realm_mkey.length; seed.data = (char *)rdp->realm_mkey.contents; if ((kret = krb5_c_random_add_entropy(rdp->realm_context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) goto whoops; rkey_init_done = 1; } whoops: /* * If we choked, then clean up any dirt we may have dropped on the floor. */ if (kret) { finish_realm(rdp); } return(kret); }