summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2011-07-20 18:11:05 -0400
committerSimo Sorce <ssorce@redhat.com>2011-08-26 08:26:08 -0400
commitdfa944da247f71f4ccf8a18eee30459e6c25caa5 (patch)
treea0734aaade4426e61f24e4a026b6c6f47ce30305
parenta60a71497bb412217922b00d0e8398bfc3e6a9db (diff)
downloadfreeipa-dfa944da247f71f4ccf8a18eee30459e6c25caa5.tar.gz
freeipa-dfa944da247f71f4ccf8a18eee30459e6c25caa5.tar.xz
freeipa-dfa944da247f71f4ccf8a18eee30459e6c25caa5.zip
daemons: Remove ipa_kpasswd
Now that we have our own database we can properly enforce stricter constraints on how the db can be changed. Stop shipping our own kpasswd daemon and instead use the regular kadmin daemon.
-rw-r--r--.gitignore1
-rw-r--r--daemons/Makefile.am1
-rw-r--r--daemons/configure.ac1
-rw-r--r--daemons/ipa-kpasswd/Makefile.am59
-rw-r--r--daemons/ipa-kpasswd/README2
-rw-r--r--daemons/ipa-kpasswd/ipa_kpasswd.c1408
-rw-r--r--daemons/ipa-kpasswd/ipa_kpasswd.init83
-rw-r--r--freeipa.spec.in15
-rw-r--r--install/tools/man/Makefile.am1
-rw-r--r--install/tools/man/ipa-server-install.12
-rw-r--r--install/tools/man/ipa_kpasswd.836
-rw-r--r--ipa.12
-rw-r--r--ipaserver/install/krbinstance.py2
-rw-r--r--ipaserver/install/service.py2
-rw-r--r--selinux/Makefile5
-rw-r--r--selinux/ipa-server-selinux.spec.in5
-rw-r--r--selinux/ipa_kpasswd/ipa_kpasswd.fc9
-rw-r--r--selinux/ipa_kpasswd/ipa_kpasswd.te80
18 files changed, 14 insertions, 1700 deletions
diff --git a/.gitignore b/.gitignore
index fb0d12edc..19da265b1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -28,7 +28,6 @@ daemons/config.status
daemons/config.sub
daemons/depcomp
daemons/install-sh
-daemons/ipa-kpasswd/ipa_kpasswd
daemons/ipa-version.h
daemons/libtool
daemons/ltmain.sh
diff --git a/daemons/Makefile.am b/daemons/Makefile.am
index 254d20b45..031df16ac 100644
--- a/daemons/Makefile.am
+++ b/daemons/Makefile.am
@@ -14,7 +14,6 @@ export AM_CFLAGS
SUBDIRS = \
ipa-kdb \
- ipa-kpasswd \
ipa-slapi-plugins \
$(NULL)
diff --git a/daemons/configure.ac b/daemons/configure.ac
index 5e411fe36..e238d8b15 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -289,7 +289,6 @@ AC_SUBST(LDFLAGS)
AC_CONFIG_FILES([
Makefile
ipa-kdb/Makefile
- ipa-kpasswd/Makefile
ipa-slapi-plugins/Makefile
ipa-slapi-plugins/ipa-enrollment/Makefile
ipa-slapi-plugins/ipa-lockout/Makefile
diff --git a/daemons/ipa-kpasswd/Makefile.am b/daemons/ipa-kpasswd/Makefile.am
deleted file mode 100644
index 40e8c58f0..000000000
--- a/daemons/ipa-kpasswd/Makefile.am
+++ /dev/null
@@ -1,59 +0,0 @@
-NULL =
-
-INCLUDES = \
- -I. \
- -I$(srcdir) \
- -DPREFIX=\""$(prefix)"\" \
- -DBINDIR=\""$(bindir)"\" \
- -DLIBDIR=\""$(libdir)"\" \
- -DLIBEXECDIR=\""$(libexecdir)"\" \
- -DDATADIR=\""$(datadir)"\" \
- $(AM_CFLAGS) \
- $(OPENLDAP_CFLAGS) \
- $(KRB5_CFLAGS) \
- $(WARN_CFLAGS) \
- $(NULL)
-
-sbin_PROGRAMS = \
- ipa_kpasswd \
- $(NULL)
-
-ipa_kpasswd_SOURCES = \
- ipa_kpasswd.c \
- $(NULL)
-
-ipa_kpasswd_LDADD = \
- $(OPENLDAP_LIBS) \
- $(KRB5_LIBS) \
- $(NULL)
-
-install-exec-local:
- mkdir -p $(DESTDIR)$(localstatedir)/cache/ipa/kpasswd
- chmod 700 $(DESTDIR)$(localstatedir)/cache/ipa/kpasswd
-
-uninstall-local:
- -rmdir $(DESTDIR)$(localstatedir)/cache/ipa/kpasswd
- -rmdir $(DESTDIR)$(localstatedir)/cache/ipa
-
-EXTRA_DIST = \
- README \
- ipa_kpasswd.init \
- $(NULL)
-
-MAINTAINERCLEANFILES = \
- *~ \
- Makefile.in
-
-initdir=$(sysconfdir)/rc.d/init.d
-
-install-data-hook: ipa_kpasswd.init
-
- if test '!' -d $(DESTDIR)$(initdir); then \
- $(mkinstalldirs) $(DESTDIR)$(initdir); \
- chmod 755 $(DESTDIR)$(initdir); \
- fi
-
- $(INSTALL_SCRIPT) $(srcdir)/ipa_kpasswd.init $(DESTDIR)$(initdir)/ipa_kpasswd
-
-uninstall-hook:
- rm -f $(DESTDIR)$(initdir)/ipa_kpasswd
diff --git a/daemons/ipa-kpasswd/README b/daemons/ipa-kpasswd/README
deleted file mode 100644
index c0a2767a4..000000000
--- a/daemons/ipa-kpasswd/README
+++ /dev/null
@@ -1,2 +0,0 @@
-This is an implementation of the RFC3244 kpasswd protocol.
-It is used to proxy password change operations to Directory Server.
diff --git a/daemons/ipa-kpasswd/ipa_kpasswd.c b/daemons/ipa-kpasswd/ipa_kpasswd.c
deleted file mode 100644
index f973e425d..000000000
--- a/daemons/ipa-kpasswd/ipa_kpasswd.c
+++ /dev/null
@@ -1,1408 +0,0 @@
-
-/* Kpasswd-LDAP proxy */
-
-/* Authors: Simo Sorce <ssorce@redhat.com>
- *
- * Copyright (C) 2007, 2008 Red Hat
- * see file 'COPYING' for use and warranty information
- *
- * This program is free software you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <sys/poll.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <netdb.h>
-#include <syslog.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <time.h>
-#include <krb5.h>
-#include <ldap.h>
-#include <sasl/sasl.h>
-#include <ifaddrs.h>
-
-#define DEFAULT_KEYTAB "FILE:/var/kerberos/krb5kdc/kpasswd.keytab"
-#define TMP_TEMPLATE "/var/cache/ipa/kpasswd/krb5_cc.XXXXXX"
-#define KPASSWD_PORT 464
-
-/* blacklist entries are released only BLCAKLIST_TIMEOUT seconds
- * after the children performing the noperation has finished.
- * this is to avoid races */
-
-#define BLACKLIST_TIMEOUT 5
-
-struct blacklist {
- struct blacklist *next;
- char *address;
- pid_t pid;
- time_t expire;
-};
-
-static struct blacklist *global_blacklist = NULL;
-
-struct socklist {
- int fd;
- int socktype;
- int dest_addr_len;
- struct sockaddr_storage dest_addr;
- struct socklist *next;
-};
-
-int check_blacklist(char *address)
-{
- struct blacklist *bl, *prev_bl;
- time_t now = time(NULL);
-
- if (!global_blacklist) {
- return 0;
- }
-
- prev_bl = NULL;
- bl = global_blacklist;
- while (bl) {
- if (bl->expire && (bl->expire < now)) {
- if (prev_bl) {
- prev_bl->next = bl->next;
- free(bl->address);
- free(bl);
- bl = prev_bl->next;
- } else {
- global_blacklist = bl->next;
- free(bl->address);
- free(bl);
- bl = global_blacklist;
- }
- continue;
- }
-
- if (strcmp(address, bl->address) == 0) {
- return 1;
- }
-
- prev_bl = bl;
- bl = bl->next;
- }
-
- return 0;
-}
-
-int add_blacklist(pid_t pid, char *address)
-{
- struct blacklist *bl, *gbl;
-
- bl = malloc(sizeof(struct blacklist));
- if (!bl) return -1;
-
- bl->next = NULL;
- bl->pid = pid;
- bl->expire = 0;
- bl->address = strdup(address);
- if (!bl->address) {
- free(bl);
- return -1;
- }
-
- if (!global_blacklist) {
- global_blacklist = bl;
- return 0;
- }
-
- gbl = global_blacklist;
- while (gbl->next) {
- gbl = gbl->next;
- }
- gbl->next = bl;
- return 0;
-}
-
-int remove_blacklist(pid_t pid)
-{
- struct blacklist *bl;
-
- if (!global_blacklist) {
- return -1;
- }
-
- bl = global_blacklist;
- while (bl) {
- if (pid == bl->pid) {
- bl->expire = time(NULL) + BLACKLIST_TIMEOUT;
- return 0;
- }
- bl = bl->next;
- }
- return -1;
-}
-
-int debug = 0;
-char *srv_pri_name = "kadmin/changepw";
-char *keytab_name = NULL;
-
-static int get_krb5_ticket(char *tmp_file)
-{
- char *ccname;
- char *realm_name = NULL;
- krb5_context context = NULL;
- krb5_keytab keytab = NULL;
- krb5_ccache ccache = NULL;
- krb5_principal kprincpw;
- krb5_creds my_creds;
- krb5_get_init_creds_opt options;
- krb5_error_code krberr;
- int ret;
-
- krberr = krb5_init_context(&context);
- if (krberr) {
- syslog(LOG_ERR, "Failed to init kerberos context");
- return -1;
- }
-
- krberr = krb5_get_default_realm(context, &realm_name);
- if (krberr) {
- syslog(LOG_ERR, "Failed to get default realm name: %s",
- krb5_get_error_message(context, krberr));
- ret = -1;
- goto done;
- }
-
- krberr = krb5_build_principal(context, &kprincpw,
- strlen(realm_name), realm_name,
- "kadmin", "changepw", NULL);
- if (krberr) {
- syslog(LOG_ERR, "Unable to build principal: %s",
- krb5_get_error_message(context, krberr));
- ret = -1;
- goto done;
- }
-
- krberr = krb5_kt_resolve(context, keytab_name, &keytab);
- if (krberr) {
- syslog(LOG_ERR, "Failed to read keytab file: %s",
- krb5_get_error_message(context, krberr));
- ret = -1;
- goto done;
- }
-
- ret = asprintf(&ccname, "FILE:%s", tmp_file);
- if (ret == -1) {
- syslog(LOG_ERR, "Out of memory!");
- goto done;
- }
-
- ret = setenv("KRB5CCNAME", ccname, 1);
- if (ret == -1) {
- syslog(LOG_ERR, "Unable to set env. variable KRB5CCNAME!");
- goto done;
- }
-
- krberr = krb5_cc_resolve(context, ccname, &ccache);
- if (krberr) {
- syslog(LOG_ERR, "Failed to set cache name: %s",
- krb5_get_error_message(context, krberr));
- ret = -1;
- goto done;
- }
-
- memset(&my_creds, 0, sizeof(my_creds));
- memset(&options, 0, sizeof(options));
-
- krb5_get_init_creds_opt_set_address_list(&options, NULL);
- krb5_get_init_creds_opt_set_forwardable(&options, 0);
- krb5_get_init_creds_opt_set_proxiable(&options, 0);
- /* set a very short lifetime, we don't keep the ticket around */
- krb5_get_init_creds_opt_set_tkt_life(&options, 300);
-
- krberr = krb5_get_init_creds_keytab(context, &my_creds, kprincpw,
- keytab, 0, NULL,
- &options);
-
- if (krberr) {
- syslog(LOG_ERR, "Failed to init credentials: %s",
- krb5_get_error_message(context, krberr));
- ret = -1;
- goto done;
- }
-
- krberr = krb5_cc_initialize(context, ccache, kprincpw);
- if (krberr) {
- syslog(LOG_ERR, "Failed to init ccache: %s",
- krb5_get_error_message(context, krberr));
- ret = -1;
- goto done;
- }
-
- krberr = krb5_cc_store_cred(context, ccache, &my_creds);
- if (krberr) {
- syslog(LOG_ERR, "Failed to store creds: %s",
- krb5_get_error_message(context, krberr));
- ret = -1;
- goto done;
- }
-
- ret = 0;
-
-done:
- /* TODO: mem cleanup */
- if (keytab) krb5_kt_close(context, keytab);
- if (context) krb5_free_context(context);
- return ret;
-}
-
-int ldap_sasl_interact(LDAP *ld, unsigned flags, void *priv_data, void *sit)
-{
- sasl_interact_t *in = NULL;
- int ret = LDAP_OTHER;
- char *realm_name = (char *)priv_data;
-
- if (!ld) return LDAP_PARAM_ERROR;
-
- for (in = sit; in && in->id != SASL_CB_LIST_END; in++) {
- switch(in->id) {
- case SASL_CB_USER:
- in->result = srv_pri_name;
- in->len = strlen(srv_pri_name);
- ret = LDAP_SUCCESS;
- break;
- case SASL_CB_GETREALM:
- in->result = realm_name;
- in->len = strlen(realm_name);
- ret = LDAP_SUCCESS;
- break;
- default:
- if (debug > 0) {
- syslog(LOG_ERR,
- "Unhandled SASL int. option %ld",
- in->id);
- }
- in->result = NULL;
- in->len = 0;
- ret = LDAP_OTHER;
- }
- }
- return ret;
-}
-
-/* from DS ldaprot.h */
-#define LDAP_TAG_PWP_WARNING 0xA0 /* context specific + constructed + 0 */
-#define LDAP_TAG_PWP_SECSLEFT 0x80L /* context specific + primitive */
-#define LDAP_TAG_PWP_GRCLOGINS 0x81L /* context specific + primitive + 1 */
-#define LDAP_TAG_PWP_ERROR 0x81L /* context specific + primitive + 1 */
-
-int ldap_pwd_change(char *client_name, char *realm_name, krb5_data pwd, char **errstr)
-{
- char *tmp_file = NULL;
- int version;
- LDAP *ld = NULL;
- BerElement *ctrl = NULL;
- BerElement *sctrl = NULL;
- struct berval *control = NULL;
- struct berval newpw;
- char hostname[1024];
- char *uri;
- struct berval **ncvals;
- char *filter;
- char *attrs[] = {"krbprincipalname", NULL};
- char *root_attrs[] = {"namingContexts", NULL};
- char *userdn = NULL;
- char *retoid = NULL;
- struct berval *retdata = NULL;
- struct timeval tv;
- LDAPMessage *entry, *res = NULL;
- LDAPControl **srvctrl = NULL;
- char *exterr0 = NULL;
- char *exterr1 = NULL;
- char *exterr2 = NULL;
- char *err = NULL;
- int msgid;
- int ret, rc;
- int fd;
- int kpwd_err = KRB5_KPASSWD_HARDERROR;
- int i;
-
- tmp_file = strdup(TMP_TEMPLATE);
- if (!tmp_file) {
- syslog(LOG_ERR, "Out of memory!");
- goto done;
- }
-
- fd = mkstemp(tmp_file);
- if (fd == -1) {
- syslog(LOG_ERR,
- "Failed to create tmp file with errno: %d", errno);
- goto done;
- }
- /* close mimmediately, we don't need to keep the file open,
- * just that it exist and has a unique name */
- close(fd);
-
- /* In the long term we may want to do this in the main daemon
- * and just renew when needed.
- * Right now do it at every password change for robustness */
- ret = get_krb5_ticket(tmp_file);
- if (ret) {
- syslog(LOG_ERR, "Unable to kinit!");
- goto done;
- }
-
- newpw.bv_len = pwd.length;
- newpw.bv_val = pwd.data;
-
- /* retrieve server name and build uri */
- ret = gethostname(hostname, 1023);
- if (ret == -1) {
- syslog(LOG_ERR, "Unable to get the hostname!");
- goto done;
- }
-
- ret = asprintf(&uri, "ldap://%s:389", hostname);
- if (ret == -1) {
- syslog(LOG_ERR, "Out of memory!");
- goto done;
- }
-
- /* connect to ldap server */
- /* TODO: support referrals ? */
- ret = ldap_initialize(&ld, uri);
- free(uri);
- if(ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "Unable to connect to ldap server: %s",
- ldap_err2string(ret));
- goto done;
- }
-
- version = LDAP_VERSION3;
- ret = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
- if (ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "Unable to set ldap protocol version");
- goto done;
- }
-
- ret = ldap_sasl_interactive_bind_s(ld,
- NULL, "GSSAPI",
- NULL, NULL,
- LDAP_SASL_AUTOMATIC,
- ldap_sasl_interact, realm_name);
- if (ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "Unable to bind to ldap server");
- goto done;
- }
-
- /* find base dn */
- tv.tv_sec = 10;
- tv.tv_usec = 0;
-
- ret = ldap_search_ext_s(ld, "", LDAP_SCOPE_BASE,
- "objectclass=*", root_attrs, 0,
- NULL, NULL, &tv, 0, &res);
-
- if (ret != LDAP_SUCCESS) {
- syslog(LOG_ERR,
- "Search for %s on rootdse failed with error %d",
- root_attrs[0], ret);
- goto done;
- }
-
- /* for now just use the first result we get */
- entry = ldap_first_entry(ld, res);
- ncvals = ldap_get_values_len(ld, entry, root_attrs[0]);
- if (!ncvals) {
- syslog(LOG_ERR, "No values for %s", root_attrs[0]);
- goto done;
- }
-
- ldap_msgfree(res);
- res = NULL;
-
- /* find user dn */
- ret = asprintf(&filter, "krbPrincipalName=%s", client_name);
- if (ret == -1) {
- syslog(LOG_ERR, "Out of memory!");
- goto done;
- }
-
- tv.tv_sec = 10;
- tv.tv_usec = 0;
-
- for (i = 0; !userdn && ncvals[i]; i++) {
- ret = ldap_search_ext_s(ld, ncvals[i]->bv_val,
- LDAP_SCOPE_SUBTREE, filter, attrs, 1,
- NULL, NULL, &tv, 0, &res);
-
- if (ret != LDAP_SUCCESS) {
- break;
- }
-
- /* for now just use the first result we get */
- entry = ldap_first_entry(ld, res);
- if (entry) {
- userdn = ldap_get_dn(ld, entry);
- }
-
- ldap_msgfree(res);
- res = NULL;
- }
-
- ldap_value_free_len(ncvals);
-
- if (ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "Search for %s failed with error %d",
- filter, ret);
- if (ret == LDAP_CONSTRAINT_VIOLATION) {
- *errstr = strdup("Password Change Failed");
- kpwd_err = KRB5_KPASSWD_SOFTERROR;
- }
- goto done;
- }
-
- free(filter);
- filter = NULL;
-
- if (!userdn) {
- syslog(LOG_ERR, "No userdn, can't change password!");
- goto done;
- }
-
- /* build password change control */
- ctrl = ber_alloc_t(LBER_USE_DER);
- if (!ctrl) {
- syslog(LOG_ERR, "Out of memory!");
- goto done;
- }
-
- ret = ber_printf(ctrl, "{tstO}",
- LDAP_TAG_EXOP_MODIFY_PASSWD_ID, userdn,
- LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &newpw);
- if (ret < 0) {
- syslog(LOG_ERR, "ber printf failed!");
- goto done;
- }
-
- ret = ber_flatten(ctrl, &control);
- if (ret < 0) {
- syslog(LOG_ERR, "ber flattening failed!");
- goto done;
- }
-
- /* perform password change */
- ret = ldap_extended_operation(ld,
- LDAP_EXOP_MODIFY_PASSWD,
- control, NULL, NULL,
- &msgid);
- if (ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "ldap_extended_operation() failed. (%d)", ret);
- goto done;
- }
-
- tv.tv_sec = 10;
- tv.tv_usec = 0;
-
- ret = ldap_result(ld, msgid, 1, &tv, &res);
- if (ret == -1) {
- ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &rc);
- syslog(LOG_ERR, "ldap_result() failed. (%d)", rc);
- goto done;
- }
-
- ret = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0);
- if(ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "ldap_parse_extended_result() failed.");
- ldap_msgfree(res);
- goto done;
- }
- if (retoid || retdata) {
- syslog(LOG_ERR, "ldap_parse_extended_result() returned data, but we don't handle it yet.");
- }
-
- ret = ldap_parse_result(ld, res, &rc, NULL, &err, NULL, &srvctrl, 0);
- if(ret != LDAP_SUCCESS) {
- syslog(LOG_ERR, "ldap_parse_result() failed.");
- goto done;
- }
- if (rc != LDAP_SUCCESS) {
- if (rc == LDAP_CONSTRAINT_VIOLATION) {
- kpwd_err = KRB5_KPASSWD_SOFTERROR;
- }
- ret = LDAP_OPERATIONS_ERROR;
- }
- if (err) {
- syslog(LOG_ERR, "ldap_parse_result(): [%s]", err);
- ldap_memfree(err);
- }
-
- if (srvctrl) {
-
- LDAPControl *pprc = NULL;
- int i;
-
- for (i = 0; srvctrl[i]; i++) {
- if (0 == strcmp(srvctrl[i]->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE)) {
- pprc = srvctrl[i];
- }
- }
- if (pprc) {
- sctrl = ber_init(&pprc->ldctl_value);
- }
-
- if (sctrl) {
- /*
- * PasswordPolicyResponseValue ::= SEQUENCE {
- * warning [0] CHOICE OPTIONAL {
- * timeBeforeExpiration [0] INTEGER (0 .. maxInt),
- * graceLoginsRemaining [1] INTEGER (0 .. maxInt) }
- * error [1] ENUMERATED OPTIONAL {
- * passwordExpired (0),
- * accountLocked (1),
- * changeAfterReset (2),
- * passwordModNotAllowed (3),
- * mustSupplyOldPassword (4),
- * invalidPasswordSyntax (5),
- * passwordTooShort (6),
- * passwordTooYoung (7),
- * passwordInHistory (8) } }
- */
-
- ber_tag_t rtag, btag;
- ber_int_t bint;
- rtag = ber_scanf(sctrl, "{t", &btag);
- if (btag == LDAP_TAG_PWP_WARNING) {
- rtag = ber_scanf(sctrl, "{ti}", &btag, &bint);
- if (btag == LDAP_TAG_PWP_SECSLEFT) {
- ret = asprintf(&exterr2, " (%d seconds left before password expires)", bint);
- } else {
- ret = asprintf(&exterr2, " (%d grace logins remaining)", bint);
- }
- if (ret == -1) {
- syslog(LOG_ERR, "OOM while creating error message ...");
- exterr2 = NULL;
- }
- rtag = ber_scanf(sctrl, "t", &btag);
- }
- if (btag == LDAP_TAG_PWP_ERROR) {
- rtag = ber_scanf(sctrl, "e", &bint);
- switch(bint) {
- case 0:
- ret = asprintf(&exterr1, " Err%d: Password Expired.", bint);
- break;
- case 1:
- ret = asprintf(&exterr1, " Err%d: Account locked.", bint);
- break;
- case 2:
- ret = asprintf(&exterr1, " Err%d: Password changed after reset.", bint);
- break;
- case 3:
- ret = asprintf(&exterr1, " Err%d: Password change not allowed.", bint);
- break;
- case 4:
- ret = asprintf(&exterr1, " Err%d: [Shouldn't happen].", bint);
- break;
- case 5:
- ret = asprintf(&exterr1, " Err%d: Password too simple.", bint);
- break;
- case 6:
- ret = asprintf(&exterr1, " Err%d: Password too short.", bint);
- break;
- case 7:
- ret = asprintf(&exterr1, " Err%d: Too soon to change password.", bint);
- break;
- case 8:
- ret = asprintf(&exterr1, " Err%d: Password reuse not permitted.", bint);
- break;
- default:
- ret = asprintf(&exterr1, " Err%d: Unknown Errorcode.", bint);
- break;
- }
- if (ret == -1) {
- syslog(LOG_ERR, "OOM while creating error message ...");
- exterr1 = NULL;
- }
- }
- }
- }
-
- if (ret == LDAP_SUCCESS) {
- kpwd_err = KRB5_KPASSWD_SUCCESS;
- exterr0 = "Password change succeeded";
- } else {
- exterr0 = "Password change failed";
- }
- ret = asprintf(errstr, "%s%s%s", exterr0, exterr1?exterr1:"", exterr2?exterr2:"");
- if (ret == -1) {
- syslog(LOG_ERR, "OOM while creating error message ...");
- *errstr = NULL;
- }
-
-done:
- if (ctrl) ber_free(ctrl, 1);
- if (sctrl) ber_free(sctrl, 1);
- if (srvctrl) ldap_controls_free(srvctrl);
- if (res) ldap_msgfree(res);
- if (control) ber_bvfree(control);
- free(exterr1);
- free(exterr2);
- free(filter);
- free(userdn);
- if (ld) ldap_unbind_ext(ld, NULL, NULL);
- if (tmp_file) {
- unlink(tmp_file);
- free(tmp_file);
- }
- return kpwd_err;
-}
-
-void handle_krb_packets(uint8_t *buf, ssize_t buflen,
- struct socklist *sd,
- struct sockaddr_storage *from,
- uint8_t **repbuf, ssize_t *replen)
-{
- krb5_auth_context auth_context;
- krb5_context context;
- krb5_keytab keytab;
- krb5_principal kprincpw;
- krb5_ticket *ticket;
- krb5_address lkaddr, rkaddr;
- krb5_data kreq, krep, kenc, kdec;
- krb5_replay_data replay;
- krb5_error krb5err;
- int krberr;
- size_t reqlen;
- size_t verno;
- char *client_name, *realm_name;
- char *result_string;
- int result_err;
- uint8_t *reply;
- ssize_t replylen;
-
- *replen = 0;
-
- result_string = NULL;
- auth_context = NULL;
- krep.length = 0;
- krep.data = NULL;
- kdec.length = 0;
- kdec.data = NULL;
- kprincpw = NULL;
- context = NULL;
- ticket = NULL;
-
- switch(((struct sockaddr *)from)->sa_family) {
- case AF_INET:
- lkaddr.addrtype = ADDRTYPE_INET;
- lkaddr.length = sizeof(((struct sockaddr_in *)&sd->dest_addr)->sin_addr);
- lkaddr.contents = (krb5_octet *) &(((struct sockaddr_in *)&sd->dest_addr)->sin_addr);
-
- rkaddr.addrtype = ADDRTYPE_INET;
- rkaddr.length = sizeof(((struct sockaddr_in *)from)->sin_addr);
- rkaddr.contents = (krb5_octet *) &(((struct sockaddr_in *)from)->sin_addr);
- break;
- case AF_INET6:
- if (IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)from)->sin6_addr)) {
- lkaddr.addrtype = ADDRTYPE_INET;
- lkaddr.length = 4;
- lkaddr.contents = 12 + (krb5_octet *) &(((struct sockaddr_in6 *)&sd->dest_addr)->sin6_addr);
-
- rkaddr.addrtype = ADDRTYPE_INET;
- rkaddr.length = 4;
- rkaddr.contents = 12 + (krb5_octet *) &(((struct sockaddr_in6 *)from)->sin6_addr);
- } else {
- lkaddr.addrtype = ADDRTYPE_INET6;
- lkaddr.length = sizeof(((struct sockaddr_in6 *)&sd->dest_addr)->sin6_addr);
- lkaddr.contents = (krb5_octet *) &(((struct sockaddr_in6 *)&sd->dest_addr)->sin6_addr);
-
- rkaddr.addrtype = ADDRTYPE_INET6;
- rkaddr.length = sizeof(((struct sockaddr_in6 *)from)->sin6_addr);
- rkaddr.contents = (krb5_octet *) &(((struct sockaddr_in6 *)from)->sin6_addr);
- }
- break;
- default:
- result_string = strdup("Invalid remopte IP address");
- result_err = KRB5_KPASSWD_MALFORMED;
- syslog(LOG_ERR, "%s", result_string);
- goto done;
- }
-
- if (buflen < 4) {
- result_string = strdup("Request truncated");
- result_err = KRB5_KPASSWD_MALFORMED;
- syslog(LOG_ERR, "%s", result_string);
- goto done;
- }
-
- reqlen = (buf[0] << 8) + buf[1];
-
- if (reqlen != buflen) {
- result_string = strdup("Unmatching request length");
- result_err = KRB5_KPASSWD_MALFORMED;
- syslog(LOG_ERR, "%s", result_string);
- goto done;
- }
-
- verno = (buf[2] << 8) + buf[3];
-
- if (verno != 1) {
- result_string = strdup("Unsupported version");
- result_err = KRB5_KPASSWD_BAD_VERSION;
- syslog(LOG_ERR, "%s", result_string);
- goto done;
- }
-
- kreq.length = (buf[4] << 8) + buf[5];
- if (kreq.length > (buflen - 6)) {
- result_string = strdup("Request truncated");
- result_err = KRB5_KPASSWD_MALFORMED;
- syslog(LOG_ERR, "%s", result_string);
- goto done;
- }
- kreq.data = (char *)&buf[6];
-
- krberr = krb5_init_context(&context);
- if (krberr) {
- result_string = strdup("Failed to init kerberos context");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s", result_string);
- goto done;
- }
-
- krberr = krb5_get_default_realm(context, &realm_name);
- if (krberr) {
- result_string = strdup("Failed to get default realm name");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s", result_string);
- goto done;
- }
-
- krberr = krb5_auth_con_init(context, &auth_context);
- if (krberr) {
- result_string = strdup("Unable to init auth context");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- krberr = krb5_auth_con_setflags(context, auth_context,
- KRB5_AUTH_CONTEXT_DO_SEQUENCE);
- if (krberr) {
- result_string = strdup("Unable to init auth context");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- krberr = krb5_build_principal(context, &kprincpw,
- strlen(realm_name), realm_name,
- "kadmin", "changepw", NULL);
- if (krberr) {
- result_string = strdup("Unable to build principal");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- krberr = krb5_kt_resolve(context, keytab_name, &keytab);
- if (krberr) {
- result_string = strdup("Unable to retrieve keytab");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- krberr = krb5_rd_req(context, &auth_context, &kreq,
- kprincpw, keytab, NULL, &ticket);
- if (krberr) {
- result_string = strdup("Unable to read request");
- result_err = KRB5_KPASSWD_AUTHERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- /* build the AP Reply before actually changing the password
- * this minimize the risk of a fatal error occurring _after_
- * the password have been successfully changed */
- krberr = krb5_mk_rep(context, auth_context, &krep);
- if (krberr) {
- result_string = strdup("Failed to to build reply");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- /* verify that this is an AS_REQ ticket */
- if (!(ticket->enc_part2->flags & TKT_FLG_INITIAL)) {
- result_string = strdup("Ticket must be derived from a password");
- result_err = KRB5_KPASSWD_AUTHERROR;
- syslog(LOG_ERR, "%s", result_string);
- goto kpreply;
- }
-
- krberr = krb5_unparse_name(context, ticket->enc_part2->client,
- &client_name);
- if (krberr) {
- result_string = strdup("Unable to parse client name");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s", result_string);
- goto kpreply;
- }
-
- krberr = krb5_auth_con_setaddrs(context, auth_context, NULL, &rkaddr);
- if (krberr) {
- result_string = strdup("Failed to set client address");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto kpreply;
- }
-
- /* decrypt the new password */
- kenc.length = reqlen - kreq.length - 6;
- kenc.data = kreq.data + kreq.length;
-
- /* rd_priv needs the remote address while mk_priv (used later)
- * requires the local address (from kadmin code) */
- krberr = krb5_rd_priv(context, auth_context, &kenc, &kdec, &replay);
- if (krberr) {
- result_string = strdup("Failed to decrypt password");
- result_err = KRB5_KPASSWD_HARDERROR;
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto kpreply;
- }
-
- if (debug > 100) {
- syslog(LOG_ERR, "Client %s trying to set password [%*s]",
- client_name, kdec.length, kdec.data);
- }
-
- /* Actually try to change the password */
- result_err = ldap_pwd_change(client_name, realm_name, kdec, &result_string);
- if (result_string == NULL) {
- result_string = strdup("Server Error while performing LDAP password change");
- }
- syslog(LOG_ERR, "%s", result_string);
-
- /* make sure password is cleared off before we free the memory */
- memset(kdec.data, 0, kdec.length);
- free(kdec.data);
- kdec.length = 0;
-
-kpreply:
-
- /* set-up the the clear text reply */
- kdec.length = 2 + strlen(result_string);
- kdec.data = malloc(kdec.length);
- if (!kdec.data) {
- syslog(LOG_ERR, "Out of memory!");
- kdec.length = 0;
- goto done;
- }
-
- kdec.data[0] = (result_err >> 8) & 0xff;
- kdec.data[1] = result_err & 0xff;
- memcpy(&kdec.data[2], result_string, strlen(result_string));
-
- free(result_string);
- result_string = NULL;
-
- krberr = krb5_auth_con_setaddrs(context, auth_context, &lkaddr, NULL);
- if (krberr) {
- result_string = strdup("Failed to set local address");
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- krberr = krb5_mk_priv(context, auth_context, &kdec, &kenc, &replay);
- if (krberr) {
- result_string = strdup("Failed to encrypt reply message");
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
-
- free(result_string);
- result_string = NULL;
- /* encryption was unsuccessful, let's return a krb error */
-
- /* the ap data is no more useful */
- free(krep.data);
- krep.length = 0;
-
- /* build a krberror encrypted paylod */
- krb5err.error = KRB5_CHPW_FAIL;
- krb5err.server = kprincpw;
- krb5err.client = NULL;
- krb5err.ctime = 0;
- krb5err.cusec = 0;
- krb5err.susec = 0;
- krberr = krb5_timeofday(context, &krb5err.stime);
- if (krberr) {
- result_string = strdup("Failed to set time of day");
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
-
- krb5err.text.length = 0;
- krb5err.e_data = kdec;
- krberr = krb5_mk_error(context, &krb5err, &kenc);
- if (krberr) {
- result_string = strdup("Failed to build error message");
- syslog(LOG_ERR, "%s: %s", result_string,
- krb5_get_error_message(context, krberr));
- goto done;
- }
- }
-
- replylen = 6 + krep.length + kenc.length;
- reply = malloc(replylen);
- if (!reply) {
- syslog(LOG_ERR, "Out of memory!");
- goto done;
- }
- *repbuf = reply;
-
- reply[0] = (replylen >> 8) & 0xff;
- reply[1] = replylen & 0xff;
- reply[2] = 0x00;
- reply[3] = 0x01;
- reply[4] = (krep.length >> 8) & 0xff;
- reply[5] = krep.length & 0xff;
-
- if (krep.length) {
- memcpy(&reply[6], krep.data, krep.length);
- }
- memcpy(&reply[6 + krep.length], kenc.data, kenc.length);
-
- *replen = replylen;
-
-done:
- free(result_string);
- if (auth_context) krb5_auth_con_free(context, auth_context);
- if (kprincpw) krb5_free_principal(context, kprincpw);
- if (krep.length) free(krep.data);
- if (ticket) krb5_free_ticket(context, ticket);
- if (kdec.length) free(kdec.data);
- if (context) krb5_free_context(context);
-}
-
-pid_t handle_conn(struct socklist *sd)
-{
- int mfd, tcp;
- pid_t pid;
- char addrto6[INET6_ADDRSTRLEN+1];
- char address[INET6_ADDRSTRLEN+1];
- uint8_t request[1500];
- ssize_t reqlen;
- uint8_t *reply;
- ssize_t replen;
- struct sockaddr_storage from;
- socklen_t fromlen;
- ssize_t sendret;
- int ret;
-
- fromlen = sizeof(from);
- mfd = 0;
- tcp = 0;
- reqlen = 0;
-
- /* receive request */
- if (sd->socktype == SOCK_STREAM) {
- tcp = 1;
- mfd = accept(sd->fd, (struct sockaddr *)&from, &fromlen);
- if (mfd == -1) {
- syslog(LOG_ERR, "Accept failed with error (%d) %s",
- errno, strerror(errno));
- return -1;
- }
- } else {
- /* read first to empty the buffer on udp connections */
- reqlen = recvfrom(sd->fd, request, sizeof(request), 0,
- (struct sockaddr *)&from, &fromlen);
- if (reqlen <= 0) {
- syslog(LOG_ERR, "Error receiving request (%d) %s",
- errno, strerror(errno));
- return -1;
- }
-
- }
-
- ret = getnameinfo((struct sockaddr *)&from, fromlen,
- addrto6, INET6_ADDRSTRLEN+1,
- NULL, 0, NI_NUMERICHOST);
- if (ret) {
- syslog(LOG_ERR, "Error retrieving host address\n");
- return -1;
- }
-
- if (debug > 0) {
- syslog(LOG_ERR, "Connection from %s", addrto6);
- }
-
- if (strchr(addrto6, ':') == NULL) {
- char *prefix6 = "::ffff:";
- /* this is an IPv4 formatted addr
- * convert to IPv6 mapped addr */
- memcpy(address, prefix6, 7);
- memcpy(&address[7], addrto6, INET6_ADDRSTRLEN-7);
- } else {
- /* regular IPv6 address, copy as is */
- memcpy(address, addrto6, INET6_ADDRSTRLEN);
- }
- /* make sure we have termination */
- address[INET6_ADDRSTRLEN] = '\0';
-
- /* Check blacklist for requests from the same IP until operations
- * are finished on the active client.
- * the password change may be slow and pam_krb5 sends up to 3 UDP
- * requests waiting 1 sec. each time.
- * We do not want to start 3 password changes at the same time */
-
- if (check_blacklist(address)) {
- if (debug > 0) {
- syslog(LOG_ERR, "[%s] blacklisted", address);
- }
- if (tcp) close(mfd);
- return 0;
- }
-
- /* now read data if it was a TCP connection */
- if (tcp) {
- reqlen = recvfrom(mfd, request, sizeof(request), 0,
- (struct sockaddr *)&from, &fromlen);
- if (reqlen <= 0) {
- syslog(LOG_ERR, "Error receiving request (%d) %s",
- errno, strerror(errno));
- close(mfd);
- return -1;
- }
- }
-#if 1
- /* handle kerberos and ldap operations in childrens */
- pid = fork();
- if (pid == -1) {
- syslog(LOG_ERR, "Fork failed with error (%d) %s",
- errno, strerror(errno));
- if (tcp) close(mfd);
- return 0;
- }
- if (pid != 0) { /* parent */
- if (tcp) close(mfd);
- add_blacklist(pid, address);
- return pid;
- }
-#endif
-
- /* children */
- if (debug > 0) syslog(LOG_ERR, "Servicing %s", address);
-
- /* TCP packets prepend the lenght as a 32bit network order field,
- * this information seem to be just redundant, so let's simply
- * skip it */
- if (tcp) {
- handle_krb_packets(request+4, reqlen-4, sd, &from, &reply, &replen);
- } else {
- handle_krb_packets(request, reqlen, sd, &from, &reply, &replen);
- }
-
- if (replen) { /* we have something to reply */
- if (tcp) {
- sendret = sendto(mfd, reply, replen, 0, NULL, 0);
- } else {
- sendret = sendto(sd->fd, reply, replen, 0, (struct sockaddr *)&from, fromlen);
- }
- if (sendret == -1) {
- syslog(LOG_ERR, "Error sending reply (%d)", errno);
- }
- }
- if (tcp) close(mfd);
- exit(0);
-}
-
-static int create_socket(struct addrinfo *ai, struct socklist **_sds,
- struct pollfd **_pfds, int *_nfds)
-{
- struct socklist *csd, *tsd;
- struct pollfd *pfds;
- int nfds;
- int ret;
- int tru = 1;
-
- pfds = *_pfds;
- nfds = *_nfds;
-
- csd = calloc(1, sizeof(struct socklist));
- if (csd == NULL) {
- syslog(LOG_ERR, "Out of memory, can't create socklist\n");
- return 1;
- }
- csd->socktype = ai->ai_socktype;
- csd->dest_addr_len = ai->ai_addrlen;
- memcpy(&csd->dest_addr, ai->ai_addr, ai->ai_addrlen);
-
- csd->fd = socket(csd->dest_addr.ss_family, csd->socktype, 0);
- if (csd->fd == -1) {
- syslog(LOG_ERR, "Unable to create socket (%s)",
- strerror(errno));
- goto errout;
- }
- ret = setsockopt(csd->fd, SOL_SOCKET, SO_REUSEADDR,
- (void *)&tru, sizeof(tru));
-
- ret = bind(csd->fd, (struct sockaddr *)&csd->dest_addr, csd->dest_addr_len);
- if (ret) {
- if (errno != EADDRINUSE) {
- syslog(LOG_ERR, "Unable to bind to socket");
- close(csd->fd);
- goto errout;
- }
- /* if EADDRINUSE it means we are on a machine
- * with a dual ipv4/ipv6 stack that does not
- * allow to bind on both at the same time as the
- * ipv6 bind already allows connections on ipv4
- * Just ignore */
- close(csd->fd);
- free(csd);
- return 0;
- }
-
- if (csd->socktype == SOCK_STREAM) {
- ret = listen(csd->fd, SOMAXCONN);
- if (ret) {
- syslog(LOG_ERR, "Unable to listen to TCP socket (%s)",
- strerror(errno));
- close(csd->fd);
- goto errout;
- }
- }
-
- pfds = realloc(pfds, sizeof(struct pollfd) * (nfds +1));
- if (pfds == NULL) {
- syslog(LOG_ERR, "Out of memory, can't alloc pollfd array\n");
- close(csd->fd);
- goto errout;
- }
- pfds[nfds].events = POLLIN;
- pfds[nfds].fd = csd->fd;
- nfds++;
-
- if (*_sds) {
- for (tsd = *_sds; tsd->next; tsd = tsd->next) /* skip */ ;
- tsd->next = csd;
- } else {
- *_sds = csd;
- }
-
- *_pfds = pfds;
- *_nfds = nfds;
-
- return 0;
-
-errout:
- free(csd);
- return 1;
-}
-
-int main(int argc, char *argv[])
-{
- pid_t pid;
- struct ifaddrs *ifa, *tifa;
- struct addrinfo *ai, *tai;
- struct addrinfo hints;
- char host[NI_MAXHOST];
- struct socklist *sds, *csd;
- struct pollfd *pfds;
- int nfds;
- int ret;
- char *env;
-
- /* log to syslog */
- openlog("kpasswd", LOG_PID, LOG_DAEMON);
-
- /* do not keep any fs busy */
- ret = chdir("/");
- if (ret == -1) {
- syslog(LOG_ERR, "Unable to change dir to '/'");
- exit(-1);
- }
-
- /* daemonize */
- pid = fork();
- if (pid == -1) {
- syslog(LOG_ERR, "Error fork() failed!");
- exit(-1);
- }
- if (pid != 0) { /* parent */
- exit(0);
- }
-
- /* new session */
- setsid();
-
- /* close std* descriptors */
- close(0);
- close(1);
- close(2);
-
- /* fork again to make sure we completely detach from parent process */
- pid = fork();
- if (pid == -1) {
- syslog(LOG_ERR, "Error fork() failed!");
- exit(-1);
- }
- if (pid != 0) { /* parent */
- exit(0);
- }
-
- /* source env vars */
- env = getenv("KRB5_KTNAME");
- if (!env) {
- env = DEFAULT_KEYTAB;
- }
- keytab_name = strdup(env);
- if (!keytab_name) {
- syslog(LOG_ERR, "Out of memory!");
- }
-
- env = getenv("IPA_KPASSWD_DEBUG");
- if (env) {
- debug = strtol(env, NULL, 0);
- }
-
- ret = getifaddrs(&ifa);
- if (ret) {
- syslog(LOG_ERR, "getifaddrs failed: %s", gai_strerror(ret));
- exit(1);
- }
-
- /* Write out the pid file after the sigterm handler */
- const char *pid_file = "/var/run/ipa_kpasswd.pid";
- FILE *f = fopen(pid_file, "w");
- int fail = 1;
- if (f) {
- int n_bytes = fprintf(f, "%ld\n", (long) getpid());
- if (fclose(f) == 0 && 0 < n_bytes)
- fail = 0;
- }
- if (fail) {
- syslog(LOG_ERR, "Couldn't create pid file %s: %s",
- pid_file, strerror(errno));
- exit(1);
- }
-
- nfds = 0;
- pfds = NULL;
- sds = NULL;
-
- for (tifa = ifa; tifa; tifa = tifa->ifa_next) {
-
- if (NULL == tifa->ifa_addr)
- /* uhmm no address ?? skip it */
- continue;
-
- if (tifa->ifa_addr->sa_family != AF_INET &&
- tifa->ifa_addr->sa_family != AF_INET6) {
- /* not interesting for us */
- continue;
- }
-
- ret = getnameinfo(tifa->ifa_addr, sizeof(struct sockaddr_storage),
- host, sizeof(host), NULL, 0, NI_NUMERICHOST);
- if (ret) {
- syslog(LOG_ERR, "Error converting address (%s)",
- gai_strerror(ret));
- continue;
- } else {
- syslog(LOG_INFO, "Setting up socket for [%s]", host);
- }
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_NUMERICHOST;
- hints.ai_family = AF_UNSPEC;
-
- /* this should return 2 entries, one for UDP and one for TCP */
- ret = getaddrinfo(host, "kpasswd", &hints, &ai);
- if (ret) {
- syslog(LOG_ERR, "Error getting address info (%s) for [%s]",
- gai_strerror(ret), host);
- continue;
- }
-
- for (tai = ai; tai; tai = tai->ai_next) {
- char *socktype = (tai->ai_socktype==SOCK_STREAM)?"TCP":"UDP";
- ret = create_socket(tai, &sds, &pfds, &nfds);
- if (ret) {
- syslog(LOG_ERR,
- "Failed to set up %s socket for [%s]",
- socktype, host);
- }
- }
- }
-
- if (nfds == 0) {
- syslog(LOG_ERR, "Failed to setup any socket. Aborting");
- exit(1);
- }
-
- /* now that sockets are set up, enter the poll loop */
-
- while (1) {
- int cstatus, cid, i;
-
- ret = poll(pfds, nfds, 3000);
-
- switch(ret) {
- case 0:
- break;
- case -1:
- if (errno != EINTR) {
- syslog(LOG_ERR,
- "Unexpected error in poll (%d) %s",
- errno, strerror(errno));
- exit(5);
- }
- break;
- default:
- for (i = 0; i < nfds; i++) {
- if (pfds[i].revents & POLLIN) {
- for (csd = sds; csd; csd = csd->next) {
- if (csd->fd == pfds[i].fd) {
- handle_conn(csd);
- }
- }
- }
- }
- }
-
- /* check for children exiting */
- cid = waitpid(-1, &cstatus, WNOHANG);
- if (cid != -1 && cid != 0) {
- if (debug > 0)
- syslog(LOG_ERR, "pid %d completed operations!\n", cid);
- remove_blacklist(cid);
- }
- }
-}
diff --git a/daemons/ipa-kpasswd/ipa_kpasswd.init b/daemons/ipa-kpasswd/ipa_kpasswd.init
deleted file mode 100644
index d7244bed6..000000000
--- a/daemons/ipa-kpasswd/ipa_kpasswd.init
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/sh
-#
-# ipa_kpasswd This starts and stops ipa_kpasswd
-#
-# chkconfig: - 36 64
-# description: ipa_kpasswd IPA Kpasswd daemon
-# processname: /usr/sbin/ipa_kpasswd
-# configdir: /etc/sysconfig/ipa-kpasswd
-#
-
-# Source function library.
-if [ -f /etc/rc.d/init.d/functions ] ; then
-. /etc/rc.d/init.d/functions
-fi
-# Source networking configuration.
-if [ -f /etc/sysconfig/network ] ; then
-. /etc/sysconfig/network
-fi
-
-# Check that networking is up.
-if [ "${NETWORKING}" = "no" ]
-then
- echo "Networking is down"
- exit 0
-fi
-
-# Source networking configuration.
-if [ -f /etc/sysconfig/ipa-kpasswd ] ; then
-. /etc/sysconfig/ipa-kpasswd
-fi
-
-NAME="ipa_kpasswd"
-PROG="/usr/sbin/ipa_kpasswd"
-
-start() {
- echo -n $"Starting $NAME: "
- daemon $NAME
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && touch /var/lock/subsys/ipa_kpasswd || \
- RETVAL=1
- return $RETVAL
-}
-
-stop() {
- echo -n $"Shutting down $NAME: "
- killproc $NAME
- RETVAL=$?
- echo
- [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/ipa_kpasswd
- return $RETVAL
-}
-
-restart() {
- stop
- start
-}
-
-case "$1" in
- start)
- start
- ;;
- stop)
- stop
- ;;
- status)
- status $PROG
- ;;
- restart)
- restart
- ;;
- condrestart)
- [ -f /var/lock/subsys/ipa_kpasswd ] && restart || :
- ;;
- reload)
- exit 3
- ;;
- *)
- echo $"Usage: $0 {start|stop|status|restart|condrestart}"
- exit 2
-esac
-
-exit $?
diff --git a/freeipa.spec.in b/freeipa.spec.in
index fb2462105..d25aee693 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -305,6 +305,7 @@ ln -s ../../../..%{_sysconfdir}/ipa/html/ipa_error.css \
mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d/
/bin/touch %{buildroot}%{_sysconfdir}/httpd/conf.d/ipa.conf
/bin/touch %{buildroot}%{_sysconfdir}/httpd/conf.d/ipa-rewrite.conf
+mkdir -p %{buildroot}%{_initrddir}
install -m755 ipa.init %{buildroot}%{_initrddir}/ipa
%endif
@@ -326,7 +327,6 @@ rm -rf %{buildroot}
%post server
if [ $1 = 1 ]; then
/sbin/chkconfig --add ipa
- /sbin/chkconfig --add ipa_kpasswd
fi
if [ $1 -gt 1 ] ; then
/usr/sbin/ipa-upgradeconfig || :
@@ -336,7 +336,6 @@ fi
%preun server
if [ $1 = 0 ]; then
/sbin/chkconfig --del ipa
- /sbin/chkconfig --del ipa_kpasswd
/sbin/service ipa stop >/dev/null 2>&1 || :
fi
@@ -355,7 +354,7 @@ if [ -s /etc/selinux/config ]; then
fi
%post server-selinux
-semodule -s targeted -i /usr/share/selinux/targeted/ipa_kpasswd.pp /usr/share/selinux/targeted/ipa_httpd.pp /usr/share/selinux/targeted/ipa_dogtag.pp
+semodule -s targeted -i /usr/share/selinux/targeted/ipa_httpd.pp /usr/share/selinux/targeted/ipa_dogtag.pp
. %{_sysconfdir}/selinux/config
FILE_CONTEXT=%{_sysconfdir}/selinux/targeted/contexts/files/file_contexts
selinuxenabled
@@ -377,7 +376,7 @@ fi
%postun server-selinux
if [ $1 = 0 ]; then
-semodule -s targeted -r ipa_kpasswd ipa_httpd ipa_dogtag
+semodule -s targeted -r ipa_httpd ipa_dogtag
. %{_sysconfdir}/selinux/config
FILE_CONTEXT=%{_sysconfdir}/selinux/targeted/contexts/files/file_contexts
selinuxenabled
@@ -406,13 +405,11 @@ fi
%{_sbindir}/ipa-compat-manage
%{_sbindir}/ipa-nis-manage
%{_sbindir}/ipa-host-net-manage
-%{_sbindir}/ipa_kpasswd
%{_sbindir}/ipactl
%{_sbindir}/ipa-upgradeconfig
%{_sbindir}/ipa-compliance
%{_sysconfdir}/cron.d/ipa-compliance
%attr(755,root,root) %{_initrddir}/ipa
-%attr(755,root,root) %{_initrddir}/ipa_kpasswd
%dir %{python_sitelib}/ipaserver
%{python_sitelib}/ipaserver/*
%dir %{_usr}/share/ipa
@@ -467,7 +464,6 @@ fi
%attr(700,root,root) %dir %{_localstatedir}/lib/ipa/sysrestore
%dir %{_localstatedir}/cache/ipa
%attr(700,apache,apache) %dir %{_localstatedir}/cache/ipa/sessions
-%attr(700,root,root) %dir %{_localstatedir}/cache/ipa/kpasswd
%attr(755,root,root) %{_libdir}/krb5/plugins/kdb/ipadb.so
%{_mandir}/man1/ipa-replica-conncheck.1.gz
%{_mandir}/man1/ipa-replica-install.1.gz
@@ -482,14 +478,12 @@ fi
%{_mandir}/man1/ipa-nis-manage.1.gz
%{_mandir}/man1/ipa-host-net-manage.1.gz
%{_mandir}/man1/ipa-ldap-updater.1.gz
-%{_mandir}/man8/ipa_kpasswd.8.gz
%{_mandir}/man8/ipactl.8.gz
%{_mandir}/man1/ipa-compliance.1.gz
%files server-selinux
%defattr(-,root,root,-)
%doc COPYING README Contributors.txt
-%{_usr}/share/selinux/targeted/ipa_kpasswd.pp
%{_usr}/share/selinux/targeted/ipa_httpd.pp
%{_usr}/share/selinux/targeted/ipa_dogtag.pp
%endif
@@ -540,6 +534,9 @@ fi
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/default.conf
%changelog
+* Wed Aug 25 2011 Simo Sorce <ssorce#redhat.com> - 3.0.0
+- Remove ipa_kpasswd.
+
* Tue Aug 23 2011 Jan Cholasta <jcholast@redhat.com> - 2.1.0-1
- Add subscription-manager dependency for RHEL.
diff --git a/install/tools/man/Makefile.am b/install/tools/man/Makefile.am
index 973e913ca..71d9b29c8 100644
--- a/install/tools/man/Makefile.am
+++ b/install/tools/man/Makefile.am
@@ -22,7 +22,6 @@ man1_MANS = \
man8_MANS = \
ipactl.8 \
- ipa_kpasswd.8 \
$(NULL)
install-data-hook:
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index a247c19b7..a06b849c4 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -22,7 +22,7 @@ ipa\-server\-install \- Configure an IPA server
.SH "SYNOPSIS"
ipa\-server\-install [\fIOPTION\fR]...
.SH "DESCRIPTION"
-Configures the services needed by an IPA server. This includes setting up a Kerberos Key Distribution Center (KDC) with an LDAP back\-end, configuring Apache, configuring NTP and starting the ipa_kpasswd service provided by IPA. By default a dogtag\-based CA will be configured to issue server certificates.
+Configures the services needed by an IPA server. This includes setting up a Kerberos Key Distribution Center (KDC) and a Kadmin daemon with an LDAP back\-end, configuring Apache, configuring NTP and optionally configuring and starting an LDAP-backed DNS server. By default a dogtag\-based CA will be configured to issue server certificates.
.SH "OPTIONS"
.TP
\fB\-r\fR \fIREALM_NAME\fR, \fB\-\-realm\fR=\fIREALM_NAME\fR
diff --git a/install/tools/man/ipa_kpasswd.8 b/install/tools/man/ipa_kpasswd.8
deleted file mode 100644
index 3c0d8105d..000000000
--- a/install/tools/man/ipa_kpasswd.8
+++ /dev/null
@@ -1,36 +0,0 @@
-.\" A man page for ipa_kpasswd
-.\" Copyright (C) 2008 Red Hat, Inc.
-.\"
-.\" This program is free software; you can redistribute it and/or modify
-.\" it under the terms of the GNU General Public License as published by
-.\" the Free Software Foundation, either version 3 of the License, or
-.\" (at your option) any later version.
-.\"
-.\" This program is distributed in the hope that it will be useful, but
-.\" WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-.\" General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public License
-.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
-.\"
-.\" Author: Rob Crittenden <rcritten@redhat.com>
-.\"
-.TH "ipa_kpasswd" "8" "Mar 14 2008" "freeipa" ""
-.SH "NAME"
-ipa_kpasswd \- Proxy Kerberos password change requests
-.SH "SYNOPSIS"
-ipa_kpasswd
-.SH "DESCRIPTION"
-Implementation of the kpasswd protocol (RFC 3244).
-
-It is used to proxy password change operations to Directory Server.
-.SH "ENVIRONMENT VARIABLES"
-.TP
-KRB5_KTNAME
-Location of the keytab to be used by ipa_kpasswd
-.TP
-IPA_KPASSWD_DEBUG
-Enable additional syslog output from ipa_kpasswd. Setting greater than 0 gets basic output. Setting higher than 100 gets more.
-.SH "EXIT STATUS"
-\-1 if an error occurred
diff --git a/ipa.1 b/ipa.1
index e5f0c6dbe..4c8ba377e 100644
--- a/ipa.1
+++ b/ipa.1
@@ -192,7 +192,7 @@ IPA default configuration file.
2 If an entry is not found
.SH "SEE ALSO"
ipa\-client\-install(1), ipa\-compat\-manage(1), ipactl(1), ipa\-dns\-install(1),
-ipa\-getcert(1), ipa\-getkeytab(1), ipa\-join(1), ipa_kpasswd(1), ipa\-ldap\-updater(1),
+ipa\-getcert(1), ipa\-getkeytab(1), ipa\-join(1), ipa\-ldap\-updater(1),
ipa\-nis\-manage(1), ipa\-replica\-install(1), ipa\-replica\-manage(1), ipa\-replica\-prepare(1),
ipa\-rmkeytab(1), ipa\-server\-certinstall(2), ipa\-server\-install(1), ipa\-upgradeconfig(1),
ipa\-host\-net\-manage(1)
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index 7f77fc1eb..9956b9fb7 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -71,7 +71,7 @@ def update_key_val_in_file(filename, key, val):
class KpasswdInstance(service.SimpleServiceInstance):
def __init__(self):
- service.SimpleServiceInstance.__init__(self, "ipa_kpasswd")
+ service.SimpleServiceInstance.__init__(self, "kadmin")
class KrbInstance(service.Service):
def __init__(self, fstore=None):
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 62db9baf5..2f80749ad 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -34,7 +34,7 @@ CACERT = "/etc/ipa/ca.crt"
SERVICE_LIST = {
'KDC':('krb5kdc', 10),
- 'KPASSWD':('ipa_kpasswd', 20),
+ 'KPASSWD':('kadmin', 20),
'DNS':('named', 30),
'HTTP':('httpd', 40),
'CA':('pki-cad', 50)
diff --git a/selinux/Makefile b/selinux/Makefile
index 62b7bf7ed..9e87bdd8f 100644
--- a/selinux/Makefile
+++ b/selinux/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = ipa_kpasswd ipa_httpd ipa_dogtag
+SUBDIRS = ipa_httpd ipa_dogtag
POLICY_MAKEFILE = /usr/share/selinux/devel/Makefile
POLICY_DIR = $(DESTDIR)/usr/share/selinux/targeted
@@ -21,9 +21,8 @@ maintainer-clean: distclean
install: all
install -d $(POLICY_DIR)
- install -m 644 ipa_kpasswd/ipa_kpasswd.pp $(POLICY_DIR)
install -m 644 ipa_httpd/ipa_httpd.pp $(POLICY_DIR)
install -m 644 ipa_dogtag/ipa_dogtag.pp $(POLICY_DIR)
load:
- /usr/sbin/semodule -i ipa_kpasswd/ipa_kpasswd.pp ipa_httpd/ipa_httpd.pp
+ /usr/sbin/semodule -i ipa_httpd/ipa_httpd.pp
diff --git a/selinux/ipa-server-selinux.spec.in b/selinux/ipa-server-selinux.spec.in
index 3387553ab..b3c7d89cf 100644
--- a/selinux/ipa-server-selinux.spec.in
+++ b/selinux/ipa-server-selinux.spec.in
@@ -36,7 +36,6 @@ make DESTDIR=%{buildroot} install
%files
%{_usr}/share/selinux/targeted/ipa_webgui.pp
-%{_usr}/share/selinux/targeted/ipa_kpasswd.pp
%define saveFileContext() \
@@ -61,7 +60,7 @@ fi;
%saveFileContext targeted
%post
-semodule -s targeted -i /usr/share/selinux/targeted/ipa_webgui.pp /usr/share/selinux/targeted/ipa_kpasswd.pp
+semodule -s targeted -i /usr/share/selinux/targeted/ipa_webgui.pp
%relabel targeted
%preun
@@ -71,7 +70,7 @@ fi
%postun
if [ $1 = 0 ]; then
-semodule -s targeted -r ipa_webgui ipa_kpasswd
+semodule -s targeted -r ipa_webgui
%relabel targeted
fi
diff --git a/selinux/ipa_kpasswd/ipa_kpasswd.fc b/selinux/ipa_kpasswd/ipa_kpasswd.fc
deleted file mode 100644
index 2dcf827dd..000000000
--- a/selinux/ipa_kpasswd/ipa_kpasswd.fc
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# /usr
-#
-/usr/sbin/ipa_kpasswd -- gen_context(system_u:object_r:ipa_kpasswd_exec_t,s0)
-
-#
-# /var
-#
-/var/cache/ipa/kpasswd(/.*)? gen_context(system_u:object_r:ipa_kpasswd_ccache_t,s0)
diff --git a/selinux/ipa_kpasswd/ipa_kpasswd.te b/selinux/ipa_kpasswd/ipa_kpasswd.te
deleted file mode 100644
index 292be7b89..000000000
--- a/selinux/ipa_kpasswd/ipa_kpasswd.te
+++ /dev/null
@@ -1,80 +0,0 @@
-policy_module(ipa_kpasswd, 1.0)
-
-########################################
-#
-# Declarations
-#
-
-type ipa_kpasswd_t;
-type ipa_kpasswd_exec_t;
-type ipa_kpasswd_var_run_t;
-type ipa_kpasswd_ccache_t;
-init_daemon_domain(ipa_kpasswd_t, ipa_kpasswd_exec_t)
-
-########################################
-#
-# IPA kpasswd local policy
-#
-
-allow ipa_kpasswd_t self:capability { sys_nice dac_override };
-allow ipa_kpasswd_t self:tcp_socket create_stream_socket_perms;
-allow ipa_kpasswd_t self:udp_socket create_socket_perms;
-
-files_read_etc_files(ipa_kpasswd_t)
-files_search_usr(ipa_kpasswd_t)
-
-files_pid_file(ipa_kpasswd_var_run_t);
-allow ipa_kpasswd_t ipa_kpasswd_var_run_t:file manage_file_perms;
-files_pid_filetrans(ipa_kpasswd_t,ipa_kpasswd_var_run_t,file)
-
-auth_use_nsswitch(ipa_kpasswd_t)
-
-libs_use_ld_so(ipa_kpasswd_t)
-libs_use_shared_libs(ipa_kpasswd_t)
-
-logging_send_syslog_msg(ipa_kpasswd_t)
-
-miscfiles_read_localization(ipa_kpasswd_t)
-
-kerberos_use(ipa_kpasswd_t)
-kerberos_manage_host_rcache(ipa_kpasswd_t)
-kerberos_read_kdc_config(ipa_kpasswd_t)
-
-kernel_read_system_state(ipa_kpasswd_t)
-
-# /var/cache/ipa/kpasswd
-files_type(ipa_kpasswd_ccache_t)
-manage_dirs_pattern(ipa_kpasswd_t, ipa_kpasswd_ccache_t, ipa_kpasswd_ccache_t)
-manage_files_pattern(ipa_kpasswd_t, ipa_kpasswd_ccache_t, ipa_kpasswd_ccache_t)
-files_var_filetrans(ipa_kpasswd_t, ipa_kpasswd_ccache_t,dir)
-
-kernel_read_network_state(ipa_kpasswd_t)
-kernel_read_network_state_symlinks(ipa_kpasswd_t)
-
-corenet_tcp_sendrecv_all_if(ipa_kpasswd_t)
-corenet_udp_sendrecv_all_if(ipa_kpasswd_t)
-corenet_raw_sendrecv_all_if(ipa_kpasswd_t)
-corenet_tcp_sendrecv_all_nodes(ipa_kpasswd_t)
-corenet_udp_sendrecv_all_nodes(ipa_kpasswd_t)
-corenet_raw_sendrecv_all_nodes(ipa_kpasswd_t)
-corenet_tcp_sendrecv_all_ports(ipa_kpasswd_t)
-corenet_udp_sendrecv_all_ports(ipa_kpasswd_t)
-corenet_non_ipsec_sendrecv(ipa_kpasswd_t)
-corenet_tcp_bind_all_nodes(ipa_kpasswd_t)
-corenet_udp_bind_all_nodes(ipa_kpasswd_t)
-corenet_tcp_bind_kerberos_admin_port(ipa_kpasswd_t)
-corenet_udp_bind_kerberos_admin_port(ipa_kpasswd_t)
-require {
- type krb5kdc_conf_t;
-};
-
-allow ipa_kpasswd_t krb5kdc_conf_t:dir search_dir_perms;
-
-optional_policy(`
- gen_require(`
- type kerberos_password_port_t;
- ')
- corenet_tcp_bind_kerberos_password_port(ipa_kpasswd_t)
- corenet_udp_bind_kerberos_password_port(ipa_kpasswd_t)
-')
-