Beispiel #1
0
kdb_fullresync_result_t *
iprop_full_resync_1_svc(/* LINTED */ void *argp, struct svc_req *rqstp)
{
    static kdb_fullresync_result_t ret;
    char *tmpf = 0;
    char *ubuf = 0;
    char clhost[MAXHOSTNAMELEN] = {0};
    int pret, fret;
    kadm5_server_handle_t handle = global_server_handle;
    OM_uint32 min_stat;
    gss_name_t name = NULL;
    char *client_name = NULL, *service_name = NULL;
    char *whoami = "iprop_full_resync_1";

    /* default return code */
    ret.ret = UPDATE_ERROR;

    if (!handle) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: server handle is NULL"),
			 whoami);
	goto out;
    }

    DPRINT(("%s: start\n", whoami));

    {
	gss_buffer_desc client_desc, service_desc;

	if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) {
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: setup_gss_names failed"),
			     whoami);
	    goto out;
	}
	client_name = buf_to_string(&client_desc);
	service_name = buf_to_string(&service_desc);
	if (client_name == NULL || service_name == NULL) {
	    free(client_name);
	    free(service_name);
	    krb5_klog_syslog(LOG_ERR,
			     "%s: out of memory recording principal names",
			     whoami);
	    goto out;
	}
    }

    DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
	    whoami, client_name, service_name));

    if (!kadm5int_acl_check(handle->context,
			    rqst2name(rqstp),
			    ACL_IPROP,
			    NULL,
			    NULL)) {
	ret.ret = UPDATE_PERM_DENIED;

	krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
			 "<null>", client_name, service_name,
			 client_addr(rqstp));
	goto out;
    }

    if (!getclhoststr(client_name, clhost, sizeof (clhost))) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: getclhoststr failed"),
			 whoami);
	goto out;
    }

    /*
     * construct db dump file name; kprop style name + clnt fqdn
     */
    if (asprintf(&tmpf, "%s_%s", KPROP_DEFAULT_FILE, clhost) < 0) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: unable to construct db dump file name; out of memory"),
			 whoami);
	goto out;
    }

    /*
     * note the -i; modified version of kdb5_util dump format
     * to include sno (serial number)
     */
    if (asprintf(&ubuf, "%s dump -i %s", KPROPD_DEFAULT_KDB5_UTIL,
		 tmpf) < 0) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: cannot construct kdb5 util dump string too long; out of memory"),
			 whoami);
	goto out;
    }

    /*
     * Fork to dump the db and xfer it to the slave.
     * (the fork allows parent to return quickly and the child
     * acts like a callback to the slave).
     */
    fret = fork();
    DPRINT(("%s: fork=%d (%d)\n", whoami, fret, getpid()));

    switch (fret) {
    case -1: /* error */
	if (nofork) {
	    perror(whoami);
	}
	krb5_klog_syslog(LOG_ERR,
			 _("%s: fork failed: %s"),
			 whoami,
			 error_message(errno));
	goto out;

    case 0: /* child */
	DPRINT(("%s: run `%s' ...\n", whoami, ubuf));
	(void) signal(SIGCHLD, SIG_DFL);
	/* run kdb5_util(1M) dump for IProp */
	/* XXX popen can return NULL; is pclose(NULL) okay?  */
	pret = pclose(popen(ubuf, "w"));
	DPRINT(("%s: pclose=%d\n", whoami, pret));
	if (pret != 0) {
	    /* XXX popen/pclose may not set errno
	       properly, and the error could be from the
	       subprocess anyways.  */
	    if (nofork) {
		perror(whoami);
	    }
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: pclose(popen) failed: %s"),
			     whoami,
			     error_message(errno));
	    goto out;
	}

	DPRINT(("%s: exec `kprop -f %s %s' ...\n",
		whoami, tmpf, clhost));
	/* XXX Yuck!  */
	if (getenv("KPROP_PORT"))
	    pret = execl(KPROPD_DEFAULT_KPROP, "kprop", "-f", tmpf,
			 "-P", getenv("KPROP_PORT"),
			 clhost, NULL);
	else
	    pret = execl(KPROPD_DEFAULT_KPROP, "kprop", "-f", tmpf,
			 clhost, NULL);
	if (pret == -1) {
	    if (nofork) {
		perror(whoami);
	    }
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: exec failed: %s"),
			     whoami,
			     error_message(errno));
	    goto out;
	}

    default: /* parent */
	ret.ret = UPDATE_OK;
	/* not used by slave (sno is retrieved from kdb5_util dump) */
	ret.lastentry.last_sno = 0;
	ret.lastentry.last_time.seconds = 0;
	ret.lastentry.last_time.useconds = 0;

	krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
			 "<null>",
			 "success",
			 client_name, service_name,
			 client_addr(rqstp));

	goto out;
    }

