예제 #1
0
/*
 * Find a remote realm TGS principal for an unknown host-based service
 * principal.
 */
static krb5_int32
find_referral_tgs(kdc_realm_t *kdc_active_realm, krb5_kdc_req *request,
                  krb5_principal *krbtgt_princ)
{
    krb5_error_code retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
    char **realms = NULL, *hostname = NULL;
    krb5_data srealm = request->server->realm;

    if (!is_referral_req(kdc_active_realm, request))
        goto cleanup;

    hostname = data2string(krb5_princ_component(kdc_context,
                                                request->server, 1));
    if (hostname == NULL) {
        retval = ENOMEM;
        goto cleanup;
    }
    /* If the hostname doesn't contain a '.', it's not a FQDN. */
    if (strchr(hostname, '.') == NULL)
        goto cleanup;
    retval = krb5_get_host_realm(kdc_context, hostname, &realms);
    if (retval) {
        /* no match found */
        kdc_err(kdc_context, retval, "unable to find realm of host");
        goto cleanup;
    }
    /* Don't return a referral to the empty realm or the service realm. */
    if (realms == NULL || realms[0] == NULL || *realms[0] == '\0' ||
        data_eq_string(srealm, realms[0])) {
        retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
        goto cleanup;
    }
    retval = krb5_build_principal(kdc_context, krbtgt_princ,
                                  srealm.length, srealm.data,
                                  "krbtgt", realms[0], (char *)0);
cleanup:
    krb5_free_host_realm(kdc_context, realms);
    free(hostname);

    return retval;
}
예제 #2
0
static krb5_int32
prep_reprocess_req(krb5_kdc_req *request, krb5_principal *krbtgt_princ)
{
    krb5_error_code retval = KRB5KRB_AP_ERR_BADMATCH;
    size_t len = 0;
    char **realms, **cpp, *temp_buf=NULL;
    krb5_data *comp1 = NULL, *comp2 = NULL;
    char *comp1_str = NULL;

    /* By now we know that server principal name is unknown.
     * If CANONICALIZE flag is set in the request
     * If req is not U2U authn. req
     * the requested server princ. has exactly two components
     * either
     *      the name type is NT-SRV-HST
     *      or name type is NT-UNKNOWN and
     *         the 1st component is listed in conf file under host_based_services
     * the 1st component is not in a list in conf under "no_host_referral"
     * the 2d component looks like fully-qualified domain name (FQDN)
     * If all of these conditions are satisfied - try mapping the FQDN and
     * re-process the request as if client had asked for cross-realm TGT.
     */
    if (isflagset(request->kdc_options, KDC_OPT_CANONICALIZE) &&
        !isflagset(request->kdc_options, KDC_OPT_ENC_TKT_IN_SKEY) &&
        krb5_princ_size(kdc_context, request->server) == 2) {

        comp1 = krb5_princ_component(kdc_context, request->server, 0);
        comp2 = krb5_princ_component(kdc_context, request->server, 1);

        comp1_str = calloc(1,comp1->length+1);
        if (!comp1_str) {
            retval = ENOMEM;
            goto cleanup;
         }
        strlcpy(comp1_str,comp1->data,comp1->length+1);

        if ((krb5_princ_type(kdc_context, request->server) == KRB5_NT_SRV_HST ||
            (krb5_princ_type(kdc_context, request->server) == KRB5_NT_UNKNOWN &&
            kdc_active_realm->realm_host_based_services != NULL &&
            (krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, comp1_str) == TRUE ||
             krb5_match_config_pattern(kdc_active_realm->realm_host_based_services, KRB5_CONF_ASTERISK) == TRUE))) &&
            (kdc_active_realm->realm_no_host_referral == NULL ||
            (krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, KRB5_CONF_ASTERISK) == FALSE &&
             krb5_match_config_pattern(kdc_active_realm->realm_no_host_referral, comp1_str) == FALSE))) {

            for (len=0; len < comp2->length; len++) {
                 if (comp2->data[len] == '.') break;
            }
            if (len == comp2->length)
                goto cleanup;
            temp_buf = calloc(1, comp2->length+1);
            if (!temp_buf){
                retval = ENOMEM;
                goto cleanup;
            }
            strlcpy(temp_buf, comp2->data,comp2->length+1);
            retval = krb5int_get_domain_realm_mapping(kdc_context, temp_buf, &realms);
            free(temp_buf);
            if (retval) {
                /* no match found */
                kdc_err(kdc_context, retval, 0);
                goto cleanup;
            }
            if (realms == 0) {
                retval = KRB5KRB_AP_ERR_BADMATCH;
                goto cleanup;
            }
            if (realms[0] == 0) {
                free(realms);
                retval = KRB5KRB_AP_ERR_BADMATCH;
                goto cleanup;
            }
            /* Modify request.
             * Construct cross-realm tgt :  krbtgt/REMOTE_REALM@LOCAL_REALM
             * and use it as a principal in this req.
             */
            retval = krb5_build_principal(kdc_context, krbtgt_princ,
                                          (*request->server).realm.length,
                                          (*request->server).realm.data,
                                          "krbtgt", realms[0], (char *)0);
            for (cpp = realms; *cpp; cpp++)
                   free(*cpp);
        }
    }
