From 27840093f5c9c6b2aecd6d5ce80f1af3b65c3b42 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Tue, 9 Jun 2020 17:52:07 +0200 Subject: [PATCH] feat(core): add lookupFields attribute in LDAP source This field allows for looking up attributes not returned with the default query, such as operational attributes. Fixes #568 Co-authored-by: Skrupellos --- Documentation/SOGoInstallationGuide.asciidoc | 7 +- SoObjects/SOGo/LDAPSource.h | 2 + SoObjects/SOGo/LDAPSource.m | 70 +++++++++++--------- 3 files changed, 45 insertions(+), 34 deletions(-) diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index d69703d3e..62c07f369 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -1028,6 +1028,11 @@ _bindDN_ and _bindPassword_ will still be required to find the proper DN |bindFields (optional) |An array of fields to use when doing indirect binds. +|lookupFields (optional) +|Lookup fields for LDAP queries. Default is `(*)`. This can be utilized +to lookup operational fields (which are per default not part of the result) +such as `memberOf`: `lookupFields = ("*", "memberOf");` + |hostname |A space-delimited list of LDAP URLs or LDAP hostnames. @@ -1106,7 +1111,7 @@ not work for entries in this source and thus, freebusy lookups. repository |listRequiresDot (optional) -|If set to `YES`, listing of this LDAP source is only possible when performing a search (respecting the SOGoSearchMinimumWordLength parameter) or when explicitely typing a single dot. +|If set to `YES`, listing of this LDAP source is only possible when performing a search (respecting the SOGoSearchMinimumWordLength parameter) or when explicitly typing a single dot. Defaults to `YES` when unset. |ModulesConstraints (optional) diff --git a/SoObjects/SOGo/LDAPSource.h b/SoObjects/SOGo/LDAPSource.h index 7a59c2a82..52fd21a07 100644 --- a/SoObjects/SOGo/LDAPSource.h +++ b/SoObjects/SOGo/LDAPSource.h @@ -75,6 +75,7 @@ NSMutableDictionary *_members; NSDictionary *_modulesConstraints; + NSArray *_lookupFields; BOOL _passwordPolicy; BOOL _updateSambaNTLMPasswords; @@ -110,6 +111,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses IMAPLoginField: (NSString *) newIMAPLoginField SieveHostField: (NSString *) newSieveHostField bindFields: (id) newBindFields + lookupFields: (NSArray *) newLookupFields kindField: (NSString *) newKindField andMultipleBookingsField: (NSString *) newMultipleBookingsField; diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index fbc4be281..bde444ca7 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -110,6 +110,8 @@ static Class NSStringK; _passwordPolicy = NO; _updateSambaNTLMPasswords = NO; + _lookupFields = [NSArray arrayWithObject: @"*"]; + [_lookupFields retain]; _kindField = nil; _multipleBookingsField = nil; @@ -159,6 +161,7 @@ static Class NSStringK; [_MSExchangeHostname release]; [_modifiers release]; [_displayName release]; + [_lookupFields release]; [super dealloc]; } @@ -194,6 +197,7 @@ static Class NSStringK; IMAPLoginField: [udSource objectForKey: @"IMAPLoginFieldName"] SieveHostField: [udSource objectForKey: @"SieveHostFieldName"] bindFields: [udSource objectForKey: @"bindFields"] + lookupFields: [udSource objectForKey: @"lookupFields"] kindField: [udSource objectForKey: @"KindFieldName"] andMultipleBookingsField: [udSource objectForKey: @"MultipleBookingsFieldName"]]; @@ -229,7 +233,7 @@ static Class NSStringK; if (!_contactInfoAttribute) _contactInfoAttribute = [dd ldapContactInfoAttribute]; [_contactInfoAttribute retain]; - + udQueryLimit = [udSource objectForKey: @"SOGoLDAPQueryLimit"]; if (udQueryLimit) _queryLimit = [udQueryLimit intValue]; @@ -265,7 +269,7 @@ static Class NSStringK; if ([udSource objectForKey: @"updateSambaNTLMPasswords"]) _updateSambaNTLMPasswords = [[udSource objectForKey: @"updateSambaNTLMPasswords"] boolValue]; - + ASSIGN(_MSExchangeHostname, [udSource objectForKey: @"MSExchangeHostname"]); } @@ -333,6 +337,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses IMAPLoginField: (NSString *) newIMAPLoginField SieveHostField: (NSString *) newSieveHostField bindFields: (id) newBindFields + lookupFields: (NSArray *) newLookupFields kindField: (NSString *) newKindField andMultipleBookingsField: (NSString *) newMultipleBookingsField { @@ -379,6 +384,8 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses ASSIGN(_bindFields, [newBindFields componentsSeparatedByString: @","]); } } + if (newLookupFields) + ASSIGN(_lookupFields, newLookupFields); if (newKindField) ASSIGN(_kindField, [newKindField lowercaseString]); if (newMultipleBookingsField) @@ -587,7 +594,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses didBind = [bindConnection bindWithMethod: @"simple" binddn: userDN credentials: _pwd]; - else + else didBind = [bindConnection bindWithMethod: @"simple" binddn: userDN credentials: _pwd @@ -644,14 +651,14 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses NSArray *changes; BOOL didChange; - + attr = [[NGLdapAttribute alloc] initWithAttributeName: theAttribute]; [attr addStringValue: theValue]; - + mod = [NGLdapModification replaceModification: attr]; - + changes = [NSArray arrayWithObject: mod]; - + if ([bindConnection bindWithMethod: @"simple" binddn: theUserDN credentials: theUserPassword]) @@ -661,7 +668,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses } else didChange = NO; - + RELEASE(attr); return didChange; @@ -674,7 +681,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses oldPassword: (NSString *) oldPassword newPassword: (NSString *) newPassword perr: (SOGoPasswordPolicyError *) perr - + { NGLdapConnection *bindConnection; NSString *userDN; @@ -723,7 +730,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses // We don't use a password policy - we simply use // a modify-op to change the password NSString* encryptedPass; - + if ([_userPasswordAlgorithm isEqualToString: @"none"]) { encryptedPass = newPassword; @@ -732,7 +739,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses { encryptedPass = [self _encryptPassword: newPassword]; } - + if (encryptedPass != nil) { *perr = PolicyNoError; @@ -752,7 +759,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses userDN: userDN password: newPassword connection: bindConnection]; - + [self _ldapModifyAttribute: @"sambaLMPassword" withValue: [newPassword asLMHash] userDN: userDN @@ -775,7 +782,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses } } NS_ENDHANDLER ; - + [bindConnection release]; return didChange; } @@ -919,11 +926,11 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses [qs appendFormat: @" AND %@", _filter]; qualifier = [EOQualifier qualifierWithQualifierFormat: qs]; - if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame) + if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame) entries = [ldapConnection baseSearchAtBaseDN: _baseDN qualifier: qualifier attributes: attributes]; - else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame) + else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame) entries = [ldapConnection flatSearchAtBaseDN: _baseDN qualifier: qualifier attributes: attributes]; @@ -1127,7 +1134,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses ldifRecord = [ldapEntry asDictionary]; [ldifRecord setObject: self forKey: @"source"]; [ldifRecord setObject: [ldapEntry dn] forKey: @"dn"]; - + // We get our objectClass attribute values. We lowercase // everything for ease of search after. o = [ldapEntry objectClasses]; @@ -1255,7 +1262,6 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses NSEnumerator *entries; NSMutableArray *contacts; EOQualifier *qualifier; - NSArray *attributes; contacts = [NSMutableArray array]; @@ -1263,20 +1269,19 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses { ldapConnection = [self _ldapConnection]; qualifier = [self _qualifierForFilter: match onCriteria: criteria]; - attributes = [NSArray arrayWithObject: @"*"]; if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame) entries = [ldapConnection baseSearchAtBaseDN: _baseDN qualifier: qualifier - attributes: attributes]; + attributes: _lookupFields]; else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame) entries = [ldapConnection flatSearchAtBaseDN: _baseDN qualifier: qualifier - attributes: attributes]; - else /* we do it like before */ + attributes: _lookupFields]; + else /* we do it like before */ entries = [ldapConnection deepSearchAtBaseDN: _baseDN qualifier: qualifier - attributes: attributes]; + attributes: _lookupFields]; while ((currentEntry = [entries nextObject])) [contacts addObject: [self _convertLDAPEntryToContact: currentEntry]]; @@ -1289,23 +1294,21 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses { NGLdapConnection *ldapConnection; NSEnumerator *entries; - NSArray *attributes; ldapConnection = [self _ldapConnection]; - attributes = [NSArray arrayWithObject: @"*"]; if ([_scope caseInsensitiveCompare: @"BASE"] == NSOrderedSame) entries = [ldapConnection baseSearchAtBaseDN: _baseDN qualifier: theQualifier - attributes: attributes]; + attributes: _lookupFields]; else if ([_scope caseInsensitiveCompare: @"ONE"] == NSOrderedSame) entries = [ldapConnection flatSearchAtBaseDN: _baseDN qualifier: theQualifier - attributes: attributes]; + attributes: _lookupFields]; else entries = [ldapConnection deepSearchAtBaseDN: _baseDN qualifier: theQualifier - attributes: attributes]; + attributes: _lookupFields]; return [entries nextObject]; } @@ -1359,7 +1362,7 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses NGLdapEntry *entry; EOQualifier *qualifier; NSString *login; - + login = nil; qualifier = nil; @@ -1412,24 +1415,24 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses EOQualifier *qualifier; NGLdapEntry *ldapEntry; NSString *s; - + if ([theValue length] > 0 && [theAttributes count] > 0) { if ([theAttributes count] == 1) { s = [NSString stringWithFormat: @"(%@='%@')", [theAttributes lastObject], SafeLDAPCriteria(theValue)]; - + } else { NSString *fieldFormat; - + fieldFormat = [NSString stringWithFormat: @"(%%@='%@')", SafeLDAPCriteria(theValue)]; s = [[theAttributes stringsWithFormat: fieldFormat] componentsJoinedByString: @" OR "]; } - + qualifier = [EOQualifier qualifierWithQualifierFormat: s]; ldapEntry = [self _lookupLDAPEntry: qualifier]; } @@ -1826,6 +1829,7 @@ _makeLDAPChanges (NGLdapConnection *ldapConnection, IMAPLoginField: nil SieveHostField: nil bindFields: nil + lookupFields: nil kindField: nil andMultipleBookingsField: nil]; [ab setListRequiresDot: NO]; @@ -1956,7 +1960,7 @@ _makeLDAPChanges (NGLdapConnection *ldapConnection, reason: @"user addressbooks" @" are not supported" userInfo: nil]; - + return result; }