LDAPPermissionCalculator.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. /*
  2. * Password Management Servlets (PWM)
  3. * http://www.pwm-project.org
  4. *
  5. * Copyright (c) 2006-2009 Novell, Inc.
  6. * Copyright (c) 2009-2019 The PWM Project
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. package password.pwm.util;
  21. import com.novell.ldapchai.ChaiConstant;
  22. import lombok.Value;
  23. import password.pwm.config.Configuration;
  24. import password.pwm.config.LDAPPermissionInfo;
  25. import password.pwm.config.PwmSetting;
  26. import password.pwm.config.PwmSettingCategory;
  27. import password.pwm.config.PwmSettingTemplate;
  28. import password.pwm.config.PwmSettingTemplateSet;
  29. import password.pwm.config.option.DataStorageMethod;
  30. import password.pwm.config.profile.LdapProfile;
  31. import password.pwm.config.stored.StoredConfiguration;
  32. import password.pwm.config.stored.StoredConfigurationUtil;
  33. import password.pwm.config.value.data.ActionConfiguration;
  34. import password.pwm.config.value.data.FormConfiguration;
  35. import password.pwm.config.value.data.UserPermission;
  36. import password.pwm.error.ErrorInformation;
  37. import password.pwm.error.PwmError;
  38. import password.pwm.error.PwmUnrecoverableException;
  39. import password.pwm.i18n.Config;
  40. import password.pwm.util.i18n.LocaleHelper;
  41. import password.pwm.util.logging.PwmLogger;
  42. import password.pwm.util.queue.SmsQueueManager;
  43. import java.io.Serializable;
  44. import java.util.ArrayList;
  45. import java.util.Arrays;
  46. import java.util.Collection;
  47. import java.util.Collections;
  48. import java.util.HashSet;
  49. import java.util.LinkedHashMap;
  50. import java.util.List;
  51. import java.util.Map;
  52. import java.util.Set;
  53. import java.util.TreeMap;
  54. public class LDAPPermissionCalculator implements Serializable
  55. {
  56. private static final long serialVersionUID = 1L;
  57. private static final PwmLogger LOGGER = PwmLogger.forClass( LDAPPermissionCalculator.class );
  58. private final transient StoredConfiguration storedConfiguration;
  59. private final transient Configuration configuration;
  60. private final Collection<PermissionRecord> permissionRecords;
  61. public LDAPPermissionCalculator( final StoredConfiguration storedConfiguration ) throws PwmUnrecoverableException
  62. {
  63. this.storedConfiguration = storedConfiguration;
  64. this.configuration = new Configuration( storedConfiguration );
  65. permissionRecords = figureRecords( storedConfiguration );
  66. }
  67. public Collection<PermissionRecord> getPermissionRecords( )
  68. {
  69. return permissionRecords;
  70. }
  71. public Map<String, Map<LDAPPermissionInfo.Access, List<PermissionRecord>>> getPermissionsByActor( final LDAPPermissionInfo.Actor actor )
  72. {
  73. final Map<String, Map<LDAPPermissionInfo.Access, List<PermissionRecord>>> returnObj = new TreeMap<>();
  74. for ( final PermissionRecord permissionRecord : getPermissionRecords() )
  75. {
  76. if ( permissionRecord.getActor() == actor )
  77. {
  78. if ( !returnObj.containsKey( permissionRecord.getAttribute() ) )
  79. {
  80. returnObj.put( permissionRecord.getAttribute(), new TreeMap<LDAPPermissionInfo.Access, List<PermissionRecord>>() );
  81. }
  82. if ( !returnObj.get( permissionRecord.getAttribute() ).containsKey( permissionRecord.getAccess() ) )
  83. {
  84. returnObj.get( permissionRecord.getAttribute() ).put( permissionRecord.getAccess(), new ArrayList<PermissionRecord>() );
  85. }
  86. returnObj.get( permissionRecord.getAttribute() ).get( permissionRecord.getAccess() ).add( permissionRecord );
  87. }
  88. }
  89. return Collections.unmodifiableMap( returnObj );
  90. }
  91. private Collection<PermissionRecord> figureRecords( final StoredConfiguration storedConfiguration ) throws PwmUnrecoverableException
  92. {
  93. final List<PermissionRecord> permissionRecords = new ArrayList<>();
  94. for ( final PwmSetting pwmSetting : PwmSetting.values() )
  95. {
  96. if ( pwmSetting.getCategory().hasProfiles() )
  97. {
  98. final List<String> profiles = StoredConfigurationUtil.profilesForSetting( pwmSetting, storedConfiguration );
  99. for ( final String profile : profiles )
  100. {
  101. permissionRecords.addAll( figureRecord( pwmSetting, profile ) );
  102. }
  103. }
  104. else
  105. {
  106. permissionRecords.addAll( figureRecord( pwmSetting, null ) );
  107. }
  108. }
  109. permissionRecords.addAll( permissionsForUserPassword() );
  110. permissionRecords.addAll( figureStaticRecords() );
  111. return permissionRecords;
  112. }
  113. private Collection<PermissionRecord> figureRecord( final PwmSetting pwmSetting, final String profile ) throws PwmUnrecoverableException
  114. {
  115. final List<PermissionRecord> permissionRecords = new ArrayList<>();
  116. final Collection<LDAPPermissionInfo> permissionInfos = figurePermissionInfos( pwmSetting, profile );
  117. if ( permissionInfos == null )
  118. {
  119. return Collections.emptyList();
  120. }
  121. for ( final LDAPPermissionInfo permissionInfo : permissionInfos )
  122. {
  123. switch ( pwmSetting.getSyntax() )
  124. {
  125. case STRING:
  126. {
  127. final String attrName = ( String ) storedConfiguration.readSetting( pwmSetting, profile ).toNativeObject();
  128. if ( attrName != null && !attrName.trim().isEmpty() )
  129. {
  130. permissionRecords.add( new PermissionRecord( attrName, pwmSetting, profile, permissionInfo.getAccess(), permissionInfo.getActor() ) );
  131. }
  132. }
  133. break;
  134. case FORM:
  135. {
  136. final List<FormConfiguration> formItems = ( List<FormConfiguration> ) storedConfiguration.readSetting( pwmSetting, profile ).toNativeObject();
  137. if ( formItems != null )
  138. {
  139. for ( final FormConfiguration formConfiguration : formItems )
  140. {
  141. final String attrName = formConfiguration.getName();
  142. if ( attrName != null && !attrName.trim().isEmpty() )
  143. {
  144. permissionRecords.add( new PermissionRecord( attrName, pwmSetting, profile, permissionInfo.getAccess(), permissionInfo.getActor() ) );
  145. }
  146. }
  147. }
  148. }
  149. break;
  150. case ACTION:
  151. {
  152. final List<ActionConfiguration> actionItems = ( List<ActionConfiguration> ) storedConfiguration.readSetting( pwmSetting, profile ).toNativeObject();
  153. if ( actionItems != null )
  154. {
  155. for ( final ActionConfiguration actionConfiguration : actionItems )
  156. {
  157. for ( final ActionConfiguration.LdapAction ldapMethod : actionConfiguration.getLdapActions() )
  158. {
  159. final String attrName = ldapMethod.getAttributeName();
  160. if ( attrName != null && !attrName.trim().isEmpty() )
  161. {
  162. permissionRecords.add( new PermissionRecord( attrName, pwmSetting, profile, permissionInfo.getAccess(), permissionInfo.getActor() ) );
  163. }
  164. }
  165. }
  166. }
  167. }
  168. break;
  169. case STRING_ARRAY:
  170. {
  171. final List<String> strings = ( List<String> ) storedConfiguration.readSetting( pwmSetting, profile ).toNativeObject();
  172. for ( final String attrName : strings )
  173. {
  174. if ( attrName != null && !attrName.trim().isEmpty() )
  175. {
  176. permissionRecords.add( new PermissionRecord( attrName, pwmSetting, profile, permissionInfo.getAccess(), permissionInfo.getActor() ) );
  177. }
  178. }
  179. }
  180. break;
  181. case USER_PERMISSION:
  182. {
  183. final List<UserPermission> userPermissions = ( List<UserPermission> ) storedConfiguration.readSetting( pwmSetting, profile ).toNativeObject();
  184. if ( configuration.getLdapProfiles() != null && !configuration.getLdapProfiles().isEmpty() )
  185. {
  186. for ( final LdapProfile ldapProfile : configuration.getLdapProfiles().values() )
  187. {
  188. final String groupAttribute = ldapProfile.readSettingAsString( PwmSetting.LDAP_USER_GROUP_ATTRIBUTE );
  189. if ( groupAttribute != null && !groupAttribute.trim().isEmpty() )
  190. {
  191. for ( final UserPermission userPermission : userPermissions )
  192. {
  193. if ( userPermission.getType() == UserPermission.Type.ldapGroup )
  194. {
  195. permissionRecords.add( new PermissionRecord( groupAttribute, pwmSetting, profile, permissionInfo.getAccess(), permissionInfo.getActor() ) );
  196. }
  197. }
  198. }
  199. }
  200. }
  201. }
  202. break;
  203. default:
  204. throw new PwmUnrecoverableException( new ErrorInformation(
  205. PwmError.ERROR_INTERNAL,
  206. "no ldap permission record reader handler for setting " + pwmSetting.getKey() )
  207. );
  208. }
  209. }
  210. return permissionRecords;
  211. }
  212. @SuppressWarnings( "checkstyle:MethodLength" )
  213. private Collection<LDAPPermissionInfo> figurePermissionInfos( final PwmSetting pwmSetting, final String profile )
  214. {
  215. PwmSettingCategory category = pwmSetting.getCategory();
  216. while ( category.hasProfiles() && !category.isTopLevelProfile() )
  217. {
  218. category = category.getParent();
  219. }
  220. switch ( category )
  221. {
  222. case PEOPLE_SEARCH:
  223. {
  224. if ( !( Boolean ) storedConfiguration.readSetting( PwmSetting.PEOPLE_SEARCH_ENABLE, null ).toNativeObject() )
  225. {
  226. return Collections.emptyList();
  227. }
  228. final boolean proxyOverride = ( Boolean ) storedConfiguration.readSetting( PwmSetting.PEOPLE_SEARCH_USE_PROXY, profile ).toNativeObject();
  229. final boolean publicOverride = ( Boolean ) storedConfiguration.readSetting( PwmSetting.PEOPLE_SEARCH_ENABLE_PUBLIC, profile ).toNativeObject();
  230. if ( proxyOverride || publicOverride )
  231. {
  232. final Collection<LDAPPermissionInfo> configuredRecords = pwmSetting.getLDAPPermissionInfo();
  233. final Collection<LDAPPermissionInfo> returnRecords = new ArrayList<>();
  234. for ( final LDAPPermissionInfo ldapPermissionInfo : configuredRecords )
  235. {
  236. if ( !( proxyOverride && publicOverride ) )
  237. {
  238. // include regular self-other permission
  239. returnRecords.add( ldapPermissionInfo );
  240. }
  241. returnRecords.add( new LDAPPermissionInfo( ldapPermissionInfo.getAccess(), LDAPPermissionInfo.Actor.proxy ) );
  242. }
  243. return returnRecords;
  244. }
  245. }
  246. break;
  247. case GUEST:
  248. {
  249. if ( !( Boolean ) storedConfiguration.readSetting( PwmSetting.GUEST_ENABLE, null ).toNativeObject() )
  250. {
  251. return Collections.emptyList();
  252. }
  253. }
  254. break;
  255. case UPDATE:
  256. case UPDATE_PROFILE:
  257. case UPDATE_SETTINGS:
  258. {
  259. if ( !( Boolean ) storedConfiguration.readSetting( PwmSetting.UPDATE_PROFILE_ENABLE, null ).toNativeObject() )
  260. {
  261. return Collections.emptyList();
  262. }
  263. }
  264. break;
  265. case FORGOTTEN_USERNAME:
  266. {
  267. if ( !( Boolean ) storedConfiguration.readSetting( PwmSetting.FORGOTTEN_USERNAME_ENABLE, null ).toNativeObject() )
  268. {
  269. return Collections.emptyList();
  270. }
  271. }
  272. break;
  273. case NEWUSER:
  274. case NEWUSER_PROFILE:
  275. case NEWUSER_SETTINGS:
  276. {
  277. if ( !( Boolean ) storedConfiguration.readSetting( PwmSetting.NEWUSER_ENABLE, null ).toNativeObject() )
  278. {
  279. return Collections.emptyList();
  280. }
  281. }
  282. break;
  283. case ACTIVATION:
  284. {
  285. if ( !( Boolean ) storedConfiguration.readSetting( PwmSetting.ACTIVATE_USER_ENABLE, null ).toNativeObject() )
  286. {
  287. return Collections.emptyList();
  288. }
  289. }
  290. break;
  291. case HELPDESK_PROFILE:
  292. {
  293. if ( !( Boolean ) storedConfiguration.readSetting( PwmSetting.HELPDESK_ENABLE, null ).toNativeObject() )
  294. {
  295. return Collections.emptyList();
  296. }
  297. if ( ( Boolean ) storedConfiguration.readSetting( PwmSetting.HELPDESK_USE_PROXY, profile ).toNativeObject() )
  298. {
  299. final Collection<LDAPPermissionInfo> configuredRecords = pwmSetting.getLDAPPermissionInfo();
  300. final Collection<LDAPPermissionInfo> returnRecords = new ArrayList<>();
  301. for ( final LDAPPermissionInfo ldapPermissionInfo : configuredRecords )
  302. {
  303. returnRecords.add( new LDAPPermissionInfo( ldapPermissionInfo.getAccess(), LDAPPermissionInfo.Actor.proxy ) );
  304. }
  305. return returnRecords;
  306. }
  307. }
  308. break;
  309. default:
  310. //continue processing
  311. break;
  312. }
  313. switch ( pwmSetting )
  314. {
  315. case CHALLENGE_USER_ATTRIBUTE:
  316. {
  317. final Set<DataStorageMethod> storageMethods = new HashSet<>();
  318. storageMethods.addAll( configuration.getResponseStorageLocations( PwmSetting.FORGOTTEN_PASSWORD_WRITE_PREFERENCE ) );
  319. storageMethods.addAll( configuration.getResponseStorageLocations( PwmSetting.FORGOTTEN_PASSWORD_READ_PREFERENCE ) );
  320. if ( !storageMethods.contains( DataStorageMethod.LDAP ) )
  321. {
  322. return Collections.emptyList();
  323. }
  324. }
  325. break;
  326. case SMS_USER_PHONE_ATTRIBUTE:
  327. {
  328. if ( !SmsQueueManager.smsIsConfigured( configuration ) )
  329. {
  330. return Collections.emptyList();
  331. }
  332. }
  333. break;
  334. default:
  335. //continue processing
  336. break;
  337. }
  338. return pwmSetting.getLDAPPermissionInfo();
  339. }
  340. private Collection<PermissionRecord> permissionsForUserPassword( )
  341. {
  342. final String userPasswordAttributeName = LocaleHelper.getLocalizedMessage( Config.Label_UserPasswordAttribute, null );
  343. final Collection<PermissionRecord> records = new ArrayList<>();
  344. // user set password
  345. records.add( new PermissionRecord( userPasswordAttributeName, null, null, LDAPPermissionInfo.Access.write, LDAPPermissionInfo.Actor.self ) );
  346. // proxy user set password
  347. if ( configuration.readSettingAsBoolean( PwmSetting.FORGOTTEN_PASSWORD_ENABLE ) )
  348. {
  349. final Collection<PwmSettingTemplate> templates = configuration.getTemplate().getTemplates();
  350. if ( templates.contains( PwmSettingTemplate.NOVL ) || templates.contains( PwmSettingTemplate.NOVL_IDM ) )
  351. {
  352. records.add( new PermissionRecord(
  353. userPasswordAttributeName,
  354. PwmSetting.FORGOTTEN_PASSWORD_ENABLE,
  355. null,
  356. LDAPPermissionInfo.Access.read,
  357. LDAPPermissionInfo.Actor.proxy ) );
  358. }
  359. else
  360. {
  361. records.add( new PermissionRecord(
  362. userPasswordAttributeName,
  363. PwmSetting.FORGOTTEN_PASSWORD_ENABLE,
  364. null,
  365. LDAPPermissionInfo.Access.write,
  366. LDAPPermissionInfo.Actor.proxy ) );
  367. }
  368. }
  369. if ( configuration.readSettingAsBoolean( PwmSetting.HELPDESK_ENABLE ) )
  370. {
  371. records.add( new PermissionRecord(
  372. userPasswordAttributeName,
  373. PwmSetting.HELPDESK_ENABLE,
  374. null,
  375. LDAPPermissionInfo.Access.write,
  376. LDAPPermissionInfo.Actor.helpdesk ) );
  377. }
  378. if ( configuration.readSettingAsBoolean( PwmSetting.GUEST_ENABLE ) )
  379. {
  380. records.add( new PermissionRecord(
  381. userPasswordAttributeName,
  382. PwmSetting.GUEST_ENABLE,
  383. null,
  384. LDAPPermissionInfo.Access.write,
  385. LDAPPermissionInfo.Actor.guestManager ) );
  386. }
  387. if ( configuration.readSettingAsBoolean( PwmSetting.NEWUSER_ENABLE ) )
  388. {
  389. records.add( new PermissionRecord(
  390. userPasswordAttributeName,
  391. PwmSetting.NEWUSER_ENABLE,
  392. null,
  393. LDAPPermissionInfo.Access.write,
  394. LDAPPermissionInfo.Actor.proxy ) );
  395. }
  396. return records;
  397. }
  398. private Collection<PermissionRecord> figureStaticRecords( )
  399. {
  400. final Set<PwmSettingTemplate> edirInterestedTemplates =
  401. Collections.unmodifiableSet( new HashSet<>( Arrays.asList(
  402. PwmSettingTemplate.NOVL, PwmSettingTemplate.NOVL_IDM ) )
  403. );
  404. final List<PermissionRecord> permissionRecords = new ArrayList<>();
  405. final PwmSettingTemplateSet templateSet = storedConfiguration.getTemplateSet();
  406. {
  407. // edir specific attributes
  408. if ( !Collections.disjoint( templateSet.getTemplates(), edirInterestedTemplates ) )
  409. {
  410. final Map<String, LDAPPermissionInfo.Access> ldapAttributes = new LinkedHashMap<>();
  411. ldapAttributes.put( ChaiConstant.ATTR_LDAP_LOCKED_BY_INTRUDER, LDAPPermissionInfo.Access.write );
  412. ldapAttributes.put( ChaiConstant.ATTR_LDAP_LOGIN_INTRUDER_ATTEMPTS, LDAPPermissionInfo.Access.write );
  413. ldapAttributes.put( ChaiConstant.ATTR_LDAP_LOGIN_INTRUDER_RESET_TIME, LDAPPermissionInfo.Access.write );
  414. ldapAttributes.put( ChaiConstant.ATTR_LDAP_LOGIN_GRACE_LIMIT, LDAPPermissionInfo.Access.write );
  415. ldapAttributes.put( ChaiConstant.ATTR_LDAP_LOGIN_GRACE_REMAINING, LDAPPermissionInfo.Access.write );
  416. ldapAttributes.put( ChaiConstant.ATTR_LDAP_PASSWORD_EXPIRE_TIME, LDAPPermissionInfo.Access.read );
  417. for ( final Map.Entry<String, LDAPPermissionInfo.Access> entry : ldapAttributes.entrySet() )
  418. {
  419. final String ldapAttribute = entry.getKey();
  420. permissionRecords.add( new PermissionRecord(
  421. ldapAttribute,
  422. null,
  423. null,
  424. entry.getValue(),
  425. LDAPPermissionInfo.Actor.proxy
  426. ) );
  427. }
  428. }
  429. }
  430. if ( configuration.getLdapProfiles() != null && !configuration.getLdapProfiles().isEmpty() )
  431. {
  432. for ( final LdapProfile ldapProfile : configuration.getLdapProfiles().values() )
  433. {
  434. final List<String> autoAddObjectClasses = ldapProfile.readSettingAsStringArray( PwmSetting.AUTO_ADD_OBJECT_CLASSES );
  435. if ( autoAddObjectClasses != null && !autoAddObjectClasses.isEmpty() )
  436. {
  437. permissionRecords.add( new PermissionRecord(
  438. ChaiConstant.ATTR_LDAP_OBJECTCLASS,
  439. PwmSetting.AUTO_ADD_OBJECT_CLASSES,
  440. ldapProfile.getIdentifier(),
  441. LDAPPermissionInfo.Access.write,
  442. LDAPPermissionInfo.Actor.proxy
  443. ) );
  444. }
  445. }
  446. }
  447. return permissionRecords;
  448. }
  449. @Value
  450. public static class PermissionRecord implements Serializable
  451. {
  452. private final String attribute;
  453. private final PwmSetting pwmSetting;
  454. private final String profile;
  455. private final LDAPPermissionInfo.Access access;
  456. private final LDAPPermissionInfo.Actor actor;
  457. }
  458. }