out:
    if (nofork)
	debprret(whoami, ret.ret, 0);
    free(client_name);
    free(service_name);
    if (name)
	gss_release_name(&min_stat, &name);
    free(tmpf);
    free(ubuf);
    return (&ret);
}
Beispiel #2
0
kdb_incr_result_t *
iprop_get_updates_1_svc(kdb_last_t *arg, struct svc_req *rqstp)
{
    static kdb_incr_result_t ret;
    char *whoami = "iprop_get_updates_1";
    int kret;
    kadm5_server_handle_t handle = global_server_handle;
    char *client_name = 0, *service_name = 0;
    char obuf[256] = {0};

    /* default return code */
    ret.ret = UPDATE_ERROR;

    DPRINT(("%s: start, last_sno=%lu\n", whoami,
	    (unsigned long) arg->last_sno));

    if (!handle) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: server handle is NULL"),
			 whoami);
	goto out;
    }

    {
	gss_buffer_desc client_desc, service_desc;

	if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) {
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: setup_gss_names failed"),
			     whoami);
	    goto out;
	}
	client_name = buf_to_string(&client_desc);
	service_name = buf_to_string(&service_desc);
	if (client_name == NULL || service_name == NULL) {
	    free(client_name);
	    free(service_name);
	    krb5_klog_syslog(LOG_ERR,
			     "%s: out of memory recording principal names",
			     whoami);
	    goto out;
	}
    }

    DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
	    whoami, client_name, service_name));

    if (!kadm5int_acl_check(handle->context,
			    rqst2name(rqstp),
			    ACL_IPROP,
			    NULL,
			    NULL)) {
	ret.ret = UPDATE_PERM_DENIED;

	krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
			 "<null>", client_name, service_name,
			 client_addr(rqstp));
	goto out;
    }

    kret = ulog_get_entries(handle->context, *arg, &ret);

    if (ret.ret == UPDATE_OK) {
	(void) snprintf(obuf, sizeof (obuf),
			_("%s; Incoming SerialNo=%lu; Outgoing SerialNo=%lu"),
			replystr(ret.ret),
			(unsigned long)arg->last_sno,
			(unsigned long)ret.lastentry.last_sno);
    } else {
	(void) snprintf(obuf, sizeof (obuf),
			_("%s; Incoming SerialNo=%lu; Outgoing SerialNo=N/A"),
			replystr(ret.ret),
			(unsigned long)arg->last_sno);
    }

    krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
		     obuf,
		     ((kret == 0) ? "success" : error_message(kret)),
		     client_name, service_name,
		     client_addr(rqstp));

out:
    if (nofork)
	debprret(whoami, ret.ret, ret.lastentry.last_sno);
    free(client_name);
    free(service_name);
    return (&ret);
}
Beispiel #3
0
kdb_fullresync_result_t *
iprop_full_resync_1(
	/* LINTED */
	void *argp,
	struct svc_req *rqstp)
{
	static kdb_fullresync_result_t ret;
	char tmpf[MAX_FILENAME] = {0};
	char ubuf[MAX_FILENAME + sizeof (KDB5_UTIL_DUMP_STR)] = {0};
	char clhost[MAXHOSTNAMELEN] = {0};
	int pret, fret;
	kadm5_server_handle_t handle = global_server_handle;
	OM_uint32 min_stat;
	gss_name_t name = NULL;
	char *client_name = NULL, *service_name = NULL;
	char *whoami = "iprop_full_resync_1";

	/* default return code */
	ret.ret = UPDATE_ERROR;

	if (!handle) {
		krb5_klog_syslog(LOG_ERR,
				gettext("%s: server handle is NULL"),
					whoami);
		goto out;
	}

	DPRINT(("%s: start\n", whoami));

