From 8856b2af41e69f5e1c9fdc2045fd84350d382327 Mon Sep 17 00:00:00 2001 From: mchyzer Date: Tue, 15 Nov 2022 00:46:56 -0500 Subject: [PATCH] GRP-4484: ldaptive upgrade now uses durations --- .../ldap/ldaptive/LdaptiveSessionImpl$1.class | Bin 0 -> 4766 bytes .../ldaptive/LdaptiveSessionImpl$10.class | Bin 0 -> 1829 bytes .../ldap/ldaptive/LdaptiveSessionImpl$2.class | Bin 0 -> 4916 bytes .../ldap/ldaptive/LdaptiveSessionImpl$3.class | Bin 0 -> 2947 bytes .../ldap/ldaptive/LdaptiveSessionImpl$4.class | Bin 0 -> 5061 bytes .../ldap/ldaptive/LdaptiveSessionImpl$5.class | Bin 0 -> 3018 bytes .../ldap/ldaptive/LdaptiveSessionImpl$6.class | Bin 0 -> 4276 bytes .../ldap/ldaptive/LdaptiveSessionImpl$7.class | Bin 0 -> 6922 bytes .../ldap/ldaptive/LdaptiveSessionImpl$8.class | Bin 0 -> 5089 bytes .../ldap/ldaptive/LdaptiveSessionImpl$9.class | Bin 0 -> 5723 bytes .../ldap/ldaptive/LdaptiveSessionImpl.class | Bin 0 -> 36442 bytes .../ldap/ldaptive/LdaptiveSessionImpl.java | 1292 +++++++++++++++++ 12 files changed, 1292 insertions(+) create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$1.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$10.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$2.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$3.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$4.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$5.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$6.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$7.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$8.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$9.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl.class create mode 100644 container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl.java diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$1.class b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$1.class new file mode 100644 index 0000000000000000000000000000000000000000..1cd57b07a9e4375ca7108a54e73ea3a3bfbefc24 GIT binary patch literal 4766 zcmb_g`&S%i8GgQDVU}eAgd~t{8oN!gfemCsY!d^RO1QMx4UHk8rqP;VcUU%EX2{Ge zO=@kuRjW~3Z`IU$y`I zBbDZtB*qQL$y?^=%xs~(M@2-S`Mf@-rwY26OFb}o-pIHr>I8bK!T^}Wz(+ll#&A4ID8TM#ape4N~?YL{_%^cTha-C!7c4m6W6xg=5 zO%9D`tXV_gaFsI26ODUV-bTX5B;HiMKwS%Ll^?oG){{lo7}IA6-6+Rw!!6q8sY{aA z){vBg1>JFoQrDk1^X^fBe{@tS$)?%~aR~HKVWc`Ml%Kc)&^o1u*7yhPoDhf%T3MqW z0<9WUL?yLTLp@@Wx?VF2wh4C7uEBLeY~ zqlFKjF`qn7CPpY))L{RPNk%mVmOTtX*h$2SYIgq zz)H#&IM5MNVqo1eHAX~UHm9b`Km<0R^?8BX= zwjB*RCRsO(3q`#^z3r{Qwt^rJNy)Ps3`_~sQgT@mOJgsPIfiMRSCOx#*n76R*Y7N( zbQ&H(fyQuI?*?_pWql2c7i77RctMp2jRb2NU}9E<#WK2PE$L($E`Ua^(X*`kJ1U@e z@~AH6R1_;^&sFtncvSje6IJ0Kd_pf24M%#(B@K_^V@y)hx-&+H@M;ZF`|)uNPvFV5 z#Ly$Khu&7nY*sGEHYAm{a`e1U;?pWV#mct%N)4Zpd>ix5kTF@z4V$upWmSBZ$Qn$BujD|CF30L~=Hz-rW_A-K#n6m7I6Le#}o*dtlaNiQ>4qIqN zj*z*_VV`GQbrH+&+IkaFd`F<6E8#aXuZx?yX&WbuttoB`U`43nd2w=?^ zE7D1UrtyM?AK}MTu50-`M=YDhDGQ*$`zoBgPb%rB8m`I!imrf2)Ba4u&+!XJRaP3U zO!Wbv*Q&_U5GsXlulWpZWSbC?SWK~{X*yKAsYYLke$p1$Rk}2sj)_<2Tavo-ZQ}*D z3^&fz8Zz@y>7@v(Igv~1S4}{_S-)&G=(x1WWOF=f$`;vSrlSWou5R{1u(X>G^v8r; z+SW0_1g+i4DtkI9Z%B!o^*yvg>W4DSvMq75SSH4 z-l?8rJ#>&1#bBnw;cyHbsyf^O*-kUcD@6G#y z_vUSZ_hN;=7HlKRc2X1kCJMTe`{uDD*)@;0WcNJc$#`TQyOQzRdF)Qc>*jG=GOo_! z_T+Wk@v?_2Le=Zb^UFr+J#^TE5RmJkp$9 z#1Ba=;3rFXQ9(TNlBZs2iigogh5j2+@gH=HWgMcNPbdOsl^PV32ppvrPbhVGT2XOX zsmHTQj1U@LQMO=FX~Y}+{u}qarR=~zl~&QDw26eWQyd|ERN3X3c*-|gU}BmNzr?R- z+^9H$U*k74Z@1Wvm+&$Te@Haow|IrdKY_<_4fAx`vusoraGj3pU;JI|nQ8ADK22o(oa99A)`vW~0lRIrQ@M9XGW zoaUU$CWzD95ZiFtL)f!SX*L4CfZDR%o(cZIr$Qg}z5I`O!yE0#pKy~@j7N~s!N30j D$)Rnq literal 0 HcmV?d00001 diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$10.class b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$10.class new file mode 100644 index 0000000000000000000000000000000000000000..ebfddc755d79d2d2ea3941e3142a3e8644ae5dad GIT binary patch literal 1829 zcmb_dT~pIQ6g}J421>BytDuOYR&5IsKoPNsT0~{6GGiSc`sB7*N-%6XNs9WfbVmGo zaD4Vx_~PGiyjzN;P=eXs@o+^%G z8>_q1gb&YK(()G=%;ZTBI5Jvll_9j~n4%L5Q5_mOl+~l76Ojml=+n`KeuiLDL8CcK zis#kMqHtgGqAeJDb54odtK79zzdjgJ8Dw~T0`#f8l#&jLVHbJnHN(?(ld`9#S;1u{ zm1|W9IgTv7EeR@~BRvfx41EpEzZr(kyj7Omue!A1wPVJgZ?40lBPEHH0%sNuq87nL zT-I=jVWvG1wrp2N0#_KcvhdXmLx1vs1ZcR%FxVu=2C*)rFs32RFx-S_7OakOT&D`v z1x^_nNbb*cst|#JDGhY2dKx*-lJ==KI;L@h$dZq$SXpC;CkuPo)?rkys5)!)ld7u9 zFx#fcTJl4_;?2^1SJ{>Ci{rUGs=}nSyi;{c;*q6J&5&Z#a*<7_v@pEdpS=I4b2OFc zk}TPdXUXz2;jcTUhPw>e_GG5=f7o58;~wraoc4w1H)PZzh`jGo;7qE(pfA%Ia2IXv zdBVde-8(^Qrx1w6)I|iudet>V|BC>%F6cDdP1YRsgY=E2$F^}gJ-&@t`ZIbz)PMu@ z4igZeUx<^f77-MK7@{x38JwlX!(@l3cMj*t3gAM`ae*uqsz3b^v9V7W{ei1rkqqDq zCf?I{5Do9YYu@8K__}vmNx!xk@_UQWJCW7MERBS4yB2A#9`Oz`)DK}E3wS_QgfNOJ GJ%0fz*%!0` literal 0 HcmV?d00001 diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$2.class b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$2.class new file mode 100644 index 0000000000000000000000000000000000000000..c4d3cefb926f52bf998311609685da101daa731d GIT binary patch literal 4916 zcmb_g`FGUT8NE*)TjQ|+Ed!=3O(M^T@xWM`N*V%A z+oWkq_kE#B*Q5(=x+N_(c4%n2(Ink|$PfK*O7D|okH$7Wlb-mTkv=^=-EV#Oea~Phhx_$QlG@~z5qoLonEG~BH z@7=qYg$ZoMHWlv^*j|4bMZDIq9XkZng6YY42;AMVNE}q`5?FHw!&Ibe=qV`l1p2U7 z#U6qE^%=I*I@0idJjg5?xg3d++$9qAhIc90-blu0m**XvTx@E6e#x*#nQEcV(+h_p zBN?0Q*;!i^0p3y5t(3f875m9${@Sm2#Zu~^;f@_P$_ea4djf+vpkhcsuW>92py42f zS?Mf+L5qxOa$&BWtpXph-!7HHB5c7S99EHGp;R?i-)lI6hnc7%S=jJwGV$sfq~UP9 zw*?e{BLltNCt%hT=C}Wm+k=qVaG4nDleVzNFH-RF~t2nn956#WeP?GsvL0tjnh*7GTZUPp{ zD(rfi20!Zuf)3?4Yf8gMz+A>X?wkFF%W&+Bn!Yd`;cl}qKrQfaK}ChzaW&R5Wf~sG zMF!i*vwv8%2zuu!Su+zFp1?;*SYw8JgyrGyJEtVsd|bnmc&bVgTLkW7?a9h9%0_O? zOy%tHaq@VoWETo-Nm3cRz&d;yq$ce$l!YWS4YyS(TQn4^`#pe1*+yoyhg7=2It z)+`A4{z|cwH=Q^>%Z6geu2}hG0+;c5xl?{&o_DipACXn~B@JK3S6KOOae{jYx71g8=rpIcsy8;j-`(4L`+IhTO9QtA=ccDHGTj^&zaiMdHELav49@@S-Gu z_$-J__%Aj53cn^R+BV! zN0HDk)lZStBR(>CeG67XxbORfD1*><>?j+ty>w?)75JB-HL_jqYP0Hv-2ReBd=)xx2+D$peryisz zDcCHvDsRvt+9>vHn!=XXu=8-&H7dV`HQl`E{H^0}L+n-TKG{I&o~)Qg?~xnWck(*= z)3JsfjXhHsn88B=Y4s{5bae(F5O@v8(@i&Ug0oJh<9gE+PNkdmnBJ_%XYfb^PUuY% zZ3_8xLQmYnemyaTu>eN9icVegVbU#n3+LTCjd3a7LhCb)LXYb$GjJ7xa25&Xx!Z3^ zwZ8Q9G(I+iPY67Va};mj^2xT(T*v41*bKfXFomzSeRB#|Ry9iLIZA|I!&}>T16h~y z_XBx@lz$k=H1$f`3%uyD*8DVnOlb-~o53#>=&_gl(8@GCf;9~4F2t2IdXzrwQ1)QA zvKLw9L7Y+cA*b}iRt7Pl9Ke&xL0nND!VAhFTval7Q8|oj9J|T+uPa%+r5qD2%5kw? z84=qlri5BSkGj#>He<5yw z@mFHp;;acY-o^pMRZubijkHt6po&M?J+YI*Z46=A{8uWD^Q8**-MdwGoBquEZ_|`J lqCA17`6$#K!{2yS@OoI_Z{SUTv=4vBzbGYWw_F(f`yaPHpez6Y literal 0 HcmV?d00001 diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$3.class b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$3.class new file mode 100644 index 0000000000000000000000000000000000000000..836d9b6096d0d29695900a83e09a4187cae7b373 GIT binary patch literal 2947 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 literal 0 HcmV?d00001 diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$5.class b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$5.class new file mode 100644 index 0000000000000000000000000000000000000000..18ffae4efc6d25ffa38595219706e9cbf1777e22 GIT binary patch literal 3018 zcmb_e>r)$56#v~Nur%EY1zJcgw$)&h@Ce0XZGu>N32gv*2*p}ulU%~WvYT!;(E8DT zreAeN9u=qUjE_;r@lO)ZNg^bHVC)noyXW3L_dI{+ocqV$KRgF;6B!kXz=%v{!-nNb z$C7Sec*960O}V8zGMsYkY+5>DGpVO@57*d~;TWx$n3I`|VOtX$Y17}Y!XwbQrf=$D zQ@2v#>G+yVxGL%dZd50q#g6M1>2?I_+*Kpv?fu0jM${=tkIhT)N%xRd%X9RfpSSGSA6>7N5m4ca6Y$YBX zhKXaksNp{MyxN3mXQYbH36e*Byr?5I@GK}y5^gdAx2kM;Wpzp*@~|vQV5wb4Wk4*A ziNki0$A-X_O6&#jkP|GokL1TGNtD{s10@h36&Fj}`IGd&Eq(UY96PPwQ7z25)YK>S zbZ%~_SS<PDQ1wgN8I7(d9tTx~p6*37z44`=lB;!eXIrio8CoBoZ}2!^Igk z>82qwxJqNahJLlEX>8<)4>UIMywAO9+S5Hvp`V6x#PtSIgS7V0yCu}QjfPOyHqM8- zx6vHh#f9&3+->x%BW@^r@DZ&sjTT(OoAf5Ip`CQTMYM-jS8$Ce1#h!-@lDV0Q5-S|W9PhVCj)Q5#WxbuWsS;#;z(9n3Vwva^(WdfOE(U`X5x^?MfT;)g zg1oQC3LfH1^1q4JUy)X}WCl9zd1yXfMjQ#sPLfXN=E&X4YZS+Jg<)aES7fcFrjM{R73z BX{7)F literal 0 HcmV?d00001 diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$6.class b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$6.class new file mode 100644 index 0000000000000000000000000000000000000000..003e1a8342dc8e8792d1f93a19425a115e1bf079 GIT binary patch literal 4276 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 PpYb=gyj)h-694`Sc4!3w literal 0 HcmV?d00001 diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$9.class b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl$9.class new file mode 100644 index 0000000000000000000000000000000000000000..4a47d433a188209cdfb1d4696df065ddd243c033 GIT binary patch literal 5723 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 literal 0 HcmV?d00001 diff --git a/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl.java b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl.java new file mode 100644 index 0000000..2d9a405 --- /dev/null +++ b/container_files/api/edu/internet2/middleware/grouper/ldap/ldaptive/LdaptiveSessionImpl.java @@ -0,0 +1,1292 @@ +/** + * Copyright 2014 Internet2 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package edu.internet2.middleware.grouper.ldap.ldaptive; + +import java.io.IOException; +import java.net.URL; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.net.ssl.SSLSocketFactory; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.ldaptive.AddOperation; +import org.ldaptive.AddRequest; +import org.ldaptive.AttributeModification; +import org.ldaptive.AttributeModificationType; +import org.ldaptive.BindConnectionInitializer; +import org.ldaptive.BindOperation; +import org.ldaptive.BindRequest; +import org.ldaptive.CompareRequest; +import org.ldaptive.Connection; +import org.ldaptive.ConnectionConfig; +import org.ldaptive.Credential; +import org.ldaptive.DefaultConnectionFactory; +import org.ldaptive.DeleteOperation; +import org.ldaptive.DeleteRequest; +import org.ldaptive.LdapAttribute; +import org.ldaptive.LdapEntry; +import org.ldaptive.LdapException; +import org.ldaptive.ModifyDnOperation; +import org.ldaptive.ModifyDnRequest; +import org.ldaptive.ModifyOperation; +import org.ldaptive.ModifyRequest; +import org.ldaptive.Response; +import org.ldaptive.ResultCode; +import org.ldaptive.SearchFilter; +import org.ldaptive.SearchOperation; +import org.ldaptive.SearchRequest; +import org.ldaptive.SearchResult; +import org.ldaptive.SearchScope; +import org.ldaptive.control.util.PagedResultsClient; +import org.ldaptive.handler.SearchEntryHandler; +import org.ldaptive.pool.BlockingConnectionPool; +import org.ldaptive.pool.CompareValidator; +import org.ldaptive.pool.IdlePruneStrategy; +import org.ldaptive.pool.PoolConfig; +import org.ldaptive.pool.PooledConnectionFactory; +import org.ldaptive.pool.SearchValidator; +import org.ldaptive.pool.Validator; +import org.ldaptive.props.BindConnectionInitializerPropertySource; +import org.ldaptive.props.ConnectionConfigPropertySource; +import org.ldaptive.props.DefaultConnectionFactoryPropertySource; +import org.ldaptive.props.PoolConfigPropertySource; +import org.ldaptive.props.SearchRequestPropertySource; +import org.ldaptive.provider.jndi.JndiProviderConfig; +import org.ldaptive.referral.AddReferralHandler; +import org.ldaptive.referral.DeleteReferralHandler; +import org.ldaptive.referral.ModifyDnReferralHandler; +import org.ldaptive.referral.ModifyReferralHandler; +import org.ldaptive.referral.SearchReferralHandler; +import org.ldaptive.sasl.GssApiConfig; + +import edu.internet2.middleware.grouper.app.loader.GrouperLoaderConfig; +import edu.internet2.middleware.grouper.ldap.LdapConfiguration; +import edu.internet2.middleware.grouper.ldap.LdapHandler; +import edu.internet2.middleware.grouper.ldap.LdapHandlerBean; +import edu.internet2.middleware.grouper.ldap.LdapModificationItem; +import edu.internet2.middleware.grouper.ldap.LdapModificationType; +import edu.internet2.middleware.grouper.ldap.LdapPEMSocketFactory; +import edu.internet2.middleware.grouper.ldap.LdapSearchScope; +import edu.internet2.middleware.grouper.ldap.LdapSession; +import edu.internet2.middleware.grouper.util.GrouperUtil; +import edu.internet2.middleware.morphString.Morph; +/** + * will handle the ldap config, and inverse of control for pooling + * + * @author mchyzer + * + */ +public class LdaptiveSessionImpl implements LdapSession { + + /** + * debug log where lines are separated by newlines + */ + private StringBuilder debugLog = null; + + /** + * debug log where lines are separated by newlines + * @return + */ + public StringBuilder getDebugLog() { + return debugLog; + } + + /** + * if we are debugging + */ + private boolean debug = false; + + /** + * if we are debugging + * @return + */ + public boolean isDebug() { + return debug; + } + + /** + * if we should capture debug info + * @param isDebug + */ + public void assignDebug(boolean isDebug, StringBuilder theDebugLog) { + this.debug = isDebug; + if (isDebug) { + this.debugLog = theDebugLog; + } else { + this.debugLog = null; + } + + } + + /** + * if we should capture debug info + * @param isDebug + */ + public void assignDebug(boolean isDebug) { + assignDebug(isDebug, new StringBuilder()); + } + + /** map of connection name to pool */ + private static Map poolMap = Collections.synchronizedMap(new HashMap()); + + /** map of connection name to properties */ + private static Map propertiesMap = Collections.synchronizedMap(new HashMap()); + + /** pools that need to be cleaned up */ + private static List poolsNeedingCleanup = new ArrayList(); + + /** + * What ldaptive properties will be decrypted if their values are Morph files? + * (We don't decrypt all properties because that would prevent the use of slashes in the property values) + **/ + public static final String ENCRYPTABLE_LDAPTIVE_PROPERTIES[] = new String[]{"org.ldaptive.bindCredential"}; + + private static Map>> searchEntryHandlers = Collections.synchronizedMap(new HashMap>>()); + + private static boolean hasWarnedAboutMissingDnAttributeForSearches = false; + + /** + * get or create the pool based on the server id + * @param ldapServerId + * @return the pool + */ + @SuppressWarnings("unchecked") + private static PooledConnectionFactory blockingLdapPool(String ldapServerId) { + + PooledConnectionFactory blockingLdapPool = poolMap.get(ldapServerId); + + if (blockingLdapPool == null) { + synchronized (LdaptiveSessionImpl.class) { + blockingLdapPool = poolMap.get(ldapServerId); + + if (blockingLdapPool == null) { + + BlockingConnectionPool result; + + Properties ldaptiveProperties = getLdaptiveProperties(ldapServerId); + propertiesMap.put(ldapServerId, ldaptiveProperties); + + boolean isActiveDirectory = LdapConfiguration.getConfig(ldapServerId).isActiveDirectory(); + + // search result handlers + LinkedHashSet> handlers = new LinkedHashSet>(); + String handlerNames = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".searchResultHandlers"); + if (StringUtils.isEmpty(handlerNames) && isActiveDirectory) { + handlerNames = "edu.internet2.middleware.grouper.ldap.ldaptive.GrouperRangeEntryHandler"; + } + + if (!StringUtils.isBlank(handlerNames)) { + String[] handlerClassNames = GrouperUtil.splitTrim(handlerNames, ","); + for (String className : handlerClassNames) { + if (className.equals("edu.internet2.middleware.grouper.ldap.handler.RangeSearchResultHandler")) { + className = "edu.internet2.middleware.grouper.ldap.ldaptive.GrouperRangeEntryHandler"; + } else if (className.equals("edu.vt.middleware.ldap.handler.EntryDnSearchResultHandler")) { + className = "org.ldaptive.handler.DnAttributeEntryHandler"; + } else if (className.equals("edu.vt.middleware.ldap.handler.FqdnSearchResultHandler")) { + // ldaptive already gives back the full dn so hopefully we don't have to do anything here. + continue; + } else if (className.equals("edu.vt.middleware.ldap.handler.BinarySearchResultHandler")) { + // ldaptive already handles binary attributes separately so maybe this isn't needed?? need to check + continue; + } + Class customClass = GrouperUtil.forName(className); + handlers.add(customClass); + } + } + + searchEntryHandlers.put(ldapServerId, handlers); + + // Setup ldaptive ConnectionConfig + ConnectionConfig connConfig = new ConnectionConfig(); + DefaultConnectionFactory connectionFactory = new DefaultConnectionFactory(); + + ConnectionConfigPropertySource ccpSource = new ConnectionConfigPropertySource(connConfig, ldaptiveProperties); + ccpSource.initialize(); + + ///////////// + // Binding + BindConnectionInitializer binder = new BindConnectionInitializer(); + + BindConnectionInitializerPropertySource bcip = new BindConnectionInitializerPropertySource(binder, ldaptiveProperties); + bcip.initialize(); + + // I'm not sure if SaslRealm and/or SaslAuthorizationId can be used independently + // Therefore, we'll initialize gssApiConfig when either one of them is used. + // And, then, we'll attach the gssApiConfig to the binder if there is a gssApiConfig + GssApiConfig gssApiConfig = null; + String val = (String) ldaptiveProperties.get("org.ldaptive.saslRealm"); + if (!StringUtils.isBlank(val)) { + LOG.info("Processing saslRealm"); + if ( gssApiConfig == null ) + gssApiConfig = new GssApiConfig(); + gssApiConfig.setRealm(val); + } + + val = (String) ldaptiveProperties.get("org.ldaptive.saslAuthorizationId"); + if (!StringUtils.isBlank(val)) { + LOG.info("Processing saslAuthorizationId"); + if ( gssApiConfig == null ) + gssApiConfig = new GssApiConfig(); + gssApiConfig.setAuthorizationId(val); + } + + // If there was a sasl/gssapi attribute, then save the gssApiConfig + if ( gssApiConfig != null ) { + LOG.info("Setting gssApiConfig"); + binder.setBindSaslConfig(gssApiConfig); + } + + // handle ssl socket factory + String cafile = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".pemCaFile"); + String certfile = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".pemCertFile"); + String keyfile = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".pemKeyFile"); + if (cafile != null && certfile != null && keyfile != null) { + LdapPEMSocketFactory sf = new LdapPEMSocketFactory(cafile, certfile, keyfile); + SSLSocketFactory ldapSocketFactory = sf.getSocketFactory(); + ((JndiProviderConfig) connectionFactory.getProvider().getProviderConfig()).setSslSocketFactory(ldapSocketFactory); + } + + connConfig.setConnectionInitializer(binder); + + DefaultConnectionFactoryPropertySource dcfSource = new DefaultConnectionFactoryPropertySource(connectionFactory, ldaptiveProperties); + dcfSource.initialize(); + connectionFactory.setConnectionConfig(connConfig); + + LinkedHashSet codesToIgnore = new LinkedHashSet(); + String searchIgnoreResultCodes = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".searchIgnoreResultCodes", "SIZE_LIMIT_EXCEEDED"); + if (!StringUtils.isBlank(searchIgnoreResultCodes)) { + String[] searchIgnoreResultCodesArray = GrouperUtil.splitTrim(searchIgnoreResultCodes, ","); + for (String searchIgnoreResultCode : searchIgnoreResultCodesArray) { + codesToIgnore.add(ResultCode.valueOf(searchIgnoreResultCode)); + } + } + ((JndiProviderConfig) connectionFactory.getProvider().getProviderConfig()).setSearchIgnoreResultCodes(codesToIgnore.toArray(new ResultCode[]{})); + + + // batch size + int batchSize = GrouperLoaderConfig.retrieveConfig().propertyValueInt("ldap." + ldapServerId + ".batchSize", -1); + if (batchSize > -1) { + connectionFactory.getProvider().getProviderConfig().getProperties().put("java.naming.batchsize", "" + batchSize); + } + + //((org.ldaptive.BindConnectionInitializer)connectionFactory.getConnectionConfig().getConnectionInitializer()).setBindDn(""); + + ///////////// + // PoolConfig + + PoolConfig ldapPoolConfig = new PoolConfig(); + PoolConfigPropertySource pcps = new PoolConfigPropertySource(ldapPoolConfig, ldaptiveProperties); + pcps.initialize(); + + result = new BlockingConnectionPool(ldapPoolConfig, connectionFactory); + + int pruneTimerPeriod = GrouperLoaderConfig.retrieveConfig().propertyValueInt("ldap." + ldapServerId + ".pruneTimerPeriod", 300000); + int expirationTime = GrouperLoaderConfig.retrieveConfig().propertyValueInt("ldap." + ldapServerId + ".expirationTime", 600000); + + int validateTimerPeriod = GrouperLoaderConfig.retrieveConfig().propertyValueInt("ldap." + ldapServerId + ".validateTimerPeriod", 0); + if (validateTimerPeriod > 0) { + ldapPoolConfig.setValidatePeriod(Duration.ofMillis(validateTimerPeriod)); + } + + IdlePruneStrategy idlePruneStrategy = new IdlePruneStrategy(); + idlePruneStrategy.setIdleTime(Duration.ofMillis(expirationTime)); + idlePruneStrategy.setPrunePeriod(Duration.ofMillis(pruneTimerPeriod)); + result.setPruneStrategy(idlePruneStrategy); + + Validator validator = retrieveValidator(ldapServerId); + + if (validator != null) { + result.setValidator(validator); + + // Make sure some kind of validation is turned on + if ( !ldapPoolConfig.isValidateOnCheckIn() && + !ldapPoolConfig.isValidateOnCheckOut() && + !ldapPoolConfig.isValidatePeriodically() ) { + ldapPoolConfig.setValidatePeriodically(true); + } + } + + result.initialize(); + + blockingLdapPool = new PooledConnectionFactory(result); + + poolMap.put(ldapServerId, blockingLdapPool); + } + } + } + return blockingLdapPool; + } + + private static Validator retrieveValidator(String ldapServerId) { + + Validator validator = null; + + String ldapValidator = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".validator", "SearchValidator"); + + if (StringUtils.equalsIgnoreCase(ldapValidator, CompareValidator.class.getSimpleName()) + || StringUtils.equalsIgnoreCase(ldapValidator, "CompareLdapValidator")) { + String validationDn = GrouperLoaderConfig.retrieveConfig().propertyValueStringRequired("ldap." + ldapServerId + ".validatorCompareDn"); + String validationAttribute = GrouperLoaderConfig.retrieveConfig().propertyValueStringRequired("ldap." + ldapServerId + ".validatorCompareAttribute"); + String validationValue = GrouperLoaderConfig.retrieveConfig().propertyValueStringRequired("ldap." + ldapServerId + ".validatorCompareValue"); + validator = new CompareValidator(new CompareRequest(validationDn, new LdapAttribute(validationAttribute, validationValue))); + } else if (StringUtils.equalsIgnoreCase(ldapValidator, SearchValidator.class.getSimpleName())) { + validator = new SearchValidator(); + } + return validator; + } + + private static Properties getLdaptiveProperties(String ldapSystemName) { + Properties _ldaptiveProperties = new Properties(); + String ldapPropertyPrefix = "ldap." + ldapSystemName + "."; + + _ldaptiveProperties.setProperty("org.ldaptive.bindDn", ""); + + // load this ldaptive config file before the configs here. load from classpath + String configFileFromClasspathParam = ldapPropertyPrefix + "configFileFromClasspath"; + String configFileFromClasspathValue = GrouperLoaderConfig.retrieveConfig().propertyValueString(configFileFromClasspathParam); + if (!StringUtils.isBlank(configFileFromClasspathValue)) { + URL url = GrouperUtil.computeUrl(configFileFromClasspathValue, false); + try { + _ldaptiveProperties.load(url.openStream()); + } catch (IOException ioe) { + throw new RuntimeException("Error processing classpath file: " + configFileFromClasspathValue, ioe); + } + } + + for (String propName : GrouperLoaderConfig.retrieveConfig().propertyNames()) { + if ( propName.startsWith(ldapPropertyPrefix) ) { + String propValue = GrouperLoaderConfig.retrieveConfig().propertyValueString(propName, ""); + + // Get the part of the property after ldapPropertyPrefix 'ldap.person.' + String propNameTail = propName.substring(ldapPropertyPrefix.length()); + + if (propValue == null) { + propValue = ""; + } + + // GRP-4484: ldaptive upgrade now uses durations + if (propNameTail.equalsIgnoreCase("timeout") || propNameTail.equalsIgnoreCase("timeLimit")) { + if (!StringUtils.isBlank(propValue)) { + try { + propValue = "PT" + (GrouperUtil.longValue(propValue)/1000) + "S"; + } catch (Throwable t) { + // if its not a number, then forget it + LOG.debug("Error parsing: " + propValue, t); + } + } + } + _ldaptiveProperties.put("org.ldaptive." + propNameTail, propValue); + + if (propNameTail.equalsIgnoreCase("url")) { + LOG.info("Setting org.ldaptive.ldapUrl"); + _ldaptiveProperties.put("org.ldaptive.ldapUrl", propValue); + } + // tls (vtldap) ==> useStartTls + if (propNameTail.equalsIgnoreCase("tls")) { + LOG.info("Setting org.ldaptive.useStartTLS"); + _ldaptiveProperties.put("org.ldaptive.useStartTLS", propValue); + } + // user (vtldap) ==> bindDn + if (propNameTail.equalsIgnoreCase("user")) { + LOG.info("Setting org.ldaptive.bindDn"); + _ldaptiveProperties.put("org.ldaptive.bindDn", propValue); + } + // pass (vtldap) ==> bindCredential + if (propNameTail.equalsIgnoreCase("pass")) { + LOG.info("Setting org.ldaptive.bindCredential"); + _ldaptiveProperties.put("org.ldaptive.bindCredential", propValue); + } + // countLimit (vtldap) ==> sizeLimit + if (propNameTail.equalsIgnoreCase("countLimit")) { + LOG.info("Setting org.ldaptive.sizeLimit"); + _ldaptiveProperties.put("org.ldaptive.sizeLimit", propValue); + } + // timeout (vtldap) ==> connectTimeout + if (propNameTail.equalsIgnoreCase("timeout")) { + LOG.info("Setting org.ldaptive.connectTimeout"); + _ldaptiveProperties.put("org.ldaptive.connectTimeout", propValue); + } + } + } + + // Go through the properties that can be encrypted and decrypt them if they're Morph files + for (String encryptablePropertyKey : ENCRYPTABLE_LDAPTIVE_PROPERTIES) { + String value = _ldaptiveProperties.getProperty(encryptablePropertyKey); + value = Morph.decryptIfFile(value); + _ldaptiveProperties.put(encryptablePropertyKey, value); + } + return _ldaptiveProperties; + } + + + /** + * call this to send a callback for the ldap session object. + * @param ldapServerId is the config id from the grouper-loader.properties + * @param ldapHandler is the logic of the ldap calls + * @return the result of the handler + */ + private static Object callbackLdapSession( + String ldapServerId, LdapHandler ldapHandler) { + + Object ret = null; + PooledConnectionFactory blockingLdapPool = null; + Connection ldap = null; + try { + + blockingLdapPool = blockingLdapPool(ldapServerId); + + if (LOG.isDebugEnabled()) { + LOG.debug("pre-checkout: ldap id: " + ldapServerId + ", pool active: " + blockingLdapPool.getConnectionPool().activeCount() + ", available: " + blockingLdapPool.getConnectionPool().availableCount()); + } + + ldap = blockingLdapPool.getConnection(); + + if (LOG.isDebugEnabled()) { + LOG.debug("post-checkout: ldap id: " + ldapServerId + ", pool active: " + blockingLdapPool.getConnectionPool().activeCount() + ", available: " + blockingLdapPool.getConnectionPool().availableCount()); + } + + LdapHandlerBean ldapHandlerBean = new LdapHandlerBean(); + + ldapHandlerBean.setLdap(ldap); + + ret = ldapHandler.callback(ldapHandlerBean); + + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Problem with ldap conection: " + ldapServerId); + throw re; + } catch (Exception e) { + throw new RuntimeException("Problem with ldap conection: " + ldapServerId, e); + } finally { + if (ldap != null) { + try { + ldap.close(); + } catch (Exception e) { + // ignore + } + } + } + return ret; + + } + + /** + * @see edu.internet2.middleware.grouper.ldap.LdapSession#list(java.lang.Class, java.lang.String, java.lang.String, edu.internet2.middleware.grouper.ldap.LdapSearchScope, java.lang.String, java.lang.String) + */ + @SuppressWarnings("unchecked") + public List list(final Class returnType, final String ldapServerId, + final String searchDn, final LdapSearchScope ldapSearchScope, final String filter, final String attributeName) { + + try { + + return (List)callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + SearchResult searchResult = processSearchRequest(ldapServerId, ldap, searchDn, ldapSearchScope, filter, new String[] { attributeName }, null); + + List result = new ArrayList(); + for (LdapEntry entry : searchResult.getEntries()) { + LdapAttribute attribute = entry.getAttribute(attributeName); + + if (attribute == null && StringUtils.equals("dn", attributeName)) { + String nameInNamespace = entry.getDn(); + Object attributeValue = GrouperUtil.typeCast(nameInNamespace, returnType); + result.add((R)attributeValue); + } else { + + if (attribute != null) { + for (Object attributeValue : attribute.getStringValues()) { + + attributeValue = GrouperUtil.typeCast(attributeValue, returnType); + if (attributeValue != null) { + result.add((R)attributeValue); + } + } + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Found " + result.size() + " results for serverId: " + ldapServerId + ", searchDn: " + searchDn + + ", filter: '" + filter + "', returning attribute: " + + attributeName + ", some results: " + GrouperUtil.toStringForLog(result, 100) ); + } + + return result; + } + }); + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Error querying ldap server id: " + ldapServerId + ", searchDn: " + searchDn + + ", filter: '" + filter + "', returning attribute: " + attributeName); + throw re; + } + + } + + /** + * logger + */ + private static final Log LOG = GrouperUtil.getLog(LdaptiveSessionImpl.class); + + /** + * @see edu.internet2.middleware.grouper.ldap.LdapSession#listInObjects(java.lang.Class, java.lang.String, java.lang.String, edu.internet2.middleware.grouper.ldap.LdapSearchScope, java.lang.String, java.lang.String) + */ + @SuppressWarnings("unchecked") + public Map> listInObjects(final Class returnType, final String ldapServerId, + final String searchDn, final LdapSearchScope ldapSearchScope, final String filter, final String attributeName) { + + try { + + return (Map>)callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + SearchResult searchResult = processSearchRequest(ldapServerId, ldap, searchDn, ldapSearchScope, filter, new String[] { attributeName }, null); + + Map> result = new HashMap>(); + int subObjectCount = 0; + for (LdapEntry entry : searchResult.getEntries()) { + + List valueResults = new ArrayList(); + String nameInNamespace = entry.getDn(); + + result.put(nameInNamespace, valueResults); + + LdapAttribute attribute = entry.getAttribute(attributeName); + + if (attribute != null) { + for (Object attributeValue : attribute.getStringValues()) { + + attributeValue = GrouperUtil.typeCast(attributeValue, returnType); + if (attributeValue != null) { + subObjectCount++; + valueResults.add((R)attributeValue); + } + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Found " + result.size() + " results, (" + subObjectCount + " sub-results) for serverId: " + ldapServerId + ", searchDn: " + searchDn + + ", filter: '" + filter + "', returning attribute: " + + attributeName + ", some results: " + GrouperUtil.toStringForLog(result, 100) ); + } + + return result; + } + }); + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Error querying ldap server id: " + ldapServerId + ", searchDn: " + searchDn + + ", filter: '" + filter + "', returning attribute: " + attributeName); + throw re; + } + + } + + /** + * @see edu.internet2.middleware.grouper.ldap.LdapSession#list(java.lang.String, java.lang.String, edu.internet2.middleware.grouper.ldap.LdapSearchScope, java.lang.String, java.lang.String[], java.lang.Long) + */ + @SuppressWarnings("unchecked") + public List list(final String ldapServerId, final String searchDn, + final LdapSearchScope ldapSearchScope, final String filter, final String[] attributeNames, final Long sizeLimit) { + + try { + + return (List)callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + SearchResult searchResults = processSearchRequest(ldapServerId, ldap, searchDn, ldapSearchScope, filter, attributeNames, sizeLimit); + + List results = getLdapEntriesFromSearchResult(searchResults, attributeNames); + + return results; + } + }); + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Error querying ldap server id: " + ldapServerId + ", searchDn: " + searchDn + + ", filter: '" + filter + "', returning attributes: " + StringUtils.join(attributeNames, ", ")); + throw re; + } + } + + @SuppressWarnings("unchecked") + @Override + public List read(String ldapServerId, String searchDn, List dnList, String[] attributeNames) { + try { + return (List)callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + List results = new ArrayList(); + + LdapConfiguration config = LdapConfiguration.getConfig(ldapServerId); + int batchSize = config.getQueryBatchSize(); + + if (StringUtils.isEmpty(config.getDnAttributeForSearches()) && !hasWarnedAboutMissingDnAttributeForSearches) { + LOG.warn("Performance impact due to missing config: ldap." + ldapServerId + ".dnAttributeForSearches"); + hasWarnedAboutMissingDnAttributeForSearches = true; + } + + if (!StringUtils.isEmpty(config.getDnAttributeForSearches()) && batchSize > 1) { + int numberOfBatches = GrouperUtil.batchNumberOfBatches(GrouperUtil.length(dnList), batchSize); + for (int i = 0; i < numberOfBatches; i++) { + List currentBatch = GrouperUtil.batchList(dnList, batchSize, i); + StringBuilder builder = new StringBuilder(); + for (String dn : currentBatch) { + builder.append("(" + config.getDnAttributeForSearches() + "=" + SearchFilter.encodeValue(dn) + ")"); + } + + String filter = "(|" + builder.toString() + ")"; + SearchResult searchResults = processSearchRequest(ldapServerId, ldap, searchDn, LdapSearchScope.SUBTREE_SCOPE, filter, attributeNames, null); + results.addAll(getLdapEntriesFromSearchResult(searchResults, attributeNames)); + } + } else { + for (String dn : dnList) { + SearchResult searchResults = processSearchRequest(ldapServerId, ldap, dn, LdapSearchScope.OBJECT_SCOPE, "(objectclass=*)", attributeNames, null); + results.addAll(getLdapEntriesFromSearchResult(searchResults, attributeNames)); + } + } + + return results; + } + }); + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Error querying ldap server id: " + ldapServerId + ", dnList size: " + dnList.size() + + ", returning attributes: " + StringUtils.join(attributeNames, ", ")); + throw re; + } + } + + /** + * @see edu.internet2.middleware.grouper.ldap.LdapSession#authenticate(java.lang.String, java.lang.String, java.lang.String) + */ + public void authenticate(final String ldapServerId, final String userDn, final String password) { + + callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + ConnectionConfig connectionConfig = ConnectionConfig.newConnectionConfig(ldap.getConnectionConfig()); + connectionConfig.setConnectionInitializer(null); + Connection ldap2 = DefaultConnectionFactory.getConnection(connectionConfig); + + try { + ldap2.open(); + BindOperation bind = new BindOperation(ldap2); + bind.execute(new BindRequest(userDn, new Credential(password))); + } finally { + try { + ldap2.close(); + } catch (Exception e) { + // ignore + } + } + + return null; + } + }); + + } + + private SearchScope translateScope(LdapSearchScope jndiScope) { + if (jndiScope == null) { + return null; + } + + SearchScope ldaptiveScope = null; + + if (jndiScope == LdapSearchScope.OBJECT_SCOPE) { + ldaptiveScope = SearchScope.OBJECT; + } else if (jndiScope == LdapSearchScope.ONELEVEL_SCOPE) { + ldaptiveScope = SearchScope.ONELEVEL; + } else if (jndiScope == LdapSearchScope.SUBTREE_SCOPE) { + ldaptiveScope = SearchScope.SUBTREE; + } else { + throw new RuntimeException("Unexpected scope " + jndiScope); + } + + return ldaptiveScope; + } + + private AttributeModificationType translateModificationType(LdapModificationType modificationType) { + if (modificationType == null) { + return null; + } + + AttributeModificationType ldaptiveModificationType = null; + + if (modificationType == LdapModificationType.ADD_ATTRIBUTE) { + ldaptiveModificationType = AttributeModificationType.ADD; + } else if (modificationType == LdapModificationType.REMOVE_ATTRIBUTE) { + ldaptiveModificationType = AttributeModificationType.REMOVE; + } else if (modificationType == LdapModificationType.REPLACE_ATTRIBUTE) { + ldaptiveModificationType = AttributeModificationType.REPLACE; + } else { + throw new RuntimeException("Unexpected modification type " + modificationType); + } + + return ldaptiveModificationType; + } + + private SearchResult processSearchRequest(String ldapServerId, Connection ldap, String searchDn, LdapSearchScope ldapSearchScope, String filter, String[] attributeNames, Long sizeLimit) throws LdapException { + + SearchRequest searchRequest = new SearchRequest(); + + if (filter != null) { + filter = filter.trim(); + if (filter.startsWith("${") && filter.endsWith("}")) { + + if (this.debug) { + this.debugLog.append("Ldaptive filterJexl '").append(filter).append("'\n"); + } + filter = StringUtils.replace(filter, "$newline$", "\n"); + Map variableMap = new HashMap(); + variableMap.put("grouperUtil", new GrouperUtil()); + filter = (String)GrouperUtil.substituteExpressionLanguageScript(filter, variableMap, true, false, false); + } + } + + searchRequest.setSearchFilter(new SearchFilter(filter)); + searchRequest.setReturnAttributes(attributeNames); + + if (searchEntryHandlers.get(ldapServerId).size() > 0) { + SearchEntryHandler[] handlers = new SearchEntryHandler[searchEntryHandlers.get(ldapServerId).size()]; + int count = 0; + for (Class handlerClass : searchEntryHandlers.get(ldapServerId)) { + handlers[count] = GrouperUtil.newInstance(handlerClass); + count++; + } + + searchRequest.setSearchEntryHandlers(handlers); + } + + SearchRequestPropertySource srSource = new SearchRequestPropertySource(searchRequest, propertiesMap.get(ldapServerId)); + srSource.initialize(); + + // add this after the properties get initialized so that this would override if needed + // note that the searchDn here is relative + if (StringUtils.isNotBlank(searchDn)) { + searchRequest.setBaseDn(searchDn); + } + + if (sizeLimit != null) { + searchRequest.setSizeLimit(sizeLimit); + } + + if (ldapSearchScope != null) { + searchRequest.setSearchScope(translateScope(ldapSearchScope)); + } + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + searchRequest.setReferralHandler(new SearchReferralHandler()); + } + + Response response = null; + SearchResult searchResults; + + Integer pageSize = LdapConfiguration.getConfig(ldapServerId).getPageSize(); + if (pageSize != null) { + if (pageSize < 0) { + pageSize = null; + } + } else if (LdapConfiguration.getConfig(ldapServerId).isActiveDirectory()) { + pageSize = getDefaultActiveDirectoryPageSize(ldapServerId, ldap); + } + + if (this.debug) { + this.debugLog.append("Ldaptive searchRequest (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(searchRequest.toString(), 2000)).append("\n"); + } + if (pageSize == null) { + SearchOperation search = new SearchOperation(ldap); + response = search.execute(searchRequest); + } else { + PagedResultsClient client = new PagedResultsClient(ldap, pageSize); + response = client.executeToCompletion(searchRequest); + } + if (this.debug) { + this.debugLog.append("Ldaptive searchResponse (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(response.toString(), 2000)).append("\n"); + } + searchResults = response.getResult(); + if (this.debug) { + this.debugLog.append("Ldaptive searchResults (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(searchResults.toString(), 2000)).append("\n"); + } + return searchResults; + } + + private synchronized Integer getDefaultActiveDirectoryPageSize(String ldapServerId, Connection ldap) { + Integer pageSize = 1000; + + try { + LdapEntry rootLdapEntry; + + { + SearchRequest searchRequest = new SearchRequest(); + searchRequest.setSearchFilter(new SearchFilter("(objectClass=*)")); + searchRequest.setReturnAttributes("configurationNamingContext"); + searchRequest.setBaseDn(""); + searchRequest.setSearchScope(SearchScope.OBJECT); + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + searchRequest.setReferralHandler(new SearchReferralHandler()); + } + + SearchOperation search = new SearchOperation(ldap); + Response response = search.execute(searchRequest); + SearchResult searchResult = response.getResult(); + rootLdapEntry = searchResult.getEntry(); + } + if (rootLdapEntry != null && rootLdapEntry.getAttribute("configurationNamingContext") != null && !GrouperUtil.isEmpty(rootLdapEntry.getAttribute("configurationNamingContext").getStringValue())) { + String configurationDn = rootLdapEntry.getAttribute("configurationNamingContext").getStringValue(); + + SearchRequest searchRequest = new SearchRequest(); + searchRequest.setSearchFilter(new SearchFilter("(&(objectClass=queryPolicy)(cn=Default Query Policy))")); + searchRequest.setReturnAttributes("lDAPAdminLimits"); + searchRequest.setBaseDn(configurationDn); + searchRequest.setSearchScope(SearchScope.SUBTREE); + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + searchRequest.setReferralHandler(new SearchReferralHandler()); + } + + SearchOperation search = new SearchOperation(ldap); + Response response = search.execute(searchRequest); + SearchResult searchResult = response.getResult(); + LdapEntry queryPolicyLdapEntry = searchResult.getEntry(); + if (queryPolicyLdapEntry != null && queryPolicyLdapEntry.getAttribute("lDAPAdminLimits") != null) { + for (String adminLimit : GrouperUtil.nonNull(queryPolicyLdapEntry.getAttribute("lDAPAdminLimits").getStringValues())) { + if (adminLimit != null && adminLimit.startsWith("MaxPageSize=")) { + String pageSizeString = adminLimit.substring("MaxPageSize=".length()); + pageSize = Integer.parseInt(pageSizeString); + LOG.warn("Using pagedResultsSize from " + queryPolicyLdapEntry.getDn()); + break; + } + } + } + + } + } catch (Exception e) { + LOG.error("Exception trying to determine default Active Directory page size", e); + } + + LOG.warn("pagedResultsSize is not set for '" + ldapServerId + "' even though it is usually required with Active Directory. Set to -1 to force no paging. Defaulting to " + pageSize + "."); + + LdapConfiguration.getConfig(ldapServerId).setPageSize(pageSize); + + return pageSize; + } + + private List getLdapEntriesFromSearchResult(SearchResult searchResults, String[] attributeNames) { + + List results = new ArrayList(); + + for (LdapEntry searchResult : searchResults.getEntries()) { + + String nameInNamespace = searchResult.getDn(); + + edu.internet2.middleware.grouper.ldap.LdapEntry entry = new edu.internet2.middleware.grouper.ldap.LdapEntry(nameInNamespace); + for (String attributeName : attributeNames) { + edu.internet2.middleware.grouper.ldap.LdapAttribute attribute = new edu.internet2.middleware.grouper.ldap.LdapAttribute(attributeName); + + LdapAttribute sourceAttribute = searchResult.getAttribute(attributeName); + if (sourceAttribute != null) { + if (sourceAttribute.isBinary()) { + attribute.setBinaryValues(sourceAttribute.getBinaryValues()); + } else { + attribute.setStringValues(sourceAttribute.getStringValues()); + } + } + + entry.addAttribute(attribute); + } + + results.add(entry); + } + + return results; + } + + @Override + public void delete(final String ldapServerId, final String dn) { + + try { + + if (GrouperUtil.isEmpty(dn)) { + throw new RuntimeException("No dn!"); + } + + callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + DeleteOperation delete = new DeleteOperation(ldap); + DeleteRequest deleteRequest = new DeleteRequest(dn); + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + deleteRequest.setReferralHandler(new DeleteReferralHandler()); + } + if (debug) { + debugLog.append("Ldaptive deleteRequest (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(deleteRequest.toString(), 2000)).append("\n"); + } + + try { + Response response = delete.execute(deleteRequest); + if (debug) { + debugLog.append("Ldaptive deleteResponse (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(response.toString(), 2000)).append("\n"); + } + if (response.getResultCode() == ResultCode.SUCCESS) { + return null; + } else { + throw new RuntimeException("Received result code: " + response.getResultCode()); + } + } catch (LdapException e) { + + + // note that this only happens if an intermediate context does not exist + if (e.getResultCode() == ResultCode.NO_SUCH_OBJECT) { + if (debug) { + debugLog.append("Ldaptive deleteResultCode (").append(ldapServerId).append("): NO_SUCH_OBJECT\n"); + } + return null; + } + + if (debug) { + debugLog.append("Ldaptive delete error (").append(ldapServerId).append("): ").append(GrouperUtil.getFullStackTrace(e)).append("\n"); + } + + // TODO should we re-query just to be sure? + throw e; + } + } + }); + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Error deleting entry server id: " + ldapServerId + ", dn: " + dn); + throw re; + } + } + + @Override + public boolean create(final String ldapServerId, final edu.internet2.middleware.grouper.ldap.LdapEntry ldapEntry) { + + // if create failed because object is there, then do an update with the attributes that were given + // some attributes given may have no values and therefore clear those attributes + // true if created, false if updated + + try { + if (GrouperUtil.isEmpty(ldapEntry.getDn())) { + throw new RuntimeException("No dn!"); + } + + return (Boolean)callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + List ldaptiveAttributes = new ArrayList(); // if doing create + List ldaptiveModifications = new ArrayList(); // if doing modify + + for (edu.internet2.middleware.grouper.ldap.LdapAttribute grouperLdapAttribute : ldapEntry.getAttributes()) { + LdapAttribute ldaptiveAttribute = new LdapAttribute(grouperLdapAttribute.getName()); + if (grouperLdapAttribute.getStringValues().size() > 0) { + ldaptiveAttribute.addStringValues(grouperLdapAttribute.getStringValues()); + } else if (grouperLdapAttribute.getBinaryValues().size() > 0) { + ldaptiveAttribute.addBinaryValues(grouperLdapAttribute.getBinaryValues()); + } + + if (ldaptiveAttribute.size() > 0) { + ldaptiveAttributes.add(ldaptiveAttribute); + } + + ldaptiveModifications.add(new AttributeModification(AttributeModificationType.REPLACE, ldaptiveAttribute)); + } + + AddOperation add = new AddOperation(ldap); + AddRequest addRequest = new AddRequest(); + addRequest.setDn(ldapEntry.getDn()); + addRequest.setLdapAttributes(ldaptiveAttributes); + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + addRequest.setReferralHandler(new AddReferralHandler()); + } + if (debug) { + debugLog.append("Ldaptive addRequest (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(addRequest.toString(), 2000)).append("\n"); + } + + try { + Response response = add.execute(addRequest); + if (debug) { + debugLog.append("Ldaptive addResponse (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(response.toString(), 2000)).append("\n"); + } + if (response.getResultCode() == ResultCode.SUCCESS) { + return true; + } else { + throw new RuntimeException("Received result code: " + (response == null ? null : response.getResultCode())); + } + } catch (LdapException e) { + + // update attributes instead + if (e.getResultCode() == ResultCode.ENTRY_ALREADY_EXISTS) { + if (debug) { + debugLog.append("Ldaptive addResponse (").append(ldapServerId).append("): ENTRY_ALREADY_EXISTS\n"); + } + ModifyOperation modify = new ModifyOperation(ldap); + ModifyRequest modifyRequest = new ModifyRequest(ldapEntry.getDn(), ldaptiveModifications.toArray(new AttributeModification[] { })); + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + modifyRequest.setReferralHandler(new ModifyReferralHandler()); + } + if (debug) { + debugLog.append("Ldaptive addModifyRequest (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(modifyRequest.toString(), 2000)).append("\n"); + } + + Response response = modify.execute(modifyRequest); + if (debug) { + debugLog.append("Ldaptive addModifyResponse (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(response.toString(), 2000)).append("\n"); + } + if (response.getResultCode() == ResultCode.SUCCESS) { + return false; + } else { + throw new RuntimeException("Received result code: " + response.getResultCode()); + } + } + if (debug) { + debugLog.append("Ldaptive add error (").append(ldapServerId).append("): ").append(GrouperUtil.getFullStackTrace(e)).append("\n"); + } + + throw e; + } + } + }); + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Error creating entry server id: " + ldapServerId + ", dn: " + ldapEntry.getDn()); + throw re; + } + } + + @Override + public boolean move(final String ldapServerId, final String oldDn, final String newDn) { + // return true if moved + // return false if newDn exists and oldDn doesn't + try { + + if (GrouperUtil.isEmpty(oldDn)) { + throw new RuntimeException("No oldDn!"); + } + + if (GrouperUtil.isEmpty(newDn)) { + throw new RuntimeException("No newDn!"); + } + + return (Boolean)callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + ModifyDnOperation modifyDn = new ModifyDnOperation(ldap); + ModifyDnRequest modifyDnRequest = new ModifyDnRequest(); + modifyDnRequest.setDeleteOldRDn(true); + modifyDnRequest.setDn(oldDn); + modifyDnRequest.setNewDn(newDn); + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + modifyDnRequest.setReferralHandler(new ModifyDnReferralHandler()); + } + + if (debug) { + debugLog.append("Ldaptive moveRequest (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(modifyDnRequest.toString(), 2000)).append("\n"); + } + try { + Response response = modifyDn.execute(modifyDnRequest); + if (debug) { + debugLog.append("Ldaptive moveResponse (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(response.toString(), 2000)).append("\n"); + } + if (response.getResultCode() == ResultCode.SUCCESS) { + return true; + } else { + throw new RuntimeException("Received result code: " + response.getResultCode()); + } + } catch (LdapException e) { + + if (e.getResultCode() == ResultCode.NO_SUCH_OBJECT) { + + if (debug) { + debugLog.append("Ldaptive moveResponse (").append(ldapServerId).append("): NO_SUCH_OBJECT\n"); + } + // old entry doesn't exist. if the new one does, then let's assume it was already renamed and return false + // note that this exception could also happen if the oldDn exists but the newDn is an invalid location - in that case we should still end up throwing the original exception below + + try { + processSearchRequest(ldapServerId, ldap, newDn, LdapSearchScope.OBJECT_SCOPE, "(objectclass=*)", new String[] { "objectclass" }, null); + return false; + } catch (LdapException e2) { + if (e2.getResultCode() == ResultCode.NO_SUCH_OBJECT) { + // throw original exception + throw e; + } + + // something else went wrong so throw this + throw e2; + } + } + if (debug) { + debugLog.append("Ldaptive move error (").append(ldapServerId).append("): ").append(GrouperUtil.getFullStackTrace(e)).append("\n"); + } + throw e; + } + } + }); + } catch (RuntimeException re) { + GrouperUtil.injectInException(re, "Error moving entry server id: " + ldapServerId + ", oldDn: " + oldDn + ", newDn: " + newDn); + throw re; + } + } + + @Override + public void internal_modifyHelper(final String ldapServerId, String dn, final List ldapModificationItems) { + + if (ldapModificationItems.size() == 0) { + return; + } + + try { + + if (GrouperUtil.isEmpty(dn)) { + throw new RuntimeException("No dn!"); + } + + callbackLdapSession(ldapServerId, new LdapHandler() { + + public Object callback(LdapHandlerBean ldapHandlerBean) throws LdapException { + + Connection ldap = ldapHandlerBean.getLdap(); + + List ldaptiveModifications = new ArrayList(); + + for (LdapModificationItem ldapModificationItem : ldapModificationItems) { + LdapAttribute ldaptiveAttribute = new LdapAttribute(ldapModificationItem.getAttribute().getName()); + if (ldapModificationItem.getAttribute().getStringValues().size() > 0) { + ldaptiveAttribute.addStringValues(ldapModificationItem.getAttribute().getStringValues()); + } else if (ldapModificationItem.getAttribute().getBinaryValues().size() > 0) { + ldaptiveAttribute.addBinaryValues(ldapModificationItem.getAttribute().getBinaryValues()); + } + + ldaptiveModifications.add(new AttributeModification(translateModificationType(ldapModificationItem.getLdapModificationType()), ldaptiveAttribute)); + } + + ModifyOperation modify = new ModifyOperation(ldap); + ModifyRequest modifyRequest = new ModifyRequest(dn, ldaptiveModifications.toArray(new AttributeModification[] { })); + + if ("follow".equals(GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".referral"))) { + modifyRequest.setReferralHandler(new ModifyReferralHandler()); + } + + if (debug) { + debugLog.append("Ldaptive modifyRequest (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(modifyRequest.toString(), 2000)).append("\n"); + } + + Response response = modify.execute(modifyRequest); + if (debug) { + debugLog.append("Ldaptive modifyResponse (").append(ldapServerId).append("): ").append(StringUtils.abbreviate(response.toString(), 2000)).append("\n"); + } + if (response.getResultCode() == ResultCode.SUCCESS) { + return null; + } else { + throw new RuntimeException("Received result code: " + response.getResultCode()); + } + } + }); + } catch (RuntimeException re) { + if (debug) { + debugLog.append("Ldaptive modify error (").append(ldapServerId).append("): ").append(GrouperUtil.getFullStackTrace(re)).append("\n"); + } + GrouperUtil.injectInException(re, "Error modifying entry server id: " + ldapServerId + ", dn: " + dn); + throw re; + } + } + + @Override + public boolean testConnection(final String ldapServerId) { + Validator validator = retrieveValidator(ldapServerId); + boolean valid = false; + if (validator != null) { + valid = (Boolean)callbackLdapSession(ldapServerId, new LdapHandler() { + + @Override + public Object callback(LdapHandlerBean ldapHandlerBean) + throws Exception { + return validator.validate(ldapHandlerBean.getLdap()); + } + }); + } + // if not valid, maybe this will throw a useful exception + if (validator == null || !valid) { + String user = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".user"); + String pass = GrouperLoaderConfig.retrieveConfig().propertyValueString("ldap." + ldapServerId + ".pass"); + pass = Morph.decryptIfFile(pass); + authenticate(ldapServerId, user, + pass); + } + return valid; + } + + public void refreshConnectionsIfNeeded(final String ldapServerId) { + synchronized (LdaptiveSessionImpl.class) { + + Iterator poolsNeedingCleanupIter = poolsNeedingCleanup.iterator(); + while (poolsNeedingCleanupIter.hasNext()) { + PooledConnectionFactory pool = poolsNeedingCleanupIter.next(); + if (pool.getConnectionPool().activeCount() == 0) { + pool.getConnectionPool().close(); + poolsNeedingCleanupIter.remove(); + LOG.warn("Closed old LDAP pool after confirming not in use."); + } else { + LOG.warn("Unable to close old LDAP pool since it is being used. Will check again later."); + } + } + + if (poolMap.containsKey(ldapServerId) && propertiesMap.containsKey(ldapServerId)) { + if (!propertiesMap.get(ldapServerId).equals(getLdaptiveProperties(ldapServerId))) { + PooledConnectionFactory pool = poolMap.remove(ldapServerId); + poolsNeedingCleanup.add(pool); + LdapConfiguration.removeConfig(ldapServerId); + } + } + } + } +}