mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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, ...
This commit is contained in:
committed by
Jason Gerard DeRose
parent
4f4d57cd30
commit
d0587cbdd5
@@ -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
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
NULL =
|
||||
|
||||
SUBDIRS = \
|
||||
ipa-enrollment \
|
||||
ipa-pwd-extop \
|
||||
ipa-memberof \
|
||||
ipa-winsync \
|
||||
|
||||
42
daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am
Normal file
42
daemons/ipa-slapi-plugins/ipa-enrollment/Makefile.am
Normal file
@@ -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
|
||||
@@ -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
|
||||
457
daemons/ipa-slapi-plugins/ipa-enrollment/ipa_enrollment.c
Normal file
457
daemons/ipa-slapi-plugins/ipa-enrollment/ipa_enrollment.c
Normal file
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user