	if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: setup_gss_names failed"),
			whoami);
		goto out;
	}

	DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
		whoami, client_name, service_name));

	if (!(name = get_clnt_name(rqstp))) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: Couldn't obtain client's name"),
			whoami);
		goto out;
	}
	if (!kadm5int_acl_check(handle->context,
		    name,
		    ACL_IPROP,
		    NULL,
		    NULL)) {
		ret.ret = UPDATE_PERM_DENIED;

		audit_kadmind_unauth(rqstp->rq_xprt, l_port,
				    whoami,
				    "<null>", client_name);
		krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
				"<null>", client_name, service_name,
				client_addr(rqstp, abuf));
		goto out;
	}

	if (!getclhoststr(client_name, clhost, sizeof (clhost))) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: getclhoststr failed"),
			whoami);
		goto out;
	}

	/*
	 * construct db dump file name; kprop style name + clnt fqdn
	 */
	(void) strcpy(tmpf, "/var/krb5/slave_datatrans_");
	if (strlcat(tmpf, clhost, sizeof (tmpf)) >= sizeof (tmpf)) {
		krb5_klog_syslog(LOG_ERR,
		gettext("%s: db dump file name too long; max length=%d"),
				whoami,
				(sizeof (tmpf) - 1));
		goto out;
	}

	/*
	 * note the -i; modified version of kdb5_util dump format
	 * to include sno (serial number)
	 */
	if (strlcpy(ubuf, KDB5_UTIL_DUMP_STR, sizeof (ubuf)) >=
	    sizeof (ubuf)) {
		goto out;
	}
	if (strlcat(ubuf, tmpf, sizeof (ubuf)) >= sizeof (ubuf)) {
		krb5_klog_syslog(LOG_ERR,
		gettext("%s: kdb5 util dump string too long; max length=%d"),
				whoami,
				(sizeof (ubuf) - 1));
		goto out;
	}

	/*
	 * Fork to dump the db and xfer it to the slave.
	 * (the fork allows parent to return quickly and the child
	 * acts like a callback to the slave).
	 */
	fret = fork();
	DPRINT(("%s: fork=%d (%d)\n", whoami, fret, getpid()));

	switch (fret) {
	case -1: /* error */
		if (nofork) {
			perror(whoami);
		}
		krb5_klog_syslog(LOG_ERR,
				gettext("%s: fork failed: %s"),
				whoami,
				error_message(errno));
		goto out;

	case 0: /* child */
		DPRINT(("%s: run `%s' ...\n", whoami, ubuf));
#ifdef POSIX_SIGNALS
		(void) sigemptyset(&s_action.sa_mask);
		s_action.sa_handler = SIG_DFL;
		(void) sigaction(SIGCHLD, &s_action, (struct sigaction *) NULL);
#else
		(void) signal(SIGCHLD, SIG_DFL);
#endif /* POSIX_SIGNALS */
		/* run kdb5_util(1M) dump for IProp */
		pret = pclose(popen(ubuf, "w"));
		DPRINT(("%s: pclose=%d\n", whoami, pret));
		if (pret == -1) {
			if (nofork) {
				perror(whoami);
			}
			krb5_klog_syslog(LOG_ERR,
				gettext("%s: pclose(popen) failed: %s"),
					whoami,
					error_message(errno));
			goto out;
		}

		DPRINT(("%s: exec `kprop -f %s %s' ...\n",
			whoami, tmpf, clhost));
		pret = execl("/usr/lib/krb5/kprop", "kprop", "-f", tmpf,
			    clhost, NULL);
		if (pret == -1) {
			if (nofork) {
				perror(whoami);
			}
			krb5_klog_syslog(LOG_ERR,
					gettext("%s: exec failed: %s"),
					whoami,
					error_message(errno));
			goto out;
		}

	default: /* parent */
		ret.ret = UPDATE_OK;
		/* not used by slave (sno is retrieved from kdb5_util dump) */
		ret.lastentry.last_sno = 0;
		ret.lastentry.last_time.seconds = 0;
		ret.lastentry.last_time.useconds = 0;

		audit_kadmind_auth(rqstp->rq_xprt, l_port,
				whoami,
				"<null>", client_name, 0);

		krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
				"<null>",
				"success",
				client_name, service_name,
				client_addr(rqstp, abuf));

		goto out;
	}

