static kadm5_ret_t
find_db_spec(kadm5_server_context *ctx)
{
    krb5_context context = ctx->context;
    struct hdb_dbinfo *info, *d;
    krb5_error_code ret;

    if (ctx->config.realm) {
	/* fetch the databases */
	ret = hdb_get_dbinfo(context, &info);
	if (ret)
	    return ret;

	d = NULL;
	while ((d = hdb_dbinfo_get_next(info, d)) != NULL) {
	    const char *p = hdb_dbinfo_get_realm(context, d);

	    /* match default (realm-less) */
	    if(p != NULL && strcmp(ctx->config.realm, p) != 0)
		continue;

	    p = hdb_dbinfo_get_dbname(context, d);
	    if (p)
		ctx->config.dbname = strdup(p);

	    p = hdb_dbinfo_get_acl_file(context, d);
	    if (p)
		ctx->config.acl_file = strdup(p);

	    p = hdb_dbinfo_get_mkey_file(context, d);
	    if (p)
		ctx->config.stash_file = strdup(p);

	    p = hdb_dbinfo_get_log_file(context, d);
	    if (p)
		ctx->log_context.log_file = strdup(p);
	    break;
	}
	hdb_free_dbinfo(context, &info);
    }

    /* If any of the values was unset, pick up the default value */

    if (ctx->config.dbname == NULL)
	ctx->config.dbname = strdup(hdb_default_db(context));
    if (ctx->config.acl_file == NULL)
	asprintf(&ctx->config.acl_file, "%s/kadmind.acl", hdb_db_dir(context));
    if (ctx->config.stash_file == NULL)
	asprintf(&ctx->config.stash_file, "%s/m-key", hdb_db_dir(context));
    if (ctx->log_context.log_file == NULL)
	asprintf(&ctx->log_context.log_file, "%s/log", hdb_db_dir(context));

#ifndef NO_UNIX_SOCKETS
    set_socket_name(context, &ctx->log_context.socket_name);
#else
    set_socket_info(context, &ctx->log_context.socket_info);
#endif

    return 0;
}
Esempio n. 2
0
static int
check_acl (krb5_context context, const char *name)
{
    const char *fn;
    FILE *fp;
    char buf[256];
    int ret = 1;
    char *slavefile = NULL;

    if (asprintf(&slavefile, "%s/slaves", hdb_db_dir(context)) == -1
	|| slavefile == NULL)
	errx(1, "out of memory");

    fn = krb5_config_get_string_default(context,
					NULL,
					slavefile,
					"kdc",
					"iprop-acl",
					NULL);

    fp = fopen (fn, "r");
    free(slavefile);
    if (fp == NULL)
	return 1;
    while (fgets(buf, sizeof(buf), fp) != NULL) {
	buf[strcspn(buf, "\r\n")] = '\0';
	if (strcmp (buf, name) == 0) {
	    ret = 0;
	    break;
	}
    }
    fclose (fp);
    return ret;
}
Esempio n. 3
0
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");
}
Esempio n. 4
0
static FILE *
open_stats(krb5_context context)
{
    char *statfile = NULL;
    const char *fn = NULL;
    FILE *out = NULL;

    /*
     * krb5_config_get_string_default() returs default value as-is,
     * delay free() of "statfile" until we're done with "fn".
     */
    if (slave_stats_file)
	fn = slave_stats_file;
    else if (asprintf(&statfile,  "%s/slaves-stats", hdb_db_dir(context)) != -1
	     && statfile != NULL)
	fn = krb5_config_get_string_default(context,
					    NULL,
					    statfile,
					    "kdc",
					    "iprop-stats",
					    NULL);
    if (fn != NULL)
	out = fopen(fn, "w");
    if (statfile != NULL)
	free(statfile);
    return out;
}
Esempio n. 5
0
static FILE *
open_stats(krb5_context context)
{
    char *statfile = NULL;
    const char *fn;
    int ret;

    if (slave_stats_file)
	fn = slave_stats_file;
    else {
	ret = asprintf(&statfile,  "%s/slaves-stats", hdb_db_dir(context));
	if (ret == -1)
	    return NULL;
	fn = krb5_config_get_string_default(context,
					    NULL,
					    statfile,
					    "kdc",
					    "iprop-stats",
					    NULL);
	free(statfile);
    }
    if (fn == NULL)
	return NULL;
    return fopen(fn, "w");
}
Esempio n. 6
0
const char *
kadm5_log_signal_socket(krb5_context context)
{
    HEIMDAL_MUTEX_lock(&signal_mutex);
    if (!default_signal)
	asprintf(&default_signal, "%s/signal", hdb_db_dir(context));
    HEIMDAL_MUTEX_unlock(&signal_mutex);

    return krb5_config_get_string_default(context,
					  NULL,
					  default_signal,
					  "kdc",
					  "signal_socket",
					  NULL);
}
Esempio n. 7
0
static kadm5_server_context *
get_kadmin_context(const char *config_file, char *realm)
{
    kadm5_config_params conf;
    krb5_error_code ret;
    void *kadm_handle;
    char **files;
    int aret;

    if (config_file == NULL) {
	char *file;
	aret = asprintf(&file, "%s/kdc.conf", hdb_db_dir(context));
	if (aret == -1 || file == NULL)
	    errx(1, "out of memory");
	config_file = file;
    }

    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");

    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");

    return (kadm5_server_context *)kadm_handle;
}
Esempio n. 8
0
static void
init_stats_names(krb5_context context)
{
    const char *fn = NULL;
    char *buf = NULL;

    if (slave_stats_file)
	fn = slave_stats_file;
    else if ((fn = krb5_config_get_string(context, NULL, "kdc",
                                          "iprop-stats", NULL)) == NULL) {
        if (asprintf(&buf, "%s/slaves-stats", hdb_db_dir(context)) != -1
	    && buf != NULL)
            fn = buf;
        buf = NULL;
    }
    if (fn != NULL) {
        slave_stats_file = fn;
        if (asprintf(&buf, "%s.tmp", fn) != -1 && buf != NULL)
            slave_stats_temp_file = buf;
    }
}
Esempio n. 9
0
File: log.c Progetto: AllardJ/Tomato
void
kdc_openlog(krb5_context context,
	    krb5_kdc_configuration *config)
{
    char **s = NULL, **p;
    krb5_initlog(context, "kdc", &config->logf);
    s = krb5_config_get_strings(context, NULL, "kdc", "logging", NULL);
    if(s == NULL)
	s = krb5_config_get_strings(context, NULL, "logging", "kdc", NULL);
    if(s){
	for(p = s; *p; p++)
	    krb5_addlog_dest(context, config->logf, *p);
	krb5_config_free_strings(s);
    }else {
	char *s;
	asprintf(&s, "0-1/FILE:%s/%s", hdb_db_dir(context), KDC_LOG_FILE);
	krb5_addlog_dest(context, config->logf, s);
	free(s);
    }
    krb5_set_warn_dest(context, config->logf);
}
Esempio n. 10
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    char **files;
    kadm5_config_params conf;
    int optidx = 0;
    int exit_status = 0;

    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))
	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");

    memset(&conf, 0, sizeof(conf));
    if(realm) {
	krb5_set_default_realm(context, realm); /* XXX should be fixed
						   some other way */
	conf.realm = realm;
	conf.mask |= KADM5_CONFIG_REALM;
    }

    if (admin_server) {
	conf.admin_server = admin_server;
	conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
    }

    if (server_port) {
	conf.kadmind_port = htons(server_port);
	conf.mask |= KADM5_CONFIG_KADMIND_PORT;
    }

    if (keyfile) {
	conf.stash_file = keyfile;
	conf.mask |= KADM5_CONFIG_STASH_FILE;
    }

    if(local_flag) {
	int i;

	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");

	ret = kadm5_s_init_with_password_ctx(context,
					     KADM5_ADMIN_SERVICE,
					     NULL,
					     KADM5_ADMIN_SERVICE,
					     &conf, 0, 0,
					     &kadm_handle);
    } else if (mit_flag) {
	ret = kadm5_mit_init_with_password_ctx(context,
					       client_name,
					       NULL,
					       &conf, 0, 0,
					       &kadm_handle);
    } else if (ad_flag) {
	if (client_name == NULL)
	    krb5_errx(context, 1, "keytab mode require principal name");
	ret = kadm5_ad_init_with_password_ctx(context,
					      client_name,
					      NULL,
					      KADM5_ADMIN_SERVICE,
					      &conf, 0, 0,
					      &kadm_handle);
    } else if (keytab) {
	if (client_name == NULL)
	    krb5_errx(context, 1, "keytab mode require principal name");
        ret = kadm5_c_init_with_skey_ctx(context,
					 client_name,
					 keytab,
					 KADM5_ADMIN_SERVICE,
                                         &conf, 0, 0,
                                         &kadm_handle);
    } else
	ret = kadm5_c_init_with_password_ctx(context,
					     client_name,
					     NULL,
					     KADM5_ADMIN_SERVICE,
					     &conf, 0, 0,
					     &kadm_handle);

    if(ret)
	krb5_err(context, 1, ret, "kadm5_init_with_password");

    signal(SIGINT, SIG_IGN); /* ignore signals for now, the sl command
                                parser will handle SIGINT its own way;
                                we should really take care of this in
                                each function, f.i `get' might be
                                interruptable, but not `create' */
    if (argc != 0) {
	ret = sl_command (commands, argc, argv);
	if(ret == -1)
	    krb5_warnx (context, "unrecognized command: %s", argv[0]);
	else if (ret == -2)
	    ret = 0;
	if(ret != 0)
	    exit_status = 1;
    } else {
	while(!exit_seen) {
	    ret = sl_command_loop(commands, "kadmin> ", NULL);
	    if (ret == -2)
		exit_seen = 1;
	    else if (ret != 0)
		exit_status = 1;
	}
    }

    kadm5_destroy(kadm_handle);
    krb5_free_context(context);
    return exit_status;
}
Esempio n. 11
0
krb5_error_code
krb5_kdc_pk_initialize(krb5_context context,
		       krb5_kdc_configuration *config,
		       const char *user_id,
		       const char *anchors,
		       char **pool,
		       char **revoke_list)
{
    const char *file;
    char *fn = NULL;
    krb5_error_code ret;

    file = krb5_config_get_string(context, NULL,
				  "libdefaults", "moduli", NULL);

    ret = _krb5_parse_moduli(context, file, &moduli);
    if (ret)
	krb5_err(context, 1, ret, "PKINIT: failed to load modidi file");

    principal_mappings.len = 0;
    principal_mappings.val = NULL;

    ret = _krb5_pk_load_id(context,
			   &kdc_identity,
			   user_id,
			   anchors,
			   pool,
			   revoke_list,
			   NULL,
			   NULL,
			   NULL);
    if (ret) {
	krb5_warn(context, ret, "PKINIT: ");
	config->enable_pkinit = 0;
	return ret;
    }

    {
	hx509_query *q;
	hx509_cert cert;

	ret = hx509_query_alloc(context->hx509ctx, &q);
	if (ret) {
	    krb5_warnx(context, "PKINIT: out of memory");
	    return ENOMEM;
	}

	hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
	if (config->pkinit_kdc_friendly_name)
	    hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);

	ret = hx509_certs_find(context->hx509ctx,
			       kdc_identity->certs,
			       q,
			       &cert);
	hx509_query_free(context->hx509ctx, q);
	if (ret == 0) {
	    if (hx509_cert_check_eku(context->hx509ctx, cert,
				     &asn1_oid_id_pkkdcekuoid, 0)) {
		hx509_name name;
		char *str;
		ret = hx509_cert_get_subject(cert, &name);
		if (ret == 0) {
		    hx509_name_to_string(name, &str);
		    krb5_warnx(context, "WARNING Found KDC certificate (%s)"
			       "is missing the PK-INIT KDC EKU, this is bad for "
			       "interoperability.", str);
		    hx509_name_free(&name);
		    free(str);
		}
	    }
	    hx509_cert_free(cert);
	} else
	    krb5_warnx(context, "PKINIT: failed to find a signing "
		       "certifiate with a public key");
    }

    if (krb5_config_get_bool_default(context,
				     NULL,
				     FALSE,
				     "kdc",
				     "pkinit_allow_proxy_certificate",
				     NULL))
	config->pkinit_allow_proxy_certs = 1;

    file = krb5_config_get_string(context,
				  NULL,
				  "kdc",
				  "pkinit_mappings_file",
				  NULL);
    if (file == NULL) {
	int aret;

	aret = asprintf(&fn, "%s/pki-mapping", hdb_db_dir(context));
	if (aret == -1) {
	    krb5_warnx(context, "PKINIT: out of memory");
	    return ENOMEM;
	}

	file = fn;
    }

    load_mappings(context, file);
    if (fn)
	free(fn);

    return 0;
}
Esempio n. 12
0
static int
send_complete (krb5_context context, slave *s, const char *database,
	       uint32_t current_version, uint32_t oldest_version,
	       uint32_t initial_log_tstamp)
{
    krb5_error_code ret;
    krb5_storage *dump = NULL;
    uint32_t vno = 0;
    krb5_data data;
    int fd = -1;
    struct stat st;
    char *dfn;

    ret = asprintf(&dfn, "%s/ipropd.dumpfile", hdb_db_dir(context));
    if (ret == -1 || !dfn) {
	krb5_warn(context, ENOMEM, "Cannot allocate memory");
	return ENOMEM;
    }

    fd = open(dfn, O_CREAT|O_RDWR, 0600);
    if (fd == -1) {
	ret = errno;
	krb5_warn(context, ret, "Cannot open/create iprop dumpfile %s", dfn);
	free(dfn);
        return ret;
    }
    free(dfn);

    dump = krb5_storage_from_fd(fd);
    if (!dump) {
	ret = errno;
	krb5_warn(context, ret, "krb5_storage_from_fd");
	goto done;
    }

    for (;;) {
	ret = flock(fd, LOCK_SH);
	if (ret == -1) {
	    ret = errno;
	    krb5_warn(context, ret, "flock(fd, LOCK_SH)");
	    goto done;
	}

	if (krb5_storage_seek(dump, 0, SEEK_SET) == (off_t)-1) {
	    ret = errno;
	    krb5_warn(context, ret, "krb5_storage_seek(dump, 0, SEEK_SET)");
	    goto done;
	}

	vno = 0;
	ret = krb5_ret_uint32(dump, &vno);
	if (ret && ret != HEIM_ERR_EOF) {
	    krb5_warn(context, ret, "krb5_ret_uint32(dump, &vno)");
	    goto done;
	}

        if (fstat(fd, &st) == -1) {
            ret = errno;
            krb5_warn(context, ret, "send_complete: could not stat dump file");
            goto done;
        }

	/*
	 * If the current dump has an appropriate version, then we can
	 * break out of the loop and send the file below.
	 */

	if (ret == 0 && vno != 0 && st.st_mtime > initial_log_tstamp &&
            vno >= oldest_version && vno <= current_version)
	    break;

        if (verbose)
            krb5_warnx(context, "send_complete: dumping HDB");

	/*
	 * Otherwise, we may need to write a new dump file.  We
	 * obtain an exclusive lock on the fd.  Because this is
	 * not guaranteed to be an upgrade of our existing shared
	 * lock, someone else may have written a new dumpfile while
	 * we were waiting and so we must first check the vno of
	 * the dump to see if that happened.  If it did, we need
	 * to go back to the top of the loop so that we can downgrade
	 * our lock to a shared one.
	 */

	ret = flock(fd, LOCK_EX);
	if (ret == -1) {
	    ret = errno;
	    krb5_warn(context, ret, "flock(fd, LOCK_EX)");
	    goto done;
	}

	ret = krb5_storage_seek(dump, 0, SEEK_SET);
	if (ret == -1) {
	    ret = errno;
	    krb5_warn(context, ret, "krb5_storage_seek(dump, 0, SEEK_SET)");
	    goto done;
	}

	vno = 0;
	ret = krb5_ret_uint32(dump, &vno);
	if (ret && ret != HEIM_ERR_EOF) {
	    krb5_warn(context, ret, "krb5_ret_uint32(dump, &vno)");
	    goto done;
	}

        if (fstat(fd, &st) == -1) {
            ret = errno;
            krb5_warn(context, ret, "send_complete: could not stat dump file");
            goto done;
        }

	/* check if someone wrote a better version for us */
        if (ret == 0 && vno != 0 && st.st_mtime > initial_log_tstamp &&
            vno >= oldest_version && vno <= current_version)
	    continue;

	/* Now, we know that we must write a new dump file.  */

	ret = write_dump(context, dump, database, current_version);
	if (ret)
	    goto done;

	/*
	 * And we must continue to the top of the loop so that we can
	 * downgrade to a shared lock.
	 */
    }

    /*
     * Leaving the above loop, dump should have a ptr right after the initial
     * 4 byte DB version number and we should have a shared lock on the file
     * (which we may have just created), so we are reading to simply blast
     * the data down the wire.
     */

    for (;;) {
	ret = krb5_ret_data(dump, &data);
	if (ret == HEIM_ERR_EOF) {
	    ret = 0;	/* EOF is not an error, it's success */
	    goto done;
	}

	if (ret) {
	    krb5_warn(context, ret, "krb5_ret_data(dump, &data)");
	    slave_dead(context, s);
	    goto done;
	}

	ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
	krb5_data_free(&data);

	if (ret) {
	    krb5_warn (context, ret, "krb5_write_priv_message");
	    slave_dead(context, s);
	    goto done;
	}
    }

done:
    if (!ret) {
	s->version = vno;
	slave_seen(s);
    }
    if (fd != -1)
	close(fd);
    if (dump)
	krb5_storage_free(dump);
    return ret;
}
Esempio n. 13
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;
    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,
                             &current_version, &current_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,
                                     &current_version, &current_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,
                                     &current_version, &current_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,
                                     &current_version, &current_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;
}
Esempio n. 14
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;
}
Esempio n. 15
0
int
main(int argc, char **argv)
{
    char buf[1024];
    krb5_error_code ret;

    krb5_enctype enctype;

    hdb_master_key mkey;

    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 (master_key_fd != -1 && random_key_flag)
	krb5_errx(context, 1, "random-key and master-key-fd "
		  "is mutual exclusive");

    if (keyfile == NULL)
	asprintf(&keyfile, "%s/m-key", hdb_db_dir(context));

    ret = krb5_string_to_enctype(context, enctype_str, &enctype);
    if(ret)
	krb5_err(context, 1, ret, "krb5_string_to_enctype");

    ret = hdb_read_master_key(context, keyfile, &mkey);
    if(ret && ret != ENOENT)
	krb5_err(context, 1, ret, "reading master key from %s", keyfile);

    if (convert_flag) {
	if (ret)
	    krb5_err(context, 1, ret, "reading master key from %s", keyfile);
    } else {
	krb5_keyblock key;
	krb5_salt salt;
	salt.salttype = KRB5_PW_SALT;
	/* XXX better value? */
	salt.saltvalue.data = NULL;
	salt.saltvalue.length = 0;
	if (random_key_flag) {
	    ret = krb5_generate_random_keyblock(context, enctype, &key);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_generate_random_keyblock");

	} else {
	    if(master_key_fd != -1) {
		ssize_t n;
		n = read(master_key_fd, buf, sizeof(buf));
		if(n <= 0)
		    krb5_err(context, 1, errno, "failed to read passphrase");
		buf[n] = '\0';
		buf[strcspn(buf, "\r\n")] = '\0';
		
	    } else {
		if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", 1))
		    exit(1);
	    }
	    krb5_string_to_key_salt(context, enctype, buf, salt, &key);
	}
	ret = hdb_add_master_key(context, &key, &mkey);
	
	krb5_free_keyblock_contents(context, &key);

    }

    {
	char *new, *old;
	asprintf(&old, "%s.old", keyfile);
	asprintf(&new, "%s.new", keyfile);
	if(unlink(new) < 0 && errno != ENOENT) {
	    ret = errno;
	    goto out;
	}
	krb5_warnx(context, "writing key to `%s'", keyfile);
	ret = hdb_write_master_key(context, new, mkey);
	if(ret)
	    unlink(new);
	else {
#ifndef NO_POSIX_LINKS
	    unlink(old);
	    if(link(keyfile, old) < 0 && errno != ENOENT) {
		ret = errno;
		unlink(new);
	    } else {
#endif
		if(rename(new, keyfile) < 0) {
Esempio n. 16
0
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;
}
Esempio n. 17
0
int
stash(struct stash_options *opt, int argc, char **argv)
{
    char buf[1024];
    krb5_error_code ret;
    krb5_enctype enctype;
    hdb_master_key mkey;
    int aret;

    if(!local_flag) {
	krb5_warnx(context, "stash is only available in local (-l) mode");
	return 0;
    }

    ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
    if(ret) {
	krb5_warn(context, ret, "%s", opt->enctype_string);
	return 0;
    }

    if(opt->key_file_string == NULL) {
	aret = asprintf(&opt->key_file_string, "%s/m-key", hdb_db_dir(context));
	if (aret == -1)
	    errx(1, "out of memory");
    }

    ret = hdb_read_master_key(context, opt->key_file_string, &mkey);
    if(ret && ret != ENOENT) {
	krb5_warn(context, ret, "reading master key from %s",
		  opt->key_file_string);
	return 0;
    }

    if (opt->convert_file_flag) {
	if (ret)
	    krb5_warn(context, ret, "reading master key from %s",
		      opt->key_file_string);
	return 0;
    } else {
	krb5_keyblock key;
	krb5_salt salt;
	salt.salttype = KRB5_PW_SALT;
	/* XXX better value? */
	salt.saltvalue.data = NULL;
	salt.saltvalue.length = 0;
	if(opt->master_key_fd_integer != -1) {
	    ssize_t n;
	    n = read(opt->master_key_fd_integer, buf, sizeof(buf));
	    if(n == 0)
		krb5_warnx(context, "end of file reading passphrase");
	    else if(n < 0) {
		krb5_warn(context, errno, "reading passphrase");
		n = 0;
	    }
	    buf[n] = '\0';
	    buf[strcspn(buf, "\r\n")] = '\0';
	} else if (opt->random_password_flag) {
	    random_password (buf, sizeof(buf));
	    printf("Using random master stash password: %s\n", buf);
	} else {
	    if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", 1)) {
		hdb_free_master_key(context, mkey);
		return 0;
	    }
	}
	ret = krb5_string_to_key_salt(context, enctype, buf, salt, &key);
	ret = hdb_add_master_key(context, &key, &mkey);
	krb5_free_keyblock_contents(context, &key);
    }

    {
	char *new = NULL, *old = NULL;
	int aret;

	aret = asprintf(&old, "%s.old", opt->key_file_string);
	if (aret == -1) {
	    ret = ENOMEM;
	    goto out;
	}
	aret = asprintf(&new, "%s.new", opt->key_file_string);
	if (aret == -1) {
	    ret = ENOMEM;
	    goto out;
	}

	if(unlink(new) < 0 && errno != ENOENT) {
	    ret = errno;
	    goto out;
	}
	krb5_warnx(context, "writing key to \"%s\"", opt->key_file_string);
	ret = hdb_write_master_key(context, new, mkey);
	if(ret)
	    unlink(new);
	else {
	    unlink(old);
#ifndef NO_POSIX_LINKS
	    if(link(opt->key_file_string, old) < 0 && errno != ENOENT) {
		ret = errno;
		unlink(new);
	    } else {
#endif
		if(rename(new, opt->key_file_string) < 0) {
Esempio n. 18
0
krb5_kdc_configuration *
configure(krb5_context context, int argc, char **argv, int *optidx)
{
    krb5_kdc_configuration *config;
    krb5_error_code ret;
    
    const char *p;

    *optidx = 0;

    while(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);
    }

    if (builtin_hdb_flag) {
	char *list;
	ret = hdb_list_builtin(context, &list);
	if (ret)
	    krb5_err(context, 1, ret, "listing builtin hdb backends");
	printf("builtin hdb backends: %s\n", list);
	free(list);
	exit(0);
    }

    {
	char **files;
	int aret;

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

    ret = krb5_kdc_get_config(context, &config);
    if (ret)
	krb5_err(context, 1, ret, "krb5_kdc_default_config");

    kdc_openlog(context, "kdc", config);

    ret = krb5_kdc_set_dbinfo(context, config);
    if (ret)
	krb5_err(context, 1, ret, "krb5_kdc_set_dbinfo");

    if(max_request_str)
	max_request_tcp = max_request_udp = parse_bytes(max_request_str, NULL);

    if(max_request_tcp == 0){
	p = krb5_config_get_string (context,
				    NULL,
				    "kdc",
				    "max-request",
				    NULL);
	if(p)
	    max_request_tcp = max_request_udp = parse_bytes(p, NULL);
    }

    if(require_preauth != -1)
	config->require_preauth = require_preauth;

    if(port_str == NULL){
	p = krb5_config_get_string(context, NULL, "kdc", "ports", NULL);
	if (p != NULL)
	    port_str = strdup(p);
    }

    explicit_addresses.len = 0;

    if (addresses_str.num_strings) {
	int i;

	for (i = 0; i < addresses_str.num_strings; ++i)
	    add_one_address (context, addresses_str.strings[i], i == 0);
	free_getarg_strings (&addresses_str);
    } else {
	char **foo = krb5_config_get_strings (context, NULL,
					      "kdc", "addresses", NULL);

	if (foo != NULL) {
	    add_one_address (context, *foo++, TRUE);
	    while (*foo)
		add_one_address (context, *foo++, FALSE);
	}
    }

    if(enable_http == -1)
	enable_http = krb5_config_get_bool(context, NULL, "kdc",
					   "enable-http", NULL);

    if(request_log == NULL)
	request_log = krb5_config_get_string(context, NULL,
					     "kdc",
					     "kdc-request-log",
					     NULL);

    if (krb5_config_get_string(context, NULL, "kdc",
			       "enforce-transited-policy", NULL))
	krb5_errx(context, 1, "enforce-transited-policy deprecated, "
		  "use [kdc]transited-policy instead");

#ifdef SUPPORT_DETACH
    if(detach_from_console == -1)
	detach_from_console = krb5_config_get_bool_default(context, NULL,
							   DETACH_IS_DEFAULT,
							   "kdc",
							   "detach", NULL);
#endif /* SUPPORT_DETACH */

    if(max_request_tcp == 0)
	max_request_tcp = 64 * 1024;
    if(max_request_udp == 0)
	max_request_udp = 64 * 1024;

    if (port_str == NULL)
	port_str = "+";

    if(disable_des == -1)
	disable_des = krb5_config_get_bool_default(context, NULL,
						   FALSE,
						   "kdc",
						   "disable-des", NULL);
    if(disable_des) {
	krb5_enctype_disable(context, ETYPE_DES_CBC_CRC);
	krb5_enctype_disable(context, ETYPE_DES_CBC_MD4);
	krb5_enctype_disable(context, ETYPE_DES_CBC_MD5);
	krb5_enctype_disable(context, ETYPE_DES_CBC_NONE);
	krb5_enctype_disable(context, ETYPE_DES_CFB64_NONE);
	krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE);
    }

    krb5_kdc_windc_init(context);

    krb5_kdc_pkinit_config(context, config);

    return config;
}
Esempio n. 19
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;
}
Esempio n. 20
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;
    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, &current_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, &current_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, &current_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;
}
Esempio n. 21
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);
}
Esempio n. 22
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;
}
Esempio n. 23
0
krb5_kdc_configuration *
configure(krb5_context context, int argc, char **argv)
{
    krb5_kdc_configuration *config;
    krb5_error_code ret;
    int optidx = 0;
    const char *p;

    while(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);
    }

    if (builtin_hdb_flag) {
	char *list;
	ret = hdb_list_builtin(context, &list);
	if (ret)
	    krb5_err(context, 1, ret, "listing builtin hdb backends");
	printf("builtin hdb backends: %s\n", list);
	free(list);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (argc != 0)
	usage(1);

    {
	char **files;

	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_kdc_get_config(context, &config);
    if (ret)
	krb5_err(context, 1, ret, "krb5_kdc_default_config");

    kdc_openlog(context, "kdc", config);

    ret = krb5_kdc_set_dbinfo(context, config);
    if (ret)
	krb5_err(context, 1, ret, "krb5_kdc_set_dbinfo");

    if(max_request_str)
	max_request_tcp = max_request_udp = parse_bytes(max_request_str, NULL);

    if(max_request_tcp == 0){
	p = krb5_config_get_string (context,
				    NULL,
				    "kdc",
				    "max-request",
				    NULL);
	if(p)
	    max_request_tcp = max_request_udp = parse_bytes(p, NULL);
    }

    if(require_preauth != -1)
	config->require_preauth = require_preauth;

    if(port_str == NULL){
	p = krb5_config_get_string(context, NULL, "kdc", "ports", NULL);
	if (p != NULL)
	    port_str = strdup(p);
    }

    explicit_addresses.len = 0;

    if (addresses_str.num_strings) {
	int i;

	for (i = 0; i < addresses_str.num_strings; ++i)
	    add_one_address (context, addresses_str.strings[i], i == 0);
	free_getarg_strings (&addresses_str);
    } else {
	char **foo = krb5_config_get_strings (context, NULL,
					      "kdc", "addresses", NULL);

	if (foo != NULL) {
	    add_one_address (context, *foo++, TRUE);
	    while (*foo)
		add_one_address (context, *foo++, FALSE);
	}
    }

    if(enable_v4 != -1)
	config->enable_v4 = enable_v4;

    if(enable_v4_cross_realm != -1)
	config->enable_v4_cross_realm = enable_v4_cross_realm;

    if(enable_524 != -1)
	config->enable_524 = enable_524;

    if(enable_http == -1)
	enable_http = krb5_config_get_bool(context, NULL, "kdc",
					   "enable-http", NULL);

    if(request_log == NULL)
	request_log = krb5_config_get_string(context, NULL,
					     "kdc",
					     "kdc-request-log",
					     NULL);

    if (krb5_config_get_string(context, NULL, "kdc",
			       "enforce-transited-policy", NULL))
	krb5_errx(context, 1, "enforce-transited-policy deprecated, "
		  "use [kdc]transited-policy instead");

    if (enable_kaserver != -1)
	config->enable_kaserver = enable_kaserver;

#ifdef SUPPORT_DETACH
    if(detach_from_console == -1)
	detach_from_console = krb5_config_get_bool_default(context, NULL,
							   DETACH_IS_DEFAULT,
							   "kdc",
							   "detach", NULL);
#endif /* SUPPORT_DETACH */
    
    if(max_request_tcp == 0)
	max_request_tcp = 64 * 1024;
    if(max_request_udp == 0)
	max_request_udp = 64 * 1024;

    if (port_str == NULL)
	port_str = "+";

    if (v4_realm)
	config->v4_realm = v4_realm;

    if(config->v4_realm == NULL && (config->enable_kaserver || config->enable_v4))
	krb5_errx(context, 1, "Kerberos 4 enabled but no realm configured");

    if(disable_des == -1)
	disable_des = krb5_config_get_bool_default(context, NULL,
						   FALSE,
						   "kdc",
						   "disable-des", NULL);
    if(disable_des) {
	krb5_enctype_disable(context, ETYPE_DES_CBC_CRC);
	krb5_enctype_disable(context, ETYPE_DES_CBC_MD4);
	krb5_enctype_disable(context, ETYPE_DES_CBC_MD5);
	krb5_enctype_disable(context, ETYPE_DES_CBC_NONE);
	krb5_enctype_disable(context, ETYPE_DES_CFB64_NONE);
	krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE);

	kdc_log(context, config,
		0, "DES was disabled, turned off Kerberos V4, 524 "
		"and kaserver");
	config->enable_v4 = 0;
	config->enable_524 = 0;
	config->enable_kaserver = 0;
    }

    krb5_kdc_windc_init(context);

#ifdef PKINIT
#ifdef __APPLE__
    config->enable_pkinit = 1;

    if (config->pkinit_kdc_identity == NULL) {
	if (config->pkinit_kdc_friendly_name == NULL)
	    config->pkinit_kdc_friendly_name = 
		strdup("O=System Identity,CN=com.apple.kerberos.kdc");
	config->pkinit_kdc_identity = strdup("KEYCHAIN:");
    }
    if (config->pkinit_kdc_anchors == NULL)
	config->pkinit_kdc_anchors = strdup("KEYCHAIN:");

#endif /* __APPLE__ */

    if (config->enable_pkinit) {
	if (config->pkinit_kdc_identity == NULL)
	    krb5_errx(context, 1, "pkinit enabled but no identity");
 
	if (config->pkinit_kdc_anchors == NULL)
	    krb5_errx(context, 1, "pkinit enabled but no X509 anchors");

	krb5_kdc_pk_initialize(context, config,
			       config->pkinit_kdc_identity,
			       config->pkinit_kdc_anchors,
			       config->pkinit_kdc_cert_pool,
			       config->pkinit_kdc_revoke);

    }

#endif /* PKINIT */
    
    return config;
}