summaryrefslogtreecommitdiffstats
path: root/daemons
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-09-14 17:04:08 -0400
committerJason Gerard DeRose <jderose@redhat.com>2009-09-24 17:45:49 -0600
commitd0587cbdd5bc5e07a6e8519deb07adaace643740 (patch)
treeaa6b96e33337a809687ab025ec4d2a392ca757f0 /daemons
parent4f4d57cd30ac7169e18a8e2e22e62d8bdda083c4 (diff)
downloadfreeipa-d0587cbdd5bc5e07a6e8519deb07adaace643740.tar.gz
freeipa-d0587cbdd5bc5e07a6e8519deb07adaace643740.tar.xz
freeipa-d0587cbdd5bc5e07a6e8519deb07adaace643740.zip
Enrollment for a host in an IPA domain
This will create a host service principal and may create a host entry (for admins). A keytab will be generated, by default in /etc/krb5.keytab If no kerberos credentails are available then enrollment over LDAPS is used if a password is provided. This change requires that openldap be used as our C LDAP client. It is much easier to do SSL using openldap than mozldap (no certdb required). Otherwise we'd have to write a slew of extra code to create a temporary cert database, import the CA cert, ...
Diffstat (limited to 'daemons')
-rw-r--r--daemons/configure.ac1
-rw-r--r--daemons/ipa-slapi-plugins/Makefile.am1
-rw-r--r--daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am42
-rw-r--r--daemons/ipa-slapi-plugins/ipa-enrollment/enrollment-conf.ldif16
-rw-r--r--daemons/ipa-slapi-plugins/ipa-enrollment/ipa_enrollment.c457
-rw-r--r--daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c40
6 files changed, 556 insertions, 1 deletions
diff --git a/daemons/configure.ac b/daemons/configure.ac
index e726bd982..7f0fd680f 100644
--- a/daemons/configure.ac
+++ b/daemons/configure.ac
@@ -260,6 +260,7 @@ AC_CONFIG_FILES([
Makefile
ipa-kpasswd/Makefile
ipa-slapi-plugins/Makefile
+ ipa-slapi-plugins/ipa-enrollment/Makefile
ipa-slapi-plugins/ipa-memberof/Makefile
ipa-slapi-plugins/ipa-pwd-extop/Makefile
ipa-slapi-plugins/ipa-winsync/Makefile
diff --git a/daemons/ipa-slapi-plugins/Makefile.am b/daemons/ipa-slapi-plugins/Makefile.am
index 3b58ccb14..ac2d26879 100644
--- a/daemons/ipa-slapi-plugins/Makefile.am
+++ b/daemons/ipa-slapi-plugins/Makefile.am
@@ -1,6 +1,7 @@
NULL =
SUBDIRS = \
+ ipa-enrollment \
ipa-pwd-extop \
ipa-memberof \
ipa-winsync \
diff --git a/daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am b/daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am
new file mode 100644
index 000000000..8a4ba09c7
--- /dev/null
+++ b/daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am
@@ -0,0 +1,42 @@
+NULL =
+
+INCLUDES = \
+ -I. \
+ -I$(srcdir) \
+ -DPREFIX=\""$(prefix)"\" \
+ -DBINDIR=\""$(bindir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DDATADIR=\""$(datadir)"\" \
+ $(MOZLDAP_CFLAGS) \
+ $(KRB5_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(NULL)
+
+plugindir = $(libdir)/dirsrv/plugins
+plugin_LTLIBRARIES = \
+ libipa_enrollment_extop.la \
+ $(NULL)
+
+libipa_enrollment_extop_la_SOURCES = \
+ ipa_enrollment.c \
+ $(NULL)
+
+libipa_enrollment_extop_la_LDFLAGS = -avoid-version
+
+libipa_enrollment_extop_la_LIBADD = \
+ $(MOZLDAP_LIBS) \
+ $(NULL)
+
+appdir = $(IPA_DATA_DIR)
+app_DATA = \
+ enrollment-conf.ldif \
+ $(NULL)
+
+EXTRA_DIST = \
+ $(app_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
diff --git a/daemons/ipa-slapi-plugins/ipa-enrollment/enrollment-conf.ldif b/daemons/ipa-slapi-plugins/ipa-enrollment/enrollment-conf.ldif
new file mode 100644
index 000000000..1c98277a8
--- /dev/null
+++ b/daemons/ipa-slapi-plugins/ipa-enrollment/enrollment-conf.ldif
@@ -0,0 +1,16 @@
+dn: cn=ipa_enrollment_extop,cn=plugins,cn=config
+changetype: add
+objectclass: top
+objectclass: nsSlapdPlugin
+objectclass: extensibleObject
+cn: ipa_enrollment_extop
+nsslapd-pluginpath: libipa_enrollment_extop
+nsslapd-plugininitfunc: ipaenrollment_init
+nsslapd-plugintype: extendedop
+nsslapd-pluginenabled: on
+nsslapd-pluginid: ipa_enrollment_extop
+nsslapd-pluginversion: 1.0
+nsslapd-pluginvendor: RedHat
+nsslapd-plugindescription: Enroll hosts into the IPA domain
+nsslapd-plugin-depends-on-type: database
+nsslapd-realmTree: $SUFFIX
diff --git a/daemons/ipa-slapi-plugins/ipa-enrollment/ipa_enrollment.c b/daemons/ipa-slapi-plugins/ipa-enrollment/ipa_enrollment.c
new file mode 100644
index 000000000..8a9906aab
--- /dev/null
+++ b/daemons/ipa-slapi-plugins/ipa-enrollment/ipa_enrollment.c
@@ -0,0 +1,457 @@
+/** BEGIN COPYRIGHT BLOCK
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * In addition, as a special exception, Red Hat, Inc. gives You the additional
+ * right to link the code of this Program with code not covered under the GNU
+ * General Public License ("Non-GPL Code") and to distribute linked combinations
+ * including the two, subject to the limitations in this paragraph. Non-GPL Code
+ * permitted under this exception must only link to the code of this Program
+ * through those well defined interfaces identified in the file named EXCEPTION
+ * found in the source code files (the "Approved Interfaces"). The files of
+ * Non-GPL Code may instantiate templates or use macros or inline functions from
+ * the Approved Interfaces without causing the resulting work to be covered by
+ * the GNU General Public License. Only Red Hat, Inc. may make changes or
+ * additions to the list of Approved Interfaces. You must obey the GNU General
+ * Public License in all respects for all of the Program code and other code used
+ * in conjunction with the Program except the Non-GPL Code covered by this
+ * exception. If you modify this file, you may extend this exception to your
+ * version of the file, but you are not obligated to do so. If you do not wish to
+ * provide this exception without modification, you must delete this exception
+ * statement from your version and license this file solely under the GPL without
+ * exception.
+ *
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/*
+ * Enroll a host into the IPA domain.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <dirsrv/slapi-plugin.h>
+#include <krb5.h>
+
+/* OID of the extended operation handled by this plug-in */
+#define JOIN_OID "2.16.840.1.113730.3.8.3.53"
+
+Slapi_PluginDesc pdesc = {
+ "ipa-enrollment",
+ "IPA Project",
+ "IPA/2.0",
+ "IPA Enrollment Extended Operation plugin"
+};
+
+static char *ipaenrollment_oid_list[] = {
+ JOIN_OID,
+ NULL
+};
+
+static char *ipaenrollment_name_list[] = {
+ "Enrollment Extended Operation",
+ NULL
+};
+
+static void *ipaenrollment_plugin_id;
+
+static char *realm;
+static const char *ipa_realm_dn;
+
+static int
+ipaenrollement_secure(Slapi_PBlock *pb, char **errMesg)
+{
+ int sasl_ssf, is_ssl;
+ int rc = LDAP_SUCCESS;
+
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_enrollment", "=> ipaenrollment_secure\n");
+
+ /* Allow enrollment only for SSL/TLS established connections and
+ * connections using SASL privacy layers */
+ if (slapi_pblock_get(pb, SLAPI_CONN_SASL_SSF, &sasl_ssf) != 0) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
+ "Could not get SASL SSF from connection\n");
+ *errMesg = "Operation requires a secure connection.\n";
+ rc = LDAP_OPERATIONS_ERROR;
+ goto done;
+ }
+
+ if (slapi_pblock_get(pb, SLAPI_CONN_IS_SSL_SESSION, &is_ssl) != 0) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
+ "Could not get IS SSL from connection\n");
+ *errMesg = "Operation requires a secure connection.\n";
+ rc = LDAP_OPERATIONS_ERROR;
+ goto done;
+ }
+
+ if ((0 == is_ssl) && (sasl_ssf <= 1)) {
+ *errMesg = "Operation requires a secure connection.\n";
+ rc = LDAP_CONFIDENTIALITY_REQUIRED;
+ goto done;
+ }
+
+done:
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_enrollment", "<= ipaenrollment_secure\n");
+ return rc;
+
+}
+
+/* The extop call passes in the FQDN of the host to enroll.
+ * We take that and set the krbPrincipalName and add the appropriate
+ * objectclasses, then return krbPrincipalName. The caller should take
+ * this and pass it to ipa-getkeytab to generate the keytab.
+ *
+ * The password for the entry is removed by ipa-getkeytab.
+ */
+static int
+ipa_join(Slapi_PBlock *pb)
+{
+ char *bindDN = NULL;
+ char *errMesg = NULL;
+ struct berval *extop_value = NULL;
+ Slapi_PBlock *pbte = NULL;
+ Slapi_PBlock *pbtm = NULL;
+ Slapi_Entry *targetEntry=NULL;
+ Slapi_DN *sdn;
+ Slapi_Backend *be;
+ Slapi_Entry **es = NULL;
+ int rc=0, ret=0, res, i;
+ int is_root=0;
+ char *krbLastPwdChange = NULL;
+ char *fqdn = NULL;
+ Slapi_Mods *smods;
+ char *attrlist[] = {"fqdn", "krbPrincipalKey", "krbLastPwdChange", "krbPrincipalName", NULL };
+ char * filter;
+
+ int scope = LDAP_SCOPE_SUBTREE;
+ char *principal;
+ struct berval retbval;
+
+ /* Get Bind DN */
+ slapi_pblock_get(pb, SLAPI_CONN_DN, &bindDN);
+
+ /* If the connection is bound anonymously we must refuse to process
+ * this operation.
+ */
+ if (bindDN == NULL || *bindDN == '\0') {
+ /* Refuse the operation because they're bound anonymously */
+ errMesg = "Anonymous Binds are not allowed.\n";
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ goto free_and_return;
+ }
+
+ /* Get the ber value of the extended operation */
+ slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
+
+ /* We are passed in the FQDN of the host to enroll. Do an internal
+ * search and pull that entry.
+ */
+ filter = slapi_ch_smprintf("(fqdn=%s)", extop_value->bv_val);
+ pbte = slapi_pblock_new();
+ slapi_search_internal_set_pb(pbte,
+ ipa_realm_dn, scope, filter, attrlist, 0,
+ NULL, /* Controls */
+ NULL, /* UniqueID */
+ ipaenrollment_plugin_id,
+ 0); /* Flags */
+
+ /* do search the tree */
+ ret = slapi_search_internal_pb(pbte);
+ slapi_pblock_get(pbte, SLAPI_PLUGIN_INTOP_RESULT, &res);
+ if (ret == -1 || res != LDAP_SUCCESS) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipaenrollment_extop",
+ "Search for host failed, err (%d)\n",
+ res?res:ret);
+ errMesg = "Host not found.\n";
+ rc = LDAP_NO_SUCH_OBJECT;
+ goto free_and_return;
+ }
+
+ /* get entries */
+ slapi_pblock_get(pbte, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &es);
+ if (!es) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "No entries ?!");
+ errMesg = "Host not found.\n";
+ rc = LDAP_NO_SUCH_OBJECT;
+ goto free_and_return;
+ }
+
+ /* count entries */
+ for (i = 0; es[i]; i++) /* count */ ;
+
+ /* if there is none or more than one, freak out */
+ if (i != 1) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipaenrollment_extop",
+ "Too many entries, or entry no found (%d)", i);
+ errMesg = "Host not found.\n";
+ rc = LDAP_NO_SUCH_OBJECT;
+ goto free_and_return;
+ }
+ targetEntry = es[0];
+
+ /* Is this host already enrolled? */
+ krbLastPwdChange = slapi_entry_attr_get_charptr(targetEntry, "krbLastPwdChange");
+ if (NULL != krbLastPwdChange) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipaenrollment_extop",
+ "Host already enrolled");
+ errMesg = "Host already enrolled.\n";
+ rc = LDAP_OPERATIONS_ERROR;
+ goto free_and_return;
+ }
+
+ /* First thing to do is to ask access control if the bound identity has
+ * rights to modify the userpassword attribute on this entry. If not,
+ * then we fail immediately with insufficient access. This means that
+ * we don't leak any useful information to the client such as current
+ * password wrong, etc.
+ */
+
+ is_root = slapi_dn_isroot(bindDN);
+ slapi_pblock_set(pb, SLAPI_REQUESTOR_ISROOT, &is_root);
+
+ /* In order to perform the access control check,
+ * we need to select a backend (even though
+ * we don't actually need it otherwise).
+ */
+ sdn = slapi_sdn_new_dn_byval(bindDN);
+ be = slapi_be_select(sdn);
+ slapi_pblock_set(pb, SLAPI_BACKEND, be);
+
+ /* Access Strategy:
+ * If the user has WRITE-ONLY access, a new keytab is set on the entry.
+ */
+
+ ret = slapi_access_allowed(pb, targetEntry, "krbPrincipalKey", NULL, SLAPI_ACL_WRITE);
+ if (ret != LDAP_SUCCESS) {
+ errMesg = "Insufficient access rights\n";
+ rc = LDAP_INSUFFICIENT_ACCESS;
+ goto free_and_return;
+ }
+
+ /* If a principal is already set return the name */
+ principal = slapi_entry_attr_get_charptr(targetEntry, "krbPrincipalName");
+ if (NULL != principal)
+ goto done;
+
+ /* Add the elements needed for enrollment */
+ smods = slapi_mods_new();
+ fqdn = slapi_entry_attr_get_charptr(targetEntry, "fqdn");
+ principal = slapi_ch_smprintf("host/%s@%s", fqdn, realm);
+ slapi_mods_add_string(smods, LDAP_MOD_ADD, "krbPrincipalName", principal);
+ slapi_mods_add_string(smods, LDAP_MOD_ADD, "objectClass", "krbPrincipalAux");
+
+ pbtm = slapi_pblock_new();
+ slapi_modify_internal_set_pb (pbtm, slapi_entry_get_dn_const(targetEntry),
+ slapi_mods_get_ldapmods_byref(smods),
+ NULL, /* Controls */
+ NULL, /* UniqueID */
+ ipaenrollment_plugin_id, /* PluginID */
+ 0); /* Flags */
+
+ rc = slapi_modify_internal_pb (pbtm);
+ if (rc) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipaenrollment_extop",
+ "WARNING: modify error %d on entry '%s'\n",
+ rc, slapi_entry_get_dn_const(targetEntry));
+ } else {
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+
+ if (rc != LDAP_SUCCESS){
+ slapi_log_error(SLAPI_LOG_TRACE, "ipaenrollment_extop",
+ "WARNING: modify error %d on entry '%s'\n",
+ rc, slapi_entry_get_dn_const(targetEntry));
+ } else {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipaenrollment_extop",
+ "<= apply mods: Successful\n");
+ }
+ }
+
+done:
+ /* Return the krbprincipalname */
+ retbval.bv_val = principal;
+ retbval.bv_len = strlen(principal);
+
+ ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, JOIN_OID);
+ if (!ret) ret = slapi_pblock_set(pb, SLAPI_EXT_OP_RET_VALUE, &retbval);
+ if (ret) {
+ errMesg = "Could not set return values";
+ slapi_log_error(SLAPI_LOG_PLUGIN, "ipaenrollmenti_extop", "%s\n",
+ errMesg);
+ rc = SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
+ }
+
+ /* Free anything that we allocated above */
+free_and_return:
+
+ if (pbte) {
+ slapi_free_search_results_internal(pbte);
+ slapi_pblock_destroy(pbte);
+ }
+ if (pbtm) {
+ slapi_pblock_destroy(pbtm);
+ }
+
+ if (krbLastPwdChange) slapi_ch_free_string(&krbLastPwdChange);
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, "ipaenrollment_extop", errMesg ? errMesg : "success\n");
+ slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
+
+ free(principal);
+
+ return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
+}
+
+/* Extended operation plug-in */
+static int
+ipaenrollment_extop(Slapi_PBlock *pb)
+{
+ char *oid;
+ char *errMesg = NULL;
+ int rc, ret;
+
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_enrollment", "=> ipaenrollment_extop\n");
+
+ rc = ipaenrollement_secure(pb, &errMesg);
+ if (rc) {
+ goto free_and_return;
+ }
+
+ /* Get the OID and the value included in the request */
+ if (slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_OID, &oid ) != 0) {
+ errMesg = "Could not get OID and value from request.\n";
+ rc = LDAP_OPERATIONS_ERROR;
+ slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop", errMesg);
+ goto free_and_return;
+ }
+
+ if (strcasecmp(oid, JOIN_OID) == 0) {
+ ret = ipa_join(pb);
+ return ret;
+ }
+
+ errMesg = "Request OID does not match supported OIDs.\n";
+ rc = LDAP_OPERATIONS_ERROR;
+
+free_and_return:
+ slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_enrollment", errMesg);
+ slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
+
+ return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
+}
+
+static int
+ipaenrollment_start(Slapi_PBlock *pb)
+{
+ krb5_error_code krberr;
+ krb5_context krbctx;
+ char *config_dn = NULL;
+ char *partition_dn = NULL;
+ Slapi_Entry *config_entry = NULL;
+ int ret = LDAP_SUCCESS;
+ Slapi_DN *sdn;
+ int rc = 0;
+
+ krberr = krb5_init_context(&krbctx);
+ if (krberr) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ipaenrollment_init",
+ "krb5_init_context failed\n");
+ return LDAP_OPERATIONS_ERROR;
+ }
+
+ ret = krb5_get_default_realm(krbctx, &realm);
+ if (ret) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ipaenrollment_init",
+ "Failed to get default realm?!\n");
+ ret = LDAP_OPERATIONS_ERROR;
+ }
+
+ if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &config_dn) != 0) {
+ slapi_log_error( SLAPI_LOG_FATAL, "ipaenrollment_start", "No config DN?\n");
+ ret = LDAP_OPERATIONS_ERROR;
+ goto done;
+ }
+ sdn = slapi_sdn_new_dn_byref(config_dn);
+ if ((rc = slapi_search_internal_get_entry(sdn, NULL, &config_entry,
+ ipaenrollment_plugin_id)) != LDAP_SUCCESS ){
+ slapi_log_error(SLAPI_LOG_TRACE, "ipaenrollment_extop",
+ "ipaenrollment_start: No such entry-(%s), err (%d)\n",
+ config_dn, rc);
+ }
+ slapi_sdn_free(&sdn);
+
+ partition_dn = slapi_entry_attr_get_charptr(config_entry, "nsslapd-realmtree");
+ if (!partition_dn) {
+ slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Missing partition configuration entry (nsslapd-realmTree)!\n");
+ ret = LDAP_OPERATIONS_ERROR;
+ goto done;
+ }
+
+ ipa_realm_dn = slapi_ch_smprintf("cn=computers,cn=accounts,%s", partition_dn);
+ slapi_ch_free_string(&partition_dn);
+ if (!ipa_realm_dn) {
+ slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Out of memory ?\n");
+ ret = LDAP_OPERATIONS_ERROR;
+ goto done;
+ }
+
+done:
+ if (krbctx) krb5_free_context(krbctx);
+ if (config_entry) slapi_entry_free(config_entry);
+
+ return ret;
+}
+
+int
+ipaenrollment_init(Slapi_PBlock *pb)
+{
+ int ret;
+
+ /* Get the arguments appended to the plugin extendedop directive
+ * in the plugin entry. The first argument
+ * (after the standard arguments for the directive) should
+ * contain the OID of the extended op.
+ */
+
+ ret = slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &ipaenrollment_plugin_id);
+ if ((ret != 0) || (NULL == ipaenrollment_plugin_id)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ "ipaenrollment_init", "Could not get identity or identity was NULL\n");
+ return -1;
+ }
+
+ slapi_log_error(SLAPI_LOG_PLUGIN, "ipaenrollment_init",
+ "Registering plug-in for extended op.\n");
+
+ /* Register the plug-in function as an extended operation
+ plug-in function. */
+ ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
+ if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *)ipaenrollment_start);
+ if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&pdesc);
+ if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, ipaenrollment_oid_list);
+ if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, ipaenrollment_name_list);
+ if (!ret) slapi_pblock_set(pb, SLAPI_PLUGIN_EXT_OP_FN, (void *)ipaenrollment_extop);
+
+ if (ret) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "ipaenrollment_init",
+ "Failed to set plug-in version, function, and OID.\n");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
index 24acc8875..744d7dd3a 100644
--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
@@ -2088,6 +2088,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
Slapi_Entry *targetEntry=NULL;
struct berval *bval = NULL;
Slapi_Value **svals = NULL;
+ Slapi_Value **evals = NULL;
const char *bdn;
const Slapi_DN *bsdn;
Slapi_DN *sdn;
@@ -2095,7 +2096,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
Slapi_Entry **es = NULL;
int scope, res;
char *filter;
- char *attrlist[] = {"krbPrincipalKey", "krbLastPwdChange", NULL };
+ char *attrlist[] = {"krbPrincipalKey", "krbLastPwdChange", "userPassword", "krbPrincipalName", "enrolledBy", NULL };
krb5_context krbctx = NULL;
krb5_principal krbname = NULL;
krb5_error_code krberr;
@@ -2108,6 +2109,8 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
struct tm utctime;
char timestr[GENERALIZED_TIME_LENGTH+1];
time_t time_now = time(NULL);
+ char *pw = NULL;
+ char *krbPrincipalName = NULL;
svals = (Slapi_Value **)calloc(2, sizeof(Slapi_Value *));
if (!svals) {
@@ -2522,6 +2525,31 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "krbPrincipalKey", svals);
+ /* If we are creating a keytab for a host service attempt to remove
+ * the userPassword attribute if it exists
+ */
+ pw = slapi_entry_attr_get_charptr(targetEntry, "userPassword");
+ krbPrincipalName = slapi_entry_attr_get_charptr(targetEntry, "krbPrincipalName");
+ if ((strncmp(krbPrincipalName, "host/", 5) == 0)) {
+ char * krbLastPwdChange = slapi_entry_attr_get_charptr(targetEntry, "krbLastPwdChange");
+ char * enrolledBy = slapi_entry_attr_get_charptr(targetEntry, "enrolledBy");
+ if (NULL == enrolledBy) {
+ evals = (Slapi_Value **)calloc(2, sizeof(Slapi_Value *));
+ evals[0] = slapi_value_new_string(bindDN);
+ slapi_mods_add_mod_values(smods, LDAP_MOD_ADD, "enrolledBy", evals);
+ } else {
+ slapi_ch_free_string(&enrolledBy);
+ }
+ if ((NULL != pw) && (NULL == krbLastPwdChange)) {
+ slapi_mods_add_mod_values(smods, LDAP_MOD_DELETE, "userPassword", NULL);
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
+ "Removing userPassword from host entry\n");
+ slapi_ch_free_string(&pw);
+ }
+ slapi_ch_free_string(&krbLastPwdChange);
+ }
+ slapi_ch_free_string(&krbPrincipalName);
+
/* commit changes */
ret = ipapwd_apply_mods(slapi_entry_get_dn_const(targetEntry), smods);
@@ -2603,10 +2631,18 @@ free_and_return:
}
free(svals);
}
+ if (evals) {
+ for (i = 0; evals[i]; i++) {
+ slapi_value_free(&evals[i]);
+ }
+ free(evals);
+ }
if (krbname) krb5_free_principal(krbctx, krbname);
if (krbctx) krb5_free_context(krbctx);
+ if (rc == LDAP_SUCCESS)
+ errMesg = NULL;
slapi_log_error(SLAPI_LOG_PLUGIN, "ipa_pwd_extop", errMesg ? errMesg : "success");
slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
@@ -2938,6 +2974,8 @@ static int ipapwd_gen_checks(Slapi_PBlock *pb, char **errMesg,
}
sdn = slapi_sdn_new_dn_byref(dn);
if (!sdn) {
+ slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
+ "Unable to convert dn to sdn %s", dn?dn:"<NULL>");
*errMesg = "Internal Error";
rc = LDAP_OPERATIONS_ERROR;
goto done;