/** * @internal Initialize KDB for given realm * @param context pointer to context that will be re-initialized * @@param realm name of realm to initialize */ krb5_error_code kinit_kdb_init(krb5_context *pcontext, char *realm) { kadm5_config_params config; krb5_error_code retval = 0; if (*pcontext) { krb5_free_context(*pcontext); *pcontext = NULL; } memset(&config, 0, sizeof config); retval = kadm5_init_krb5_context(pcontext); if (retval) return retval; config.mask = KADM5_CONFIG_REALM; config.realm = realm; retval = kadm5_init(*pcontext, "kinit", NULL /*pass*/, "kinit", &config, KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, NULL, &server_handle); if (retval) return retval; retval = krb5_kt_register(*pcontext, &krb5_kt_kdb_ops); return retval; }
static void setup_context(krb5_context ctx) { krb5_log_facility *logfacility; krb5_error_code ret; char **files; if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(ctx)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(ctx, 1, ret, "getting configuration files"); ret = krb5_set_config_files(ctx, files); krb5_free_config_files(files); if(ret) krb5_err(ctx, 1, ret, "reading configuration files"); ret = krb5_openlog(ctx, "kadmind", &logfacility); if (ret) krb5_err(ctx, 1, ret, "krb5_openlog"); ret = krb5_set_warn_dest(ctx, logfacility); if (ret) krb5_err(ctx, 1, ret, "krb5_set_warn_dest"); ret = krb5_kt_register(ctx, &hdb_kt_ops); if(ret) krb5_err(ctx, 1, ret, "krb5_kt_register"); }
int main(int argc, char **argv) { krb5_error_code ret; int optidx = 0; setprogname(argv[0]); ret = krb5_init_context(&kdc_context); if (ret == KRB5_CONFIG_BADFORMAT) errx (1, "krb5_init_context failed to parse configuration file"); else if (ret) errx (1, "krb5_init_context failed: %d", ret); ret = krb5_kt_register(kdc_context, &hdb_kt_ops); if (ret) errx (1, "krb5_kt_register(HDB) failed: %d", ret); kdc_config = configure(kdc_context, argc, argv, &optidx); argc -= optidx; argv += optidx; if (argc == 0) errx(1, "missing operations"); krb5_plugin_register(kdc_context, PLUGIN_TYPE_DATA, KRB5_PLUGIN_SEND_TO_KDC, &send_to_kdc); { void *buf; size_t size; heim_object_t o; if (rk_undumpdata(argv[0], &buf, &size)) errx(1, "undumpdata: %s", argv[0]); o = heim_json_create_with_bytes(buf, size, 10, 0, NULL); free(buf); if (o == NULL) errx(1, "heim_json"); /* * do the work here */ eval_object(o); heim_release(o); } krb5_free_context(kdc_context); return 0; }
NTSTATUS libnet_export_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_export_keytab *r) { krb5_error_code ret; struct smb_krb5_context *smb_krb5_context; const char *from_keytab; /* Register hdb-samba4 hooks for use as a keytab */ struct samba_kdc_base_context *base_ctx = talloc_zero(mem_ctx, struct samba_kdc_base_context); if (!base_ctx) { return NT_STATUS_NO_MEMORY; } base_ctx->ev_ctx = ctx->event_ctx; base_ctx->lp_ctx = ctx->lp_ctx; from_keytab = talloc_asprintf(base_ctx, "HDB:samba4&%p", base_ctx); if (!from_keytab) { return NT_STATUS_NO_MEMORY; } ret = smb_krb5_init_context(ctx, ctx->event_ctx, ctx->lp_ctx, &smb_krb5_context); if (ret) { return NT_STATUS_NO_MEMORY; } ret = krb5_plugin_register(smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "hdb", &hdb_samba4); if(ret) { return NT_STATUS_NO_MEMORY; } ret = krb5_kt_register(smb_krb5_context->krb5_context, &hdb_kt_ops); if(ret) { return NT_STATUS_NO_MEMORY; } unlink(r->in.keytab_name); ret = kt_copy(smb_krb5_context->krb5_context, from_keytab, r->in.keytab_name); if(ret) { r->out.error_string = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx); return NT_STATUS_UNSUCCESSFUL; } return NT_STATUS_OK; }
static void get_creds(krb5_context context, krb5_ccache *cache) { krb5_keytab keytab; krb5_principal client; krb5_error_code ret; krb5_get_init_creds_opt *init_opts; krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP; krb5_creds creds; ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, ktname, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve"); ret = krb5_make_principal(context, &client, NULL, "kadmin", HPROP_NAME, NULL); if(ret) krb5_err(context, 1, ret, "krb5_make_principal"); ret = krb5_get_init_creds_opt_alloc(context, &init_opts); if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc"); krb5_get_init_creds_opt_set_preauth_list(init_opts, &preauth, 1); ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, init_opts); if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds"); krb5_get_init_creds_opt_free(context, init_opts); ret = krb5_kt_close(context, keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_close"); ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, cache); if(ret) krb5_err(context, 1, ret, "krb5_cc_new_unique"); ret = krb5_cc_initialize(context, *cache, client); if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); krb5_free_principal(context, client); ret = krb5_cc_store_cred(context, *cache, &creds); if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); krb5_free_cred_contents(context, &creds); }
static krb5_error_code kt_ops_register(krb5_context context) { context->num_kt_types = 0; context->kt_types = NULL; krb5_kt_register (context, &krb5_fkt_ops); krb5_kt_register (context, &krb5_wrfkt_ops); krb5_kt_register (context, &krb5_javakt_ops); krb5_kt_register (context, &krb5_mkt_ops); #ifndef HEIMDAL_SMALLER krb5_kt_register (context, &krb5_akf_ops); #endif krb5_kt_register (context, &krb5_any_ops); return 0; }
static krb5_error_code kt_ops_register(krb5_context context) { context->num_kt_types = 0; context->kt_types = NULL; krb5_kt_register (context, &krb5_fkt_ops); krb5_kt_register (context, &krb5_wrfkt_ops); krb5_kt_register (context, &krb5_javakt_ops); #ifdef HEIM_KT_MEMORY krb5_kt_register (context, &krb5_mkt_ops); #endif #ifdef HEIM_KT_AKF krb5_kt_register (context, &krb5_akf_ops); #endif #ifdef HEIM_KT_ANY krb5_kt_register (context, &krb5_any_ops); #endif return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_auth_context ac = NULL; krb5_principal c1, c2; krb5_authenticator authent; krb5_keytab keytab; krb5_socket_t sock = rk_INVALID_SOCKET; HDB *db = NULL; int optidx = 0; char *tmp_db; krb5_log_facility *fac; int nprincs; setprogname(argv[0]); ret = krb5_init_context(&context); if(ret) exit(1); ret = krb5_openlog(context, "hpropd", &fac); if(ret) errx(1, "krb5_openlog"); krb5_set_warn_dest(context, fac); if(getarg(args, num_args, argc, argv, &optidx)) usage(1); if(local_realm != NULL) krb5_set_default_realm(context, local_realm); if(help_flag) usage(0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (argc != 0) usage(1); if (database == NULL) database = hdb_default_db(context); if(from_stdin) { sock = STDIN_FILENO; } else { struct sockaddr_storage ss; struct sockaddr *sa = (struct sockaddr *)&ss; socklen_t sin_len = sizeof(ss); char addr_name[256]; krb5_ticket *ticket; char *server; sock = STDIN_FILENO; #ifdef SUPPORT_INETD if (inetd_flag == -1) { if (getpeername (sock, sa, &sin_len) < 0) { inetd_flag = 0; } else { inetd_flag = 1; } } #else inetd_flag = 0; #endif if (!inetd_flag) { mini_inetd (krb5_getportbyname (context, "hprop", "tcp", HPROP_PORT), &sock); } sin_len = sizeof(ss); if(getpeername(sock, sa, &sin_len) < 0) krb5_err(context, 1, errno, "getpeername"); if (inet_ntop(sa->sa_family, socket_get_address (sa), addr_name, sizeof(addr_name)) == NULL) strlcpy (addr_name, "unknown address", sizeof(addr_name)); krb5_log(context, fac, 0, "Connection from %s", addr_name); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); if (ktname != NULL) { ret = krb5_kt_resolve(context, ktname, &keytab); if (ret) krb5_err (context, 1, ret, "krb5_kt_resolve %s", ktname); } else { ret = krb5_kt_default (context, &keytab); if (ret) krb5_err (context, 1, ret, "krb5_kt_default"); } ret = krb5_recvauth(context, &ac, &sock, HPROP_VERSION, NULL, 0, keytab, &ticket); if(ret) krb5_err(context, 1, ret, "krb5_recvauth"); ret = krb5_unparse_name(context, ticket->server, &server); if (ret) krb5_err(context, 1, ret, "krb5_unparse_name"); if (strncmp(server, "hprop/", 5) != 0) krb5_errx(context, 1, "ticket not for hprop (%s)", server); free(server); krb5_free_ticket (context, ticket); ret = krb5_auth_con_getauthenticator(context, ac, &authent); if(ret) krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator"); ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL); if(ret) krb5_err(context, 1, ret, "krb5_make_principal"); _krb5_principalname2krb5_principal(context, &c2, authent->cname, authent->crealm); if(!krb5_principal_compare(context, c1, c2)) { char *s; ret = krb5_unparse_name(context, c2, &s); if (ret) s = unparseable_name; krb5_errx(context, 1, "Unauthorized connection from %s", s); } krb5_free_principal(context, c1); krb5_free_principal(context, c2); ret = krb5_kt_close(context, keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_close"); } if(!print_dump) { asprintf(&tmp_db, "%s~", database); ret = hdb_create(context, &db, tmp_db); if(ret) krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db); ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600); if(ret) krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db); } nprincs = 0; while(1){ krb5_data data; hdb_entry_ex entry; if(from_stdin) { ret = krb5_read_message(context, &sock, &data); if(ret != 0 && ret != HEIM_ERR_EOF) krb5_err(context, 1, ret, "krb5_read_message"); } else { ret = krb5_read_priv_message(context, ac, &sock, &data); if(ret) krb5_err(context, 1, ret, "krb5_read_priv_message"); } if(ret == HEIM_ERR_EOF || data.length == 0) { if(!from_stdin) { data.data = NULL; data.length = 0; krb5_write_priv_message(context, ac, &sock, &data); } if(!print_dump) { ret = db->hdb_close(context, db); if(ret) krb5_err(context, 1, ret, "db_close"); ret = db->hdb_rename(context, db, database); if(ret) krb5_err(context, 1, ret, "db_rename"); } break; } memset(&entry, 0, sizeof(entry)); ret = hdb_value2entry(context, &data, &entry.entry); krb5_data_free(&data); if(ret) krb5_err(context, 1, ret, "hdb_value2entry"); if(print_dump) hdb_print_entry(context, db, &entry, stdout); else { ret = db->hdb_store(context, db, 0, &entry); if(ret == HDB_ERR_EXISTS) { char *s; ret = krb5_unparse_name(context, entry.entry.principal, &s); if (ret) s = strdup(unparseable_name); krb5_warnx(context, "Entry exists: %s", s); free(s); } else if(ret) krb5_err(context, 1, ret, "db_store"); else nprincs++; } hdb_free_entry(context, &entry); } if (!print_dump) krb5_log(context, fac, 0, "Received %d principals", nprincs); if (inetd_flag == 0) rk_closesocket(sock); exit(0); }
NTSTATUS libnet_export_keytab(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_export_keytab *r) { krb5_error_code ret; struct smb_krb5_context *smb_krb5_context; const char *from_keytab; /* Register hdb-samba4 hooks for use as a keytab */ struct samba_kdc_base_context *base_ctx = talloc_zero(mem_ctx, struct samba_kdc_base_context); if (!base_ctx) { return NT_STATUS_NO_MEMORY; } base_ctx->ev_ctx = ctx->event_ctx; base_ctx->lp_ctx = ctx->lp_ctx; from_keytab = talloc_asprintf(base_ctx, "HDB:samba4&%p", base_ctx); if (!from_keytab) { return NT_STATUS_NO_MEMORY; } ret = smb_krb5_init_context(ctx, ctx->event_ctx, ctx->lp_ctx, &smb_krb5_context); if (ret) { return NT_STATUS_NO_MEMORY; } ret = krb5_plugin_register(smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "hdb", &hdb_samba4_interface); if(ret) { return NT_STATUS_NO_MEMORY; } ret = krb5_kt_register(smb_krb5_context->krb5_context, &hdb_kt_ops); if(ret) { return NT_STATUS_NO_MEMORY; } if (r->in.principal) { /* TODO: Find a way not to have to use a fixed list */ krb5_enctype enctypes[] = { KRB5_ENCTYPE_DES_CBC_CRC, KRB5_ENCTYPE_DES_CBC_MD5, KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96, KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96, KRB5_ENCTYPE_ARCFOUR_HMAC_MD5 }; ret = kt_copy_one_principal(smb_krb5_context->krb5_context, from_keytab, r->in.keytab_name, r->in.principal, 0, enctypes); } else { unlink(r->in.keytab_name); ret = kt_copy(smb_krb5_context->krb5_context, from_keytab, r->in.keytab_name); } if(ret) { r->out.error_string = smb_get_krb5_error_message(smb_krb5_context->krb5_context, ret, mem_ctx); if (ret == KRB5_KT_NOTFOUND) { return NT_STATUS_NO_SUCH_USER; } else { return NT_STATUS_UNSUCCESSFUL; } } return NT_STATUS_OK; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; krb5_socket_t signal_fd, listen_fd; int log_fd; slave *slaves = NULL; uint32_t current_version = 0, old_version = 0; uint32_t current_tstamp = 0; krb5_keytab keytab; char **files; int aret; int optidx = 0; int restarter_fd = -1; struct stat st; setprogname(argv[0]); if (getarg(args, num_args, argc, argv, &optidx)) krb5_std_usage(1, args, num_args); if (help_flag) krb5_std_usage(0, args, num_args); if (version_flag) { print_version(NULL); exit(0); } if (detach_from_console && daemon_child == -1) roken_detach_prep(argc, argv, "--daemon-child"); rk_pidfile(NULL); ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); setup_signal(); if (config_file == NULL) { aret = asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (aret == -1 || config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); time_before_gone = parse_time (slave_time_gone, "s"); if (time_before_gone < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone); time_before_missing = parse_time (slave_time_missing, "s"); if (time_before_missing < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing); krb5_openlog(context, "ipropd-master", &log_facility); krb5_set_warn_dest(context, log_facility); ret = krb5_kt_register(context, &hdb_get_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_skey_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; log_fd = open (server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err (context, 1, errno, "open %s", server_context->log_context.log_file); if (fstat(log_fd, &st) == -1) krb5_err(context, 1, errno, "stat %s", server_context->log_context.log_file); if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, 1, errno, "shared flock %s", server_context->log_context.log_file); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); signal_fd = make_signal_socket (context); listen_fd = make_listen_socket (context, port_str); krb5_warnx(context, "ipropd-master started at version: %lu", (unsigned long)current_version); roken_detach_finish(NULL, daemon_child); restarter_fd = restarter(context, NULL); while (exit_flag == 0){ slave *p; fd_set readset; int max_fd = 0; struct timeval to = {30, 0}; uint32_t vers; struct stat st2;; #ifndef NO_LIMIT_FD_SETSIZE if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE || restarter_fd >= FD_SETSIZE) krb5_errx (context, IPROPD_RESTART, "fd too large"); #endif FD_ZERO(&readset); FD_SET(signal_fd, &readset); max_fd = max(max_fd, signal_fd); FD_SET(listen_fd, &readset); max_fd = max(max_fd, listen_fd); if (restarter_fd > -1) { FD_SET(restarter_fd, &readset); max_fd = max(max_fd, restarter_fd); } for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; FD_SET(p->fd, &readset); max_fd = max(max_fd, p->fd); } ret = select (max_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, IPROPD_RESTART, errno, "select"); } if (stat(server_context->log_context.log_file, &st2) == -1) { krb5_warn(context, errno, "could not stat log file by path"); st2 = st; } if (st2.st_dev != st.st_dev || st2.st_ino != st.st_ino) { (void) close(log_fd); log_fd = open(server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err(context, 1, IPROPD_RESTART_SLOW, "open %s", server_context->log_context.log_file); if (fstat(log_fd, &st) == -1) krb5_err(context, IPROPD_RESTART_SLOW, errno, "stat %s", server_context->log_context.log_file); if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, IPROPD_RESTART, errno, "shared flock %s", server_context->log_context.log_file); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); } if (ret == 0) { /* Recover from failed transactions */ if (kadm5_log_init_nb(server_context) == 0) kadm5_log_end(server_context); if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, IPROPD_RESTART, errno, "could not lock log file"); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); if (current_version > old_version) { krb5_warnx(context, "Missed a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (server_context, p, log_fd, database, current_version, current_tstamp); } old_version = current_version; } } if (ret && FD_ISSET(restarter_fd, &readset)) { exit_flag = SIGTERM; break; } if (ret && FD_ISSET(signal_fd, &readset)) { #ifndef NO_UNIX_SOCKETS struct sockaddr_un peer_addr; #else struct sockaddr_storage peer_addr; #endif socklen_t peer_len = sizeof(peer_addr); if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0, (struct sockaddr *)&peer_addr, &peer_len) < 0) { krb5_warn (context, errno, "recvfrom"); continue; } --ret; assert(ret >= 0); old_version = current_version; if (flock(log_fd, LOCK_SH) == -1) krb5_err(context, IPROPD_RESTART, errno, "shared flock %s", server_context->log_context.log_file); kadm5_log_get_version_fd(server_context, log_fd, LOG_VERSION_LAST, ¤t_version, ¤t_tstamp); flock(log_fd, LOCK_UN); if (current_version != old_version) { /* * If current_version < old_version then the log got * truncated and we'll end up doing full propagations. * * Truncating the log when the current version is * numerically small can lead to race conditions. * Ideally we should identify log versions as * {init_or_trunc_time, vno}, then we could not have any * such race conditions, but this would either require * breaking backwards compatibility for the protocol or * adding new messages to it. */ krb5_warnx(context, "Got a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (server_context, p, log_fd, database, current_version, current_tstamp); } } else { krb5_warnx(context, "Got a signal, but no update in log version %lu", (unsigned long)current_version); } } for(p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; if (ret && FD_ISSET(p->fd, &readset)) { --ret; assert(ret >= 0); if(process_msg (server_context, p, log_fd, database, current_version, current_tstamp)) slave_dead(context, p); } else if (slave_gone_p (p)) slave_dead(context, p); else if (slave_missing_p (p)) send_are_you_there (context, p); } if (ret && FD_ISSET(listen_fd, &readset)) { add_slave (context, keytab, &slaves, listen_fd); --ret; assert(ret >= 0); } write_stats(context, slaves, current_version); } if(exit_flag == SIGINT || exit_flag == SIGTERM) krb5_warnx(context, "%s terminated", getprogname()); #ifdef SIGXCPU else if(exit_flag == SIGXCPU) krb5_warnx(context, "%s CPU time limit exceeded", getprogname()); #endif else krb5_warnx(context, "%s unexpected exit reason: %ld", getprogname(), (long)exit_flag); write_master_down(context); return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_auth_context auth_context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; int master_fd; krb5_ccache ccache; krb5_principal server; char **files; int optidx = 0; time_t reconnect_min; time_t backoff; time_t reconnect_max; time_t reconnect; time_t before = 0; const char *master; setprogname(argv[0]); if(getarg(args, num_args, argc, argv, &optidx)) usage(1); if(help_flag) usage(0); if(version_flag) { print_version(NULL); exit(0); } ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); setup_signal(); if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); argc -= optidx; argv += optidx; if (argc != 1) usage(1); master = argv[0]; #ifdef SUPPORT_DETACH if (detach_from_console) daemon(0, 0); #endif pidfile (NULL); krb5_openlog (context, "ipropd-slave", &log_facility); krb5_set_warn_dest(context, log_facility); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); time_before_lost = parse_time (server_time_lost, "s"); if (time_before_lost < 0) krb5_errx (context, 1, "couldn't parse time: %s", server_time_lost); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_password_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; ret = kadm5_log_init (server_context); if (ret) krb5_err (context, 1, ret, "kadm5_log_init"); get_creds(context, keytab_str, &ccache, master); ret = krb5_sname_to_principal (context, master, IPROP_NAME, KRB5_NT_SRV_HST, &server); if (ret) krb5_err (context, 1, ret, "krb5_sname_to_principal"); auth_context = NULL; master_fd = -1; krb5_appdefault_time(context, config_name, NULL, "reconnect-min", 10, &reconnect_min); krb5_appdefault_time(context, config_name, NULL, "reconnect-max", 300, &reconnect_max); krb5_appdefault_time(context, config_name, NULL, "reconnect-backoff", 10, &backoff); reconnect = reconnect_min; while (!exit_flag) { time_t now, elapsed; int connected = FALSE; now = time(NULL); elapsed = now - before; if (elapsed < reconnect) { time_t left = reconnect - elapsed; krb5_warnx(context, "sleeping %d seconds before " "retrying to connect", (int)left); sleep(left); } before = now; master_fd = connect_to_master (context, master, port_str); if (master_fd < 0) goto retry; reconnect = reconnect_min; if (auth_context) { krb5_auth_con_free(context, auth_context); auth_context = NULL; krb5_cc_destroy(context, ccache); get_creds(context, keytab_str, &ccache, master); } ret = krb5_sendauth (context, &auth_context, &master_fd, IPROP_VERSION, NULL, server, AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, ccache, NULL, NULL, NULL); if (ret) { krb5_warn (context, ret, "krb5_sendauth"); goto retry; } krb5_warnx(context, "ipropd-slave started at version: %ld", (long)server_context->log_context.version); ret = ihave (context, auth_context, master_fd, server_context->log_context.version); if (ret) goto retry; connected = TRUE; while (connected && !exit_flag) { krb5_data out; krb5_storage *sp; int32_t tmp; fd_set readset; struct timeval to; #ifndef NO_LIMIT_FD_SETSIZE if (master_fd >= FD_SETSIZE) krb5_errx (context, 1, "fd too large"); #endif FD_ZERO(&readset); FD_SET(master_fd, &readset); to.tv_sec = time_before_lost; to.tv_usec = 0; ret = select (master_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } if (ret == 0) krb5_errx (context, 1, "server didn't send a message " "in %d seconds", time_before_lost); ret = krb5_read_priv_message(context, auth_context, &master_fd, &out); if (ret) { krb5_warn (context, ret, "krb5_read_priv_message"); connected = FALSE; continue; } sp = krb5_storage_from_mem (out.data, out.length); krb5_ret_int32 (sp, &tmp); switch (tmp) { case FOR_YOU : receive (context, sp, server_context); ret = ihave (context, auth_context, master_fd, server_context->log_context.version); if (ret) connected = FALSE; break; case TELL_YOU_EVERYTHING : ret = receive_everything (context, master_fd, server_context, auth_context); if (ret) connected = FALSE; break; case ARE_YOU_THERE : send_im_here (context, master_fd, auth_context); break; case NOW_YOU_HAVE : case I_HAVE : case ONE_PRINC : case I_AM_HERE : default : krb5_warnx (context, "Ignoring command %d", tmp); break; } krb5_storage_free (sp); krb5_data_free (&out); } retry: if (connected == FALSE) krb5_warnx (context, "disconnected for server"); if (exit_flag) krb5_warnx (context, "got an exit signal"); if (master_fd >= 0) close(master_fd); reconnect += backoff; if (reconnect > reconnect_max) reconnect = reconnect_max; } if (0); #ifndef NO_SIGXCPU else if(exit_flag == SIGXCPU) krb5_warnx(context, "%s CPU time limit exceeded", getprogname()); #endif else if(exit_flag == SIGINT || exit_flag == SIGTERM) krb5_warnx(context, "%s terminated", getprogname()); else krb5_warnx(context, "%s unexpected exit reason: %ld", getprogname(), (long)exit_flag); return 0; }
/* startup the kdc task */ static void kdc_task_init(struct task_server *task) { struct kdc_server *kdc; krb5_kdc_configuration *kdc_config = NULL; NTSTATUS status; krb5_error_code ret; struct interface *ifaces; int ldb_ret; switch (lpcfg_server_role(task->lp_ctx)) { case ROLE_STANDALONE: task_server_terminate(task, "kdc: no KDC required in standalone configuration", false); return; case ROLE_DOMAIN_MEMBER: task_server_terminate(task, "kdc: no KDC required in member server configuration", false); return; case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: task_server_terminate(task, "Cannot start KDC as a 'classic Samba' DC", true); return; case ROLE_ACTIVE_DIRECTORY_DC: /* Yes, we want a KDC */ break; } load_interface_list(task, task->lp_ctx, &ifaces); if (iface_list_count(ifaces) == 0) { task_server_terminate(task, "kdc: no network interfaces configured", false); return; } task_server_set_title(task, "task[kdc]"); kdc = talloc_zero(task, struct kdc_server); if (kdc == NULL) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc->task = task; /* get a samdb connection */ kdc->samdb = samdb_connect(kdc, kdc->task->event_ctx, kdc->task->lp_ctx, system_session(kdc->task->lp_ctx), NULL, 0); if (!kdc->samdb) { DEBUG(1,("kdc_task_init: unable to connect to samdb\n")); task_server_terminate(task, "kdc: krb5_init_context samdb connect failed", true); return; } ldb_ret = samdb_rodc(kdc->samdb, &kdc->am_rodc); if (ldb_ret != LDB_SUCCESS) { DEBUG(1, ("kdc_task_init: Cannot determine if we are an RODC: %s\n", ldb_errstring(kdc->samdb))); task_server_terminate(task, "kdc: krb5_init_context samdb RODC connect failed", true); return; } kdc->proxy_timeout = lpcfg_parm_int(kdc->task->lp_ctx, NULL, "kdc", "proxy timeout", 5); initialize_krb5_error_table(); ret = smb_krb5_init_context(kdc, task->lp_ctx, &kdc->smb_krb5_context); if (ret) { DEBUG(1,("kdc_task_init: krb5_init_context failed (%s)\n", error_message(ret))); task_server_terminate(task, "kdc: krb5_init_context failed", true); return; } krb5_add_et_list(kdc->smb_krb5_context->krb5_context, initialize_hdb_error_table_r); ret = krb5_kdc_get_config(kdc->smb_krb5_context->krb5_context, &kdc_config); if(ret) { task_server_terminate(task, "kdc: failed to get KDC configuration", true); return; } kdc_config->logf = (krb5_log_facility *)kdc->smb_krb5_context->pvt_log_data; kdc_config->db = talloc(kdc, struct HDB *); if (!kdc_config->db) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc_config->num_db = 1; /* * This restores the behavior before * commit 255e3e18e00f717d99f3bc57c8a8895ff624f3c3 * s4:heimdal: import lorikeet-heimdal-201107150856 * (commit 48936803fae4a2fb362c79365d31f420c917b85b) * * as_use_strongest_session_key,preauth_use_strongest_session_key * and tgs_use_strongest_session_key are input to the * _kdc_find_etype() function. The old bahavior is in * the use_strongest_session_key=FALSE code path. * (The only remaining difference in _kdc_find_etype() * is the is_preauth parameter.) * * The old behavior in the _kdc_get_preferred_key() * function is use_strongest_server_key=TRUE. */ kdc_config->as_use_strongest_session_key = false; kdc_config->preauth_use_strongest_session_key = false; kdc_config->tgs_use_strongest_session_key = false; kdc_config->use_strongest_server_key = true; kdc_config->autodetect_referrals = false; /* Register hdb-samba4 hooks for use as a keytab */ kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context); if (!kdc->base_ctx) { task_server_terminate(task, "kdc: out of memory", true); return; } kdc->base_ctx->ev_ctx = task->event_ctx; kdc->base_ctx->lp_ctx = task->lp_ctx; kdc->base_ctx->msg_ctx = task->msg_ctx; status = hdb_samba4_create_kdc(kdc->base_ctx, kdc->smb_krb5_context->krb5_context, &kdc_config->db[0]); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc: hdb_samba4_create_kdc (setup KDC database) failed", true); return; } ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "hdb", &hdb_samba4_interface); if(ret) { task_server_terminate(task, "kdc: failed to register hdb plugin", true); return; } ret = krb5_kt_register(kdc->smb_krb5_context->krb5_context, &hdb_kt_ops); if(ret) { task_server_terminate(task, "kdc: failed to register keytab plugin", true); return; } kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx); if (kdc->keytab_name == NULL) { task_server_terminate(task, "kdc: Failed to set keytab name", true); return; } /* Register WinDC hooks */ ret = krb5_plugin_register(kdc->smb_krb5_context->krb5_context, PLUGIN_TYPE_DATA, "windc", &windc_plugin_table); if(ret) { task_server_terminate(task, "kdc: failed to register windc plugin", true); return; } ret = krb5_kdc_windc_init(kdc->smb_krb5_context->krb5_context); if(ret) { task_server_terminate(task, "kdc: failed to init windc plugin", true); return; } ret = krb5_kdc_pkinit_config(kdc->smb_krb5_context->krb5_context, kdc_config); if(ret) { task_server_terminate(task, "kdc: failed to init kdc pkinit subsystem", true); return; } kdc->private_data = kdc_config; /* start listening on the configured network interfaces */ status = kdc_startup_interfaces(kdc, task->lp_ctx, ifaces, task->model_ops); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc failed to setup interfaces", true); return; } status = IRPC_REGISTER(task->msg_ctx, irpc, KDC_CHECK_GENERIC_KERBEROS, kdc_check_generic_kerberos, kdc); if (!NT_STATUS_IS_OK(status)) { task_server_terminate(task, "kdc failed to setup monitoring", true); return; } irpc_add_name(task->msg_ctx, "kdc_server"); }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; krb5_socket_t signal_fd, listen_fd; int log_fd; slave *slaves = NULL; uint32_t current_version = 0, old_version = 0; krb5_keytab keytab; int optidx; char **files; optidx = krb5_program_setup(&context, argc, argv, args, num_args, NULL); if(help_flag) krb5_std_usage(0, args, num_args); if(version_flag) { print_version(NULL); exit(0); } setup_signal(); if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); time_before_gone = parse_time (slave_time_gone, "s"); if (time_before_gone < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone); time_before_missing = parse_time (slave_time_missing, "s"); if (time_before_missing < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing); #ifdef SUPPORT_DETACH if (detach_from_console) daemon(0, 0); #endif pidfile (NULL); krb5_openlog (context, "ipropd-master", &log_facility); krb5_set_warn_dest(context, log_facility); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_skey_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; log_fd = open (server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err (context, 1, errno, "open %s", server_context->log_context.log_file); signal_fd = make_signal_socket (context); listen_fd = make_listen_socket (context, port_str); kadm5_log_get_version_fd (log_fd, ¤t_version); krb5_warnx(context, "ipropd-master started at version: %lu", (unsigned long)current_version); while(exit_flag == 0){ slave *p; fd_set readset; int max_fd = 0; struct timeval to = {30, 0}; uint32_t vers; #ifndef NO_LIMIT_FD_SETSIZE if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE) krb5_errx (context, 1, "fd too large"); #endif FD_ZERO(&readset); FD_SET(signal_fd, &readset); max_fd = max(max_fd, signal_fd); FD_SET(listen_fd, &readset); max_fd = max(max_fd, listen_fd); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; FD_SET(p->fd, &readset); max_fd = max(max_fd, p->fd); } ret = select (max_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } if (ret == 0) { old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); if (current_version > old_version) { krb5_warnx(context, "Missed a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (context, p, log_fd, database, current_version); } } } if (ret && FD_ISSET(signal_fd, &readset)) { #ifndef NO_UNIX_SOCKETS struct sockaddr_un peer_addr; #else struct sockaddr_storage peer_addr; #endif socklen_t peer_len = sizeof(peer_addr); if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0, (struct sockaddr *)&peer_addr, &peer_len) < 0) { krb5_warn (context, errno, "recvfrom"); continue; } --ret; assert(ret >= 0); old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); if (current_version > old_version) { krb5_warnx(context, "Got a signal, updating slaves %lu to %lu", (unsigned long)old_version, (unsigned long)current_version); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (context, p, log_fd, database, current_version); } } else { krb5_warnx(context, "Got a signal, but no update in log version %lu", (unsigned long)current_version); } } for(p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; if (ret && FD_ISSET(p->fd, &readset)) { --ret; assert(ret >= 0); if(process_msg (context, p, log_fd, database, current_version)) slave_dead(context, p); } else if (slave_gone_p (p)) slave_dead(context, p); else if (slave_missing_p (p)) send_are_you_there (context, p); } if (ret && FD_ISSET(listen_fd, &readset)) { add_slave (context, keytab, &slaves, listen_fd); --ret; assert(ret >= 0); } write_stats(context, slaves, current_version); } if(exit_flag == SIGINT || exit_flag == SIGTERM) krb5_warnx(context, "%s terminated", getprogname()); #ifdef SIGXCPU else if(exit_flag == SIGXCPU) krb5_warnx(context, "%s CPU time limit exceeded", getprogname()); #endif else krb5_warnx(context, "%s unexpected exit reason: %ld", getprogname(), (long)exit_flag); write_master_down(context); return 0; }
int main (int argc, char **argv) { krb5_keytab keytab; krb5_error_code ret; char **files; int port, i; krb5_program_setup(&context, argc, argv, args, num_args, NULL); if(help_flag) krb5_std_usage(0, args, num_args); if(version_flag) { print_version(NULL); exit(0); } if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); if(realm_str) krb5_set_default_realm(context, realm_str); krb5_openlog (context, "kpasswdd", &log_facility); krb5_set_warn_dest(context, log_facility); if (port_str != NULL) { struct servent *s = roken_getservbyname (port_str, "udp"); if (s != NULL) port = s->s_port; else { char *ptr; port = strtol (port_str, &ptr, 10); if (port == 0 && ptr == port_str) krb5_errx (context, 1, "bad port `%s'", port_str); port = htons(port); } } else port = krb5_getportbyname (context, "kpasswd", "udp", KPASSWD_PORT); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "%s", keytab_str); kadm5_setup_passwd_quality_check (context, check_library, check_function); for (i = 0; i < policy_libraries.num_strings; i++) { ret = kadm5_add_passwd_quality_verifier(context, policy_libraries.strings[i]); if (ret) krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier"); } ret = kadm5_add_passwd_quality_verifier(context, NULL); if (ret) krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier"); explicit_addresses.len = 0; if (addresses_str.num_strings) { int j; for (j = 0; j < addresses_str.num_strings; ++j) add_one_address (addresses_str.strings[j], j == 0); free_getarg_strings (&addresses_str); } else { char **foo = krb5_config_get_strings (context, NULL, "kdc", "addresses", NULL); if (foo != NULL) { add_one_address (*foo++, TRUE); while (*foo) add_one_address (*foo++, FALSE); } } #ifdef HAVE_SIGACTION { struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = sigterm; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); } #else signal(SIGINT, sigterm); signal(SIGTERM, sigterm); #endif pidfile(NULL); return doit (keytab, port); }
int main(int argc, char **argv) { krb5_error_code ret, ret2; krb5_context context; krb5_auth_context auth_context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; int master_fd; krb5_ccache ccache; krb5_principal server; char **files; int optidx = 0; time_t reconnect_min; time_t backoff; time_t reconnect_max; time_t reconnect; time_t before = 0; int restarter_fd = -1; const char *master; setprogname(argv[0]); if (getarg(args, num_args, argc, argv, &optidx)) usage(1); if (help_flag) usage(0); if (version_flag) { print_version(NULL); exit(0); } if (detach_from_console && daemon_child == -1) roken_detach_prep(argc, argv, "--daemon-child"); rk_pidfile(NULL); ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); setup_signal(); if (config_file == NULL) { if (asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)) == -1 || config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); argc -= optidx; argv += optidx; if (argc != 1) usage(1); master = argv[0]; if (status_file == NULL) { if (asprintf(&status_file, "%s/ipropd-slave-status", hdb_db_dir(context)) < 0 || status_file == NULL) krb5_errx(context, 1, "can't allocate status file buffer"); } krb5_openlog(context, "ipropd-slave", &log_facility); krb5_set_warn_dest(context, log_facility); slave_status(context, status_file, "bootstrapping"); ret = krb5_kt_register(context, &hdb_get_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); time_before_lost = parse_time (server_time_lost, "s"); if (time_before_lost < 0) krb5_errx (context, 1, "couldn't parse time: %s", server_time_lost); slave_status(context, status_file, "getting credentials from keytab/database"); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_password_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; slave_status(context, status_file, "creating log file"); ret = server_context->db->hdb_open(context, server_context->db, O_RDWR | O_CREAT, 0600); if (ret) krb5_err (context, 1, ret, "db->open"); ret = kadm5_log_init (server_context); if (ret) krb5_err (context, 1, ret, "kadm5_log_init"); ret = server_context->db->hdb_close (context, server_context->db); if (ret) krb5_err (context, 1, ret, "db->close"); get_creds(context, keytab_str, &ccache, master); ret = krb5_sname_to_principal (context, master, IPROP_NAME, KRB5_NT_SRV_HST, &server); if (ret) krb5_err (context, 1, ret, "krb5_sname_to_principal"); auth_context = NULL; master_fd = -1; krb5_appdefault_time(context, config_name, NULL, "reconnect-min", 10, &reconnect_min); krb5_appdefault_time(context, config_name, NULL, "reconnect-max", 300, &reconnect_max); krb5_appdefault_time(context, config_name, NULL, "reconnect-backoff", 10, &backoff); reconnect = reconnect_min; slave_status(context, status_file, "ipropd-slave started"); roken_detach_finish(NULL, daemon_child); restarter_fd = restarter(context, NULL); while (!exit_flag) { struct timeval to; time_t now, elapsed; fd_set readset; int connected = FALSE; #ifndef NO_LIMIT_FD_SETSIZE if (restarter_fd >= FD_SETSIZE) krb5_errx(context, IPROPD_RESTART, "fd too large"); #endif FD_ZERO(&readset); if (restarter_fd > -1) FD_SET(restarter_fd, &readset); now = time(NULL); elapsed = now - before; if (elapsed < reconnect) { time_t left = reconnect - elapsed; krb5_warnx(context, "sleeping %d seconds before " "retrying to connect", (int)left); to.tv_sec = left; to.tv_usec = 0; if (select(restarter_fd + 1, &readset, NULL, NULL, &to) == 1) { exit_flag = SIGTERM; continue; } } before = now; slave_status(context, status_file, "connecting to master: %s\n", master); master_fd = connect_to_master (context, master, port_str); if (master_fd < 0) goto retry; reconnect = reconnect_min; if (auth_context) { krb5_auth_con_free(context, auth_context); auth_context = NULL; krb5_cc_destroy(context, ccache); get_creds(context, keytab_str, &ccache, master); } if (verbose) krb5_warnx(context, "authenticating to master"); ret = krb5_sendauth (context, &auth_context, &master_fd, IPROP_VERSION, NULL, server, AP_OPTS_MUTUAL_REQUIRED, NULL, NULL, ccache, NULL, NULL, NULL); if (ret) { krb5_warn (context, ret, "krb5_sendauth"); goto retry; } krb5_warnx(context, "ipropd-slave started at version: %ld", (long)server_context->log_context.version); ret = ihave(context, auth_context, master_fd, server_context->log_context.version); if (ret) goto retry; connected = TRUE; if (verbose) krb5_warnx(context, "connected to master"); slave_status(context, status_file, "connected to master, waiting instructions"); while (connected && !exit_flag) { krb5_data out; krb5_storage *sp; uint32_t tmp; int max_fd; #ifndef NO_LIMIT_FD_SETSIZE if (master_fd >= FD_SETSIZE) krb5_errx(context, IPROPD_RESTART, "fd too large"); if (restarter_fd >= FD_SETSIZE) krb5_errx(context, IPROPD_RESTART, "fd too large"); max_fd = max(restarter_fd, master_fd); #endif FD_ZERO(&readset); FD_SET(master_fd, &readset); if (restarter_fd != -1) FD_SET(restarter_fd, &readset); to.tv_sec = time_before_lost; to.tv_usec = 0; ret = select (max_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } if (ret == 0) { krb5_warnx(context, "server didn't send a message " "in %d seconds", time_before_lost); connected = FALSE; continue; } if (restarter_fd > -1 && FD_ISSET(restarter_fd, &readset)) { if (verbose) krb5_warnx(context, "slave restarter exited"); exit_flag = SIGTERM; } if (!FD_ISSET(master_fd, &readset)) continue; if (verbose) krb5_warnx(context, "message from master"); ret = krb5_read_priv_message(context, auth_context, &master_fd, &out); if (ret) { krb5_warn(context, ret, "krb5_read_priv_message"); connected = FALSE; continue; } sp = krb5_storage_from_mem (out.data, out.length); if (sp == NULL) krb5_err(context, IPROPD_RESTART, errno, "krb5_storage_from_mem"); ret = krb5_ret_uint32(sp, &tmp); if (ret == HEIM_ERR_EOF) { krb5_warn(context, ret, "master sent zero-length message"); connected = FALSE; continue; } if (ret != 0) { krb5_warn(context, ret, "couldn't read master's message"); connected = FALSE; continue; } ret = server_context->db->hdb_open(context, server_context->db, O_RDWR | O_CREAT, 0600); if (ret) krb5_err (context, 1, ret, "db->open while handling a " "message from the master"); ret = kadm5_log_init(server_context); if (ret) { krb5_err(context, IPROPD_RESTART, ret, "kadm5_log_init while " "handling a message from the master"); } ret = server_context->db->hdb_close (context, server_context->db); if (ret) krb5_err (context, 1, ret, "db->close while handling a " "message from the master"); switch (tmp) { case FOR_YOU : if (verbose) krb5_warnx(context, "master sent us diffs"); ret2 = receive(context, sp, server_context); if (ret2) krb5_warn(context, ret2, "receive from ipropd-master had errors"); ret = ihave(context, auth_context, master_fd, server_context->log_context.version); if (ret || ret2) connected = FALSE; /* * If it returns an error, receive() may nonetheless * have committed some entries successfully, so we must * update the slave_status even if there were errors. */ is_up_to_date(context, status_file, server_context); break; case TELL_YOU_EVERYTHING : if (verbose) krb5_warnx(context, "master sent us a full dump"); ret = receive_everything(context, master_fd, server_context, auth_context); if (ret == 0) { ret = ihave(context, auth_context, master_fd, server_context->log_context.version); } if (ret) connected = FALSE; else is_up_to_date(context, status_file, server_context); break; case ARE_YOU_THERE : if (verbose) krb5_warnx(context, "master sent us a ping"); is_up_to_date(context, status_file, server_context); ret = ihave(context, auth_context, master_fd, server_context->log_context.version); if (ret) connected = FALSE; send_im_here(context, master_fd, auth_context); break; case YOU_HAVE_LAST_VERSION: if (verbose) krb5_warnx(context, "master tells us we are up to date"); is_up_to_date(context, status_file, server_context); break; case NOW_YOU_HAVE : case I_HAVE : case ONE_PRINC : case I_AM_HERE : default : krb5_warnx (context, "Ignoring command %d", tmp); break; } krb5_storage_free (sp); krb5_data_free (&out); } slave_status(context, status_file, "disconnected from master"); retry: if (connected == FALSE) krb5_warnx (context, "disconnected for server"); if (exit_flag) krb5_warnx (context, "got an exit signal"); if (master_fd >= 0) close(master_fd); reconnect += backoff; if (reconnect > reconnect_max) { slave_status(context, status_file, "disconnected from master for a long time"); reconnect = reconnect_max; } } if (status_file) { /* XXX It'd be better to leave it saying we're not here */ unlink(status_file); } if (0); #ifndef NO_SIGXCPU else if(exit_flag == SIGXCPU) krb5_warnx(context, "%s CPU time limit exceeded", getprogname()); #endif else if(exit_flag == SIGINT || exit_flag == SIGTERM) krb5_warnx(context, "%s terminated", getprogname()); else krb5_warnx(context, "%s unexpected exit reason: %ld", getprogname(), (long)exit_flag); return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; void *kadm_handle; kadm5_server_context *server_context; kadm5_config_params conf; int signal_fd, listen_fd; int log_fd; slave *slaves = NULL; u_int32_t current_version = 0, old_version = 0; krb5_keytab keytab; int optind; char **files; optind = krb5_program_setup(&context, argc, argv, args, num_args, NULL); if(help_flag) krb5_std_usage(0, args, num_args); if(version_flag) { print_version(NULL); exit(0); } if (config_file == NULL) config_file = HDB_DB_DIR "/kdc.conf"; ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if (ret) krb5_err(context, 1, ret, "reading configuration files"); time_before_gone = parse_time (slave_time_gone, "s"); if (time_before_gone < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone); time_before_missing = parse_time (slave_time_missing, "s"); if (time_before_missing < 0) krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing); if (detach_from_console) daemon(0, 0); pidfile (NULL); krb5_openlog (context, "ipropd-master", &log_facility); krb5_set_warn_dest(context, log_facility); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str); memset(&conf, 0, sizeof(conf)); if(realm) { conf.mask |= KADM5_CONFIG_REALM; conf.realm = realm; } ret = kadm5_init_with_skey_ctx (context, KADM5_ADMIN_SERVICE, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm_handle); if (ret) krb5_err (context, 1, ret, "kadm5_init_with_password_ctx"); server_context = (kadm5_server_context *)kadm_handle; log_fd = open (server_context->log_context.log_file, O_RDONLY, 0); if (log_fd < 0) krb5_err (context, 1, errno, "open %s", server_context->log_context.log_file); signal_fd = make_signal_socket (context); listen_fd = make_listen_socket (context, port_str); signal (SIGPIPE, SIG_IGN); for (;;) { slave *p; fd_set readset; int max_fd = 0; struct timeval to = {30, 0}; u_int32_t vers; if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE) krb5_errx (context, 1, "fd too large"); FD_ZERO(&readset); FD_SET(signal_fd, &readset); max_fd = max(max_fd, signal_fd); FD_SET(listen_fd, &readset); max_fd = max(max_fd, listen_fd); for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; FD_SET(p->fd, &readset); max_fd = max(max_fd, p->fd); } ret = select (max_fd + 1, &readset, NULL, NULL, &to); if (ret < 0) { if (errno == EINTR) continue; else krb5_err (context, 1, errno, "select"); } if (ret == 0) { old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); if (current_version > old_version) { for (p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; send_diffs (context, p, log_fd, database, current_version); } } } if (ret && FD_ISSET(signal_fd, &readset)) { struct sockaddr_un peer_addr; socklen_t peer_len = sizeof(peer_addr); if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0, (struct sockaddr *)&peer_addr, &peer_len) < 0) { krb5_warn (context, errno, "recvfrom"); continue; } --ret; assert(ret >= 0); old_version = current_version; kadm5_log_get_version_fd (log_fd, ¤t_version); for (p = slaves; p != NULL; p = p->next) send_diffs (context, p, log_fd, database, current_version); } for(p = slaves; p != NULL; p = p->next) { if (p->flags & SLAVE_F_DEAD) continue; if (ret && FD_ISSET(p->fd, &readset)) { --ret; assert(ret >= 0); if(process_msg (context, p, log_fd, database, current_version)) slave_dead(p); } else if (slave_gone_p (p)) slave_dead (p); else if (slave_missing_p (p)) send_are_you_there (context, p); } if (ret && FD_ISSET(listen_fd, &readset)) { add_slave (context, keytab, &slaves, listen_fd); --ret; assert(ret >= 0); } write_stats(context, slaves, current_version); } return 0; }
int main(int argc, char **argv) { krb5_error_code ret; setprogname(argv[0]); ret = krb5_init_context(&context); if (ret == KRB5_CONFIG_BADFORMAT) errx (1, "krb5_init_context failed to parse configuration file"); else if (ret) errx (1, "krb5_init_context failed: %d", ret); ret = krb5_kt_register(context, &hdb_kt_ops); if (ret) errx (1, "krb5_kt_register(HDB) failed: %d", ret); config = configure(context, argc, argv); #ifdef SIGPIPE #ifdef HAVE_SIGACTION { struct sigaction sa; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); } #else signal(SIGPIPE, SIG_IGN); #endif #endif /* SIGPIPE */ #ifdef SUPPORT_DETACH if (detach_from_console) daemon(0, 0); #endif #ifdef __APPLE__ if (sandbox_flag) { char *errorstring; ret = sandbox_init("kdc", SANDBOX_NAMED, &errorstring); if (ret) errx(1, "sandbox_init failed: %d: %s", ret, errorstring); } bonjour_announce(get_realms); #endif /* __APPLE__ */ pidfile(NULL); switch_environment(); setup_listeners(context, config, listen_on_ipc, listen_on_network); heim_sipc_signal_handler(SIGINT, terminated, "SIGINT"); heim_sipc_signal_handler(SIGTERM, terminated, "SIGTERM"); #ifdef SIGXCPU heim_sipc_signal_handler(SIGXCPU, terminated, "CPU time limit exceeded"); #endif heim_ipc_main(); krb5_free_context(context); return 0; }
int main(int argc, char **argv) { krb5_error_code ret; char **files; int optidx = 0; int e, i; krb5_log_facility *logfacility; krb5_keytab keytab; setprogname(argv[0]); ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); while((e = getarg(args, num_args, argc, argv, &optidx))) warnx("error at argument `%s'", argv[optidx]); if (help_flag) usage (0); if (version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if(ret) krb5_err(context, 1, ret, "reading configuration files"); ret = krb5_openlog(context, "kadmind", &logfacility); if (ret) krb5_err(context, 1, ret, "krb5_openlog"); ret = krb5_set_warn_dest(context, logfacility); if (ret) krb5_err(context, 1, ret, "krb5_set_warn_dest"); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve"); kadm5_setup_passwd_quality_check (context, check_library, check_function); for (i = 0; i < policy_libraries.num_strings; i++) { ret = kadm5_add_passwd_quality_verifier(context, policy_libraries.strings[i]); if (ret) krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier"); } ret = kadm5_add_passwd_quality_verifier(context, NULL); if (ret) krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier"); { int fd = 0; struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; socklen_t sa_size = sizeof(__ss); krb5_auth_context ac = NULL; int debug_port; if(debug_flag) { if(port_str == NULL) debug_port = krb5_getportbyname (context, "kerberos-adm", "tcp", 749); else debug_port = htons(atoi(port_str)); mini_inetd(debug_port); } else if(roken_getsockname(STDIN_FILENO, sa, &sa_size) < 0 && errno == ENOTSOCK) { parse_ports(context, port_str ? port_str : "+"); pidfile(NULL); start_server(context); } if(realm) krb5_set_default_realm(context, realm); /* XXX */ kadmind_loop(context, ac, keytab, fd); } return 0; }
int main(int argc, char **argv) { krb5_error_code ret; char **files; int optidx = 0; int i; krb5_log_facility *logfacility; krb5_keytab keytab; krb5_socket_t sfd = rk_INVALID_SOCKET; setprogname(argv[0]); ret = krb5_init_context(&context); if (ret) errx (1, "krb5_init_context failed: %d", ret); if (getarg(args, num_args, argc, argv, &optidx)) { warnx("error at argument `%s'", argv[optidx]); usage(1); } if (help_flag) usage (0); if (version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (config_file == NULL) { asprintf(&config_file, "%s/kdc.conf", hdb_db_dir(context)); if (config_file == NULL) errx(1, "out of memory"); } ret = krb5_prepend_config_files_default(config_file, &files); if (ret) krb5_err(context, 1, ret, "getting configuration files"); ret = krb5_set_config_files(context, files); krb5_free_config_files(files); if(ret) krb5_err(context, 1, ret, "reading configuration files"); ret = krb5_openlog(context, "kadmind", &logfacility); if (ret) krb5_err(context, 1, ret, "krb5_openlog"); ret = krb5_set_warn_dest(context, logfacility); if (ret) krb5_err(context, 1, ret, "krb5_set_warn_dest"); ret = krb5_kt_register(context, &hdb_kt_ops); if(ret) krb5_err(context, 1, ret, "krb5_kt_register"); ret = krb5_kt_resolve(context, keytab_str, &keytab); if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve"); kadm5_setup_passwd_quality_check (context, check_library, check_function); for (i = 0; i < policy_libraries.num_strings; i++) { ret = kadm5_add_passwd_quality_verifier(context, policy_libraries.strings[i]); if (ret) krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier"); } ret = kadm5_add_passwd_quality_verifier(context, NULL); if (ret) krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier"); if(debug_flag) { int debug_port; if(port_str == NULL) debug_port = krb5_getportbyname (context, "kerberos-adm", "tcp", 749); else debug_port = htons(atoi(port_str)); mini_inetd(debug_port, &sfd); } else { #ifdef _WIN32 pidfile(NULL); start_server(context, port_str); #else struct sockaddr_storage __ss; struct sockaddr *sa = (struct sockaddr *)&__ss; socklen_t sa_size = sizeof(__ss); /* * Check if we are running inside inetd or not, if not, start * our own server. */ if(roken_getsockname(STDIN_FILENO, sa, &sa_size) < 0 && rk_SOCK_ERRNO == ENOTSOCK) { pidfile(NULL); start_server(context, port_str); } #endif /* _WIN32 */ sfd = STDIN_FILENO; } if(realm) krb5_set_default_realm(context, realm); /* XXX */ kadmind_loop(context, keytab, sfd); return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_kdc_configuration *config; setprogname(argv[0]); ret = krb5_init_context(&context); if (ret == KRB5_CONFIG_BADFORMAT) errx (1, "krb5_init_context failed to parse configuration file"); else if (ret) errx (1, "krb5_init_context failed: %d", ret); ret = krb5_kt_register(context, &hdb_kt_ops); if (ret) errx (1, "krb5_kt_register(HDB) failed: %d", ret); config = configure(context, argc, argv); #ifdef HAVE_SIGACTION { struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = sigterm; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); #ifdef SIGXCPU sigaction(SIGXCPU, &sa, NULL); #endif sa.sa_handler = SIG_IGN; #ifdef SIGPIPE sigaction(SIGPIPE, &sa, NULL); #endif } #else signal(SIGINT, sigterm); signal(SIGTERM, sigterm); #ifdef SIGXCPU signal(SIGXCPU, sigterm); #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif #endif #ifdef SUPPORT_DETACH if (detach_from_console) daemon(0, 0); #endif #ifdef __APPLE__ bonjour_announce(context, config); #endif pidfile(NULL); switch_environment(); loop(context, config); krb5_free_context(context); return 0; }