summaryrefslogtreecommitdiffstats
path: root/ipa-slapi-plugins
diff options
context:
space:
mode:
Diffstat (limited to 'ipa-slapi-plugins')
-rw-r--r--ipa-slapi-plugins/README0
-rw-r--r--ipa-slapi-plugins/ipa-pwd-extop/Makefile5
-rw-r--r--ipa-slapi-plugins/ipa-pwd-extop/README0
-rw-r--r--ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c1359
-rw-r--r--ipa-slapi-plugins/ipa-pwd-extop/plugin-conf.ldif14
5 files changed, 0 insertions, 1378 deletions
diff --git a/ipa-slapi-plugins/README b/ipa-slapi-plugins/README
deleted file mode 100644
index e69de29bb..000000000
--- a/ipa-slapi-plugins/README
+++ /dev/null
diff --git a/ipa-slapi-plugins/ipa-pwd-extop/Makefile b/ipa-slapi-plugins/ipa-pwd-extop/Makefile
deleted file mode 100644
index 2a5646432..000000000
--- a/ipa-slapi-plugins/ipa-pwd-extop/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-all:
- gcc ipa_pwd_extop.c -I/usr/include -I/usr/include/nss3 -I/usr/include/mozldap -I/usr/include/nspr4 -I/usr/include/fedora-ds -lkrb5 -lmhash -llber -lssl -shared -g -fPIC -DPIC -Wl,-soname -Wl,libipa_pwd_extop.so -o libipa_pwd_extop.so
-
-install:
- cp -f libipa_pwd_extop.so /usr/lib/fedora-ds/plugins/
diff --git a/ipa-slapi-plugins/ipa-pwd-extop/README b/ipa-slapi-plugins/ipa-pwd-extop/README
deleted file mode 100644
index e69de29bb..000000000
--- a/ipa-slapi-plugins/ipa-pwd-extop/README
+++ /dev/null
diff --git a/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c b/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
deleted file mode 100644
index f871ee4f6..000000000
--- a/ipa-slapi-plugins/ipa-pwd-extop/ipa_pwd_extop.c
+++ /dev/null
@@ -1,1359 +0,0 @@
-/** 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.
- *
- * Authors:
- * Simo Sorce <ssorce@redhat.com>
- *
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-/*
- * Password Modify - LDAP Extended Operation.
- * RFC 3062
- *
- *
- * This plugin implements the "Password Modify - LDAP3"
- * extended operation for LDAP. The plugin function is called by
- * the server if an LDAP client request contains the OID:
- * "1.3.6.1.4.1.4203.1.11.1".
- *
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <prio.h>
-#include <ssl.h>
-#include <slapi-plugin.h>
-#include <krb5.h>
-#include <lber.h>
-#include <time.h>
-#include <iconv.h>
-#include <mhash.h>
-#include <openssl/des.h>
-
-/* Type of connection for this operation;*/
-#define LDAP_EXTOP_PASSMOD_CONN_SECURE
-
-/* Uncomment the following line FOR TESTING: allows non-SSL connections to use the password change extended op */
-/* #undef LDAP_EXTOP_PASSMOD_CONN_SECURE */
-
-/* ber tags for the PasswdModifyRequestValue sequence */
-#define LDAP_EXTOP_PASSMOD_TAG_USERID 0x80U
-#define LDAP_EXTOP_PASSMOD_TAG_OLDPWD 0x81U
-#define LDAP_EXTOP_PASSMOD_TAG_NEWPWD 0x82U
-
-/* ber tags for the PasswdModifyResponseValue sequence */
-#define LDAP_EXTOP_PASSMOD_TAG_GENPWD 0x80U
-
-/* number of bytes used for random password generation */
-#define LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN 8
-
-/* number of random bytes needed to generate password */
-#define LDAP_EXTOP_PASSMOD_RANDOM_BYTES 6
-
-/* OID of the extended operation handled by this plug-in */
-#define EXOP_PASSWD_OID "1.3.6.1.4.1.4203.1.11.1"
-
-/* These are thye default enc:salt ypes if nothing is defined.
- * TODO: retrieve the configure set of ecntypes either from the
- * kfc.conf file or by synchronizing the the file content into
- * the directory */
-
-#define KTF_DISALLOW_POSTDATED 0x00000001
-#define KTF_DISALLOW_FORWARDABLE 0x00000002
-#define KTF_DISALLOW_TGT_BASED 0x00000004
-#define KTF_DISALLOW_RENEWABLE 0x00000008
-#define KTF_DISALLOW_PROXIABLE 0x00000010
-#define KTF_DISALLOW_DUP_SKEY 0x00000020
-#define KTF_DISALLOW_ALL_TIX 0x00000040
-#define KTF_REQUIRES_PRE_AUTH 0x00000080
-#define KTF_REQUIRES_HW_AUTH 0x00000100
-#define KTF_REQUIRES_PWCHANGE 0x00000200
-#define KTF_DISALLOW_SVR 0x00001000
-#define KTF_PWCHANGE_SERVICE 0x00002000
-
-/* Salt types */
-#define KRB5_KDB_SALTTYPE_NORMAL 0
-#define KRB5_KDB_SALTTYPE_V4 1
-#define KRB5_KDB_SALTTYPE_NOREALM 2
-#define KRB5_KDB_SALTTYPE_ONLYREALM 3
-#define KRB5_KDB_SALTTYPE_SPECIAL 4
-#define KRB5_KDB_SALTTYPE_AFS3 5
-
-#define KRB5P_SALT_SIZE 16
-
-struct krb5p_keysalt {
- krb5_int32 enc_type;
- krb5_int32 salt_type;
-};
-
-static void *ipapwd_plugin_id;
-
-krb5_keyblock kmkey;
-
-struct krb5p_keysalt *keysalts;
-int n_keysalts;
-
-/* Novell key-format scheme:
-
- KrbKeySet ::= SEQUENCE {
- attribute-major-vno [0] UInt16,
- attribute-minor-vno [1] UInt16,
- kvno [2] UInt32,
- mkvno [3] UInt32 OPTIONAL,
- keys [4] SEQUENCE OF KrbKey,
- ...
- }
-
- KrbKey ::= SEQUENCE {
- salt [0] KrbSalt OPTIONAL,
- key [1] EncryptionKey,
- s2kparams [2] OCTET STRING OPTIONAL,
- ...
- }
-
- KrbSalt ::= SEQUENCE {
- type [0] Int32,
- salt [1] OCTET STRING OPTIONAL
- }
-
- EncryptionKey ::= SEQUENCE {
- keytype [0] Int32,
- keyvalue [1] OCTET STRING
- }
-
- */
-
-static inline void encode_int16(unsigned int val, unsigned char *p)
-{
- p[1] = (val >> 8) & 0xff;
- p[0] = (val ) & 0xff;
-}
-
-static Slapi_Value **encrypt_encode_key(krb5_context krbctx, Slapi_Entry *e, const char *newPasswd)
-{
- struct berval *bval = NULL;
- Slapi_Value **svals = NULL;
- BerElement *be = NULL;
- int num_versions;
- int krbTicketFlags;
- const char *krbPrincipalName;
- krb5_principal princ;
- krb5_error_code krberr;
- krb5_data pwd;
- int ret, i;
-
- krbPrincipalName = slapi_entry_attr_get_charptr(e, "krbPrincipalName");
- if (!krbPrincipalName) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "no krbPrincipalName present in this entry\n");
- return NULL;
- }
-
- /* TODO: retrieve current kvno and increment it */
- /* TODO: keep previous version */
- num_versions = 1;
-
- svals = (Slapi_Value **)calloc(num_versions + 1, sizeof(Slapi_Value *));
- if (!svals) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "memory allocation failed\n");
- return NULL;
- }
-
- svals[1] = NULL;
-
- krberr = krb5_parse_name(krbctx, krbPrincipalName, &princ);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_parse_name failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
-
- krbTicketFlags = slapi_entry_attr_get_int(e, "krbTicketFlags");
-
- pwd.data = (char *)newPasswd;
- pwd.length = strlen(newPasswd);
-
- be = ber_alloc_t( LBER_USE_DER );
-
- if (!be) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- goto enc_error;
- }
-
- /* major-vno = 1 and minor-von = 1 */
- /* this encoding assumes all keys have the same kvno (currently set at 1) */
- /* we also assum mkvno is 0 */
- ret = ber_printf(be, "{t[i]t[i]t[i]t[i]t[{",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), 1,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), 1,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2), 1,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 3), 0,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4));
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 vno info failed\n");
- goto enc_error;
- }
-
- for (i = 0; i < n_keysalts; i++) {
- krb5_keyblock key;
- krb5_data salt;
- krb5_octet *ptr;
- krb5_data plain;
- krb5_enc_data cipher;
- size_t len;
- const char *p;
-
- salt.data = NULL;
-
- switch (keysalts[i].salt_type) {
-
- case KRB5_KDB_SALTTYPE_ONLYREALM:
-
- p = strchr(krbPrincipalName, '@');
- if (!p) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Invalid principal name, no realm found!\n");
- goto enc_error;
- }
- p++;
- salt.data = strdup(p);
- if (!salt.data) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- goto enc_error;
- }
- salt.length = strlen(salt.data); /* final \0 omitted on purpose */
- break;
-
- case KRB5_KDB_SALTTYPE_NOREALM:
-
- krberr = krb5_principal2salt_norealm(krbctx, princ, &salt);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_principal2salt failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
- break;
-
- case KRB5_KDB_SALTTYPE_NORMAL:
-
- /* If pre auth is required we can set a random salt, otherwise
- * we have to use a more conservative approach and set the salt
- * to be REALMprincipal (the concatenation of REALM and principal
- * name without any separator) */
- if (krbTicketFlags & KTF_REQUIRES_PRE_AUTH) {
- salt.length = KRB5P_SALT_SIZE;
- krberr = krb5_c_random_make_octets(krbctx, &salt);
- if (!krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_random_make_octets failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
- } else {
- krberr = krb5_principal2salt(krbctx, princ, &salt);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_principal2salt failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- goto enc_error;
- }
- }
- break;
-
- case KRB5_KDB_SALTTYPE_V4:
- salt.length = 0;
- break;
-
- case KRB5_KDB_SALTTYPE_AFS3:
-
- p = strchr(krbPrincipalName, '@');
- if (!p) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Invalid principal name, no realm found!\n");
- goto enc_error;
- }
- p++;
- salt.data = strdup(p);
- if (!salt.data) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- goto enc_error;
- }
- salt.length = SALT_TYPE_AFS_LENGTH; /* special value */
- break;
-
- default:
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Invalid salt type [%d]\n", keysalts[i].salt_type);
- goto enc_error;
- }
-
- /* need to build the key now to manage the AFS salt.length special case */
- krberr = krb5_c_string_to_key(krbctx, keysalts[i].enc_type, &pwd, &salt, &key);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_string_to_key failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- krb5_free_data_contents(krbctx, &salt);
- goto enc_error;
- }
- if (salt.length == SALT_TYPE_AFS_LENGTH) {
- salt.length = strlen(salt.data);
- }
-
- krberr = krb5_c_encrypt_length(krbctx, kmkey.enctype, key.length, &len);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_string_to_key failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- goto enc_error;
- }
-
- if ((ptr = (krb5_octet *) malloc(2 + len)) == NULL) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "memory allocation failed\n");
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- goto enc_error;
- }
-
- encode_int16(key.length, ptr);
-
- plain.length = key.length;
- plain.data = key.contents;
-
- cipher.ciphertext.length = len;
- cipher.ciphertext.data = ptr+2;
-
- krberr = krb5_c_encrypt(krbctx, &kmkey, 0, 0, &plain, &cipher);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "krb5_c_encrypt failed [%s]\n",
- krb5_get_error_message(krbctx, krberr));
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- free(ptr);
- goto enc_error;
- }
-
- /* KrbSalt */
- if (salt.length) {
- ret = ber_printf(be, "{t[{t[i]t[o]}]",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), keysalts[i].salt_type,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), salt.data, salt.length);
- } else {
- ret = ber_printf(be, "{t[{t[i]}]",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), keysalts[i].salt_type);
- }
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 KrbSalt failed\n");
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- free(ptr);
- goto enc_error;
- }
-
- /* EncryptionKey */
- ret = ber_printf(be, "t[{t[i]t[o]}]}",
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0), key.enctype,
- (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1), ptr, len+2);
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 EncryptionKey failed\n");
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- free(ptr);
- goto enc_error;
- }
-
- /* make sure we free the memory used now that we are done with it */
- krb5int_c_free_keyblock_contents(krbctx, &key);
- krb5_free_data_contents(krbctx, &salt);
- free(ptr);
- }
-
- ret = ber_printf(be, "}]}");
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "encoding asn1 end of sequences failed\n");
- goto enc_error;
- }
-
- ret = ber_flatten(be, &bval);
- if (ret == -1) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "flattening asn1 failed\n");
- goto enc_error;
- }
-
- svals[0] = slapi_value_new_berval(bval);
- if (!svals[0]) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop",
- "Converting berval to Slapi_Value\n");
- goto enc_error;
- }
-
- krb5_free_principal(krbctx, princ);
- ber_bvfree(bval);
- ber_free(be, 1);
- return svals;
-
-enc_error:
- krb5_free_principal(krbctx, princ);
- if (bval) ber_bvfree(bval);
- if (svals) free(svals);
- if (be) ber_free(be, 1);
- return NULL;
-}
-
-struct ntlm_keys {
- uint8_t lm[16];
- uint8_t nt[16];
-};
-
-#define KTF_LM_HASH 0x01
-#define KTF_NT_HASH 0x02
-#define KTF_DOS_CHARSET "CP850" /* same default as samba */
-#define KTF_UTF8 "UTF-8"
-#define KTF_UCS2 "UCS-2LE"
-
-static const uint8_t parity_table[128] = {
- 1, 2, 4, 7, 8, 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31,
- 32, 35, 37, 38, 41, 42, 44, 47, 49, 50, 52, 55, 56, 59, 61, 62,
- 64, 67, 69, 70, 73, 74, 76, 79, 81, 82, 84, 87, 88, 91, 93, 94,
- 97, 98,100,103,104,107,109,110,112,115,117,118,121,122,124,127,
- 128,131,133,134,137,138,140,143,145,146,148,151,152,155,157,158,
- 161,162,164,167,168,171,173,174,176,179,181,182,185,186,188,191,
- 193,194,196,199,200,203,205,206,208,211,213,214,217,218,220,223,
- 224,227,229,230,233,234,236,239,241,242,244,247,248,251,253,254};
-
-static void lm_shuffle(char *out, char *in)
-{
- uint8_t *outb = (uint8_t *)out;
- uint8_t *inb = (uint8_t *)in;
-
- outb[0] = parity_table[inb[0]>>1];
- outb[1] = parity_table[((inb[0]<<6)|(in[1]>>2)) & 0x7F];
- outb[2] = parity_table[((inb[1]<<5)|(in[2]>>3)) & 0x7F];
- outb[3] = parity_table[((inb[2]<<4)|(in[3]>>4)) & 0x7F];
- outb[4] = parity_table[((inb[3]<<3)|(in[4]>>5)) & 0x7F];
- outb[5] = parity_table[((inb[4]<<2)|(in[5]>>6)) & 0x7F];
- outb[6] = parity_table[((inb[5]<<1)|(in[6]>>7)) & 0x7F];
- outb[7] = parity_table[inb[6] & 0x7F];
-}
-
-/* create the lm and nt hashes
- newPassword: the clear text utf8 password
- flags: KTF_LM_HASH | KTF_NT_HASH
-*/
-static int encode_ntlm_keys(char *newPasswd, unsigned int flags, struct ntlm_keys *keys)
-{
- int ret = 0;
-
- /* do lanman first */
- if (flags & KTF_LM_HASH) {
- iconv_t cd;
- size_t cs, il, ol;
- char *inc, *outc;
- char *upperPasswd;
- char *asciiPasswd;
- DES_key_schedule schedule;
- DES_cblock deskey;
- DES_cblock magic = "KGS!@#$%";
-
- /* TODO: must store the dos charset somewhere in the directory */
- cd = iconv_open(KTF_DOS_CHARSET, KTF_UTF8);
- if (cd == (iconv_t)(-1)) {
- ret = -1;
- goto done;
- }
-
- /* the lanman password is upper case */
- upperPasswd = slapi_utf8StrToUpper(newPasswd);
- if (!upperPasswd) {
- ret = -1;
- goto done;
- }
- il = strlen(upperPasswd);
-
- /* an ascii string can only be smaller than or equal to an utf8 one */
- ol = il;
- if (ol < 14) ol = 14;
- asciiPasswd = calloc(ol+1, 1);
- if (!asciiPasswd) {
- slapi_ch_free_string(&upperPasswd);
- ret = -1;
- goto done;
- }
-
- inc = upperPasswd;
- outc = asciiPasswd;
- cs = iconv(cd, &inc, &il, &outc, &ol);
- if (cs == -1) {
- ret = -1;
- slapi_ch_free_string(&upperPasswd);
- free(asciiPasswd);
- iconv_close(cd);
- goto done;
- }
-
- /* done with these */
- slapi_ch_free_string(&upperPasswd);
- iconv_close(cd);
-
- /* we are interested only in the first 14 ASCII chars for lanman */
- if (strlen(asciiPasswd) > 14) {
- asciiPasswd[14] = '\0';
- }
-
- /* first half */
- lm_shuffle(deskey, asciiPasswd);
-
- DES_set_key_unchecked(&deskey, &schedule);
- DES_ecb_encrypt(&magic, (DES_cblock *)keys->lm, &schedule, DES_ENCRYPT);
-
- /* second half */
- lm_shuffle(deskey, &asciiPasswd[7]);
-
- DES_set_key_unchecked(&deskey, &schedule);
- DES_ecb_encrypt(&magic, (DES_cblock *)&(keys->lm[8]), &schedule, DES_ENCRYPT);
-
- /* done with it */
- free(asciiPasswd);
-
- } else {
- memset(keys->lm, 0, 16);
- }
-
- if (flags & KTF_NT_HASH) {
- iconv_t cd;
- size_t cs, il, ol, sl;
- char *inc, *outc;
- char *ucs2Passwd;
- MHASH td;
-
- /* TODO: must store the dos charset somewhere in the directory */
- cd = iconv_open(KTF_UCS2, KTF_UTF8);
- if (cd == (iconv_t)(-1)) {
- ret = -1;
- goto done;
- }
-
- il = strlen(newPasswd);
-
- /* an ucs2 string can be at most double than an utf8 one */
- sl = ol = (il+1)*2;
- ucs2Passwd = calloc(ol, 1);
- if (!ucs2Passwd) {
- ret = -1;
- goto done;
- }
-
- inc = newPasswd;
- outc = ucs2Passwd;
- cs = iconv(cd, &inc, &il, &outc, &ol);
- if (cs == -1) {
- ret = -1;
- free(ucs2Passwd);
- iconv_close(cd);
- goto done;
- }
-
- /* done with it */
- iconv_close(cd);
-
- /* get the final ucs2 string length */
- sl -= ol;
- /* we are interested only in the first 14 wchars for the nt password */
- if (sl > 28) {
- sl = 28;
- }
-
- td = mhash_init(MHASH_MD4);
- if (td == MHASH_FAILED) {
- ret = -1;
- free(ucs2Passwd);
- goto done;
- }
-
- mhash(td, ucs2Passwd, sl);
- mhash_deinit(td, keys->nt);
-
- } else {
- memset(keys->nt, 0, 16);
- }
-
-done:
- return ret;
-}
-
-/* Searches the dn in directory,
- * If found : fills in slapi_entry structure and returns 0
- * If NOT found : returns the search result as LDAP_NO_SUCH_OBJECT
- */
-static int
-ipapwd_getEntry( const char *dn, Slapi_Entry **e2 ) {
- int search_result = 0;
- Slapi_DN *sdn;
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_getEntry\n");
-
- sdn = slapi_sdn_new_dn_byref(dn);
- if ((search_result = slapi_search_internal_get_entry( sdn, NULL, e2,
- ipapwd_plugin_id)) != LDAP_SUCCESS ){
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "ipapwd_getEntry: No such entry-(%s), err (%d)\n",
- dn, search_result);
- }
-
- slapi_sdn_free( &sdn );
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "<= ipapwd_getEntry: %d\n", search_result);
- return search_result;
-}
-
-
-/* Construct Mods pblock and perform the modify operation
- * Sets result of operation in SLAPI_PLUGIN_INTOP_RESULT
- */
-static int ipapwd_apply_mods(const char *dn, Slapi_Mods *mods)
-{
- Slapi_PBlock *pb;
- int ret=0;
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_apply_mods\n");
-
- if (mods && (slapi_mods_get_num_mods(mods) > 0))
- {
- pb = slapi_pblock_new();
- slapi_modify_internal_set_pb (pb, dn,
- slapi_mods_get_ldapmods_byref(mods),
- NULL, /* Controls */
- NULL, /* UniqueID */
- ipapwd_plugin_id, /* PluginID */
- 0); /* Flags */
-
- ret = slapi_modify_internal_pb (pb);
-
- slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
-
- if (ret != LDAP_SUCCESS){
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "WARNING: modify error %d on entry '%s'\n",
- ret, dn);
- }
-
- slapi_pblock_destroy(pb);
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "<= ipapwd_apply_mods: %d\n", ret);
-
- return ret;
-}
-
-/* ascii hex output of bytes in "in"
- * out len is 32 (preallocated)
- * in len is 16 */
-static const char hexchars[] = "0123456789ABCDEF";
-static void hexbuf(char *out, const uint8_t *in)
-{
- int i;
-
- for (i = 0; i < 16; i++) {
- out[i*2] = hexchars[in[i] >> 4];
- out[i*2+1] = hexchars[in[i] & 0x0f];
- }
-}
-
-/* Modify the userPassword attribute field of the entry */
-static int ipapwd_userpassword(Slapi_Entry *targetEntry, const char *newPasswd)
-{
- char *dn = NULL;
- int ret = 0, i = 0;
- Slapi_Mods *smods;
- Slapi_Mod *keymod;
- Slapi_Value **svals;
- time_t curtime;
- struct tm utctime;
- char timestr[16];
- krb5_context krbctx;
- krb5_error_code krberr;
- char lm[33], nt[33];
- struct ntlm_keys ntlm;
- int ntlm_flags = 0;
- Slapi_Value *sambaSamAccount;
-
- krberr = krb5_init_context(&krbctx);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "krb5_init_context failed\n");
- return LDAP_OPERATIONS_ERROR;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipapwd_userpassword\n");
-
- smods = slapi_mods_new();
- dn = slapi_entry_get_ndn( targetEntry );
-
- /* generate kerberos keys to be put into krbPrincipalKey */
- svals = encrypt_encode_key(krbctx, targetEntry, newPasswd);
- if (!svals) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "key encryption/encoding failed\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
- /* done with it */
- krb5_free_context(krbctx);
-
- slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE, "krbPrincipalKey", svals);
-
- /* change Last Password Change field with the current date */
- curtime = time(NULL);
- if (!gmtime_r(&curtime, &utctime)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "failed to retrieve current date (buggy gmtime_r ?)\n");
- return LDAP_OPERATIONS_ERROR;
- }
- if (utctime.tm_year > 8099 || utctime.tm_mon > 11 || utctime.tm_mday > 31 ||
- utctime.tm_hour > 23 || utctime.tm_min > 59 || utctime.tm_sec > 59) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "retrieved a bad date (buggy gmtime_r ?)\n");
- return LDAP_OPERATIONS_ERROR;
- }
-
- snprintf(timestr, 16, "%04d%02d%02d%02d%02d%02dZ", utctime.tm_year+1900, utctime.tm_mon+1,
- utctime.tm_mday, utctime.tm_hour, utctime.tm_min, utctime.tm_sec);
-
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "krbLastPwdChange", timestr);
- /* TODO: krbPasswordExpiration, (krbMaxTicketLife, krbMaxRenewableAge, krbTicketFlags ?) */
-
- sambaSamAccount = slapi_value_new_string("sambaSamAccount");
- if (slapi_entry_attr_has_syntax_value(targetEntry, "objectClass", sambaSamAccount)) {
- /* TODO: retrieve if we want to store the LM hash or not */
- ntlm_flags = KTF_LM_HASH | KTF_NT_HASH;
- }
- slapi_value_free(&sambaSamAccount);
-
- if (ntlm_flags) {
- if (encode_ntlm_keys((char *)newPasswd, ntlm_flags, &ntlm) != 0) {
- return LDAP_OPERATIONS_ERROR;
- }
- if (ntlm_flags & KTF_LM_HASH) {
- hexbuf(lm, ntlm.lm);
- lm[32] = '\0';
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "sambaLMPassword", lm);
- }
- if (ntlm_flags & KTF_NT_HASH) {
- hexbuf(nt, ntlm.nt);
- nt[32] = '\0';
- slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "sambaNTPassword", nt);
- }
- }
-
- /* commit changes */
- ret = ipapwd_apply_mods(dn, smods);
-
- slapi_mods_free(&smods);
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "<= ipapwd_userpassword: %d\n", ret);
-
-
-mod_done:
- for (i = 0; svals[i]; i++) {
- slapi_value_free(&svals[i]);
- }
- free(svals);
- return ret;
-}
-
-/* Generate a new, basic random password */
-static int ipapwd_generate_basic_passwd( int passlen, char **genpasswd )
-{
- unsigned char *data = NULL;
- char *enc = NULL;
- int datalen = LDAP_EXTOP_PASSMOD_RANDOM_BYTES;
- int enclen = LDAP_EXTOP_PASSMOD_GEN_PASSWD_LEN + 1;
-
- if ( genpasswd == NULL ) {
- return LDAP_OPERATIONS_ERROR;
- }
-
- if ( passlen > 0 ) {
- datalen = passlen * 3 / 4 + 1;
- enclen = datalen * 4; /* allocate the large enough space */
- }
-
- data = (unsigned char *)slapi_ch_calloc( datalen, 1 );
- enc = (char *)slapi_ch_calloc( enclen, 1 );
-
- /* get random bytes from NSS */
- PK11_GenerateRandom( data, datalen );
-
- /* b64 encode the random bytes to get a password made up
- * of printable characters. ldif_base64_encode() will
- * zero-terminate the string */
- (void)ldif_base64_encode( data, enc, passlen, -1 );
-
- /* This will get freed by the caller */
- *genpasswd = slapi_ch_malloc( 1 + passlen );
-
- /* trim the password to the proper length */
- PL_strncpyz( *genpasswd, enc, passlen + 1 );
-
- slapi_ch_free( (void **)&data );
- slapi_ch_free_string( &enc );
-
- return LDAP_SUCCESS;
-}
-
-
-/* Password Modify Extended operation plugin function */
-int
-ipapwd_extop( Slapi_PBlock *pb )
-{
- char *oid = NULL;
- char *bindDN = NULL;
- char *authmethod = NULL;
- char *dn = NULL;
- char *oldPasswd = NULL;
- char *newPasswd = NULL;
- char *errMesg = NULL;
- int ret=0, rc=0, sasl_ssf=0, is_ssl=0, is_root=0;
- ber_tag_t tag=0;
- ber_len_t len=-1;
- struct berval *extop_value = NULL;
- BerElement *ber = NULL;
- BerElement *response_ber = NULL;
- Slapi_Entry *targetEntry=NULL;
- /* Slapi_DN sdn; */
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "=> ipa_pwd_extop\n");
-
- /* Before going any further, we'll make sure that the right extended operation plugin
- * has been called: i.e., the OID shipped whithin the extended operation request must
- * match this very plugin's OID: EXOP_PASSWD_OID. */
- if ( slapi_pblock_get( pb, SLAPI_EXT_OP_REQ_OID, &oid ) != 0 ) {
- errMesg = "Could not get OID value from request.\n";
- rc = LDAP_OPERATIONS_ERROR;
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- errMesg );
- goto free_and_return;
- } else {
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "Received extended operation request with OID %s\n", oid );
- }
-
- if ( strcasecmp( oid, EXOP_PASSWD_OID ) != 0) {
- errMesg = "Request OID does not match Passwd OID.\n";
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- } else {
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- "Password Modify extended operation request confirmed.\n" );
- }
-
- /* Now , at least we know that the request was indeed a Password Modify one. */
-
-#ifdef LDAP_EXTOP_PASSMOD_CONN_SECURE
- /* Allow password modify only for SSL/TLS established connections and
- * connections using SASL privacy layers */
- if ( slapi_pblock_get(pb, SLAPI_CONN_SASL_SSF, &sasl_ssf) != 0) {
- errMesg = "Could not get SASL SSF from connection\n";
- rc = LDAP_OPERATIONS_ERROR;
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- errMesg );
- goto free_and_return;
- }
-
- if (slapi_pblock_get(pb, SLAPI_CONN_IS_SSL_SESSION, &is_ssl) != 0) {
- errMesg = "Could not get IS SSL from connection\n";
- rc = LDAP_OPERATIONS_ERROR;
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- errMesg );
- goto free_and_return;
- }
-
- if ( (is_ssl <=1) && (sasl_ssf <= 1) ) {
- errMesg = "Operation requires a secure connection.\n";
- rc = LDAP_CONFIDENTIALITY_REQUIRED;
- goto free_and_return;
- }
-#endif
-
- /* Get the ber value of the extended operation */
- slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
-
- if ((ber = ber_init(extop_value)) == NULL)
- {
- errMesg = "PasswdModify Request decode failed.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- /* Format of request to parse
- *
- * PasswdModifyRequestValue ::= SEQUENCE {
- * userIdentity [0] OCTET STRING OPTIONAL
- * oldPasswd [1] OCTET STRING OPTIONAL
- * newPasswd [2] OCTET STRING OPTIONAL }
- *
- * The request value field is optional. If it is
- * provided, at least one field must be filled in.
- */
-
- /* ber parse code */
- if ( ber_scanf( ber, "{") == LBER_ERROR )
- {
- /* The request field wasn't provided. We'll
- * now try to determine the userid and verify
- * knowledge of the old password via other
- * means.
- */
- goto parse_req_done;
- } else {
- tag = ber_peek_tag( ber, &len);
- }
-
-
- /* identify userID field by tags */
- if (tag == LDAP_EXTOP_PASSMOD_TAG_USERID )
- {
- if ( ber_scanf( ber, "a", &dn) == LBER_ERROR )
- {
- slapi_ch_free_string(&dn);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "ber_scanf failed :{\n");
- errMesg = "ber_scanf failed at userID parse.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
-
- tag = ber_peek_tag( ber, &len);
- }
-
-
- /* identify oldPasswd field by tags */
- if (tag == LDAP_EXTOP_PASSMOD_TAG_OLDPWD )
- {
- if ( ber_scanf( ber, "a", &oldPasswd ) == LBER_ERROR )
- {
- slapi_ch_free_string(&oldPasswd);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "ber_scanf failed :{\n");
- errMesg = "ber_scanf failed at oldPasswd parse.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
- tag = ber_peek_tag( ber, &len);
- }
-
- /* identify newPasswd field by tags */
- if (tag == LDAP_EXTOP_PASSMOD_TAG_NEWPWD )
- {
- if ( ber_scanf( ber, "a", &newPasswd ) == LBER_ERROR )
- {
- slapi_ch_free_string(&newPasswd);
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "ber_scanf failed :{\n");
- errMesg = "ber_scanf failed at newPasswd parse.\n";
- rc = LDAP_PROTOCOL_ERROR;
- goto free_and_return;
- }
- }
-
-parse_req_done:
- /* Uncomment for debugging, otherwise we don't want to leak the password values into the log... */
- /* LDAPDebug( LDAP_DEBUG_ARGS, "passwd: dn (%s), oldPasswd (%s) ,newPasswd (%s)\n",
- dn, oldPasswd, newPasswd); */
-
-
- /* 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;
- }
-
- /* A new password was not supplied in the request, and we do not support
- * password generation yet.
- */
- if (newPasswd == NULL || *newPasswd == '\0') {
- errMesg = "Password generation not implemented.\n";
- rc = LDAP_UNWILLING_TO_PERFORM;
- goto free_and_return;
- }
-
- if (oldPasswd == NULL || *oldPasswd == '\0') {
- /* If user is authenticated, they already gave their password during
- the bind operation (or used sasl or client cert auth or OS creds) */
- slapi_pblock_get(pb, SLAPI_CONN_AUTHMETHOD, &authmethod);
- if (!authmethod || !strcmp(authmethod, SLAPD_AUTH_NONE)) {
- errMesg = "User must be authenticated to the directory server.\n";
- rc = LDAP_INSUFFICIENT_ACCESS;
- goto free_and_return;
- }
- }
-
- /* Determine the target DN for this operation */
- /* Did they give us a DN ? */
- if (dn == NULL || *dn == '\0') {
- /* Get the DN from the bind identity on this connection */
- dn = slapi_ch_strdup(bindDN);
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop",
- "Missing userIdentity in request, using the bind DN instead.\n");
- }
-
- slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, dn );
-
- /* Now we have the DN, look for the entry */
- ret = ipapwd_getEntry(dn, &targetEntry);
- /* If we can't find the entry, then that's an error */
- if (ret) {
- /* Couldn't find the entry, fail */
- errMesg = "No such Entry exists.\n" ;
- rc = LDAP_NO_SUCH_OBJECT ;
- 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).
- */
- {
- Slapi_Backend *be = NULL;
-
- be = slapi_be_select(slapi_entry_get_sdn(targetEntry));
- if (NULL == be) {
- errMesg = "Failed to find backend for target entry";
- rc = LDAP_OPERATIONS_ERROR;
- goto free_and_return;
- }
- slapi_pblock_set(pb, SLAPI_BACKEND, be);
- }
-
- ret = slapi_access_allowed ( pb, targetEntry, SLAPI_USERPWD_ATTR, NULL, SLAPI_ACL_WRITE );
- if ( ret != LDAP_SUCCESS ) {
- errMesg = "Insufficient access rights\n";
- rc = LDAP_INSUFFICIENT_ACCESS;
- goto free_and_return;
- }
-
- /* Now we have the entry which we want to modify
- * They gave us a password (old), check it against the target entry
- * Is the old password valid ?
- */
- if (oldPasswd && *oldPasswd) {
- /* If user is authenticated, they already gave their password during
- the bind operation (or used sasl or client cert auth or OS creds) */
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "oldPasswd provided, but we will ignore it");
- }
-
-
- /* Now we're ready to make actual password change */
- ret = ipapwd_userpassword(targetEntry, newPasswd);
- if (ret != LDAP_SUCCESS) {
- /* Failed to modify the password, e.g. because insufficient access allowed */
- errMesg = "Failed to update password\n";
- rc = ret;
- goto free_and_return;
- }
-
- slapi_log_error(SLAPI_LOG_TRACE, "ipa_pwd_extop", "<= ipa_pwd_extop: %d\n", rc);
-
- /* Free anything that we allocated above */
- free_and_return:
- slapi_ch_free_string(&oldPasswd);
- slapi_ch_free_string(&newPasswd);
- /* Either this is the same pointer that we allocated and set above,
- * or whoever used it should have freed it and allocated a new
- * value that we need to free here */
- slapi_pblock_get( pb, SLAPI_ORIGINAL_TARGET, &dn );
- slapi_ch_free_string(&dn);
- slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, NULL );
- slapi_ch_free_string(&authmethod);
-
- if ( targetEntry != NULL ){
- slapi_entry_free (targetEntry);
- }
-
- if ( ber != NULL ){
- ber_free(ber, 1);
- ber = NULL;
- }
-
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipa_pwd_extop",
- errMesg ? errMesg : "success" );
- send_ldap_result( pb, rc, NULL, errMesg, 0, NULL );
-
-
- return( SLAPI_PLUGIN_EXTENDED_SENT_RESULT );
-
-}/* ipa_pwd_extop */
-
-
-static char *ipapwd_oid_list[] = {
- EXOP_PASSWD_OID,
- NULL
-};
-
-
-static char *ipapwd_name_list[] = {
- "ipa_pwd_extop",
- NULL
-};
-
-/* will read this from the krbSupportedEncSaltTypes in the krbRealmContainer later on */
-const char *krb_sup_encs[] = {
- "des3-hmac-sha1:normal",
- "arcfour-hmac:normal",
- "des-hmac-sha1:normal",
- "des-cbc-md5:normal",
- "des-cbc-crc:normal",
- "des-cbc-crc:v4",
- "des-cbc-crc:afs3",
- NULL
-};
-
-#define KRBCHECK(ctx, err, fname) do { \
- if (err) { \
- slapi_log_error(SLAPI_LOG_PLUGIN, "ipapwd_start", \
- "%s failed [%s]\n", fname, \
- krb5_get_error_message(ctx, err)); \
- return LDAP_OPERATIONS_ERROR; \
- } } while(0)
-
-/* Init data structs */
-/* TODO: read input from tree */
-int ipapwd_start( Slapi_PBlock *pb )
-{
- int krberr, i;
- krb5_context krbctx;
- krb5_data pwd, salt;
- krb5_enctype etype;
- char *config_dn;
- Slapi_Entry *config_entry;
- const char *stash_file;
- int fd;
- ssize_t r;
- uint16_t e;
- unsigned int l;
- char *o;
-
- krberr = krb5_init_context(&krbctx);
- if (krberr) {
- slapi_log_error(SLAPI_LOG_FATAL, "ipa_pwd_extop", "krb5_init_context failed\n");
- return LDAP_OPERATIONS_ERROR;
- }
-
- for (i = 0; krb_sup_encs[i]; i++) /* count */ ;
- keysalts = (struct krb5p_keysalt *)malloc(sizeof(struct krb5p_keysalt) * (i + 1));
- if (!keysalts) {
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- for (i = 0, n_keysalts = 0; krb_sup_encs[i]; i++) {
- char *enc, *salt;
- krb5_int32 tmpenc;
- krb5_int32 tmpsalt;
- krb5_boolean similar;
- int j;
-
- enc = strdup(krb_sup_encs[i]);
- if (!enc) {
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipapwd_start", "Allocation error\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
- salt = strchr(enc, ':');
- if (!salt) {
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipapwd_start", "Invalid krb5 enc string\n");
- free(enc);
- continue;
- }
- *salt = '\0'; /* null terminate the enc type */
- salt++; /* skip : */
-
- krberr = krb5_string_to_enctype(enc, &tmpenc);
- if (krberr) {
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipapwd_start", "Invalid krb5 enctype\n");
- free(enc);
- continue;
- }
-
- krberr = krb5_string_to_salttype(salt, &tmpsalt);
- for (j = 0; j < n_keysalts; j++) {
- krb5_c_enctype_compare(krbctx, keysalts[j].enc_type, tmpenc, &similar);
- if (similar && (keysalts[j].salt_type == tmpsalt)) {
- break;
- }
- }
-
- if (j == n_keysalts) {
- /* not found */
- keysalts[j].enc_type = tmpenc;
- keysalts[j].salt_type = tmpsalt;
- n_keysalts++;
- }
-
- free(enc);
- }
-
- /*retrieve the master key from the stash file */
- if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &config_dn) != 0) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "No config DN?\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- if (ipapwd_getEntry(config_dn, &config_entry) != LDAP_SUCCESS) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "No config Entry?\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- stash_file = slapi_entry_attr_get_charptr(config_entry, "nsslapd-pluginarg0");
- if (!stash_file) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Missing Master key stash file path configuration entry (nsslapd-pluginarg0)!\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- fd = open(stash_file, O_RDONLY);
- if (fd == -1) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Missing Master key stash file!\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- r = read(fd, &e, 2); /* read enctype a local endian 16bit value */
- if (r != 2) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Error reading Master key stash file!\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- r = read(fd, &l, sizeof(l)); /* read the key length, a horrible sizeof(int) local endian value */
- if (r != sizeof(l)) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Error reading Master key stash file!\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- if (l == 0 || l > 1024) { /* the maximum key size should be 32 bytes, lets's not accept more than 1k anyway */
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Invalid key lenght, Master key stash file corrupted?\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- o = malloc(l);
- if (!o) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Memory allocation problem!\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- r = read(fd, o, l);
- if (r != l) {
- slapi_log_error( SLAPI_LOG_FATAL, "ipapwd_start", "Error reading Master key stash file!\n");
- krb5_free_context(krbctx);
- return LDAP_OPERATIONS_ERROR;
- }
-
- close(fd);
-
- kmkey.magic = KV5M_KEYBLOCK;
- kmkey.enctype = e;
- kmkey.length = l;
- kmkey.contents = o;
-
- krb5_free_context(krbctx);
- return LDAP_SUCCESS;
-}
-
-/* Initialization function */
-int ipapwd_init( Slapi_PBlock *pb )
-{
- char **argv;
- char *oid;
-
- /* Get the arguments appended to the plugin extendedop directive. The first argument
- * (after the standard arguments for the directive) should contain the OID of the
- * extended operation.
- */
-
- if ((slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &ipapwd_plugin_id) != 0)
- || (ipapwd_plugin_id == NULL)) {
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipapwd_init", "Could not get identity or identity was NULL\n");
- return( -1 );
- }
-
- /* Register the plug-in function as an extended operation
- * plug-in function that handles the operation identified by
- * OID 1.3.6.1.4.1.4203.1.11.1 . Also specify the version of the server
- * plug-in */
- if ( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) ipapwd_start ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_FN, (void *) ipapwd_extop ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_OIDLIST, ipapwd_oid_list ) != 0 ||
- slapi_pblock_set( pb, SLAPI_PLUGIN_EXT_OP_NAMELIST, ipapwd_name_list ) != 0 ) {
-
- slapi_log_error( SLAPI_LOG_PLUGIN, "ipapwd_init",
- "Failed to set plug-in version, function, and OID.\n" );
- return( -1 );
- }
-
- return( 0 );
-}
diff --git a/ipa-slapi-plugins/ipa-pwd-extop/plugin-conf.ldif b/ipa-slapi-plugins/ipa-pwd-extop/plugin-conf.ldif
deleted file mode 100644
index 738ef7ab5..000000000
--- a/ipa-slapi-plugins/ipa-pwd-extop/plugin-conf.ldif
+++ /dev/null
@@ -1,14 +0,0 @@
-dn: cn=ipa_pwd_extop,cn=plugins,cn=config
-objectclass: top
-objectclass: nsSlapdPlugin
-objectclass: extensibleObject
-cn: ipa_pwd_extop
-nsslapd-pluginpath: /usr/lib/fedora-ds/plugins/libipa_pwd_extop.so
-nsslapd-plugininitfunc: ipapwd_init
-nsslapd-plugintype: extendedop
-nsslapd-pluginenabled: on
-nsslapd-pluginid: Multi-hash Change Password Extended Operation
-nsslapd-pluginversion: 1.0
-nsslapd-pluginvendor: RedHat
-nsslapd-plugindescription: Support saving passwords in multiple fornmats for different consumers like krb5, samba, freeradius, etc.
-nsslapd-pluginarg0: /var/kerberos/krb5kdc/.k5.$REALM