int main() { krb5_db_entry *ent; krb5_context context; krb5_string_attr *strings; char *val; int count; assert(krb5int_init_context_kdc(&context) == 0); /* Start with an empty entry. */ ent = calloc(1, sizeof(*ent)); if (ent == NULL) { fprintf(stderr, "Can't allocate memory for entry.\n"); return 1; } /* Check that the entry has no strings to start. */ assert(krb5_dbe_get_strings(context, ent, &strings, &count) == 0); assert(strings == NULL && count == 0); krb5_dbe_free_strings(context, strings, count); /* Check that we get a null value querying a specific attribute. */ assert(krb5_dbe_get_string(context, ent, "foo", &val) == 0); assert(val == NULL); /* Set some attributes one at a time, including a deletion. */ assert(krb5_dbe_set_string(context, ent, "eggs", "dozen") == 0); assert(krb5_dbe_set_string(context, ent, "price", "right") == 0); assert(krb5_dbe_set_string(context, ent, "eggs", NULL) == 0); assert(krb5_dbe_set_string(context, ent, "time", "flies") == 0); /* Query each attribute. */ assert(krb5_dbe_get_string(context, ent, "price", &val) == 0); assert(strcmp(val, "right") == 0); krb5_dbe_free_string(context, val); assert(krb5_dbe_get_string(context, ent, "time", &val) == 0); assert(strcmp(val, "flies") == 0); krb5_dbe_free_string(context, val); assert(krb5_dbe_get_string(context, ent, "eggs", &val) == 0); assert(val == NULL); /* Query the list of attributes and verify it. */ assert(krb5_dbe_get_strings(context, ent, &strings, &count) == 0); assert(count == 2); assert(strcmp(strings[0].key, "price") == 0); assert(strcmp(strings[0].value, "right") == 0); assert(strcmp(strings[1].key, "time") == 0); assert(strcmp(strings[1].value, "flies") == 0); krb5_dbe_free_strings(context, strings, count); krb5_db_free_principal(context, ent); krb5_free_context(context); return 0; }
/* * 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); }
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; }
krb5_error_code osa_adb_init_db(osa_adb_db_t *dbp, char *filename, char *lockfilename, int magic) { osa_adb_db_t db; static struct _locklist *locklist = NULL; struct _locklist *lockp; krb5_error_code code; if (dbp == NULL || filename == NULL) return EINVAL; db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent)); if (db == NULL) return ENOMEM; memset(db, 0, sizeof(*db)); db->info.hash = NULL; db->info.bsize = 256; db->info.ffactor = 8; db->info.nelem = 25000; db->info.lorder = 0; db->btinfo.flags = 0; db->btinfo.cachesize = 0; db->btinfo.psize = 4096; db->btinfo.lorder = 0; db->btinfo.minkeypage = 0; db->btinfo.compare = NULL; db->btinfo.prefix = NULL; /* * A process is allowed to open the same database multiple times * and access it via different handles. If the handles use * distinct lockinfo structures, things get confused: lock(A), * lock(B), release(B) will result in the kernel unlocking the * lock file but handle A will still think the file is locked. * Therefore, all handles using the same lock file must share a * single lockinfo structure. * * It is not sufficient to have a single lockinfo structure, * however, because a single process may also wish to open * multiple different databases simultaneously, with different * lock files. This code used to use a single static lockinfo * structure, which means that the second database opened used * the first database's lock file. This was Bad. * * We now maintain a linked list of lockinfo structures, keyed by * lockfilename. An entry is added when this function is called * with a new lockfilename, and all subsequent calls with that * lockfilename use the existing entry, updating the refcnt. * When the database is closed with fini_db(), the refcnt is * decremented, and when it is zero the lockinfo structure is * freed and reset. The entry in the linked list, however, is * never removed; it will just be reinitialized the next time * init_db is called with the right lockfilename. */ /* find or create the lockinfo structure for lockfilename */ lockp = locklist; while (lockp) { if (strcmp(lockp->lockinfo.filename, lockfilename) == 0) break; else lockp = lockp->next; } if (lockp == NULL) { /* doesn't exist, create it, add to list */ lockp = (struct _locklist *) malloc(sizeof(*lockp)); if (lockp == NULL) { free(db); return ENOMEM; } memset(lockp, 0, sizeof(*lockp)); lockp->lockinfo.filename = strdup(lockfilename); if (lockp->lockinfo.filename == NULL) { free(lockp); free(db); return ENOMEM; } lockp->next = locklist; locklist = lockp; } /* now initialize lockp->lockinfo if necessary */ if (lockp->lockinfo.lockfile == NULL) { if ((code = krb5int_init_context_kdc(&lockp->lockinfo.context))) { free(db); return((krb5_error_code) code); } /* * needs be open read/write so that write locking can work with * POSIX systems */ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) { /* * maybe someone took away write permission so we could only * get shared locks? */ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r")) == NULL) { free(db); return OSA_ADB_NOLOCKFILE; } } set_cloexec_file(lockp->lockinfo.lockfile); lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0; } /* lockp is set, lockinfo is initialized, update the reference count */ db->lock = &lockp->lockinfo; db->lock->refcnt++; db->opencnt = 0; db->filename = strdup(filename); db->magic = magic; *dbp = db; return OSA_ADB_OK; }
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; }
/* * 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); }
int main(int argc, char **argv) { krb5_error_code retval; krb5_context kcontext; int errout = 0; krb5_boolean log_stderr_set; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "KRB5KDC_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); 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, gettext("%s: cannot get memory for realm list\n"), argv[0]); exit(1); } memset((char *) 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, gettext("while initializing krb5")); exit(1); } krb5_klog_init(kcontext, "kdc", argv[0], 1); /* * Solaris Kerberos: * In the early stages of krb5kdc it is desirable to log error messages * to stderr as well as any other logging locations specified in config * files. */ log_stderr_set = krb5_klog_logging_to_stderr(); if (log_stderr_set != TRUE) { krb5_klog_add_stderr(); } /* initialize_kdc5_error_table(); SUNWresync121 XXX */ /* * Scan through the argument list */ initialize_realms(kcontext, argc, argv); setup_signal_handlers(); load_preauth_plugins(kcontext); retval = setup_sam(); if (retval) { com_err(argv[0], retval, gettext("while initializing SAM")); finish_realms(argv[0]); return 1; } if ((retval = setup_network(argv[0]))) { com_err(argv[0], retval, gettext("while initializing network")); finish_realms(argv[0]); return 1; } /* Solaris Kerberos: Remove the extra stderr logging */ if (log_stderr_set != TRUE) krb5_klog_remove_stderr(); /* * Solaris Kerberos: * List the logs (FILE, STDERR, etc) which are currently being * logged to and print that to stderr. Useful when trying to * track down a failure via SMF. */ if (retval = krb5_klog_list_logs(argv[0])) { com_err(argv[0], retval, gettext("while listing logs")); if (log_stderr_set != TRUE) { fprintf(stderr, gettext("%s: %s while listing logs\n"), argv[0], error_message(retval)); } } if (!nofork && daemon(0, 0)) { com_err(argv[0], errno, gettext("while detaching from tty")); if (log_stderr_set != TRUE) { fprintf(stderr, gettext("%s: %s while detaching from tty\n"), argv[0], strerror(errno)); } finish_realms(argv[0]); return 1; } if (retval = krb5_klog_syslog(LOG_INFO, "commencing operation")) { com_err(argv[0], retval, gettext("while logging message")); errout++; }; if ((retval = listen_and_process(argv[0]))) { com_err(argv[0], retval, gettext("while processing network requests")); errout++; } if ((retval = closedown_network(argv[0]))) { com_err(argv[0], retval, gettext("while shutting down network")); errout++; } krb5_klog_syslog(LOG_INFO, "shutting down"); unload_preauth_plugins(kcontext); krb5_klog_close(kdc_context); finish_realms(argv[0]); if (kdc_realmlist) free(kdc_realmlist); #ifdef USE_RCACHE (void) krb5_rc_close(kcontext, kdc_rcache); #endif #ifndef NOCACHE kdc_free_lookaside(kcontext); #endif krb5_free_context(kcontext); return errout; }
/* * 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(krb5_context kcontext, char *progname, 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, char **db_args) { krb5_error_code kret; krb5_boolean manual; krb5_realm_params *rparams; memset((char *) rdp, 0, sizeof(kdc_realm_t)); if (!realm) { kret = EINVAL; goto whoops; } rdp->realm_name = realm; kret = krb5int_init_context_kdc(&rdp->realm_context); if (kret) { com_err(progname, kret, gettext("while getting context for realm %s"), realm); goto whoops; } /* * Solaris Kerberos: * Set the current context to that of the realm being init'ed */ krb5_klog_set_context(rdp->realm_context); kret = krb5_read_realm_params(rdp->realm_context, rdp->realm_name, &rparams); if (kret) { com_err(progname, kret, gettext("while reading realm parameters")); goto whoops; } /* Handle profile file name */ if (rparams && rparams->realm_profile) rdp->realm_profile = strdup(rparams->realm_profile); /* 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); /* 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 (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); /* Handle stash file */ if (rparams && rparams->realm_stash_file) { rdp->realm_stash = strdup(rparams->realm_stash_file); manual = FALSE; } else manual = def_manual; /* 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; 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))) { com_err(progname, kret, gettext("while setting default realm to %s"), realm); goto whoops; } /* first open the database before doing anything */ #ifdef KRBCONF_KDC_MODIFIES_KDB if ((kret = krb5_db_open(rdp->realm_context, db_args, KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_KDC))) { #else if ((kret = krb5_db_open(rdp->realm_context, db_args, KRB5_KDB_OPEN_RO | KRB5_KDB_SRV_TYPE_KDC))) { #endif /* * Solaris Kerberos: * Make sure that error messages are printed using gettext */ com_err(progname, kret, gettext("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))) { com_err(progname, kret, gettext("while setting up master key name %s for realm %s"), rdp->realm_mpname, realm); goto whoops; } /* * Get the master key. */ if ((kret = krb5_db_fetch_mkey(rdp->realm_context, rdp->realm_mprinc, rdp->realm_mkey.enctype, manual, FALSE, rdp->realm_stash, 0, &rdp->realm_mkey))) { com_err(progname, kret, gettext("while fetching master key %s for realm %s"), rdp->realm_mpname, realm); goto whoops; } /* Verify the master key */ if ((kret = krb5_db_verify_master_key(rdp->realm_context, rdp->realm_mprinc, &rdp->realm_mkey))) { com_err(progname, kret, gettext("while verifying master key for realm %s"), realm); goto whoops; } if ((kret = krb5_db_set_mkey(rdp->realm_context, &rdp->realm_mkey))) { com_err(progname, kret, gettext("while processing master key for realm %s"), realm); goto whoops; } /* Set up the keytab */ if ((kret = krb5_ktkdb_resolve(rdp->realm_context, NULL, &rdp->realm_keytab))) { com_err(progname, kret, gettext("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))) { com_err(progname, kret, gettext("while building TGS name for realm %s"), realm); goto whoops; } if (!rkey_init_done) { krb5_data seed; #ifdef KRB5_KRB4_COMPAT krb5_keyblock temp_key; #endif /* * If all that worked, then initialize the random key * generators. */ seed.length = rdp->realm_mkey.length; seed.data = (char *)rdp->realm_mkey.contents; /* SUNW14resync - XXX */ #if 0 if ((kret = krb5_c_random_add_entropy(rdp->realm_context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed))) goto whoops; #endif #ifdef KRB5_KRB4_COMPAT if ((kret = krb5_c_make_random_key(rdp->realm_context, ENCTYPE_DES_CBC_CRC, &temp_key))) { com_err(progname, kret, "while initializing V4 random key generator"); goto whoops; } (void) des_init_random_number_generator(temp_key.contents); krb5_free_keyblock_contents(rdp->realm_context, &temp_key); #endif 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); } /* * Solaris Kerberos: * Set the current context back to the general context */ krb5_klog_set_context(kcontext); return(kret); } krb5_sigtype request_exit(int signo) { signal_requests_exit = 1; #ifdef POSIX_SIGTYPE return; #else return(0); #endif }