cleanup:
    free(comp1_str);
    return retval;
}
예제 #3
0
파일: main.c 프로젝트: ln5/krb5-anonsvn
int main(int argc, char **argv)
{
    krb5_error_code     retval;
    krb5_context        kcontext;
    verto_ctx *ctx;
    int errout = 0;
    int i;

    setlocale(LC_MESSAGES, "");
    if (strrchr(argv[0], '/'))
        argv[0] = strrchr(argv[0], '/')+1;

    if (!(kdc_realmlist = (kdc_realm_t **) malloc(sizeof(kdc_realm_t *) *
                                                  KRB5_KDC_MAX_REALMS))) {
        fprintf(stderr, _("%s: cannot get memory for realm list\n"), argv[0]);
        exit(1);
    }
    memset(kdc_realmlist, 0,
           (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS));

    /*
     * A note about Kerberos contexts: This context, "kcontext", is used
     * for the KDC operations, i.e. setup, network connection and error
     * reporting.  The per-realm operations use the "realm_context"
     * associated with each realm.
     */
    retval = krb5int_init_context_kdc(&kcontext);
    if (retval) {
        com_err(argv[0], retval, _("while initializing krb5"));
        exit(1);
    }
    krb5_klog_init(kcontext, "kdc", argv[0], 1);
    kdc_err_context = kcontext;
    kdc_progname = argv[0];
    /* N.B.: After this point, com_err sends output to the KDC log
       file, and not to stderr.  We use the kdc_err wrapper around
       com_err to ensure that the error state exists in the context
       known to the krb5_klog callback. */

    initialize_kdc5_error_table();

    /*
     * Scan through the argument list
     */
    initialize_realms(kcontext, argc, argv);

    ctx = loop_init(VERTO_EV_TYPE_NONE);
    if (!ctx) {
        kdc_err(kcontext, ENOMEM, _("while creating main loop"));
        finish_realms();
        return 1;
    }

    load_preauth_plugins(kcontext);
    load_authdata_plugins(kcontext);

    retval = setup_sam();
    if (retval) {
        kdc_err(kcontext, retval, _("while initializing SAM"));
        finish_realms();
        return 1;
    }

    /* Handle each realm's ports */
    for (i=0; i<kdc_numrealms; i++) {
        char *cp = kdc_realmlist[i]->realm_ports;
        int port;
        while (cp && *cp) {
            if (*cp == ',' || isspace((int) *cp)) {
                cp++;
                continue;
            }
            port = strtol(cp, &cp, 10);
            if (cp == 0)
                break;
            retval = loop_add_udp_port(port);
            if (retval)
                goto net_init_error;
        }

        cp = kdc_realmlist[i]->realm_tcp_ports;
        while (cp && *cp) {
            if (*cp == ',' || isspace((int) *cp)) {
                cp++;
                continue;
            }
            port = strtol(cp, &cp, 10);
            if (cp == 0)
                break;
            retval = loop_add_tcp_port(port);
            if (retval)
                goto net_init_error;
        }
    }

    /*
     * Setup network listeners.  Disallow network reconfig in response to
     * routing socket messages if we're using worker processes, since the
     * children won't be able to re-open the listener sockets.  Hopefully our
     * platform has pktinfo support and doesn't need reconfigs.
     */
    if (workers == 0) {
        retval = loop_setup_routing_socket(ctx, NULL, kdc_progname);
        if (retval) {
            kdc_err(kcontext, retval, _("while initializing routing socket"));
            finish_realms();
            return 1;
        }
        retval = loop_setup_signals(ctx, NULL, reset_for_hangup);
        if (retval) {
            kdc_err(kcontext, retval, _("while initializing signal handlers"));
            finish_realms();
            return 1;
        }
    }
    if ((retval = loop_setup_network(ctx, NULL, kdc_progname))) {
    net_init_error:
        kdc_err(kcontext, retval, _("while initializing network"));
        finish_realms();
        return 1;
    }
    if (!nofork && daemon(0, 0)) {
        kdc_err(kcontext, errno, _("while detaching from tty"));
        finish_realms();
        return 1;
    }
    if (pid_file != NULL) {
        retval = write_pid_file(pid_file);
        if (retval) {
            kdc_err(kcontext, retval, _("while creating PID file"));
            finish_realms();
            return 1;
        }
    }
    if (workers > 0) {
        finish_realms();
        retval = create_workers(ctx, workers);
        if (retval) {
            kdc_err(kcontext, errno, _("creating worker processes"));
            return 1;
        }
        /* We get here only in a worker child process; re-initialize realms. */
        initialize_realms(kcontext, argc, argv);
    }
    krb5_klog_syslog(LOG_INFO, _("commencing operation"));
    if (nofork)
        fprintf(stderr, _("%s: starting...\n"), kdc_progname);

    verto_run(ctx);
    loop_free(ctx);
    krb5_klog_syslog(LOG_INFO, _("shutting down"));
    unload_preauth_plugins(kcontext);
    unload_authdata_plugins(kcontext);
    krb5_klog_close(kdc_context);
    finish_realms();
    if (kdc_realmlist)
        free(kdc_realmlist);
#ifndef NOCACHE
    kdc_free_lookaside(kcontext);
#endif
    krb5_free_context(kcontext);
    return errout;
}
예제 #4
0
파일: main.c 프로젝트: ln5/krb5-anonsvn
/*
 * 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, char *realm, char *def_mpname,
           krb5_enctype def_enctype, char *def_udp_ports, char *def_tcp_ports,
           krb5_boolean def_manual, krb5_boolean def_restrict_anon,
           char **db_args, char *no_refrls, char *host_based_srvcs)
{
    krb5_error_code     kret;
    krb5_boolean        manual;
    krb5_realm_params   *rparams;
    int                 kdb_open_flags;
    krb5_kvno       mkvno = IGNORE_VNO;

    memset(rdp, 0, sizeof(kdc_realm_t));
    if (!realm) {
        kret = EINVAL;
        goto whoops;
    }

    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;
    }

    kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name,
                                  &rparams);
    if (kret) {
        kdc_err(rdp->realm_context, kret, _("while reading realm parameters"));
        goto whoops;
    }

    /* Handle profile file name */
    if (rparams && rparams->realm_profile) {
        rdp->realm_profile = strdup(rparams->realm_profile);
        if (!rdp->realm_profile) {
            kret = ENOMEM;
            goto whoops;
        }
    }

    /* Handle master key name */
    if (rparams && rparams->realm_mkey_name)
        rdp->realm_mpname = strdup(rparams->realm_mkey_name);
    else
        rdp->realm_mpname = (def_mpname) ? strdup(def_mpname) :
            strdup(KRB5_KDB_M_NAME);
    if (!rdp->realm_mpname) {
        kret = ENOMEM;
        goto whoops;
    }

    /* Handle KDC ports */
    if (rparams && rparams->realm_kdc_ports)
        rdp->realm_ports = strdup(rparams->realm_kdc_ports);
    else
        rdp->realm_ports = strdup(def_udp_ports);
    if (!rdp->realm_ports) {
        kret = ENOMEM;
        goto whoops;
    }
    if (rparams && rparams->realm_kdc_tcp_ports)
        rdp->realm_tcp_ports = strdup(rparams->realm_kdc_tcp_ports);
    else
        rdp->realm_tcp_ports = strdup(def_tcp_ports);
    if (!rdp->realm_tcp_ports) {
        kret = ENOMEM;
        goto whoops;
    }
    /* Handle stash file */
    if (rparams && rparams->realm_stash_file) {
        rdp->realm_stash = strdup(rparams->realm_stash_file);
        if (!rdp->realm_stash) {
            kret = ENOMEM;
            goto whoops;
        }
        manual = FALSE;
    } else
        manual = def_manual;

    if (rparams && rparams->realm_restrict_anon_valid)
        rdp->realm_restrict_anon = rparams->realm_restrict_anon;
    else
        rdp->realm_restrict_anon = def_restrict_anon;

    /* Handle master key type */
    if (rparams && rparams->realm_enctype_valid)
        rdp->realm_mkey.enctype = (krb5_enctype) rparams->realm_enctype;
    else
        rdp->realm_mkey.enctype = manual ? def_enctype : ENCTYPE_UNKNOWN;

    /* Handle reject-bad-transit flag */
    if (rparams && rparams->realm_reject_bad_transit_valid)
        rdp->realm_reject_bad_transit = rparams->realm_reject_bad_transit;
    else
        rdp->realm_reject_bad_transit = 1;

    /* Handle ticket maximum life */
    rdp->realm_maxlife = (rparams && rparams->realm_max_life_valid) ?
        rparams->realm_max_life : KRB5_KDB_MAX_LIFE;

    /* Handle ticket renewable maximum life */
    rdp->realm_maxrlife = (rparams && rparams->realm_max_rlife_valid) ?
        rparams->realm_max_rlife : KRB5_KDB_MAX_RLIFE;

    /* Handle KDC referrals */
    kret = handle_referral_params(rparams, no_refrls, host_based_srvcs, rdp);
    if (kret == ENOMEM)
        goto whoops;

    if (rparams)
        krb5_free_realm_params(rdp->realm_context, rparams);

    /*
     * 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, mkvno, &rdp->mkey_list))) {
        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);
}
예제 #5
0
파일: main.c 프로젝트: mrogers950/krb5
int main(int argc, char **argv)
{
    krb5_error_code     retval;
    krb5_context        kcontext;
    kdc_realm_t *realm;
    verto_ctx *ctx;
    int tcp_listen_backlog;
    int errout = 0;
    int i;

    setlocale(LC_ALL, "");
    if (strrchr(argv[0], '/'))
        argv[0] = strrchr(argv[0], '/')+1;

    shandle.kdc_realmlist = malloc(sizeof(kdc_realm_t *) *
                                   KRB5_KDC_MAX_REALMS);
    if (shandle.kdc_realmlist == NULL) {
        fprintf(stderr, _("%s: cannot get memory for realm list\n"), argv[0]);
        exit(1);
    }
    memset(shandle.kdc_realmlist, 0,
           (size_t) (sizeof(kdc_realm_t *) * KRB5_KDC_MAX_REALMS));

    /*
     * A note about Kerberos contexts: This context, "kcontext", is used
     * for the KDC operations, i.e. setup, network connection and error
     * reporting.  The per-realm operations use the "realm_context"
     * associated with each realm.
     */
    retval = krb5int_init_context_kdc(&kcontext);
    if (retval) {
        com_err(argv[0], retval, _("while initializing krb5"));
        exit(1);
    }
    krb5_klog_init(kcontext, "kdc", argv[0], 1);
    shandle.kdc_err_context = kcontext;
    kdc_progname = argv[0];
    /* N.B.: After this point, com_err sends output to the KDC log
       file, and not to stderr.  We use the kdc_err wrapper around
       com_err to ensure that the error state exists in the context
       known to the krb5_klog callback. */

    initialize_kdc5_error_table();

    /*
     * Scan through the argument list
     */
    initialize_realms(kcontext, argc, argv, &tcp_listen_backlog);

