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