Imported Upstream version 4.8.10
This commit is contained in:
@@ -1,51 +1,48 @@
|
||||
NULL =
|
||||
|
||||
MAINTAINERCLEANFILES = *~ Makefile.in
|
||||
PLUGIN_COMMON_DIR = ../common
|
||||
KRB5_UTIL_DIR = ../../../util
|
||||
KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
|
||||
$(KRB5_UTIL_DIR)/ipa_pwd.c \
|
||||
$(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
|
||||
PLUGIN_COMMON_DIR = $(srcdir)/../common
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I. \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../libotp \
|
||||
-I$(PLUGIN_COMMON_DIR) \
|
||||
-I$(KRB5_UTIL_DIR) \
|
||||
-I$(COMMON_BER_DIR) \
|
||||
-I$(top_srcdir)/util \
|
||||
-I$(top_srcdir)/asn1 \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DBINDIR=\""$(bindir)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DLIBEXECDIR=\""$(libexecdir)"\" \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
$(LDAP_CFLAGS) \
|
||||
$(DIRSRV_CFLAGS) \
|
||||
$(CRYPTO_CFLAGS) \
|
||||
$(LDAP_CFLAGS) \
|
||||
$(KRB5_CFLAGS) \
|
||||
$(SSL_CFLAGS) \
|
||||
$(NSS_CFLAGS) \
|
||||
$(NSPR_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDFLAGS = \
|
||||
$(CRYPTO_LIBS) \
|
||||
$(KRB5_LIBS) \
|
||||
$(SSL_LIBS) \
|
||||
$(LDAP_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NSS_LIBS) \
|
||||
-avoid-version \
|
||||
-export-symbols-regex ^ipapwd_init$
|
||||
|
||||
# Plugin Binary
|
||||
plugindir = $(libdir)/dirsrv/plugins
|
||||
plugin_LTLIBRARIES = libipa_pwd_extop.la
|
||||
libipa_pwd_extop_la_LIBADD = $(builddir)/../libotp/libotp.la
|
||||
libipa_pwd_extop_la_LIBADD = \
|
||||
$(builddir)/../libotp/libotp.la \
|
||||
$(top_builddir)/asn1/libipaasn1.la \
|
||||
$(top_builddir)/util/libutil.la \
|
||||
$(NULL)
|
||||
libipa_pwd_extop_la_SOURCES = \
|
||||
authcfg.c \
|
||||
common.c \
|
||||
encoding.c \
|
||||
prepost.c \
|
||||
ipa_pwd_extop.c \
|
||||
syncreq.c \
|
||||
ipapwd.h \
|
||||
otpctrl.c \
|
||||
otpctrl.h \
|
||||
$(KRB5_UTIL_SRCS) \
|
||||
$(NULL)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Makefile.in generated by automake 1.14.1 from Makefile.am.
|
||||
# Makefile.in generated by automake 1.16.2 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994-2020 Free Software Foundation, Inc.
|
||||
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
@@ -16,7 +16,17 @@
|
||||
|
||||
|
||||
VPATH = @srcdir@
|
||||
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
|
||||
am__is_gnu_make = { \
|
||||
if test -z '$(MAKELEVEL)'; then \
|
||||
false; \
|
||||
elif test -n '$(MAKE_HOST)'; then \
|
||||
true; \
|
||||
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
|
||||
true; \
|
||||
else \
|
||||
false; \
|
||||
fi; \
|
||||
}
|
||||
am__make_running_with_option = \
|
||||
case $${target_option-} in \
|
||||
?) ;; \
|
||||
@@ -79,14 +89,20 @@ PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
subdir = ipa-slapi-plugins/ipa-pwd-extop
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
$(top_srcdir)/depcomp README
|
||||
subdir = daemons/ipa-slapi-plugins/ipa-pwd-extop
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/../version.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__aclocal_m4_deps = $(top_srcdir)/m4/gettext.m4 \
|
||||
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
|
||||
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
|
||||
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
|
||||
$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
|
||||
$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
|
||||
$(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
|
||||
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/VERSION.m4 \
|
||||
$(top_srcdir)/server.m4 $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
@@ -120,12 +136,13 @@ am__uninstall_files_from_dir = { \
|
||||
}
|
||||
am__installdirs = "$(DESTDIR)$(plugindir)" "$(DESTDIR)$(appdir)"
|
||||
LTLIBRARIES = $(plugin_LTLIBRARIES)
|
||||
libipa_pwd_extop_la_DEPENDENCIES = $(builddir)/../libotp/libotp.la
|
||||
am__objects_1 = ipa_krb5.lo ipa_pwd.lo ipa_pwd_ntlm.lo
|
||||
am__objects_2 =
|
||||
am_libipa_pwd_extop_la_OBJECTS = authcfg.lo common.lo encoding.lo \
|
||||
prepost.lo ipa_pwd_extop.lo syncreq.lo $(am__objects_1) \
|
||||
$(am__objects_2)
|
||||
am__DEPENDENCIES_1 =
|
||||
libipa_pwd_extop_la_DEPENDENCIES = $(builddir)/../libotp/libotp.la \
|
||||
$(top_builddir)/asn1/libipaasn1.la \
|
||||
$(top_builddir)/util/libutil.la $(am__DEPENDENCIES_1)
|
||||
am__objects_1 =
|
||||
am_libipa_pwd_extop_la_OBJECTS = common.lo encoding.lo prepost.lo \
|
||||
ipa_pwd_extop.lo otpctrl.lo $(am__objects_1)
|
||||
libipa_pwd_extop_la_OBJECTS = $(am_libipa_pwd_extop_la_OBJECTS)
|
||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||
@@ -145,7 +162,10 @@ am__v_at_0 = @
|
||||
am__v_at_1 =
|
||||
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
am__maybe_remake_depfiles = depfiles
|
||||
am__depfiles_remade = ./$(DEPDIR)/common.Plo ./$(DEPDIR)/encoding.Plo \
|
||||
./$(DEPDIR)/ipa_pwd_extop.Plo ./$(DEPDIR)/otpctrl.Plo \
|
||||
./$(DEPDIR)/prepost.Plo
|
||||
am__mv = mv -f
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
@@ -192,10 +212,12 @@ am__define_uniq_tagged_files = \
|
||||
done | $(am__uniquify_input)`
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp README
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
|
||||
API_VERSION = @API_VERSION@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
@@ -204,13 +226,15 @@ AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CHECK_CFLAGS = @CHECK_CFLAGS@
|
||||
CHECK_LIBS = @CHECK_LIBS@
|
||||
CMOCKA_CFLAGS = @CMOCKA_CFLAGS@
|
||||
CMOCKA_LIBS = @CMOCKA_LIBS@
|
||||
CONFIG_STATUS = @CONFIG_STATUS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CRYPTO_CFLAGS = @CRYPTO_CFLAGS@
|
||||
CRYPTO_LIBS = @CRYPTO_LIBS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DATA_VERSION = @DATA_VERSION@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DIRSRV_CFLAGS = @DIRSRV_CFLAGS@
|
||||
@@ -224,31 +248,63 @@ ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
FGREP = @FGREP@
|
||||
GETTEXT_DOMAIN = @GETTEXT_DOMAIN@
|
||||
GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
|
||||
GIT_BRANCH = @GIT_BRANCH@
|
||||
GIT_VERSION = @GIT_VERSION@
|
||||
GMSGFMT = @GMSGFMT@
|
||||
GMSGFMT_015 = @GMSGFMT_015@
|
||||
GREP = @GREP@
|
||||
INI_CFLAGS = @INI_CFLAGS@
|
||||
INI_LIBS = @INI_LIBS@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
INTLLIBS = @INTLLIBS@
|
||||
INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
|
||||
IPAPLATFORM = @IPAPLATFORM@
|
||||
IPA_DATA_DIR = @IPA_DATA_DIR@
|
||||
IPA_SYSCONF_DIR = @IPA_SYSCONF_DIR@
|
||||
JSLINT = @JSLINT@
|
||||
KRAD_LIBS = @KRAD_LIBS@
|
||||
KRB5KDC_SERVICE = @KRB5KDC_SERVICE@
|
||||
KRB5_CFLAGS = @KRB5_CFLAGS@
|
||||
KRB5_GSSAPI_CFLAGS = @KRB5_GSSAPI_CFLAGS@
|
||||
KRB5_GSSAPI_LIBS = @KRB5_GSSAPI_LIBS@
|
||||
KRB5_LIBS = @KRB5_LIBS@
|
||||
LD = @LD@
|
||||
LDAP_CFLAGS = @LDAP_CFLAGS@
|
||||
LDAP_LIBS = @LDAP_LIBS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBICONV = @LIBICONV@
|
||||
LIBINTL = @LIBINTL@
|
||||
LIBINTL_LIBS = @LIBINTL_LIBS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBPDB_NAME = @LIBPDB_NAME@
|
||||
LIBS = @LIBS@
|
||||
LIBTOOL = @LIBTOOL@
|
||||
LIBVERTO_CFLAGS = @LIBVERTO_CFLAGS@
|
||||
LIBVERTO_LIBS = @LIBVERTO_LIBS@
|
||||
LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBICONV = @LTLIBICONV@
|
||||
LTLIBINTL = @LTLIBINTL@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MK_ASSIGN = @MK_ASSIGN@
|
||||
MK_ELSE = @MK_ELSE@
|
||||
MK_ENDIF = @MK_ENDIF@
|
||||
MK_IFEQ = @MK_IFEQ@
|
||||
MSGATTRIB = @MSGATTRIB@
|
||||
MSGFMT = @MSGFMT@
|
||||
MSGFMT_015 = @MSGFMT_015@
|
||||
MSGMERGE = @MSGMERGE@
|
||||
NAMED_GROUP = @NAMED_GROUP@
|
||||
NDRNBT_CFLAGS = @NDRNBT_CFLAGS@
|
||||
NDRNBT_LIBS = @NDRNBT_LIBS@
|
||||
NDRPAC_CFLAGS = @NDRPAC_CFLAGS@
|
||||
@@ -259,12 +315,11 @@ NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
NSPR_CFLAGS = @NSPR_CFLAGS@
|
||||
NSPR_LIBS = @NSPR_LIBS@
|
||||
NSS_CFLAGS = @NSS_CFLAGS@
|
||||
NSS_LIBS = @NSS_LIBS@
|
||||
NUM_VERSION = @NUM_VERSION@
|
||||
OBJDUMP = @OBJDUMP@
|
||||
OBJEXT = @OBJEXT@
|
||||
OPENLDAP_CFLAGS = @OPENLDAP_CFLAGS@
|
||||
OPENLDAP_LIBS = @OPENLDAP_LIBS@
|
||||
ODS_GROUP = @ODS_GROUP@
|
||||
ODS_USER = @ODS_USER@
|
||||
OTOOL = @OTOOL@
|
||||
OTOOL64 = @OTOOL64@
|
||||
PACKAGE = @PACKAGE@
|
||||
@@ -278,8 +333,14 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
PLATFORM_PYTHON = @PLATFORM_PYTHON@
|
||||
POPT_CFLAGS = @POPT_CFLAGS@
|
||||
POPT_LIBS = @POPT_LIBS@
|
||||
POSUB = @POSUB@
|
||||
PYLINT = @PYLINT@
|
||||
PYTHON = @PYTHON@
|
||||
PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
|
||||
PYTHON_INSTALL_EXTRA_OPTIONS = @PYTHON_INSTALL_EXTRA_OPTIONS@
|
||||
PYTHON_PLATFORM = @PYTHON_PLATFORM@
|
||||
PYTHON_PREFIX = @PYTHON_PREFIX@
|
||||
PYTHON_VERSION = @PYTHON_VERSION@
|
||||
@@ -287,10 +348,13 @@ RANLIB = @RANLIB@
|
||||
SAMBA40EXTRA_LIBPATH = @SAMBA40EXTRA_LIBPATH@
|
||||
SAMBAUTIL_CFLAGS = @SAMBAUTIL_CFLAGS@
|
||||
SAMBAUTIL_LIBS = @SAMBAUTIL_LIBS@
|
||||
SASL_CFLAGS = @SASL_CFLAGS@
|
||||
SASL_LIBS = @SASL_LIBS@
|
||||
SED = @SED@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
SSSCERTMAP_CFLAGS = @SSSCERTMAP_CFLAGS@
|
||||
SSSCERTMAP_LIBS = @SSSCERTMAP_LIBS@
|
||||
SSSIDMAP_CFLAGS = @SSSIDMAP_CFLAGS@
|
||||
SSSIDMAP_LIBS = @SSSIDMAP_LIBS@
|
||||
SSSNSSIDMAP_CFLAGS = @SSSNSSIDMAP_CFLAGS@
|
||||
@@ -302,8 +366,16 @@ TEVENT_CFLAGS = @TEVENT_CFLAGS@
|
||||
TEVENT_LIBS = @TEVENT_LIBS@
|
||||
UNISTRING_LIBS = @UNISTRING_LIBS@
|
||||
UNLINK = @UNLINK@
|
||||
USE_NLS = @USE_NLS@
|
||||
UUID_CFLAGS = @UUID_CFLAGS@
|
||||
UUID_LIBS = @UUID_LIBS@
|
||||
VENDOR_SUFFIX = @VENDOR_SUFFIX@
|
||||
VERSION = @VERSION@
|
||||
XGETTEXT = @XGETTEXT@
|
||||
XGETTEXT_015 = @XGETTEXT_015@
|
||||
XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
|
||||
XMLRPC_CFLAGS = @XMLRPC_CFLAGS@
|
||||
XMLRPC_LIBS = @XMLRPC_LIBS@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
@@ -334,6 +406,7 @@ host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
htmldir = @htmldir@
|
||||
i18ntests = @i18ntests@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
@@ -353,48 +426,43 @@ program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
pyexecdir = @pyexecdir@
|
||||
pythondir = @pythondir@
|
||||
runstatedir = @runstatedir@
|
||||
sbindir = @sbindir@
|
||||
selinux_makefile = @selinux_makefile@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sysconfenvdir = @sysconfenvdir@
|
||||
systemdsystemunitdir = @systemdsystemunitdir@
|
||||
systemdtmpfilesdir = @systemdtmpfilesdir@
|
||||
target_alias = @target_alias@
|
||||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
NULL =
|
||||
MAINTAINERCLEANFILES = *~ Makefile.in
|
||||
PLUGIN_COMMON_DIR = ../common
|
||||
KRB5_UTIL_DIR = ../../../util
|
||||
KRB5_UTIL_SRCS = $(KRB5_UTIL_DIR)/ipa_krb5.c \
|
||||
$(KRB5_UTIL_DIR)/ipa_pwd.c \
|
||||
$(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
|
||||
|
||||
PLUGIN_COMMON_DIR = $(srcdir)/../common
|
||||
AM_CPPFLAGS = \
|
||||
-I. \
|
||||
-I$(srcdir) \
|
||||
-I$(srcdir)/../libotp \
|
||||
-I$(PLUGIN_COMMON_DIR) \
|
||||
-I$(KRB5_UTIL_DIR) \
|
||||
-I$(COMMON_BER_DIR) \
|
||||
-I$(top_srcdir)/util \
|
||||
-I$(top_srcdir)/asn1 \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DBINDIR=\""$(bindir)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DLIBEXECDIR=\""$(libexecdir)"\" \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
$(LDAP_CFLAGS) \
|
||||
$(DIRSRV_CFLAGS) \
|
||||
$(CRYPTO_CFLAGS) \
|
||||
$(LDAP_CFLAGS) \
|
||||
$(KRB5_CFLAGS) \
|
||||
$(SSL_CFLAGS) \
|
||||
$(NSS_CFLAGS) \
|
||||
$(NSPR_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDFLAGS = \
|
||||
$(CRYPTO_LIBS) \
|
||||
$(KRB5_LIBS) \
|
||||
$(SSL_LIBS) \
|
||||
$(LDAP_LIBS) \
|
||||
$(NSPR_LIBS) \
|
||||
$(NSS_LIBS) \
|
||||
-avoid-version \
|
||||
-export-symbols-regex ^ipapwd_init$
|
||||
|
||||
@@ -402,14 +470,20 @@ AM_LDFLAGS = \
|
||||
# Plugin Binary
|
||||
plugindir = $(libdir)/dirsrv/plugins
|
||||
plugin_LTLIBRARIES = libipa_pwd_extop.la
|
||||
libipa_pwd_extop_la_LIBADD = $(builddir)/../libotp/libotp.la
|
||||
libipa_pwd_extop_la_LIBADD = \
|
||||
$(builddir)/../libotp/libotp.la \
|
||||
$(top_builddir)/asn1/libipaasn1.la \
|
||||
$(top_builddir)/util/libutil.la \
|
||||
$(NULL)
|
||||
|
||||
libipa_pwd_extop_la_SOURCES = \
|
||||
authcfg.c \
|
||||
common.c \
|
||||
encoding.c \
|
||||
prepost.c \
|
||||
ipa_pwd_extop.c \
|
||||
syncreq.c \
|
||||
ipapwd.h \
|
||||
otpctrl.c \
|
||||
otpctrl.h \
|
||||
$(KRB5_UTIL_SRCS) \
|
||||
$(NULL)
|
||||
|
||||
@@ -427,7 +501,7 @@ all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
@@ -436,25 +510,24 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign ipa-slapi-plugins/ipa-pwd-extop/Makefile'; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile'; \
|
||||
$(am__cd) $(top_srcdir) && \
|
||||
$(AUTOMAKE) --foreign ipa-slapi-plugins/ipa-pwd-extop/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
$(AUTOMAKE) --foreign daemons/ipa-slapi-plugins/ipa-pwd-extop/Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
$(top_srcdir)/configure: $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(am__aclocal_m4_deps):
|
||||
|
||||
@@ -502,15 +575,17 @@ mostlyclean-compile:
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/authcfg.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoding.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa_krb5.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa_pwd.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa_pwd_extop.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa_pwd_ntlm.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prepost.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syncreq.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encoding.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipa_pwd_extop.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otpctrl.Plo@am__quote@ # am--include-marker
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prepost.Plo@am__quote@ # am--include-marker
|
||||
|
||||
$(am__depfiles_remade):
|
||||
@$(MKDIR_P) $(@D)
|
||||
@echo '# dummy' >$@-t && $(am__mv) $@-t $@
|
||||
|
||||
am--depfiles: $(am__depfiles_remade)
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@@ -533,27 +608,6 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
|
||||
|
||||
ipa_krb5.lo: $(KRB5_UTIL_DIR)/ipa_krb5.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ipa_krb5.lo -MD -MP -MF $(DEPDIR)/ipa_krb5.Tpo -c -o ipa_krb5.lo `test -f '$(KRB5_UTIL_DIR)/ipa_krb5.c' || echo '$(srcdir)/'`$(KRB5_UTIL_DIR)/ipa_krb5.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipa_krb5.Tpo $(DEPDIR)/ipa_krb5.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(KRB5_UTIL_DIR)/ipa_krb5.c' object='ipa_krb5.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ipa_krb5.lo `test -f '$(KRB5_UTIL_DIR)/ipa_krb5.c' || echo '$(srcdir)/'`$(KRB5_UTIL_DIR)/ipa_krb5.c
|
||||
|
||||
ipa_pwd.lo: $(KRB5_UTIL_DIR)/ipa_pwd.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ipa_pwd.lo -MD -MP -MF $(DEPDIR)/ipa_pwd.Tpo -c -o ipa_pwd.lo `test -f '$(KRB5_UTIL_DIR)/ipa_pwd.c' || echo '$(srcdir)/'`$(KRB5_UTIL_DIR)/ipa_pwd.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipa_pwd.Tpo $(DEPDIR)/ipa_pwd.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(KRB5_UTIL_DIR)/ipa_pwd.c' object='ipa_pwd.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ipa_pwd.lo `test -f '$(KRB5_UTIL_DIR)/ipa_pwd.c' || echo '$(srcdir)/'`$(KRB5_UTIL_DIR)/ipa_pwd.c
|
||||
|
||||
ipa_pwd_ntlm.lo: $(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ipa_pwd_ntlm.lo -MD -MP -MF $(DEPDIR)/ipa_pwd_ntlm.Tpo -c -o ipa_pwd_ntlm.lo `test -f '$(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c' || echo '$(srcdir)/'`$(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
|
||||
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipa_pwd_ntlm.Tpo $(DEPDIR)/ipa_pwd_ntlm.Plo
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c' object='ipa_pwd_ntlm.lo' libtool=yes @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ipa_pwd_ntlm.lo `test -f '$(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c' || echo '$(srcdir)/'`$(KRB5_UTIL_DIR)/ipa_pwd_ntlm.c
|
||||
|
||||
mostlyclean-libtool:
|
||||
-rm -f *.lo
|
||||
|
||||
@@ -633,7 +687,10 @@ cscopelist-am: $(am__tagged_files)
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
distdir: $(BUILT_SOURCES)
|
||||
$(MAKE) $(AM_MAKEFLAGS) distdir-am
|
||||
|
||||
distdir-am: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
@@ -700,14 +757,17 @@ distclean-generic:
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \
|
||||
mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f ./$(DEPDIR)/common.Plo
|
||||
-rm -f ./$(DEPDIR)/encoding.Plo
|
||||
-rm -f ./$(DEPDIR)/ipa_pwd_extop.Plo
|
||||
-rm -f ./$(DEPDIR)/otpctrl.Plo
|
||||
-rm -f ./$(DEPDIR)/prepost.Plo
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
@@ -753,7 +813,11 @@ install-ps-am:
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f ./$(DEPDIR)/common.Plo
|
||||
-rm -f ./$(DEPDIR)/encoding.Plo
|
||||
-rm -f ./$(DEPDIR)/ipa_pwd_extop.Plo
|
||||
-rm -f ./$(DEPDIR)/otpctrl.Plo
|
||||
-rm -f ./$(DEPDIR)/prepost.Plo
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
@@ -774,20 +838,23 @@ uninstall-am: uninstall-appDATA uninstall-pluginLTLIBRARIES
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
|
||||
clean-libtool clean-pluginLTLIBRARIES cscopelist-am ctags \
|
||||
ctags-am distclean distclean-compile distclean-generic \
|
||||
distclean-libtool distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-appDATA \
|
||||
install-data install-data-am install-dvi install-dvi-am \
|
||||
install-exec install-exec-am install-html install-html-am \
|
||||
install-info install-info-am install-man install-pdf \
|
||||
install-pdf-am install-pluginLTLIBRARIES install-ps \
|
||||
install-ps-am install-strip installcheck installcheck-am \
|
||||
installdirs maintainer-clean maintainer-clean-generic \
|
||||
mostlyclean mostlyclean-compile mostlyclean-generic \
|
||||
mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
|
||||
uninstall-am uninstall-appDATA uninstall-pluginLTLIBRARIES
|
||||
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
|
||||
clean-generic clean-libtool clean-pluginLTLIBRARIES \
|
||||
cscopelist-am ctags ctags-am distclean distclean-compile \
|
||||
distclean-generic distclean-libtool distclean-tags distdir dvi \
|
||||
dvi-am html html-am info info-am install install-am \
|
||||
install-appDATA install-data install-data-am install-dvi \
|
||||
install-dvi-am install-exec install-exec-am install-html \
|
||||
install-html-am install-info install-info-am install-man \
|
||||
install-pdf install-pdf-am install-pluginLTLIBRARIES \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
|
||||
tags tags-am uninstall uninstall-am uninstall-appDATA \
|
||||
uninstall-pluginLTLIBRARIES
|
||||
|
||||
.PRECIOUS: Makefile
|
||||
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
|
||||
@@ -1,280 +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, 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/>.
|
||||
*
|
||||
* Additional permission under GPLv3 section 7:
|
||||
*
|
||||
* In the following paragraph, "GPL" means the GNU General Public
|
||||
* License, version 3 or any later version, and "Non-GPL Code" means
|
||||
* code that is governed neither by the GPL nor a license
|
||||
* compatible with the GPL.
|
||||
*
|
||||
* You may link the code of this Program with Non-GPL Code and convey
|
||||
* linked combinations including the two, provided that such Non-GPL
|
||||
* Code only links 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 GPL. Only the copyright holders of this
|
||||
* Program may make changes or additions to the list of Approved
|
||||
* Interfaces.
|
||||
*
|
||||
* Authors:
|
||||
* Nathaniel McCallum <npmccallum@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
* END COPYRIGHT BLOCK **/
|
||||
|
||||
#include "authcfg.h"
|
||||
#include "ipapwd.h"
|
||||
|
||||
#include "pratom.h"
|
||||
|
||||
static struct config {
|
||||
struct config *next;
|
||||
Slapi_DN *suffix;
|
||||
uint32_t config;
|
||||
} *config;
|
||||
|
||||
static uint32_t string_to_config(const char *str)
|
||||
{
|
||||
static const struct {
|
||||
const char *string;
|
||||
uint32_t config;
|
||||
} map[] = {
|
||||
{ "disabled", AUTHCFG_AUTH_TYPE_DISABLED },
|
||||
{ "password", AUTHCFG_AUTH_TYPE_PASSWORD },
|
||||
{ "otp", AUTHCFG_AUTH_TYPE_OTP },
|
||||
{ "pkinit", AUTHCFG_AUTH_TYPE_PKINIT },
|
||||
{ "radius", AUTHCFG_AUTH_TYPE_RADIUS },
|
||||
{}
|
||||
};
|
||||
|
||||
for (uint32_t i = 0; map[i].string != NULL; i++) {
|
||||
if (strcasecmp(map[i].string, str) == 0)
|
||||
return map[i].config;
|
||||
}
|
||||
|
||||
return AUTHCFG_AUTH_TYPE_NONE;
|
||||
}
|
||||
|
||||
static uint32_t entry_to_config(Slapi_Entry *e)
|
||||
{
|
||||
char **auth_types = NULL;
|
||||
|
||||
if (e == NULL)
|
||||
return AUTHCFG_AUTH_TYPE_NONE;
|
||||
|
||||
/* Fetch the auth type values from the config entry. */
|
||||
auth_types = slapi_entry_attr_get_charray(e, "ipaUserAuthType");
|
||||
if (auth_types == NULL)
|
||||
return AUTHCFG_AUTH_TYPE_NONE;
|
||||
|
||||
uint32_t types = AUTHCFG_AUTH_TYPE_NONE;
|
||||
for (uint32_t i = 0; auth_types[i] != NULL; i++)
|
||||
types |= string_to_config(auth_types[i]);
|
||||
|
||||
slapi_ch_array_free(auth_types);
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
static Slapi_DN *suffix_to_config_dn(Slapi_DN *suffix)
|
||||
{
|
||||
Slapi_DN *sdn = NULL;
|
||||
char *dn = NULL;
|
||||
|
||||
if (suffix == NULL)
|
||||
return NULL;
|
||||
|
||||
dn = PR_smprintf("cn=ipaConfig,cn=etc,%s", slapi_sdn_get_dn(suffix));
|
||||
if (dn == NULL)
|
||||
return NULL;
|
||||
|
||||
sdn = slapi_sdn_new_dn_byval(dn);
|
||||
PR_smprintf_free(dn);
|
||||
return sdn;
|
||||
}
|
||||
|
||||
static uint32_t suffix_to_config(Slapi_DN *suffix)
|
||||
{
|
||||
static char *attrs[] = { "ipaUserAuthType", NULL };
|
||||
Slapi_Entry *entry = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
uint32_t types;
|
||||
int ret;
|
||||
|
||||
sdn = suffix_to_config_dn(suffix);
|
||||
if (sdn == NULL)
|
||||
return AUTHCFG_AUTH_TYPE_NONE;
|
||||
|
||||
ret = slapi_search_internal_get_entry(sdn, attrs, &entry,
|
||||
ipapwd_get_plugin_id());
|
||||
slapi_sdn_free(&sdn);
|
||||
if (ret != LDAP_SUCCESS)
|
||||
return AUTHCFG_AUTH_TYPE_NONE;
|
||||
|
||||
types = entry_to_config(entry);
|
||||
slapi_entry_free(entry);
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
static Slapi_DN *sdn_to_suffix(Slapi_DN *sdn)
|
||||
{
|
||||
Slapi_DN *suffix = NULL;
|
||||
void *node = NULL;
|
||||
|
||||
if (sdn == NULL)
|
||||
return NULL;
|
||||
|
||||
for (suffix = slapi_get_first_suffix(&node, 0); suffix != NULL;
|
||||
suffix = slapi_get_next_suffix(&node, 0)) {
|
||||
if (slapi_sdn_issuffix(sdn, suffix))
|
||||
return suffix;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool sdn_is_config(Slapi_DN *sdn)
|
||||
{
|
||||
Slapi_DN *sfx = NULL;
|
||||
Slapi_DN *cfg = NULL;
|
||||
int cmp;
|
||||
|
||||
if (sdn == NULL)
|
||||
return false;
|
||||
|
||||
sfx = sdn_to_suffix(sdn);
|
||||
if (sfx == NULL)
|
||||
return false;
|
||||
|
||||
cfg = suffix_to_config_dn(sfx);
|
||||
if (cfg == NULL)
|
||||
return false;
|
||||
|
||||
cmp = slapi_sdn_compare(cfg, sdn);
|
||||
slapi_sdn_free(&cfg);
|
||||
return cmp == 0;
|
||||
}
|
||||
|
||||
void cache_free(struct config **cfg)
|
||||
{
|
||||
if (cfg == NULL || *cfg == NULL)
|
||||
return;
|
||||
|
||||
cache_free(&(*cfg)->next);
|
||||
free(*cfg);
|
||||
*cfg = NULL;
|
||||
}
|
||||
|
||||
bool authcfg_init(void)
|
||||
{
|
||||
struct config *cfg = NULL;
|
||||
Slapi_DN *sfx = NULL;
|
||||
void *node = NULL;
|
||||
|
||||
/* If we are already initialized, return true. */
|
||||
if (config != NULL)
|
||||
return true;
|
||||
|
||||
/* Look up the config for each suffix. */
|
||||
for (sfx = slapi_get_first_suffix(&node, 0); sfx != NULL;
|
||||
sfx = slapi_get_next_suffix(&node, 0)) {
|
||||
cfg = calloc(1, sizeof(*cfg));
|
||||
if (cfg == NULL) {
|
||||
authcfg_fini();
|
||||
return false;
|
||||
}
|
||||
|
||||
cfg->suffix = sfx;
|
||||
cfg->config = suffix_to_config(sfx);
|
||||
cfg->next = config;
|
||||
config = cfg;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void authcfg_fini(void)
|
||||
{
|
||||
cache_free(&config);
|
||||
}
|
||||
|
||||
uint32_t authcfg_get_auth_types(Slapi_Entry *user_entry)
|
||||
{
|
||||
uint32_t glbl = AUTHCFG_AUTH_TYPE_NONE;
|
||||
uint32_t user = AUTHCFG_AUTH_TYPE_NONE;
|
||||
Slapi_DN *sfx = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
|
||||
/* Find the root suffix. */
|
||||
sdn = slapi_entry_get_sdn(user_entry);
|
||||
sfx = sdn_to_suffix(sdn);
|
||||
|
||||
/* Find the global config. */
|
||||
if (sfx != NULL) {
|
||||
for (struct config *cfg = config; cfg && sfx; cfg = cfg->next) {
|
||||
if (slapi_sdn_compare(sfx, cfg->suffix) == 0) {
|
||||
glbl = PR_ATOMIC_ADD(&cfg->config, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Global disabled overrides user settings. */
|
||||
if (glbl & AUTHCFG_AUTH_TYPE_DISABLED)
|
||||
return AUTHCFG_AUTH_TYPE_DISABLED;
|
||||
|
||||
/* Get the user's config. */
|
||||
user = entry_to_config(user_entry);
|
||||
|
||||
if (user == AUTHCFG_AUTH_TYPE_NONE) {
|
||||
if (glbl == AUTHCFG_AUTH_TYPE_NONE)
|
||||
return AUTHCFG_AUTH_TYPE_PASSWORD;
|
||||
return glbl;
|
||||
}
|
||||
|
||||
return user & ~AUTHCFG_AUTH_TYPE_DISABLED;
|
||||
}
|
||||
|
||||
void authcfg_reload_global_config(Slapi_DN *sdn, Slapi_Entry *config_entry)
|
||||
{
|
||||
uint32_t glbl = AUTHCFG_AUTH_TYPE_NONE;
|
||||
Slapi_DN *sfx = NULL;
|
||||
Slapi_DN *dest;
|
||||
|
||||
/* Get the destination DN. */
|
||||
dest = config_entry == NULL ? NULL : slapi_entry_get_sdn(config_entry);
|
||||
|
||||
/* Added, modified, moved into place. */
|
||||
if (sdn_is_config(dest)) {
|
||||
sfx = sdn_to_suffix(dest);
|
||||
glbl = entry_to_config(config_entry);
|
||||
|
||||
/* Deleted, moved out of place. */
|
||||
} else if (sdn_is_config(sdn)) {
|
||||
sfx = sdn_to_suffix(sdn);
|
||||
}
|
||||
|
||||
/* Reload config. */
|
||||
for (struct config *cfg = config; cfg && sfx; cfg = cfg->next) {
|
||||
if (slapi_sdn_compare(sfx, cfg->suffix) == 0) {
|
||||
PR_ATOMIC_SET(&cfg->config, glbl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +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, 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/>.
|
||||
*
|
||||
* Additional permission under GPLv3 section 7:
|
||||
*
|
||||
* In the following paragraph, "GPL" means the GNU General Public
|
||||
* License, version 3 or any later version, and "Non-GPL Code" means
|
||||
* code that is governed neither by the GPL nor a license
|
||||
* compatible with the GPL.
|
||||
*
|
||||
* You may link the code of this Program with Non-GPL Code and convey
|
||||
* linked combinations including the two, provided that such Non-GPL
|
||||
* Code only links 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 GPL. Only the copyright holders of this
|
||||
* Program may make changes or additions to the list of Approved
|
||||
* Interfaces.
|
||||
*
|
||||
* Authors:
|
||||
* Nathaniel McCallum <npmccallum@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2014 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
* END COPYRIGHT BLOCK **/
|
||||
|
||||
|
||||
#ifndef AUTHCFG_H_
|
||||
#define AUTHCFG_H_
|
||||
|
||||
#include <dirsrv/slapi-plugin.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define AUTHCFG_AUTH_TYPE_NONE 0
|
||||
#define AUTHCFG_AUTH_TYPE_DISABLED 1
|
||||
#define AUTHCFG_AUTH_TYPE_PASSWORD 2
|
||||
#define AUTHCFG_AUTH_TYPE_OTP 4
|
||||
#define AUTHCFG_AUTH_TYPE_PKINIT 8
|
||||
#define AUTHCFG_AUTH_TYPE_RADIUS 16
|
||||
|
||||
/* Initialize authentication configuration.
|
||||
*
|
||||
* Thread Safety: NO
|
||||
*/
|
||||
bool authcfg_init(void);
|
||||
|
||||
/* Free global authentication configuration resources.
|
||||
*
|
||||
* Thread Safety: NO
|
||||
*/
|
||||
void authcfg_fini(void);
|
||||
|
||||
/* Gets the permitted authentication types for the given user entry.
|
||||
*
|
||||
* The entry should be queried for the "ipaUserAuthType" attribute.
|
||||
*
|
||||
* Thread Safety: YES
|
||||
*/
|
||||
uint32_t authcfg_get_auth_types(Slapi_Entry *user_entry);
|
||||
|
||||
/* Reloads configuration from the specified global config entry.
|
||||
*
|
||||
* If the provided entry isn't a global config entry, this is a no-op.
|
||||
*
|
||||
* Thread Safety: YES
|
||||
*/
|
||||
void authcfg_reload_global_config(Slapi_DN *sdn, Slapi_Entry *config_entry);
|
||||
|
||||
#endif /* AUTHCFG_H_ */
|
||||
@@ -46,6 +46,7 @@
|
||||
/* Type of connection for this operation;*/
|
||||
#define LDAP_EXTOP_PASSMOD_CONN_SECURE
|
||||
|
||||
|
||||
/* Uncomment the following #undef FOR TESTING:
|
||||
* allows non-SSL connections to use the password change extended op */
|
||||
/* #undef LDAP_EXTOP_PASSMOD_CONN_SECURE */
|
||||
@@ -55,18 +56,10 @@ extern const char *ipa_realm_dn;
|
||||
extern const char *ipa_etc_config_dn;
|
||||
extern const char *ipa_pwd_config_dn;
|
||||
|
||||
/* These are the default enc:salt types if nothing is defined.
|
||||
* TODO: retrieve the configure set of ecntypes either from the
|
||||
* kfc.conf file or by synchronizing the file content into
|
||||
* the directory */
|
||||
/* These are the default enc:salt types if nothing is defined in LDAP */
|
||||
static const char *ipapwd_def_encsalts[] = {
|
||||
"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", */
|
||||
"aes256-cts:special",
|
||||
"aes128-cts:special",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -79,6 +72,7 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
|
||||
Slapi_Entry *config_entry = NULL;
|
||||
Slapi_Attr *a;
|
||||
Slapi_Value *v;
|
||||
Slapi_DN *sdn = NULL;
|
||||
BerElement *be = NULL;
|
||||
ber_tag_t tag, tvno;
|
||||
ber_int_t ttype;
|
||||
@@ -114,7 +108,9 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
|
||||
}
|
||||
|
||||
/* get the Realm Container entry */
|
||||
ret = ipapwd_getEntry(ipa_realm_dn, &realm_entry, NULL);
|
||||
sdn = slapi_sdn_new_dn_byval(ipa_realm_dn);
|
||||
ret = ipapwd_getEntry(sdn, &realm_entry, NULL);
|
||||
slapi_sdn_free(&sdn);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
LOG_FATAL("No realm Entry?\n");
|
||||
goto free_and_error;
|
||||
@@ -219,7 +215,9 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
|
||||
slapi_entry_free(realm_entry);
|
||||
|
||||
/* get the Realm Container entry */
|
||||
ret = ipapwd_getEntry(ipa_pwd_config_dn, &config_entry, NULL);
|
||||
sdn = slapi_sdn_new_dn_byval(ipa_pwd_config_dn);
|
||||
ret = ipapwd_getEntry(sdn, &config_entry, NULL);
|
||||
slapi_sdn_free(&sdn);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
LOG_FATAL("No config Entry? Impossible!\n");
|
||||
goto free_and_error;
|
||||
@@ -240,23 +238,29 @@ static struct ipapwd_krbcfg *ipapwd_getConfig(void)
|
||||
|
||||
/* get the ipa etc/ipaConfig entry */
|
||||
config->allow_nt_hash = false;
|
||||
ret = ipapwd_getEntry(ipa_etc_config_dn, &config_entry, NULL);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
LOG_FATAL("No config Entry?\n");
|
||||
goto free_and_error;
|
||||
if (ipapwd_fips_enabled()) {
|
||||
LOG("FIPS mode is enabled, NT hashes are not allowed.\n");
|
||||
} else {
|
||||
tmparray = slapi_entry_attr_get_charray(config_entry,
|
||||
"ipaConfigString");
|
||||
for (i = 0; tmparray && tmparray[i]; i++) {
|
||||
if (strcasecmp(tmparray[i], "AllowNThash") == 0) {
|
||||
config->allow_nt_hash = true;
|
||||
continue;
|
||||
sdn = slapi_sdn_new_dn_byval(ipa_etc_config_dn);
|
||||
ret = ipapwd_getEntry(sdn, &config_entry, NULL);
|
||||
slapi_sdn_free(&sdn);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
LOG_FATAL("No config Entry?\n");
|
||||
goto free_and_error;
|
||||
} else {
|
||||
tmparray = slapi_entry_attr_get_charray(config_entry,
|
||||
"ipaConfigString");
|
||||
for (i = 0; tmparray && tmparray[i]; i++) {
|
||||
if (strcasecmp(tmparray[i], "AllowNThash") == 0) {
|
||||
config->allow_nt_hash = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (tmparray) slapi_ch_array_free(tmparray);
|
||||
}
|
||||
if (tmparray) slapi_ch_array_free(tmparray);
|
||||
}
|
||||
|
||||
slapi_entry_free(config_entry);
|
||||
slapi_entry_free(config_entry);
|
||||
}
|
||||
|
||||
return config;
|
||||
|
||||
@@ -289,8 +293,8 @@ free_and_error:
|
||||
* slapi_pblock_destroy(pb)
|
||||
*/
|
||||
static int pwd_get_values(const Slapi_Entry *ent, const char *attrname,
|
||||
Slapi_ValueSet** results, char** actual_type_name,
|
||||
int *buffer_flags)
|
||||
Slapi_ValueSet** results, char** actual_type_name,
|
||||
int *buffer_flags)
|
||||
{
|
||||
int flags=0;
|
||||
int type_name_disposition = 0;
|
||||
@@ -325,7 +329,6 @@ int ipapwd_getPolicy(const char *dn,
|
||||
int buffer_flags=0;
|
||||
Slapi_ValueSet* results = NULL;
|
||||
char *actual_type_name = NULL;
|
||||
int tmpint;
|
||||
|
||||
LOG_TRACE("Searching policy for [%s]\n", dn);
|
||||
|
||||
@@ -390,15 +393,9 @@ int ipapwd_getPolicy(const char *dn,
|
||||
/* read data out of policy object */
|
||||
policy->min_pwd_life = slapi_entry_attr_get_int(pe, "krbMinPwdLife");
|
||||
|
||||
tmpint = slapi_entry_attr_get_int(pe, "krbMaxPwdLife");
|
||||
if (tmpint != 0) {
|
||||
policy->max_pwd_life = tmpint;
|
||||
}
|
||||
policy->max_pwd_life = slapi_entry_attr_get_int(pe, "krbMaxPwdLife");
|
||||
|
||||
tmpint = slapi_entry_attr_get_int(pe, "krbPwdMinLength");
|
||||
if (tmpint != 0) {
|
||||
policy->min_pwd_length = tmpint;
|
||||
}
|
||||
policy->min_pwd_length = slapi_entry_attr_get_int(pe, "krbPwdMinLength");
|
||||
|
||||
policy->history_length = slapi_entry_attr_get_int(pe,
|
||||
"krbPwdHistoryLength");
|
||||
@@ -425,6 +422,7 @@ done:
|
||||
|
||||
int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
|
||||
int *is_root, int *is_krb, int *is_smb, int *is_ipant,
|
||||
int *is_memberof,
|
||||
char *attr, int acc)
|
||||
{
|
||||
Slapi_Value *sval;
|
||||
@@ -443,6 +441,10 @@ int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
|
||||
}
|
||||
}
|
||||
|
||||
/* Default to not setting memberof flag: only set it for non-Kerberos principals
|
||||
* when they have krbPrincipalAux but no krbPrincipalName */
|
||||
*is_memberof = 0;
|
||||
|
||||
/* Check if this is a krbPrincial and therefore needs us to generate other
|
||||
* hashes */
|
||||
sval = slapi_value_new_string("krbPrincipalAux");
|
||||
@@ -453,6 +455,24 @@ int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
|
||||
*is_krb = slapi_entry_attr_has_syntax_value(e, SLAPI_ATTR_OBJECTCLASS, sval);
|
||||
slapi_value_free(&sval);
|
||||
|
||||
/* If entry has krbPrincipalAux object class but lacks krbPrincipalName and
|
||||
* memberOf attributes consider this not a Kerberos principal object. In
|
||||
* FreeIPA krbPrincipalAux allows to store krbPwdPolicyReference attribute
|
||||
* which is added by a CoS plugin configuration based on a memberOf
|
||||
* attribute value.
|
||||
* Note that slapi_entry_attr_find() returns 0 if attr exists, -1 for absence
|
||||
*/
|
||||
if (*is_krb) {
|
||||
Slapi_Attr *attr_prname = NULL;
|
||||
Slapi_Attr *attr_memberof = NULL;
|
||||
int has_prname = slapi_entry_attr_find(e, "krbPrincipalName", &attr_prname);
|
||||
int has_memberOf = slapi_entry_attr_find(e, "memberOf", &attr_memberof);
|
||||
if ((has_prname == -1) && (has_memberOf == 0)) {
|
||||
*is_memberof = 1;
|
||||
*is_krb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
sval = slapi_value_new_string("sambaSamAccount");
|
||||
if (!sval) {
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
@@ -563,6 +583,13 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
|
||||
pol.min_pwd_length = IPAPWD_DEFAULT_MINLEN;
|
||||
|
||||
switch(data->changetype) {
|
||||
case IPA_CHANGETYPE_NORMAL:
|
||||
/* Find the entry with the password policy */
|
||||
ret = ipapwd_getPolicy(data->dn, data->target, &pol);
|
||||
if (ret) {
|
||||
LOG_TRACE("No password policy, use defaults");
|
||||
}
|
||||
break;
|
||||
case IPA_CHANGETYPE_ADMIN:
|
||||
/* The expiration date needs to be older than the current time
|
||||
* otherwise the KDC may not immediately register the password
|
||||
@@ -571,14 +598,11 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
|
||||
*/
|
||||
data->timeNow -= 1;
|
||||
data->expireTime = data->timeNow;
|
||||
break;
|
||||
case IPA_CHANGETYPE_NORMAL:
|
||||
/* Find the entry with the password policy */
|
||||
ret = ipapwd_getPolicy(data->dn, data->target, &pol);
|
||||
if (ret) {
|
||||
LOG_TRACE("No password policy, use defaults");
|
||||
}
|
||||
break;
|
||||
|
||||
/* let set the entry password property according to its
|
||||
* entry password policy (done with ipapwd_getPolicy)
|
||||
* For this intentional fallthrough here
|
||||
*/
|
||||
case IPA_CHANGETYPE_DSMGR:
|
||||
/* PassSync agents and Directory Manager can administratively
|
||||
* change the password without expiring it.
|
||||
@@ -592,6 +616,7 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
|
||||
LOG_TRACE("No password policy, use defaults");
|
||||
} else {
|
||||
pol.max_pwd_life = tmppol.max_pwd_life;
|
||||
pol.history_length = tmppol.history_length;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -628,7 +653,11 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
|
||||
slapi_ch_array_free(pwd_history);
|
||||
|
||||
if (data->expireTime == 0) {
|
||||
data->expireTime = data->timeNow + pol.max_pwd_life;
|
||||
if (pol.max_pwd_life > 0) {
|
||||
/* max_pwd_life = 0 => never expire
|
||||
* set expire time only when max_pwd_life > 0 */
|
||||
data->expireTime = data->timeNow + pol.max_pwd_life;
|
||||
}
|
||||
}
|
||||
|
||||
data->policy = pol;
|
||||
@@ -637,25 +666,31 @@ int ipapwd_CheckPolicy(struct ipapwd_data *data)
|
||||
}
|
||||
|
||||
/* Searches the dn in directory,
|
||||
* If found : fills in slapi_entry structure and returns 0
|
||||
* If found : fills in slapi_entry structure and returns 0
|
||||
* If NOT found : returns the search result as LDAP_NO_SUCH_OBJECT
|
||||
*/
|
||||
int ipapwd_getEntry(const char *dn, Slapi_Entry **e2, char **attrlist)
|
||||
int ipapwd_getEntry(Slapi_DN *sdn, Slapi_Entry **e2, char **attrlist)
|
||||
{
|
||||
Slapi_DN *sdn;
|
||||
int search_result = 0;
|
||||
Slapi_DN *local_sdn = NULL;
|
||||
|
||||
LOG_TRACE("=>\n");
|
||||
|
||||
sdn = slapi_sdn_new_dn_byref(dn);
|
||||
search_result = slapi_search_internal_get_entry(sdn, attrlist, e2,
|
||||
ipapwd_plugin_id);
|
||||
if (search_result != LDAP_SUCCESS) {
|
||||
LOG_TRACE("No such entry-(%s), err (%d)\n", dn, search_result);
|
||||
if (sdn == NULL) {
|
||||
LOG_TRACE("No entry to fetch!\n");
|
||||
return LDAP_PARAM_ERROR;
|
||||
}
|
||||
|
||||
local_sdn = slapi_sdn_dup(sdn);
|
||||
search_result = slapi_search_internal_get_entry(local_sdn, attrlist, e2,
|
||||
ipapwd_plugin_id);
|
||||
if (search_result != LDAP_SUCCESS) {
|
||||
LOG_TRACE("No such entry-(%s), err (%d)\n",
|
||||
slapi_sdn_get_dn(sdn), search_result);
|
||||
}
|
||||
|
||||
slapi_sdn_free(&sdn);
|
||||
LOG_TRACE("<= result: %d\n", search_result);
|
||||
slapi_sdn_free(&local_sdn);
|
||||
return search_result;
|
||||
}
|
||||
|
||||
@@ -713,6 +748,33 @@ next:
|
||||
return kvno;
|
||||
}
|
||||
|
||||
int ipapwd_setdate(Slapi_Entry *source, Slapi_Mods *smods, const char *attr,
|
||||
time_t date, bool remove)
|
||||
{
|
||||
char timestr[GENERALIZED_TIME_LENGTH+1];
|
||||
struct tm utctime;
|
||||
Slapi_Attr *t;
|
||||
bool exists;
|
||||
|
||||
exists = (slapi_entry_attr_find(source, attr, &t) == 0);
|
||||
|
||||
if (remove) {
|
||||
if (exists) {
|
||||
slapi_mods_add_mod_values(smods, LDAP_MOD_DELETE, attr, NULL);
|
||||
}
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
if (!gmtime_r(&date, &utctime)) {
|
||||
LOG_FATAL("failed to convert %s date\n", attr);
|
||||
return LDAP_OPERATIONS_ERROR;
|
||||
}
|
||||
strftime(timestr, GENERALIZED_TIME_LENGTH + 1, "%Y%m%d%H%M%SZ", &utctime);
|
||||
slapi_mods_add_string(smods, exists ? LDAP_MOD_REPLACE : LDAP_MOD_ADD,
|
||||
attr, timestr);
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* Modify the Password attributes of the entry */
|
||||
int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
|
||||
struct ipapwd_data *data, int is_krb)
|
||||
@@ -722,8 +784,6 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
|
||||
Slapi_Value **svals = NULL;
|
||||
Slapi_Value **ntvals = NULL;
|
||||
Slapi_Value **pwvals = NULL;
|
||||
struct tm utctime;
|
||||
char timestr[GENERALIZED_TIME_LENGTH+1];
|
||||
char *nt = NULL;
|
||||
int is_smb = 0;
|
||||
int is_ipant = 0;
|
||||
@@ -771,33 +831,22 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
|
||||
slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
|
||||
"krbPrincipalKey", svals);
|
||||
|
||||
/* krbLastPwdChange is used to tell whether a host entry has a
|
||||
* keytab so don't set it on hosts.
|
||||
*/
|
||||
/* krbLastPwdChange is used to tell whether a host entry has a
|
||||
* keytab so don't set it on hosts. */
|
||||
if (!is_host) {
|
||||
/* change Last Password Change field with the current date */
|
||||
if (!gmtime_r(&(data->timeNow), &utctime)) {
|
||||
LOG_FATAL("failed to retrieve current date (buggy gmtime_r ?)\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
strftime(timestr, GENERALIZED_TIME_LENGTH + 1,
|
||||
"%Y%m%d%H%M%SZ", &utctime);
|
||||
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
||||
"krbLastPwdChange", timestr);
|
||||
/* change Last Password Change field with the current date */
|
||||
ret = ipapwd_setdate(data->target, smods, "krbLastPwdChange",
|
||||
data->timeNow, false);
|
||||
if (ret != LDAP_SUCCESS)
|
||||
goto free_and_return;
|
||||
|
||||
/* set Password Expiration date */
|
||||
if (!gmtime_r(&(data->expireTime), &utctime)) {
|
||||
LOG_FATAL("failed to convert expiration date\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
strftime(timestr, GENERALIZED_TIME_LENGTH + 1,
|
||||
"%Y%m%d%H%M%SZ", &utctime);
|
||||
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
||||
"krbPasswordExpiration", timestr);
|
||||
}
|
||||
}
|
||||
/* set Password Expiration date */
|
||||
ret = ipapwd_setdate(data->target, smods, "krbPasswordExpiration",
|
||||
data->expireTime, (data->expireTime == 0));
|
||||
if (ret != LDAP_SUCCESS)
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
if (nt && is_smb) {
|
||||
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
||||
@@ -839,8 +888,8 @@ int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
|
||||
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
||||
"userPassword", data->password);
|
||||
|
||||
/* set password history */
|
||||
if (data->policy.history_length > 0) {
|
||||
/* set password history if a Kerberos object */
|
||||
if (data->policy.history_length > 0 && is_krb) {
|
||||
pwvals = ipapwd_setPasswordHistory(smods, data);
|
||||
if (pwvals) {
|
||||
slapi_mods_add_mod_values(smods, LDAP_MOD_REPLACE,
|
||||
@@ -989,7 +1038,7 @@ int ipapwd_set_extradata(const char *dn,
|
||||
xdata[5] = (unixtime & 0xff000000) >> 24;
|
||||
|
||||
/* append the principal name */
|
||||
strncpy(&xdata[6], principal, p_len);
|
||||
memcpy(&xdata[6], principal, p_len);
|
||||
|
||||
xdata[xd_len -1] = 0;
|
||||
|
||||
@@ -1038,3 +1087,12 @@ void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg)
|
||||
*cfg = NULL;
|
||||
};
|
||||
|
||||
int ipapwd_check_max_pwd_len(size_t len, char **errMesg) {
|
||||
if (len > IPAPWD_PASSWORD_MAX_LEN) {
|
||||
LOG("%s\n", ipapwd_password_max_len_errmsg);
|
||||
*errMesg = ipapwd_password_max_len_errmsg;
|
||||
return LDAP_CONSTRAINT_VIOLATION;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ void ipapwd_keyset_free(struct ipapwd_keyset **pkset)
|
||||
|
||||
Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
|
||||
struct ipapwd_data *data,
|
||||
char *preferred_principal,
|
||||
int num_encsalts,
|
||||
krb5_key_salt_tuple *encsalts,
|
||||
char **errMesg)
|
||||
@@ -128,12 +129,20 @@ Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
|
||||
|
||||
kvno = ipapwd_get_cur_kvno(data->target);
|
||||
|
||||
krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
|
||||
"krbPrincipalName");
|
||||
if (!krbPrincipalName) {
|
||||
*errMesg = "no krbPrincipalName present in this entry\n";
|
||||
LOG_FATAL("%s", *errMesg);
|
||||
goto enc_error;
|
||||
if (preferred_principal) {
|
||||
krbPrincipalName = slapi_ch_strdup(preferred_principal);
|
||||
} else {
|
||||
krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
|
||||
"krbCanonicalName");
|
||||
if (!krbPrincipalName) {
|
||||
krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
|
||||
"krbPrincipalName");
|
||||
}
|
||||
if (!krbPrincipalName) {
|
||||
*errMesg = "no krbPrincipalName present in this entry\n";
|
||||
LOG_FATAL("%s", *errMesg);
|
||||
goto enc_error;
|
||||
}
|
||||
}
|
||||
|
||||
krberr = krb5_parse_name(krbctx, krbPrincipalName, &princ);
|
||||
@@ -148,7 +157,7 @@ Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
|
||||
pwd.length = strlen(data->password);
|
||||
}
|
||||
|
||||
kset = malloc(sizeof(struct ipapwd_keyset));
|
||||
kset = (struct ipapwd_keyset *) calloc(1, sizeof(struct ipapwd_keyset));
|
||||
if (!kset) {
|
||||
LOG_OOM();
|
||||
goto enc_error;
|
||||
@@ -215,7 +224,7 @@ int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
|
||||
|
||||
if (is_krb) {
|
||||
|
||||
*svals = ipapwd_encrypt_encode_key(krbcfg, data,
|
||||
*svals = ipapwd_encrypt_encode_key(krbcfg, data, NULL,
|
||||
krbcfg->num_pref_encsalts,
|
||||
krbcfg->pref_encsalts,
|
||||
errMesg);
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
|
||||
#include "ipapwd.h"
|
||||
#include "util.h"
|
||||
#include "authcfg.h"
|
||||
#include "../libotp/otp_config.h"
|
||||
#include "ipa_asn1.h"
|
||||
|
||||
/*
|
||||
* Password Modify - LDAP Extended Operation.
|
||||
@@ -88,13 +89,16 @@ Slapi_PluginDesc ipapwd_plugin_desc = {
|
||||
void *ipapwd_plugin_id;
|
||||
static int usetxn = 0;
|
||||
|
||||
extern struct otp_config *otp_config;
|
||||
|
||||
void *ipapwd_get_plugin_id(void)
|
||||
{
|
||||
return ipapwd_plugin_id;
|
||||
}
|
||||
|
||||
static void filter_keys(struct ipapwd_krbcfg *krbcfg,
|
||||
struct ipapwd_keyset *kset)
|
||||
struct ipapwd_keyset *kset,
|
||||
bool allow_nthash)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
@@ -105,6 +109,14 @@ static void filter_keys(struct ipapwd_krbcfg *krbcfg,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* if requested by the caller, allow arcfour-hmac even
|
||||
* if it is missing in the list of supported enctypes. */
|
||||
if (allow_nthash &&
|
||||
(ENCTYPE_ARCFOUR_HMAC == kset->keys[i].key_data_type[0])) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == krbcfg->num_supp_encsalts) { /* not valid */
|
||||
|
||||
/* free key */
|
||||
@@ -125,6 +137,55 @@ static void filter_keys(struct ipapwd_krbcfg *krbcfg,
|
||||
}
|
||||
}
|
||||
|
||||
static void filter_enctypes(struct ipapwd_krbcfg *krbcfg,
|
||||
krb5_key_salt_tuple *kenctypes,
|
||||
int *num_kenctypes,
|
||||
bool allow_nthash)
|
||||
{
|
||||
/* first filter for duplicates */
|
||||
for (int i = 0; i + 1 < *num_kenctypes; i++) {
|
||||
for (int j = i + 1; j < *num_kenctypes; j++) {
|
||||
if (kenctypes[i].ks_enctype == kenctypes[j].ks_enctype) {
|
||||
/* duplicate, filter out */
|
||||
for (int k = j; k + 1 < *num_kenctypes; k++) {
|
||||
kenctypes[k].ks_enctype = kenctypes[k + 1].ks_enctype;
|
||||
kenctypes[k].ks_salttype = kenctypes[k + 1].ks_salttype;
|
||||
}
|
||||
(*num_kenctypes)--;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* then filter for supported */
|
||||
for (int i = 0; i < *num_kenctypes; i++) {
|
||||
int j;
|
||||
|
||||
/* Check if supported */
|
||||
for (j = 0; j < krbcfg->num_supp_encsalts; j++) {
|
||||
if (kenctypes[i].ks_enctype ==
|
||||
krbcfg->supp_encsalts[j].ks_enctype) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* if requested by the caller, allow arcfour-hmac even
|
||||
* if it is missing in the list of supported enctypes. */
|
||||
if (allow_nthash &&
|
||||
(ENCTYPE_ARCFOUR_HMAC == kenctypes[i].ks_enctype)) {
|
||||
break;
|
||||
}
|
||||
if (j == krbcfg->num_supp_encsalts) {
|
||||
/* Unsupported, filter out */
|
||||
for (int k = i; k + 1 < *num_kenctypes; k++) {
|
||||
kenctypes[k].ks_enctype = kenctypes[k + 1].ks_enctype;
|
||||
kenctypes[k].ks_salttype = kenctypes[k + 1].ks_salttype;
|
||||
}
|
||||
(*num_kenctypes)--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ipapwd_to_ldap_pwpolicy_error(int ipapwderr)
|
||||
{
|
||||
switch (ipapwderr) {
|
||||
@@ -161,9 +222,11 @@ static int ipapwd_chpwop(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
Slapi_Value *objectclass=NULL;
|
||||
char *attrlist[] = {"*", "passwordHistory", NULL };
|
||||
struct ipapwd_data pwdata;
|
||||
int is_krb, is_smb, is_ipant;
|
||||
char *principal = NULL;
|
||||
int is_krb, is_smb, is_ipant, is_memberof;
|
||||
char *principal = NULL;
|
||||
Slapi_PBlock *chpwop_pb = NULL;
|
||||
Slapi_DN *target_sdn = NULL;
|
||||
const char *target_dn = NULL;
|
||||
|
||||
/* Get the ber value of the extended operation */
|
||||
slapi_pblock_get(pb, SLAPI_EXT_OP_REQ_VALUE, &extop_value);
|
||||
@@ -271,6 +334,11 @@ parse_req_done:
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
rc = ipapwd_check_max_pwd_len(strlen(newPasswd), &errMesg);
|
||||
if (rc) {
|
||||
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) */
|
||||
@@ -282,20 +350,38 @@ parse_req_done:
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
LOG_TRACE("Missing userIdentity in request, "
|
||||
"using the bind DN instead.\n");
|
||||
/* Determine the target DN for this operation */
|
||||
slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn);
|
||||
if (target_sdn != NULL) {
|
||||
/* If there is a TARGET_SDN we are consuming it */
|
||||
slapi_pblock_set(pb, SLAPI_TARGET_SDN, NULL);
|
||||
target_dn = slapi_sdn_get_ndn(target_sdn);
|
||||
}
|
||||
if (target_dn == NULL || *target_dn == '\0') {
|
||||
/* 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);
|
||||
LOG_TRACE("Missing userIdentity in request, "
|
||||
"using the bind DN instead.\n");
|
||||
}
|
||||
LOG_TRACE("extop dn %s (from ber)\n", dn ? dn : "<empty>");
|
||||
} else {
|
||||
/* At this point if SLAPI_TARGET_SDN was set that means
|
||||
* that a SLAPI_PLUGIN_PRE_EXTOP_FN plugin sets it
|
||||
* So take this one rather that the raw one that is in the ber
|
||||
*/
|
||||
LOG_TRACE("extop dn %s was translated to %s\n", dn ? dn : "<empty>", target_dn);
|
||||
slapi_ch_free_string(&dn);
|
||||
dn = slapi_ch_strdup(target_dn);
|
||||
}
|
||||
slapi_sdn_free(&target_sdn);
|
||||
|
||||
if (slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, dn )) {
|
||||
LOG_FATAL("slapi_pblock_set failed!\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
if (slapi_pblock_set( pb, SLAPI_ORIGINAL_TARGET, dn )) {
|
||||
LOG_FATAL("slapi_pblock_set failed!\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (usetxn) {
|
||||
Slapi_DN *sdn = slapi_sdn_new_dn_byref(dn);
|
||||
@@ -317,33 +403,45 @@ parse_req_done:
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we have the DN, look for the entry */
|
||||
ret = ipapwd_getEntry(dn, &targetEntry, attrlist);
|
||||
/* 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;
|
||||
}
|
||||
/* Now we have the DN, look for the entry */
|
||||
target_sdn = slapi_sdn_new_dn_byval(dn);
|
||||
ret = ipapwd_getEntry(target_sdn, &targetEntry, attrlist);
|
||||
slapi_sdn_free(&target_sdn);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
if (dn) {
|
||||
Slapi_DN *bind_sdn;
|
||||
Slapi_DN *target_sdn;
|
||||
|
||||
/* if the user changing the password is self, we must request the
|
||||
* old password and verify it matches the current one before
|
||||
* proceeding with the password change */
|
||||
bind_sdn = slapi_sdn_new_dn_byref(bindDN);
|
||||
target_sdn = slapi_sdn_new_dn_byref(dn);
|
||||
if (!bind_sdn || !target_sdn) {
|
||||
LOG_OOM();
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto free_and_return;
|
||||
}
|
||||
bind_sdn = slapi_sdn_new_dn_byval(bindDN);
|
||||
target_sdn = slapi_sdn_new_dn_byval(dn);
|
||||
|
||||
rc = (!bind_sdn || !target_sdn) ? LDAP_OPERATIONS_ERROR : 0;
|
||||
|
||||
/* this one will normalize and compare, so difference in case will be
|
||||
* correctly handled */
|
||||
ret = slapi_sdn_compare(bind_sdn, target_sdn);
|
||||
|
||||
slapi_sdn_free(&bind_sdn);
|
||||
slapi_sdn_free(&target_sdn);
|
||||
|
||||
/* rc should always be 0 (else slapi_sdn_new_dn_byval should have sigsev)
|
||||
* but if we end in rc==LDAP_OPERATIONS_ERROR be sure to stop here
|
||||
* because ret is not significant */
|
||||
if (rc != 0) {
|
||||
LOG_OOM();
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
Slapi_Value *cpw[2] = { NULL, NULL };
|
||||
Slapi_Value *pw;
|
||||
@@ -392,6 +490,7 @@ parse_req_done:
|
||||
|
||||
rc = ipapwd_entry_checks(pb, targetEntry,
|
||||
&is_root, &is_krb, &is_smb, &is_ipant,
|
||||
&is_memberof,
|
||||
SLAPI_USERPWD_ATTR, SLAPI_ACL_WRITE);
|
||||
if (rc) {
|
||||
goto free_and_return;
|
||||
@@ -487,16 +586,21 @@ parse_req_done:
|
||||
/* check the policy */
|
||||
ret = ipapwd_CheckPolicy(&pwdata);
|
||||
if (ret) {
|
||||
errMesg = ipapwd_error2string(ret);
|
||||
if (ret == IPAPWD_POLICY_ERROR) {
|
||||
errMesg = "Internal error";
|
||||
rc = ret;
|
||||
} else {
|
||||
goto free_and_return;
|
||||
}
|
||||
/* ipapwd_CheckPolicy happily will try to apply a policy
|
||||
* even if it doesn't need to be applied for Directory Manager
|
||||
* or passsync managers, filter that error out */
|
||||
if (pwdata.changetype != IPA_CHANGETYPE_DSMGR) {
|
||||
errMesg = ipapwd_error2string(ret);
|
||||
ret = ipapwd_to_ldap_pwpolicy_error(ret);
|
||||
slapi_pwpolicy_make_response_control(pb, -1, -1, ret);
|
||||
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||
goto free_and_return;
|
||||
}
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
/* Now we're ready to set the kerberos key material */
|
||||
@@ -521,7 +625,8 @@ parse_req_done:
|
||||
} else {
|
||||
principal = slapi_ch_smprintf("root/admin@%s", krbcfg->realm);
|
||||
}
|
||||
ipapwd_set_extradata(pwdata.dn, principal, pwdata.timeNow);
|
||||
if (principal)
|
||||
ipapwd_set_extradata(pwdata.dn, principal, pwdata.timeNow);
|
||||
|
||||
/* Free anything that we allocated above */
|
||||
free_and_return:
|
||||
@@ -616,6 +721,7 @@ static Slapi_Entry *get_entry_by_principal(const char *principal)
|
||||
Slapi_PBlock *pb = NULL;
|
||||
char *attrlist[] = { "krbPrincipalKey", "krbLastPwdChange",
|
||||
"userPassword", "krbPrincipalName",
|
||||
"krbCanonicalName",
|
||||
"enrolledBy", NULL };
|
||||
Slapi_Entry **es = NULL;
|
||||
int res, ret, i;
|
||||
@@ -1122,6 +1228,7 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
int kvno;
|
||||
char *svcname;
|
||||
bool allowed_access = false;
|
||||
bool is_nthash_allowed = false;
|
||||
struct berval *bvp = NULL;
|
||||
LDAPControl new_ctrl;
|
||||
|
||||
@@ -1194,7 +1301,12 @@ static int ipapwd_setkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
for (int i = 0; i < kset->num_keys; i++) {
|
||||
kset->keys[i].key_data_kvno = kvno;
|
||||
}
|
||||
filter_keys(krbcfg, kset);
|
||||
|
||||
/* Only allow generating arcfour-hmac keys for cifs/.. services
|
||||
* unless the enctype is allowed by the IPA configuration for use
|
||||
* by the all principals */
|
||||
is_nthash_allowed = (0 == strncmp("cifs/", serviceName, 5));
|
||||
filter_keys(krbcfg, kset, is_nthash_allowed);
|
||||
|
||||
/* check if we have any left */
|
||||
if (kset->num_keys == 0) {
|
||||
@@ -1268,31 +1380,7 @@ free_and_return:
|
||||
return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
|
||||
}
|
||||
|
||||
/* Format of getkeytab request
|
||||
*
|
||||
* KeytabGetRequest ::= CHOICE {
|
||||
* newkeys [0] Newkeys,
|
||||
* curkeys [1] CurrentKeys,
|
||||
* reply [2] Reply
|
||||
* }
|
||||
*
|
||||
* NewKeys ::= SEQUENCE {
|
||||
* serviceIdentity [0] OCTET STRING,
|
||||
* enctypes [1] SEQUENCE OF Int16
|
||||
* password [2] OCTET STRING OPTIONAL,
|
||||
* }
|
||||
*
|
||||
* CurrentKeys ::= SEQUENCE {
|
||||
* serviceIdentity [0] OCTET STRING,
|
||||
* }
|
||||
*/
|
||||
|
||||
#define GK_REQUEST_NEWKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
|
||||
#define GK_REQUEST_CURKEYS (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
|
||||
#define GKREQ_SVCNAME_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
|
||||
#define GKREQ_ENCTYPES_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
|
||||
#define GKREQ_PASSWORD_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
|
||||
|
||||
/* decode a getkeytab control request using libipaasn1 helpers */
|
||||
static int decode_getkeytab_request(struct berval *extop, bool *wantold,
|
||||
char **_svcname, char **_password,
|
||||
krb5_key_salt_tuple **kenctypes,
|
||||
@@ -1300,175 +1388,80 @@ static int decode_getkeytab_request(struct berval *extop, bool *wantold,
|
||||
{
|
||||
int rc = LDAP_OPERATIONS_ERROR;
|
||||
char *err_msg = NULL;
|
||||
BerElement *ber = NULL;
|
||||
ber_len_t tlen;
|
||||
ber_tag_t rtag;
|
||||
ber_tag_t ttag;
|
||||
ber_tag_t ctag;
|
||||
char *svcname = NULL;
|
||||
char *password = NULL;
|
||||
ber_int_t enctype;
|
||||
long *etypes = NULL;
|
||||
int numtypes = 0;
|
||||
krb5_key_salt_tuple *enctypes = NULL;
|
||||
int num = 0;
|
||||
bool newkt;
|
||||
bool ret;
|
||||
int i;
|
||||
|
||||
ber = ber_init(extop);
|
||||
if (ber == NULL) {
|
||||
err_msg = "KeytabGet Request decode failed.\n";
|
||||
ret = ipaasn1_dec_getkt(extop->bv_val, extop->bv_len, &newkt,
|
||||
&svcname, &password, &etypes, &numtypes);
|
||||
if (!ret) {
|
||||
err_msg = "Failed to decode GetKeytab Control.\n";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* check this is a request */
|
||||
rtag = ber_peek_tag(ber, &tlen);
|
||||
if (rtag != GK_REQUEST_NEWKEYS && rtag != GK_REQUEST_CURKEYS) {
|
||||
LOG_FATAL("ber_peek_tag failed, wrong request type\n");
|
||||
err_msg = "Invalid payload.\n";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* ber parse code */
|
||||
ttag = ber_scanf(ber, "{ta", &ctag, &svcname);
|
||||
if (ttag == LBER_ERROR || ctag != GKREQ_SVCNAME_TAG) {
|
||||
LOG_FATAL("ber_scanf failed to decode service name\n");
|
||||
err_msg = "Invalid payload.\n";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (rtag == GK_REQUEST_CURKEYS) {
|
||||
rc = LDAP_SUCCESS;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ttag = ber_peek_tag(ber, &tlen);
|
||||
if (ttag != GKREQ_ENCTYPES_TAG) {
|
||||
LOG_FATAL("ber_peek_tag failed to find enctypes\n");
|
||||
err_msg = "Invalid payload.\n";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
ttag = ber_peek_tag(ber, &tlen);
|
||||
for (num = 0; ttag == LBER_INTEGER; num++) {
|
||||
if ((num % 10) == 0) {
|
||||
/* allocate space for at least 10 more enctypes */
|
||||
enctypes = realloc(enctypes,
|
||||
(num + 10) * sizeof(krb5_key_salt_tuple));
|
||||
if (newkt) {
|
||||
if (numtypes) {
|
||||
enctypes = malloc(numtypes * sizeof(krb5_key_salt_tuple));
|
||||
if (!enctypes) {
|
||||
LOG_FATAL("allocation failed\n");
|
||||
err_msg = "Internal error\n";
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ttag = ber_scanf(ber, "i", &enctype);
|
||||
if (ttag == LBER_ERROR) {
|
||||
LOG_FATAL("ber_scanf failed to decode enctype\n");
|
||||
err_msg = "Invalid payload.\n";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
enctypes[num].ks_enctype = enctype;
|
||||
enctypes[num].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
|
||||
ttag = ber_peek_tag(ber, &tlen);
|
||||
}
|
||||
|
||||
/* ttag peek done as last step of the previous for loop */
|
||||
if (ttag == GKREQ_PASSWORD_TAG) {
|
||||
/* optional password present */
|
||||
ttag = ber_scanf(ber, "a", &password);
|
||||
if (ttag == LBER_ERROR) {
|
||||
LOG_FATAL("ber_scanf failed to decode password\n");
|
||||
err_msg = "Invalid payload.\n";
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
goto done;
|
||||
for (i = 0; i < numtypes; i++) {
|
||||
enctypes[i].ks_enctype = etypes[i];
|
||||
enctypes[i].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
done:
|
||||
free(etypes);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
free(password);
|
||||
free(svcname);
|
||||
free(enctypes);
|
||||
*_err_msg = err_msg;
|
||||
} else {
|
||||
*_password = password;
|
||||
*_svcname = svcname;
|
||||
*wantold = (rtag == GK_REQUEST_CURKEYS);
|
||||
*wantold = (newkt == false);
|
||||
*kenctypes = enctypes;
|
||||
*num_kenctypes = num;
|
||||
*num_kenctypes = numtypes;
|
||||
}
|
||||
if (ber) ber_free(ber, 1);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Format of getkeytab reply
|
||||
*
|
||||
* Reply ::= SEQUENCE {
|
||||
* new_kvno Int32
|
||||
* keys SEQUENCE OF KrbKey,
|
||||
* }
|
||||
*
|
||||
* KrbKey ::= SEQUENCE {
|
||||
* key [0] EncryptionKey,
|
||||
* salt [1] KrbSalt OPTIONAL,
|
||||
* s2kparams [2] OCTET STRING OPTIONAL,
|
||||
* }
|
||||
*
|
||||
* EncryptionKey ::= SEQUENCE {
|
||||
* keytype [0] Int32,
|
||||
* keyvalue [1] OCTET STRING
|
||||
* }
|
||||
*
|
||||
* KrbSalt ::= SEQUENCE {
|
||||
* type [0] Int32,
|
||||
* salt [1] OCTET STRING
|
||||
* }
|
||||
*/
|
||||
|
||||
#define GK_REPLY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
|
||||
#define GKREP_KEY_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
|
||||
#define GKREP_SALT_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
|
||||
#define GKREP_S2KPARAMS_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 2)
|
||||
#define GKREP_KEYTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
|
||||
#define GKREP_KEYVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
|
||||
#define GKREP_SALTTYPE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 0)
|
||||
#define GKREP_SALTVALUE_TAG (LBER_CLASS_CONTEXT | LBER_CONSTRUCTED | 1)
|
||||
|
||||
static int encode_getkeytab_reply(krb5_context krbctx,
|
||||
krb5_keyblock *kmkey, int mkvno,
|
||||
krb5_key_data *keys, int num_keys,
|
||||
struct berval **_bvp)
|
||||
{
|
||||
int rc = LDAP_OPERATIONS_ERROR;
|
||||
struct krb_key_salt ksdata[num_keys];
|
||||
struct keys_container ksc = { num_keys, ksdata };
|
||||
struct berval *bvp = NULL;
|
||||
BerElement *ber = NULL;
|
||||
ber_int_t kvno;
|
||||
krb5_data plain = { 0 };
|
||||
int kvno;
|
||||
bool ret;
|
||||
|
||||
ber = ber_alloc();
|
||||
if (!ber) {
|
||||
LOG_OOM();
|
||||
goto done;
|
||||
}
|
||||
memset(ksdata, '\0', num_keys * sizeof(struct krb_key_salt));
|
||||
|
||||
/* uses last key kvno */
|
||||
kvno = keys[num_keys-1].key_data_kvno;
|
||||
|
||||
rc = ber_printf(ber, "t{i{", GK_REPLY_TAG, kvno);
|
||||
if (rc == -1) {
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
LOG_FATAL("Failed to initiate key buffer\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_keys; i++) {
|
||||
krb5_enc_data cipher = { 0 };
|
||||
krb5_data plain = { 0 };
|
||||
krb5_int16 plen;
|
||||
void *p;
|
||||
|
||||
/* retrieve plain key */
|
||||
memcpy(&plen, keys[i].key_data_contents[0], 2);
|
||||
@@ -1478,13 +1471,12 @@ static int encode_getkeytab_reply(krb5_context krbctx,
|
||||
cipher.kvno = mkvno;
|
||||
|
||||
plain.length = le16toh(plen);
|
||||
p = realloc(plain.data, plain.length);
|
||||
if (!p) {
|
||||
plain.data = malloc(plain.length);
|
||||
if (!plain.data) {
|
||||
LOG_FATAL("Failed to allocate plain buffer\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
plain.data = p;
|
||||
|
||||
rc = krb5_c_decrypt(krbctx, kmkey, 0, 0, &cipher, &plain);
|
||||
if (rc) {
|
||||
@@ -1493,68 +1485,37 @@ static int encode_getkeytab_reply(krb5_context krbctx,
|
||||
goto done;
|
||||
}
|
||||
|
||||
rc = ber_printf(ber,
|
||||
"{t{tito}",
|
||||
GKREP_KEY_TAG,
|
||||
GKREP_KEYTYPE_TAG,
|
||||
(ber_int_t)keys[i].key_data_type[0],
|
||||
GKREP_KEYVALUE_TAG,
|
||||
plain.data, (ber_len_t)plain.length);
|
||||
if (rc == -1) {
|
||||
LOG_FATAL("Failed to encode key data\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
ksc.ksdata[i].enctype = keys[i].key_data_type[0];
|
||||
ksc.ksdata[i].key.enctype = keys[i].key_data_type[0];
|
||||
ksc.ksdata[i].key.contents = (void *)plain.data;
|
||||
ksc.ksdata[i].key.length = plain.length;
|
||||
|
||||
/* if salt available, add it */
|
||||
if (keys[i].key_data_length[1] != 0) {
|
||||
rc = ber_printf(ber,
|
||||
"t{tito}",
|
||||
GKREP_SALT_TAG,
|
||||
GKREP_SALTTYPE_TAG,
|
||||
(ber_int_t)keys[i].key_data_type[1],
|
||||
GKREP_SALTVALUE_TAG,
|
||||
keys[i].key_data_contents[1],
|
||||
(ber_len_t)keys[i].key_data_length[1]);
|
||||
if (rc == -1) {
|
||||
LOG_FATAL("Failed to encode salt data\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
rc = ber_printf(ber, "}");
|
||||
if (rc == -1) {
|
||||
LOG_FATAL("Failed to encode data\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
ksc.ksdata[i].salttype = keys[i].key_data_type[1];
|
||||
ksc.ksdata[i].salt.data = (void *)keys[i].key_data_contents[1];
|
||||
ksc.ksdata[i].salt.length = keys[i].key_data_length[1];
|
||||
}
|
||||
}
|
||||
|
||||
rc = ber_printf(ber, "}}");
|
||||
if (rc == -1) {
|
||||
LOG_FATAL("Failed to terminate key buffer\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
bvp = calloc(1, sizeof(struct berval));
|
||||
if (!bvp) goto done;
|
||||
|
||||
rc = ber_flatten(ber, &bvp);
|
||||
if (rc == -1) {
|
||||
LOG_FATAL("Failed to encode key buffer\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
ret = ipaasn1_enc_getktreply(kvno, &ksc,
|
||||
(void **)&bvp->bv_val, &bvp->bv_len);
|
||||
if (!ret) goto done;
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
done:
|
||||
for (int i = 0; i < ksc.nkeys; i ++) {
|
||||
free(ksc.ksdata[i].key.contents);
|
||||
}
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
if (bvp) ber_bvfree(bvp);
|
||||
} else {
|
||||
*_bvp = bvp;
|
||||
}
|
||||
if (ber) ber_free(ber, 1);
|
||||
free(plain.data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1639,7 +1600,6 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
krb5_context krbctx = NULL;
|
||||
krb5_error_code krberr;
|
||||
struct berval *extop_value = NULL;
|
||||
BerElement *ber = NULL;
|
||||
char *service_name = NULL;
|
||||
char *svcname;
|
||||
Slapi_Entry *target_entry = NULL;
|
||||
@@ -1655,6 +1615,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
struct berval *bvp = NULL;
|
||||
LDAPControl new_ctrl;
|
||||
bool wantold = false;
|
||||
bool is_nthash_allowed = false;
|
||||
|
||||
/* Get Bind DN */
|
||||
slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn);
|
||||
@@ -1719,8 +1680,8 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
READKEYS_OP_CHECK, NULL,
|
||||
SLAPI_ACL_READ);
|
||||
if (!acl_ok) {
|
||||
LOG_FATAL("Not allowed to retrieve keytab on [%s]!\n",
|
||||
service_name);
|
||||
LOG_FATAL("Not allowed to retrieve keytab on [%s] as user [%s]!\n",
|
||||
service_name, bind_dn);
|
||||
err_msg = "Insufficient access rights\n";
|
||||
rc = LDAP_INSUFFICIENT_ACCESS;
|
||||
goto free_and_return;
|
||||
@@ -1728,6 +1689,14 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
|
||||
} else {
|
||||
|
||||
if (password != NULL) {
|
||||
/* if password was passed-in, check its length */
|
||||
rc = ipapwd_check_max_pwd_len(strlen(password), &err_msg);
|
||||
if (rc) {
|
||||
goto free_and_return;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if we are allowed to *write* keys */
|
||||
acl_ok = is_allowed_to_access_attr(pb, bind_dn, target_entry,
|
||||
WRITEKEYS_OP_CHECK, NULL,
|
||||
@@ -1740,23 +1709,11 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
goto free_and_return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_kenctypes; i++) {
|
||||
|
||||
/* Check if supported */
|
||||
for (int j = 0; j < krbcfg->num_supp_encsalts; j++) {
|
||||
if (kenctypes[i].ks_enctype ==
|
||||
krbcfg->supp_encsalts[j].ks_enctype) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Unsupported, filter out */
|
||||
for (int j = i; j + 1 < num_kenctypes; j++) {
|
||||
kenctypes[j].ks_enctype = kenctypes[j + 1].ks_enctype;
|
||||
kenctypes[j].ks_salttype = kenctypes[j + 1].ks_salttype;
|
||||
}
|
||||
num_kenctypes--;
|
||||
i--;
|
||||
}
|
||||
/* Only allow generating arcfour-hmac keys for cifs/.. services
|
||||
* unless the enctype is allowed by the IPA configuration for use
|
||||
* by the all principals */
|
||||
is_nthash_allowed = (0 == strncmp("cifs/", service_name, 5));
|
||||
filter_enctypes(krbcfg, kenctypes, &num_kenctypes, is_nthash_allowed);
|
||||
|
||||
/* check if we have any left */
|
||||
if (num_kenctypes == 0 && kenctypes != NULL) {
|
||||
@@ -1771,7 +1728,7 @@ static int ipapwd_getkeytab(Slapi_PBlock *pb, struct ipapwd_krbcfg *krbcfg)
|
||||
data.target = target_entry;
|
||||
data.password = password;
|
||||
|
||||
svals = ipapwd_encrypt_encode_key(krbcfg, &data,
|
||||
svals = ipapwd_encrypt_encode_key(krbcfg, &data, service_name,
|
||||
kenctypes ? num_kenctypes :
|
||||
krbcfg->num_pref_encsalts,
|
||||
kenctypes ? kenctypes :
|
||||
@@ -1827,7 +1784,6 @@ free_and_return:
|
||||
}
|
||||
free(svals);
|
||||
}
|
||||
if (ber) ber_free(ber, 1);
|
||||
if (bvp) ber_bvfree(bvp);
|
||||
|
||||
return SLAPI_PLUGIN_EXTENDED_SENT_RESULT;
|
||||
@@ -1914,20 +1870,10 @@ static int ipapwd_start( Slapi_PBlock *pb )
|
||||
krb5_context krbctx = NULL;
|
||||
krb5_error_code krberr;
|
||||
char *realm = NULL;
|
||||
char *config_dn;
|
||||
Slapi_DN *config_sdn = NULL;
|
||||
Slapi_Entry *config_entry = NULL;
|
||||
int ret;
|
||||
|
||||
/* NOTE: We never call authcfg_fini() from a destructor. This is because
|
||||
* it may race with threaded requests at shutdown. This leak should
|
||||
* only occur when the DS is exiting, so it isn't a big deal.
|
||||
*/
|
||||
if (!authcfg_init()) {
|
||||
LOG_FATAL("AuthConf initialization failed!\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
krberr = krb5_init_context(&krbctx);
|
||||
if (krberr) {
|
||||
LOG_FATAL("krb5_init_context failed\n");
|
||||
@@ -1937,13 +1883,13 @@ static int ipapwd_start( Slapi_PBlock *pb )
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
if (slapi_pblock_get(pb, SLAPI_TARGET_DN, &config_dn) != 0) {
|
||||
if (slapi_pblock_get(pb, SLAPI_TARGET_SDN, &config_sdn) != 0) {
|
||||
LOG_FATAL("No config DN?\n");
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ipapwd_getEntry(config_dn, &config_entry, NULL) != LDAP_SUCCESS) {
|
||||
if (ipapwd_getEntry(config_sdn, &config_entry, NULL) != LDAP_SUCCESS) {
|
||||
LOG_FATAL("No config Entry extop?\n");
|
||||
ret = LDAP_SUCCESS;
|
||||
goto done;
|
||||
@@ -1972,7 +1918,7 @@ static int ipapwd_start( Slapi_PBlock *pb )
|
||||
goto done;
|
||||
}
|
||||
|
||||
ipa_pwd_config_dn = slapi_ch_strdup(config_dn);
|
||||
ipa_pwd_config_dn = slapi_ch_strdup(slapi_sdn_get_dn(config_sdn));
|
||||
if (!ipa_pwd_config_dn) {
|
||||
LOG_OOM();
|
||||
ret = LDAP_OPERATIONS_ERROR;
|
||||
@@ -1997,11 +1943,16 @@ static int ipapwd_start( Slapi_PBlock *pb )
|
||||
|
||||
ret = LDAP_SUCCESS;
|
||||
|
||||
/* NOTE: We never call otp_config_fini() from a destructor. This is because
|
||||
* it may race with threaded requests at shutdown. This leak should
|
||||
* only occur when the DS is exiting, so it isn't a big deal.
|
||||
*/
|
||||
otp_config = otp_config_init(ipapwd_plugin_id);
|
||||
|
||||
done:
|
||||
free(realm);
|
||||
krb5_free_context(krbctx);
|
||||
if (config_entry) slapi_entry_free(config_entry);
|
||||
if (ret != LDAP_SUCCESS) authcfg_fini();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libotp.h>
|
||||
#include "../libotp/otp_token.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -51,7 +51,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <prio.h>
|
||||
#include <ssl.h>
|
||||
#include <krb5.h>
|
||||
#include <kdb.h>
|
||||
#include <lber.h>
|
||||
@@ -90,6 +89,7 @@ struct ipapwd_operation {
|
||||
struct ipapwd_data pwdata;
|
||||
int pwd_op;
|
||||
int is_krb;
|
||||
int is_memberof;
|
||||
int skip_keys;
|
||||
int skip_history;
|
||||
};
|
||||
@@ -113,12 +113,15 @@ struct ipapwd_krbcfg {
|
||||
|
||||
int ipapwd_entry_checks(Slapi_PBlock *pb, struct slapi_entry *e,
|
||||
int *is_root, int *is_krb, int *is_smb, int *is_ipant,
|
||||
int *is_memberof,
|
||||
char *attr, int access);
|
||||
int ipapwd_gen_checks(Slapi_PBlock *pb, char **errMesg,
|
||||
struct ipapwd_krbcfg **config, int check_flags);
|
||||
int ipapwd_CheckPolicy(struct ipapwd_data *data);
|
||||
int ipapwd_getEntry(const char *dn, Slapi_Entry **e2, char **attrlist);
|
||||
int ipapwd_getEntry(Slapi_DN *sdn, Slapi_Entry **e2, char **attrlist);
|
||||
int ipapwd_get_cur_kvno(Slapi_Entry *target);
|
||||
int ipapwd_setdate(Slapi_Entry *source, Slapi_Mods *smods, const char *attr,
|
||||
time_t date, bool remove);
|
||||
int ipapwd_SetPassword(struct ipapwd_krbcfg *krbcfg,
|
||||
struct ipapwd_data *data, int is_krb);
|
||||
Slapi_Value **ipapwd_setPasswordHistory(Slapi_Mods *smods,
|
||||
@@ -129,6 +132,7 @@ int ipapwd_set_extradata(const char *dn,
|
||||
time_t unixtime);
|
||||
void ipapwd_free_slapi_value_array(Slapi_Value ***svals);
|
||||
void free_ipapwd_krbcfg(struct ipapwd_krbcfg **cfg);
|
||||
int ipapwd_check_max_pwd_len(size_t len, char **errMesg);
|
||||
|
||||
/* from encoding.c */
|
||||
struct ipapwd_keyset {
|
||||
@@ -143,6 +147,7 @@ void ipapwd_keyset_free(struct ipapwd_keyset **pkset);
|
||||
|
||||
Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
|
||||
struct ipapwd_data *data,
|
||||
char *preferred_principal,
|
||||
int num_encsalts,
|
||||
krb5_key_salt_tuple *encsalts,
|
||||
char **errMesg);
|
||||
|
||||
@@ -37,26 +37,23 @@
|
||||
* All rights reserved.
|
||||
* END COPYRIGHT BLOCK **/
|
||||
|
||||
#include "../libotp/otp_token.h"
|
||||
#include "otpctrl.h"
|
||||
|
||||
#include <libotp.h>
|
||||
#include "syncreq.h"
|
||||
|
||||
#define OTP_SYNC_MAX_STEPS 25
|
||||
|
||||
bool sync_request_present(Slapi_PBlock *pb)
|
||||
bool otpctrl_present(Slapi_PBlock *pb, const char *oid)
|
||||
{
|
||||
LDAPControl **controls = NULL;
|
||||
|
||||
if (slapi_pblock_get(pb, SLAPI_REQCONTROLS, &controls) != 0)
|
||||
return false;
|
||||
|
||||
return ldap_control_find(OTP_SYNC_REQUEST_OID, controls, NULL) != NULL;
|
||||
return ldap_control_find(oid, controls, NULL) != NULL;
|
||||
}
|
||||
|
||||
bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
|
||||
bool otpctrl_sync_handle(const struct otp_config *cfg, Slapi_PBlock *pb,
|
||||
const char *user_dn)
|
||||
{
|
||||
struct otptoken **tokens = NULL;
|
||||
struct otp_token **tokens = NULL;
|
||||
LDAPControl **controls = NULL;
|
||||
struct berval *second = NULL;
|
||||
struct berval *first = NULL;
|
||||
@@ -86,15 +83,15 @@ bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
|
||||
}
|
||||
|
||||
/* Decode the optional token DN. */
|
||||
ber_scanf(ber, "a", &token_dn);
|
||||
(void)ber_scanf(ber, "a", &token_dn);
|
||||
|
||||
/* Process the synchronization. */
|
||||
success = false;
|
||||
if (ber_scanf(ber, "}") != LBER_ERROR) {
|
||||
tokens = otptoken_find(plugin_id, user_dn, token_dn, true, NULL);
|
||||
tokens = otp_token_find(cfg, user_dn, token_dn, true, NULL);
|
||||
if (tokens != NULL) {
|
||||
success = otptoken_sync_berval(tokens, OTP_SYNC_MAX_STEPS, first, second);
|
||||
otptoken_free_array(tokens);
|
||||
success = otp_token_validate_berval(tokens, first, second);
|
||||
otp_token_free_array(tokens);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,9 @@
|
||||
* All rights reserved.
|
||||
* END COPYRIGHT BLOCK **/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SYNCREQ_H_
|
||||
#define SYNCREQ_H_
|
||||
|
||||
#include <dirsrv/slapi-plugin.h>
|
||||
#include "../libotp/otp_config.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
@@ -55,9 +53,10 @@
|
||||
*/
|
||||
#define OTP_SYNC_REQUEST_OID "2.16.840.1.113730.3.8.10.6"
|
||||
|
||||
bool sync_request_present(Slapi_PBlock *pb);
|
||||
/* This control has no data. */
|
||||
#define OTP_REQUIRED_OID "2.16.840.1.113730.3.8.10.7"
|
||||
|
||||
bool sync_request_handle(Slapi_ComponentId *plugin_id, Slapi_PBlock *pb,
|
||||
bool otpctrl_present(Slapi_PBlock *pb, const char *oid);
|
||||
|
||||
bool otpctrl_sync_handle(const struct otp_config *cfg, Slapi_PBlock *pb,
|
||||
const char *user_dn);
|
||||
|
||||
#endif /* SYNCREQ_H_ */
|
||||
@@ -62,25 +62,26 @@
|
||||
|
||||
#include "ipapwd.h"
|
||||
#include "util.h"
|
||||
#include "syncreq.h"
|
||||
#include "authcfg.h"
|
||||
#include "otpctrl.h"
|
||||
|
||||
#define IPAPWD_OP_NULL 0
|
||||
#define IPAPWD_OP_ADD 1
|
||||
#define IPAPWD_OP_MOD 2
|
||||
|
||||
#define OTP_VALIDATE_STEPS 3
|
||||
|
||||
extern Slapi_PluginDesc ipapwd_plugin_desc;
|
||||
extern void *ipapwd_plugin_id;
|
||||
extern const char *ipa_realm_tree;
|
||||
|
||||
struct otp_config *otp_config = NULL;
|
||||
|
||||
/* structure with information for each extension */
|
||||
struct ipapwd_op_ext {
|
||||
char *object_name; /* name of the object extended */
|
||||
int object_type; /* handle to the extended object */
|
||||
int handle; /* extension handle */
|
||||
};
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* pre/post operations to intercept writes to userPassword
|
||||
****************************************************************************/
|
||||
@@ -130,6 +131,7 @@ static char *ipapwd_getIpaConfigAttr(const char *attr)
|
||||
const char *attrs_list[] = {attr, 0};
|
||||
char *value = NULL;
|
||||
char *dn = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
int ret;
|
||||
|
||||
dn = slapi_ch_smprintf("cn=ipaconfig,cn=etc,%s", ipa_realm_tree);
|
||||
@@ -138,9 +140,12 @@ static char *ipapwd_getIpaConfigAttr(const char *attr)
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = ipapwd_getEntry(dn, &entry, (char **) attrs_list);
|
||||
/* _byref() will take ownership of the dn */
|
||||
sdn = slapi_sdn_new_dn_byref(dn);
|
||||
|
||||
ret = ipapwd_getEntry(sdn, &entry, (char **) attrs_list);
|
||||
if (ret) {
|
||||
LOG("failed to retrieve config entry: %s\n", dn);
|
||||
LOG("failed to retrieve config entry: %s\n", slapi_sdn_get_dn(sdn));
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -148,10 +153,51 @@ static char *ipapwd_getIpaConfigAttr(const char *attr)
|
||||
|
||||
done:
|
||||
slapi_entry_free(entry);
|
||||
slapi_ch_free_string(&dn);
|
||||
slapi_sdn_free(&sdn);
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool has_krbprincipalkey(Slapi_Entry *entry) {
|
||||
int rc;
|
||||
krb5_key_data *keys = NULL;
|
||||
int num_keys = 0;
|
||||
int mkvno = 0;
|
||||
int hint;
|
||||
Slapi_Attr *attr;
|
||||
Slapi_Value *keys_value;
|
||||
const struct berval *bval;
|
||||
|
||||
|
||||
if (slapi_entry_attr_find(entry, "krbPrincipalKey", &attr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* It exists a krbPrincipalKey attribute checks it exists a valid value */
|
||||
for (hint = slapi_attr_first_value(attr, &keys_value);
|
||||
hint != -1; hint = slapi_attr_next_value(attr, hint, &keys_value)) {
|
||||
bval = slapi_value_get_berval(keys_value);
|
||||
if (NULL != bval && NULL != bval->bv_val) {
|
||||
rc = ber_decode_krb5_key_data(discard_const(bval),
|
||||
&mkvno, &num_keys, &keys);
|
||||
|
||||
if (rc || (num_keys <= 0)) {
|
||||
/* this one is not valid, ignore it */
|
||||
if (keys) {
|
||||
ipa_krb5_free_key_data(keys, num_keys);
|
||||
keys = NULL;
|
||||
num_keys = 0;
|
||||
}
|
||||
} else {
|
||||
/* It exists at least this one that is valid, no need to continue */
|
||||
if (keys) ipa_krb5_free_key_data(keys, num_keys);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* PRE ADD Operation:
|
||||
* Gets the clean text password (fail the operation if the password came
|
||||
@@ -170,10 +216,10 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
char *errMesg = "Internal operations error\n";
|
||||
struct slapi_entry *e = NULL;
|
||||
char *userpw = NULL;
|
||||
char *dn = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
struct ipapwd_operation *pwdop = NULL;
|
||||
void *op;
|
||||
int is_repl_op, is_root, is_krb, is_smb, is_ipant;
|
||||
int is_repl_op, is_root, is_krb, is_smb, is_ipant, is_memberof;
|
||||
int ret;
|
||||
int rc = LDAP_SUCCESS;
|
||||
|
||||
@@ -198,8 +244,8 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
/* check this is something interesting for us first */
|
||||
userpw = slapi_entry_attr_get_charptr(e, SLAPI_USERPWD_ATTR);
|
||||
if (!userpw) {
|
||||
/* nothing interesting here */
|
||||
return 0;
|
||||
/* nothing interesting here */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ok this is interesting,
|
||||
@@ -232,6 +278,10 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||
slapi_ch_free_string(&userpw);
|
||||
} else {
|
||||
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
userpw = slapi_ch_strdup(userpw_clear);
|
||||
}
|
||||
|
||||
@@ -246,6 +296,19 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* With User Life Cycle, it could be a stage user that is activated.
|
||||
* The userPassword and krb keys were set while the user was a stage user.
|
||||
* Accept hashed userPassword and krb keys at the condition, it already contains
|
||||
* a valid krbPrincipalKey
|
||||
*/
|
||||
if (has_krbprincipalkey(e)) {
|
||||
slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
|
||||
LOG("User Life Cycle: %s is a activated stage user "
|
||||
"(with prehashed password and krb keys)\n",
|
||||
sdn ? slapi_sdn_get_dn(sdn) : "unknown");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG("pre-hashed passwords are not valid\n");
|
||||
errMesg = "pre-hashed passwords are not valid\n";
|
||||
goto done;
|
||||
@@ -255,6 +318,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
|
||||
rc = ipapwd_entry_checks(pb, e,
|
||||
&is_root, &is_krb, &is_smb, &is_ipant,
|
||||
&is_memberof,
|
||||
NULL, SLAPI_ACL_ADD);
|
||||
if (rc != LDAP_SUCCESS) {
|
||||
goto done;
|
||||
@@ -266,7 +330,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
}
|
||||
|
||||
/* Get target DN */
|
||||
ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
|
||||
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
|
||||
if (ret) {
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
@@ -289,6 +353,7 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
|
||||
pwdop->pwd_op = IPAPWD_OP_ADD;
|
||||
pwdop->pwdata.password = slapi_ch_strdup(userpw);
|
||||
pwdop->is_memberof = is_memberof;
|
||||
|
||||
if (is_root) {
|
||||
pwdop->pwdata.changetype = IPA_CHANGETYPE_DSMGR;
|
||||
@@ -310,12 +375,15 @@ static int ipapwd_pre_add(Slapi_PBlock *pb)
|
||||
}
|
||||
}
|
||||
|
||||
pwdop->pwdata.dn = slapi_ch_strdup(dn);
|
||||
pwdop->pwdata.dn = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
|
||||
pwdop->pwdata.timeNow = time(NULL);
|
||||
pwdop->pwdata.target = e;
|
||||
|
||||
ret = ipapwd_CheckPolicy(&pwdop->pwdata);
|
||||
if (ret) {
|
||||
/* For accounts created by cn=Directory Manager or a passsync
|
||||
* managers, ignore result of a policy check */
|
||||
if ((pwdop->pwdata.changetype != IPA_CHANGETYPE_DSMGR) &&
|
||||
(ret != 0) ) {
|
||||
errMesg = ipapwd_error2string(ret);
|
||||
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||
goto done;
|
||||
@@ -390,7 +458,7 @@ done:
|
||||
#define NTHASH_REGEN_VAL "MagicRegen"
|
||||
#define NTHASH_REGEN_LEN sizeof(NTHASH_REGEN_VAL)
|
||||
static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
|
||||
char *dn, struct slapi_entry *entry,
|
||||
const char *dn, struct slapi_entry *entry,
|
||||
struct ipapwd_krbcfg *krbcfg);
|
||||
|
||||
/* PRE MOD Operation:
|
||||
@@ -412,12 +480,12 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
Slapi_Mods *smods = NULL;
|
||||
char *userpw = NULL;
|
||||
char *unhashedpw = NULL;
|
||||
char *dn = NULL;
|
||||
Slapi_DN *tmp_dn;
|
||||
Slapi_DN *sdn = NULL;
|
||||
Slapi_DN *tmp_sdn;
|
||||
struct slapi_entry *e = NULL;
|
||||
struct ipapwd_operation *pwdop = NULL;
|
||||
void *op;
|
||||
int is_repl_op, is_pwd_op, is_root, is_krb, is_smb, is_ipant;
|
||||
int is_repl_op, is_pwd_op, is_root, is_krb, is_smb, is_ipant, is_memberof;
|
||||
int has_krb_keys = 0;
|
||||
int has_history = 0;
|
||||
int gen_krb_keys = 0;
|
||||
@@ -466,6 +534,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
/* check op filtering out LDAP_MOD_BVALUES */
|
||||
switch (lmod->mod_op & 0x0f) {
|
||||
case LDAP_MOD_ADD:
|
||||
case LDAP_MOD_REPLACE:
|
||||
if (!lmod->mod_bvalues ||
|
||||
!lmod->mod_bvalues[0]) {
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
@@ -477,8 +546,8 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
(strncmp(NTHASH_REGEN_VAL,
|
||||
bv->bv_val, bv->bv_len) == 0)) {
|
||||
is_magic_regen = 1;
|
||||
/* make sure the database will later ignore this mod */
|
||||
slapi_mods_remove(smods);
|
||||
/* We do not remove the mod from the list due to
|
||||
* https://pagure.io/389-ds-base/issue/387#comment-120145 */
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@@ -496,6 +565,11 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
goto done;
|
||||
}
|
||||
bv = lmod->mod_bvalues[0];
|
||||
|
||||
rc = ipapwd_check_max_pwd_len(bv->bv_len, &errMesg);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
slapi_ch_free_string(&unhashedpw);
|
||||
unhashedpw = slapi_ch_malloc(bv->bv_len+1);
|
||||
if (!unhashedpw) {
|
||||
@@ -519,14 +593,14 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
* pre-requisites */
|
||||
|
||||
/* Get target DN */
|
||||
ret = slapi_pblock_get(pb, SLAPI_TARGET_DN, &dn);
|
||||
ret = slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn);
|
||||
if (ret) {
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
tmp_dn = slapi_sdn_new_dn_byref(dn);
|
||||
if (tmp_dn) {
|
||||
tmp_sdn = slapi_sdn_dup(sdn);
|
||||
if (tmp_sdn) {
|
||||
/* xxxPAR: Ideally SLAPI_MODIFY_EXISTING_ENTRY should be
|
||||
* available but it turns out that is only true if you are
|
||||
* a dbm backend pre-op plugin - lucky dbm backend pre-op
|
||||
@@ -538,8 +612,8 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
*
|
||||
slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &e);
|
||||
*/
|
||||
ret = slapi_search_internal_get_entry(tmp_dn, 0, &e, ipapwd_plugin_id);
|
||||
slapi_sdn_free(&tmp_dn);
|
||||
ret = slapi_search_internal_get_entry(tmp_sdn, 0, &e, ipapwd_plugin_id);
|
||||
slapi_sdn_free(&tmp_sdn);
|
||||
if (ret != LDAP_SUCCESS) {
|
||||
LOG("Failed to retrieve entry?!\n");
|
||||
rc = LDAP_NO_SUCH_OBJECT;
|
||||
@@ -549,6 +623,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
|
||||
rc = ipapwd_entry_checks(pb, e,
|
||||
&is_root, &is_krb, &is_smb, &is_ipant,
|
||||
&is_memberof,
|
||||
is_pwd_op ? SLAPI_USERPWD_ATTR : "ipaNTHash",
|
||||
SLAPI_ACL_WRITE);
|
||||
if (rc) {
|
||||
@@ -566,7 +641,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
/* Make sense to call only if this entry has krb keys to source
|
||||
* the nthash from */
|
||||
if (is_krb) {
|
||||
rc = ipapwd_regen_nthash(pb, smods, dn, e, krbcfg);
|
||||
rc = ipapwd_regen_nthash(pb, smods, slapi_sdn_get_dn(sdn), e, krbcfg);
|
||||
} else {
|
||||
rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
}
|
||||
@@ -636,6 +711,8 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
is_smb = 0;
|
||||
is_ipant = 0;
|
||||
|
||||
/* After examining the output of covscan, we think that this
|
||||
* fallthrough is intentional.*/
|
||||
case LDAP_MOD_ADD:
|
||||
if (!lmod->mod_bvalues ||
|
||||
!lmod->mod_bvalues[0]) {
|
||||
@@ -713,9 +790,14 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
/* Check this is a clear text password, or refuse operation (only if we need
|
||||
* to comput other hashes */
|
||||
if (! unhashedpw && (gen_krb_keys || is_smb || is_ipant)) {
|
||||
if ('{' == userpw[0]) {
|
||||
if ((userpw != NULL) && ('{' == userpw[0])) {
|
||||
if (0 == strncasecmp(userpw, "{CLEAR}", strlen("{CLEAR}"))) {
|
||||
unhashedpw = slapi_ch_strdup(&userpw[strlen("{CLEAR}")]);
|
||||
const char *userpw_clear = &userpw[strlen("{CLEAR}")];
|
||||
rc = ipapwd_check_max_pwd_len(strlen(userpw_clear), &errMesg);
|
||||
if (rc) {
|
||||
goto done;
|
||||
}
|
||||
unhashedpw = slapi_ch_strdup(userpw_clear);
|
||||
if (NULL == unhashedpw) {
|
||||
LOG_OOM();
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
@@ -749,6 +831,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
}
|
||||
|
||||
pwdop->is_krb = is_krb;
|
||||
pwdop->is_memberof = is_memberof;
|
||||
pwdop->pwd_op = IPAPWD_OP_MOD;
|
||||
pwdop->pwdata.password = slapi_ch_strdup(unhashedpw);
|
||||
pwdop->pwdata.changetype = IPA_CHANGETYPE_NORMAL;
|
||||
@@ -765,7 +848,7 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
/* Check Bind DN */
|
||||
slapi_pblock_get(pb, SLAPI_CONN_DN, &binddn);
|
||||
bdn = slapi_sdn_new_dn_byref(binddn);
|
||||
tdn = slapi_sdn_new_dn_byref(dn);
|
||||
tdn = slapi_sdn_dup(sdn);
|
||||
|
||||
/* if the change is performed by someone else,
|
||||
* it is an admin change that will require a new
|
||||
@@ -788,16 +871,18 @@ static int ipapwd_pre_mod(Slapi_PBlock *pb)
|
||||
|
||||
}
|
||||
|
||||
pwdop->pwdata.dn = slapi_ch_strdup(dn);
|
||||
pwdop->pwdata.dn = slapi_ch_strdup(slapi_sdn_get_dn(sdn));
|
||||
pwdop->pwdata.timeNow = time(NULL);
|
||||
pwdop->pwdata.target = e;
|
||||
|
||||
/* if krb keys are being set by an external agent we assume password
|
||||
* policies have been properly checked already, so we check them only
|
||||
* if no krb keys are available */
|
||||
* policies have been properly checked already. We check them only if no
|
||||
* krb keys are available and raise error if the change is not done by a
|
||||
* cn=Directory Manager or one of passsync managers */
|
||||
if (has_krb_keys == 0) {
|
||||
ret = ipapwd_CheckPolicy(&pwdop->pwdata);
|
||||
if (ret) {
|
||||
if ((pwdop->pwdata.changetype != IPA_CHANGETYPE_DSMGR) &&
|
||||
(ret != 0)) {
|
||||
errMesg = ipapwd_error2string(ret);
|
||||
rc = LDAP_CONSTRAINT_VIOLATION;
|
||||
goto done;
|
||||
@@ -879,7 +964,7 @@ done:
|
||||
}
|
||||
|
||||
static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
|
||||
char *dn, struct slapi_entry *entry,
|
||||
const char *dn, struct slapi_entry *entry,
|
||||
struct ipapwd_krbcfg *krbcfg)
|
||||
{
|
||||
Slapi_Attr *attr;
|
||||
@@ -956,7 +1041,9 @@ static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
|
||||
bval.bv_len = 16;
|
||||
ntvals[0] = &bval;
|
||||
|
||||
slapi_mods_add_modbvps(smods, LDAP_MOD_ADD, "ipaNTHash", ntvals);
|
||||
/* add the change as a replace operation due to
|
||||
* https://pagure.io/389-ds-base/issue/387#comment-120145 */
|
||||
slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE, "ipaNTHash", ntvals);
|
||||
|
||||
ret = LDAP_SUCCESS;
|
||||
break;
|
||||
@@ -967,23 +1054,9 @@ static int ipapwd_regen_nthash(Slapi_PBlock *pb, Slapi_Mods *smods,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ipapwd_post_authcfg(Slapi_PBlock *pb)
|
||||
static int ipapwd_post_updatecfg(Slapi_PBlock *pb)
|
||||
{
|
||||
Slapi_Entry *config_entry = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
int oprc = 0;
|
||||
|
||||
/* Just bail if the operation failed. */
|
||||
if (slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &oprc) != 0 || oprc != 0)
|
||||
return 0;
|
||||
|
||||
if (slapi_pblock_get(pb, SLAPI_TARGET_SDN, &sdn) != 0)
|
||||
return 0;
|
||||
|
||||
/* Ignore the error here (delete operations). */
|
||||
slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &config_entry);
|
||||
|
||||
authcfg_reload_global_config(sdn, config_entry);
|
||||
otp_config_update(otp_config, pb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -993,8 +1066,6 @@ static int ipapwd_post_modadd(Slapi_PBlock *pb)
|
||||
struct ipapwd_operation *pwdop = NULL;
|
||||
Slapi_Mods *smods;
|
||||
Slapi_Value **pwvals;
|
||||
struct tm utctime;
|
||||
char timestr[GENERALIZED_TIME_LENGTH+1];
|
||||
int ret;
|
||||
char *errMsg = "Internal operations error\n";
|
||||
struct ipapwd_krbcfg *krbcfg = NULL;
|
||||
@@ -1003,8 +1074,7 @@ static int ipapwd_post_modadd(Slapi_PBlock *pb)
|
||||
|
||||
LOG_TRACE("=>\n");
|
||||
|
||||
/* Ignore error when parsing configuration. */
|
||||
ipapwd_post_authcfg(pb);
|
||||
otp_config_update(otp_config, pb);
|
||||
|
||||
/* time to get the operation handler */
|
||||
ret = slapi_pblock_get(pb, SLAPI_OPERATION, &op);
|
||||
@@ -1024,7 +1094,7 @@ static int ipapwd_post_modadd(Slapi_PBlock *pb)
|
||||
if (IPAPWD_OP_NULL == pwdop->pwd_op)
|
||||
return 0;
|
||||
|
||||
if ( ! (pwdop->is_krb)) {
|
||||
if ( !pwdop->is_krb || pwdop->is_memberof) {
|
||||
LOG("Not a kerberos user, ignore krb attributes\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -1081,25 +1151,19 @@ static int ipapwd_post_modadd(Slapi_PBlock *pb)
|
||||
(slapi_entry_attr_has_syntax_value(pwdop->pwdata.target,
|
||||
SLAPI_ATTR_OBJECTCLASS, ipahost)) == 0) {
|
||||
/* set Password Expiration date */
|
||||
if (!gmtime_r(&(pwdop->pwdata.expireTime), &utctime)) {
|
||||
LOG_FATAL("failed to parse expiration date (buggy gmtime_r ?)\n");
|
||||
ret = ipapwd_setdate(pwdop->pwdata.target, smods,
|
||||
"krbPasswordExpiration",
|
||||
pwdop->pwdata.expireTime,
|
||||
(pwdop->pwdata.expireTime == 0));
|
||||
if (ret != LDAP_SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
strftime(timestr, GENERALIZED_TIME_LENGTH+1,
|
||||
"%Y%m%d%H%M%SZ", &utctime);
|
||||
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
||||
"krbPasswordExpiration", timestr);
|
||||
|
||||
/* change Last Password Change field with the current date */
|
||||
if (!gmtime_r(&(pwdop->pwdata.timeNow), &utctime)) {
|
||||
LOG_FATAL("failed to parse current date (buggy gmtime_r ?)\n");
|
||||
slapi_value_free(&ipahost);
|
||||
ret = ipapwd_setdate(pwdop->pwdata.target, smods,
|
||||
"krbLastPwdChange",
|
||||
pwdop->pwdata.timeNow, false);
|
||||
if (ret != LDAP_SUCCESS)
|
||||
goto done;
|
||||
}
|
||||
strftime(timestr, GENERALIZED_TIME_LENGTH+1,
|
||||
"%Y%m%d%H%M%SZ", &utctime);
|
||||
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
||||
"krbLastPwdChange", timestr);
|
||||
}
|
||||
slapi_value_free(&ipahost);
|
||||
}
|
||||
@@ -1127,8 +1191,8 @@ done:
|
||||
}
|
||||
|
||||
/*
|
||||
* Authenticates creds against OTP tokens. Returns true when authentication
|
||||
* completed successfully against a token OR when a user has no active tokens.
|
||||
* This function handles the bind functionality for OTP. The return value
|
||||
* indicates if the OTP portion of authentication was successful.
|
||||
*
|
||||
* WARNING: This function DOES NOT authenticate the first factor. Only the OTP
|
||||
* code is validated! You still need to validate the first factor.
|
||||
@@ -1137,64 +1201,13 @@ done:
|
||||
* value at the end. This leaves only the password in creds for later
|
||||
* validation.
|
||||
*/
|
||||
static bool ipapwd_do_otp_auth(const char *dn, Slapi_Entry *bind_entry,
|
||||
struct berval *creds)
|
||||
{
|
||||
struct otptoken **tokens = NULL;
|
||||
bool success = false;
|
||||
|
||||
/* Find all of the user's active tokens. */
|
||||
tokens = otptoken_find(ipapwd_plugin_id, dn, NULL, true, NULL);
|
||||
if (tokens == NULL) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
|
||||
"%s: can't find tokens for '%s'.\n", __func__, dn);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the user has no active tokens, succeed. */
|
||||
success = tokens[0] == NULL;
|
||||
|
||||
/* Loop through each token. */
|
||||
for (int i = 0; tokens[i] && !success; i++) {
|
||||
/* Attempt authentication. */
|
||||
success = otptoken_validate_berval(tokens[i], OTP_VALIDATE_STEPS,
|
||||
creds, true);
|
||||
|
||||
/* Truncate the password to remove the OTP code at the end. */
|
||||
if (success) {
|
||||
creds->bv_len -= otptoken_get_digits(tokens[i]);
|
||||
creds->bv_val[creds->bv_len] = '\0';
|
||||
}
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPAPWD_PLUGIN_NAME,
|
||||
"%s: token authentication %s "
|
||||
"(user: '%s', token: '%s\').\n", __func__,
|
||||
success ? "succeeded" : "failed", dn,
|
||||
slapi_sdn_get_ndn(otptoken_get_sdn(tokens[i])));
|
||||
}
|
||||
|
||||
otptoken_free_array(tokens);
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the bind functionality for OTP. The return value
|
||||
* indicates if the OTP portion of authentication was successful.
|
||||
*
|
||||
* NOTE: This function may modify creds. See explanation in the comment for
|
||||
* ipapwd_do_otp_auth() above.
|
||||
*/
|
||||
static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
|
||||
struct berval *creds)
|
||||
struct berval *creds, bool otpreq)
|
||||
{
|
||||
uint32_t auth_types;
|
||||
|
||||
/* Get the configured authentication types. */
|
||||
auth_types = authcfg_get_auth_types(entry);
|
||||
|
||||
/* If global disabled flag is set, just punt. */
|
||||
if (auth_types & AUTHCFG_AUTH_TYPE_DISABLED)
|
||||
return true;
|
||||
auth_types = otp_config_auth_types(otp_config, entry);
|
||||
|
||||
/*
|
||||
* IMPORTANT SECTION!
|
||||
@@ -1206,14 +1219,36 @@ static bool ipapwd_pre_bind_otp(const char *bind_dn, Slapi_Entry *entry,
|
||||
* 2. If PWD is enabled or OTP succeeded, fall through to PWD validation.
|
||||
*/
|
||||
|
||||
if (auth_types & AUTHCFG_AUTH_TYPE_OTP) {
|
||||
if (auth_types & OTP_CONFIG_AUTH_TYPE_OTP) {
|
||||
struct otp_token **tokens = NULL;
|
||||
|
||||
LOG_PLUGIN_NAME(IPAPWD_PLUGIN_NAME,
|
||||
"Attempting OTP authentication for '%s'.\n", bind_dn);
|
||||
if (ipapwd_do_otp_auth(bind_dn, entry, creds))
|
||||
|
||||
/* Find all of the user's active tokens. */
|
||||
tokens = otp_token_find(otp_config, bind_dn, NULL, true, NULL);
|
||||
if (tokens == NULL) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPAPWD_PLUGIN_NAME,
|
||||
"%s: can't find tokens for '%s'.\n",
|
||||
__func__, bind_dn);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* With no tokens, succeed if tokens aren't required. */
|
||||
if (tokens[0] == NULL) {
|
||||
otp_token_free_array(tokens);
|
||||
return !otpreq;
|
||||
}
|
||||
|
||||
if (otp_token_validate_berval(tokens, creds, NULL)) {
|
||||
otp_token_free_array(tokens);
|
||||
return true;
|
||||
}
|
||||
|
||||
otp_token_free_array(tokens);
|
||||
}
|
||||
|
||||
return auth_types & AUTHCFG_AUTH_TYPE_PASSWORD;
|
||||
return (auth_types & OTP_CONFIG_AUTH_TYPE_PASSWORD) && !otpreq;
|
||||
}
|
||||
|
||||
static int ipapwd_authenticate(const char *dn, Slapi_Entry *entry,
|
||||
@@ -1330,7 +1365,7 @@ static void ipapwd_write_krb_keys(Slapi_PBlock *pb, char *dn,
|
||||
if (expire) {
|
||||
memset(&expire_tm, 0, sizeof (expire_tm));
|
||||
if (strptime(expire, "%Y%m%d%H%M%SZ", &expire_tm))
|
||||
pwdata.expireTime = mktime(&expire_tm);
|
||||
pwdata.expireTime = timegm(&expire_tm);
|
||||
}
|
||||
|
||||
/* check password policy */
|
||||
@@ -1381,22 +1416,28 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
static const char *attrs_list[] = {
|
||||
SLAPI_USERPWD_ATTR, "ipaUserAuthType", "krbprincipalkey", "uid",
|
||||
"krbprincipalname", "objectclass", "passwordexpirationtime",
|
||||
"passwordhistory", "krbprincipalexpiration",
|
||||
"passwordhistory", "krbprincipalexpiration", "krbcanonicalname",
|
||||
"krbPasswordExpiration", "krblastpwchange",
|
||||
NULL
|
||||
};
|
||||
struct berval *credentials = NULL;
|
||||
Slapi_Entry *entry = NULL;
|
||||
char *dn = NULL;
|
||||
Slapi_DN *target_sdn = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
const char *dn = NULL;
|
||||
int method = 0;
|
||||
bool syncreq;
|
||||
bool otpreq;
|
||||
int ret = 0;
|
||||
time_t current_time;
|
||||
time_t expire_time;
|
||||
char *principal_expire = NULL;
|
||||
struct tm expire_tm;
|
||||
int rc = LDAP_INVALID_CREDENTIALS;
|
||||
char *errMesg = NULL;
|
||||
|
||||
/* get BIND parameters */
|
||||
ret |= slapi_pblock_get(pb, SLAPI_BIND_TARGET, &dn);
|
||||
ret |= slapi_pblock_get(pb, SLAPI_BIND_TARGET_SDN, &target_sdn);
|
||||
ret |= slapi_pblock_get(pb, SLAPI_BIND_METHOD, &method);
|
||||
ret |= slapi_pblock_get(pb, SLAPI_BIND_CREDENTIALS, &credentials);
|
||||
if (ret) {
|
||||
@@ -1409,9 +1450,12 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
return 0;
|
||||
|
||||
/* Retrieve the user's entry. */
|
||||
ret = ipapwd_getEntry(dn, &entry, (char **) attrs_list);
|
||||
sdn = slapi_sdn_dup(target_sdn);
|
||||
dn = slapi_sdn_get_dn(sdn);
|
||||
ret = ipapwd_getEntry(sdn, &entry, (char **) attrs_list);
|
||||
if (ret) {
|
||||
LOG("failed to retrieve user entry: %s\n", dn);
|
||||
slapi_sdn_free(&sdn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1423,10 +1467,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
memset(&expire_tm, 0, sizeof (expire_tm));
|
||||
|
||||
if (strptime(principal_expire, "%Y%m%d%H%M%SZ", &expire_tm)) {
|
||||
expire_time = mktime(&expire_tm);
|
||||
expire_time = timegm(&expire_tm);
|
||||
current_time = time(NULL);
|
||||
|
||||
/* mktime returns -1 if the tm struct cannot be represented as
|
||||
/* timegm returns -1 if the tm struct cannot be represented as
|
||||
* as calendar time (seconds since the Epoch). This might
|
||||
* happen with tm structs that are ill-formated or on 32-bit
|
||||
* platforms with dates that would cause overflow
|
||||
@@ -1436,6 +1480,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
if (current_time > expire_time && expire_time > 0) {
|
||||
LOG_FATAL("kerberos principal in %s is expired\n", dn);
|
||||
slapi_entry_free(entry);
|
||||
slapi_sdn_free(&sdn);
|
||||
slapi_send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
|
||||
"Account (Kerberos principal) is expired",
|
||||
0, NULL);
|
||||
@@ -1445,35 +1490,44 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb)
|
||||
}
|
||||
|
||||
/* Try to do OTP first. */
|
||||
syncreq = sync_request_present(pb);
|
||||
if (!syncreq && !ipapwd_pre_bind_otp(dn, entry, credentials))
|
||||
syncreq = otpctrl_present(pb, OTP_SYNC_REQUEST_OID);
|
||||
otpreq = otpctrl_present(pb, OTP_REQUIRED_OID);
|
||||
if (!syncreq && !ipapwd_pre_bind_otp(dn, entry, credentials, otpreq))
|
||||
goto invalid_creds;
|
||||
|
||||
/* Ensure that there is a password. */
|
||||
if (credentials->bv_len == 0)
|
||||
if (credentials->bv_len == 0) {
|
||||
goto invalid_creds;
|
||||
} else {
|
||||
rc = ipapwd_check_max_pwd_len(credentials->bv_len, &errMesg);
|
||||
if (rc) {
|
||||
goto invalid_creds;
|
||||
}
|
||||
}
|
||||
|
||||
/* Authenticate the user. */
|
||||
ret = ipapwd_authenticate(dn, entry, credentials);
|
||||
if (ret) {
|
||||
slapi_entry_free(entry);
|
||||
slapi_sdn_free(&sdn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Attempt to handle a token synchronization request. */
|
||||
if (syncreq && !sync_request_handle(ipapwd_get_plugin_id(), pb, dn))
|
||||
if (syncreq && !otpctrl_sync_handle(otp_config, pb, dn))
|
||||
goto invalid_creds;
|
||||
|
||||
/* Attempt to write out kerberos keys for the user. */
|
||||
ipapwd_write_krb_keys(pb, dn, entry, credentials);
|
||||
ipapwd_write_krb_keys(pb, discard_const(dn), entry, credentials);
|
||||
|
||||
slapi_entry_free(entry);
|
||||
slapi_sdn_free(&sdn);
|
||||
return 0;
|
||||
|
||||
invalid_creds:
|
||||
slapi_entry_free(entry);
|
||||
slapi_send_ldap_result(pb, LDAP_INVALID_CREDENTIALS,
|
||||
NULL, NULL, 0, NULL);
|
||||
slapi_sdn_free(&sdn);
|
||||
slapi_send_ldap_result(pb, rc, NULL, errMesg, 0, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1483,12 +1537,11 @@ int ipapwd_pre_init(Slapi_PBlock *pb)
|
||||
int ret;
|
||||
|
||||
slapi_register_supported_control(OTP_SYNC_REQUEST_OID, SLAPI_OPERATION_BIND);
|
||||
slapi_register_supported_control(OTP_REQUIRED_OID, SLAPI_OPERATION_BIND);
|
||||
|
||||
ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_BIND_FN, (void *)ipapwd_pre_bind);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_ADD_FN, (void *)ipapwd_pre_add);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_PRE_MODIFY_FN, (void *)ipapwd_pre_mod);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1512,10 +1565,8 @@ int ipapwd_post_init(Slapi_PBlock *pb)
|
||||
|
||||
ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, (void *)ipapwd_post_modadd);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *)ipapwd_post_authcfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *)ipapwd_post_modadd);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *)ipapwd_post_authcfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *)ipapwd_post_updatecfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODRDN_FN, (void *)ipapwd_post_updatecfg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1526,10 +1577,10 @@ int ipapwd_intpost_init(Slapi_PBlock *pb)
|
||||
|
||||
ret = slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_03);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&ipapwd_plugin_desc);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, (void *)ipapwd_post_authcfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *)ipapwd_post_authcfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, (void *)ipapwd_post_authcfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, (void *)ipapwd_post_authcfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, (void *)ipapwd_post_updatecfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *)ipapwd_post_updatecfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, (void *)ipapwd_post_updatecfg);
|
||||
if (!ret) ret = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, (void *)ipapwd_post_updatecfg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user