#ifndef NOCACHE
    retval = kdc_init_lookaside(kcontext);
    if (retval) {
        kdc_err(kcontext, retval, _("while initializing lookaside cache"));
        finish_realms();
        return 1;
    }
#endif

    ctx = loop_init(VERTO_EV_TYPE_NONE);
    if (!ctx) {
        kdc_err(kcontext, ENOMEM, _("while creating main loop"));
        finish_realms();
        return 1;
    }

    load_preauth_plugins(&shandle, kcontext, ctx);
    load_authdata_plugins(kcontext);

    retval = setup_sam();
    if (retval) {
        kdc_err(kcontext, retval, _("while initializing SAM"));
        finish_realms();
        return 1;
    }

    /* Add each realm's listener addresses to the loop. */
    for (i = 0; i < shandle.kdc_numrealms; i++) {
        realm = shandle.kdc_realmlist[i];
        if (*realm->realm_listen != '\0') {
            retval = loop_add_udp_address(KRB5_DEFAULT_PORT,
                                          realm->realm_listen);
            if (retval)
                goto net_init_error;
        }
        if (*realm->realm_tcp_listen != '\0') {
            retval = loop_add_tcp_address(KRB5_DEFAULT_PORT,
                                          realm->realm_tcp_listen);
            if (retval)
                goto net_init_error;
        }
    }

    if (workers == 0) {
        retval = loop_setup_signals(ctx, &shandle, reset_for_hangup);
        if (retval) {
            kdc_err(kcontext, retval, _("while initializing signal handlers"));
            finish_realms();
            return 1;
        }
    }
    if ((retval = loop_setup_network(ctx, &shandle, kdc_progname,
                                     tcp_listen_backlog))) {
    net_init_error:
        kdc_err(kcontext, retval, _("while initializing network"));
        finish_realms();
        return 1;
    }
    if (!nofork && daemon(0, 0)) {
        kdc_err(kcontext, errno, _("while detaching from tty"));
        finish_realms();
        return 1;
    }
    if (pid_file != NULL) {
        retval = write_pid_file(pid_file);
        if (retval) {
            kdc_err(kcontext, retval, _("while creating PID file"));
            finish_realms();
            return 1;
        }
    }
    if (workers > 0) {
        finish_realms();
        retval = create_workers(ctx, workers);
        if (retval) {
            kdc_err(kcontext, errno, _("creating worker processes"));
            return 1;
        }
        /* We get here only in a worker child process; re-initialize realms. */
        initialize_realms(kcontext, argc, argv, NULL);
    }

    /* Initialize audit system and audit KDC startup. */
    retval = load_audit_modules(kcontext);
    if (retval) {
        kdc_err(kcontext, retval, _("while loading audit plugin module(s)"));
        finish_realms();
        return 1;
    }
    krb5_klog_syslog(LOG_INFO, _("commencing operation"));
    if (nofork)
        fprintf(stderr, _("%s: starting...\n"), kdc_progname);
    kau_kdc_start(kcontext, TRUE);

    verto_run(ctx);
    loop_free(ctx);
    kau_kdc_stop(kcontext, TRUE);
    krb5_klog_syslog(LOG_INFO, _("shutting down"));
    unload_preauth_plugins(kcontext);
    unload_authdata_plugins(kcontext);
    unload_audit_modules(kcontext);
    krb5_klog_close(kcontext);
    finish_realms();
    if (shandle.kdc_realmlist)
        free(shandle.kdc_realmlist);
#ifndef NOCACHE
    kdc_free_lookaside(kcontext);
#endif
    krb5_free_context(kcontext);
    return errout;
}
예제 #6
0
파일: main.c 프로젝트: mrogers950/krb5
/*
 * 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);
}