out:
	if (nofork)
		debprret(whoami, ret.ret, 0);
	if (client_name)
		free(client_name);
	if (service_name)
		free(service_name);
	if (name)
		gss_release_name(&min_stat, &name);
	return (&ret);
}
Beispiel #4
0
static kdb_fullresync_result_t *
ipropx_resync(uint32_t vers, struct svc_req *rqstp)
{
    static kdb_fullresync_result_t ret;
    char *ubuf = 0;
    char clhost[MAXHOSTNAMELEN] = {0};
    int pret, fret;
    FILE *p;
    kadm5_server_handle_t handle = global_server_handle;
    OM_uint32 min_stat;
    gss_name_t name = NULL;
    char *client_name = NULL, *service_name = NULL;
    char *whoami = "iprop_full_resync_1";

    /*
     * vers contains the highest version number the client is
     * willing to accept. A client can always accept a lower
     * version: the version number is indicated in the dump
     * header.
     */

    /* default return code */
    ret.ret = UPDATE_ERROR;

    if (!handle) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: server handle is NULL"),
			 whoami);
	goto out;
    }

    DPRINT("%s: start\n", whoami);

    {
	gss_buffer_desc client_desc, service_desc;

	if (setup_gss_names(rqstp, &client_desc, &service_desc) < 0) {
	    DPRINT("%s: setup_gss_names failed\n", whoami);
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: setup_gss_names failed"),
			     whoami);
	    goto out;
	}
	client_name = buf_to_string(&client_desc);
	service_name = buf_to_string(&service_desc);
	if (client_name == NULL || service_name == NULL) {
	    free(client_name);
	    free(service_name);
	    DPRINT("%s: out of memory\n", whoami);
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: out of memory recording principal names"),
			     whoami);
	    goto out;
	}
    }

    DPRINT("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
	    whoami, client_name, service_name);

    if (!kadm5int_acl_check(handle->context,
			    rqst2name(rqstp),
			    ACL_IPROP,
			    NULL,
			    NULL)) {
	ret.ret = UPDATE_PERM_DENIED;

	DPRINT("%s: Permission denied\n", whoami);
	krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
			 client_name, service_name,
			 client_addr(rqstp));
	goto out;
    }

    if (!getclhoststr(client_name, clhost, sizeof (clhost))) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: getclhoststr failed"),
			 whoami);
	goto out;
    }

    /*
     * Note the -i; modified version of kdb5_util dump format
     * to include sno (serial number). This argument is now
     * versioned (-i0 for legacy dump format, -i1 for ipropx
     * version 1 format, etc).
     *
     * The -c option ("conditional") causes the dump to dump only if no
     * dump already exists or that dump is not in ipropx format, or the
     * sno and timestamp in the header of that dump are outside the
     * ulog.  This allows us to share a single global dump with all
     * slaves, since it's OK to share an older dump, as long as its sno
     * and timestamp are in the ulog (then the slaves can get the
     * subsequent updates very iprop).
     */
    if (asprintf(&ubuf, "%s dump -i%d -c %s",
		 kdb5_util, vers, dump_file) < 0) {
	krb5_klog_syslog(LOG_ERR,
			 _("%s: cannot construct kdb5 util dump string too long; out of memory"),
			 whoami);
	goto out;
    }

    /*
     * Fork to dump the db and xfer it to the slave.
     * (the fork allows parent to return quickly and the child
     * acts like a callback to the slave).
     */
    fret = fork();
    DPRINT("%s: fork=%d (%d)\n", whoami, fret, getpid());

    switch (fret) {
    case -1: /* error */
	if (nofork) {
	    perror(whoami);
	}
	DPRINT("%s: fork failed\n", whoami);
	krb5_klog_syslog(LOG_ERR,
			 _("%s: fork failed: %s"),
			 whoami,
			 error_message(errno));
	goto out;

    case 0: /* child */
	DPRINT("%s: run `%s' ...\n", whoami, ubuf);
	(void) signal(SIGCHLD, SIG_DFL);
	/* run kdb5_util(1M) dump for IProp */
	p = popen(ubuf, "w");
	if (p == NULL) {
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: popen failed: %s"),
			     whoami, error_message(errno));
	    _exit(1);
	}
	pret = pclose(p);
	DPRINT("%s: pclose=%d\n", whoami, pret);
	if (pret != 0) {
	    /* XXX popen/pclose may not set errno
	       properly, and the error could be from the
	       subprocess anyways.  */
	    if (nofork) {
		perror(whoami);
	    }
	    krb5_klog_syslog(LOG_ERR,
			     _("%s: pclose(popen) failed: %s"),
			     whoami,
			     error_message(errno));
	    _exit(1);
	}

	DPRINT("%s: exec `kprop -f %s %s' ...\n",
		whoami, dump_file, clhost);
	/* XXX Yuck!  */
	if (getenv("KPROP_PORT")) {
	    pret = execl(kprop, "kprop", "-f", dump_file, "-P",
			 getenv("KPROP_PORT"), clhost, NULL);
	} else {
	    pret = execl(kprop, "kprop", "-f", dump_file, clhost, NULL);
	}
	perror(whoami);
	krb5_klog_syslog(LOG_ERR,
			 _("%s: exec failed: %s"),
			 whoami,
			 error_message(errno));
	_exit(1);

    default: /* parent */
	ret.ret = UPDATE_OK;
	/* not used by slave (sno is retrieved from kdb5_util dump) */
	ret.lastentry.last_sno = 0;
	ret.lastentry.last_time.seconds = 0;
	ret.lastentry.last_time.useconds = 0;

	DPRINT("%s: spawned resync process %d, client=%s, "
		"service=%s, addr=%s\n", whoami, fret, client_name,
		service_name, client_addr(rqstp));
	krb5_klog_syslog(LOG_NOTICE,
			 _("Request: %s, spawned resync process %d, client=%s, service=%s, addr=%s"),
			 whoami, fret,
			 client_name, service_name,
			 client_addr(rqstp));

	goto out;
    }

