Beispiel #1
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 #2
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 #3
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);
}