out:
    if (nofork)
	debprret(whoami, ret.ret, 0);
    free(client_name);
    free(service_name);
    if (name)
	gss_release_name(&min_stat, &name);
    free(ubuf);
    return (&ret);
}
Beispiel #5
0
kdb_incr_result_t *
iprop_get_updates_1(kdb_last_t *arg, struct svc_req *rqstp)
{
	static kdb_incr_result_t ret;
	char *whoami = "iprop_get_updates_1";
	int kret;
	kadm5_server_handle_t handle = global_server_handle;
	char *client_name = NULL, *service_name = NULL;
	gss_name_t name = NULL;
	OM_uint32 min_stat;
	char obuf[256] = {0};

	/* default return code */
	ret.ret = UPDATE_ERROR;

	DPRINT(("%s: start, last_sno=%u\n", whoami, (ulong_t)arg->last_sno));

	if (!handle) {
		krb5_klog_syslog(LOG_ERR,
				gettext("%s: server handle is NULL"),
					whoami);
		goto out;
	}

	if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: setup_gss_names failed"),
			whoami);
		goto out;
	}

	DPRINT(("%s: clprinc=`%s'\n\tsvcprinc=`%s'\n",
		whoami, client_name, service_name));

	if (!(name = get_clnt_name(rqstp))) {
		krb5_klog_syslog(LOG_ERR,
			gettext("%s: Couldn't obtain client's name"),
			whoami);
		goto out;
	}
	if (!kadm5int_acl_check(handle->context,
		    name,
		    ACL_IPROP,
		    NULL,
		    NULL)) {
		ret.ret = UPDATE_PERM_DENIED;

		audit_kadmind_unauth(rqstp->rq_xprt, l_port,
				    whoami,
				    "<null>", client_name);
		krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, whoami,
				"<null>", client_name, service_name,
				client_addr(rqstp, abuf));
		goto out;
	}

	kret = ulog_get_entries(handle->context, *arg, &ret);

	if (ret.ret == UPDATE_OK) {
		(void) snprintf(obuf, sizeof (obuf),
		gettext("%s; Incoming SerialNo=%u; Outgoing SerialNo=%u"),
				replystr(ret.ret),
				(ulong_t)arg->last_sno,
				(ulong_t)ret.lastentry.last_sno);
	} else {
		(void) snprintf(obuf, sizeof (obuf),
		gettext("%s; Incoming SerialNo=%u; Outgoing SerialNo=N/A"),
				replystr(ret.ret),
				(ulong_t)arg->last_sno);
	}

	audit_kadmind_auth(rqstp->rq_xprt, l_port,
			whoami,
			obuf, client_name, kret);

	krb5_klog_syslog(LOG_NOTICE, LOG_DONE, whoami,
			obuf,
			((kret == 0) ? "success" : error_message(kret)),
			client_name, service_name,
			client_addr(rqstp, abuf));

out:
	if (nofork)
		debprret(whoami, ret.ret, ret.lastentry.last_sno);
	if (client_name)
		free(client_name);
	if (service_name)
		free(service_name);
	if (name)
		gss_release_name(&min_stat, &name);
	return (&ret);
}