static NSString *LDAPInitialBindPW = @"" ;
/* this is required by SuSE EMail Server III */
-#define ISOLATIN1_CREDENTIALS 1
+static BOOL LDAPUseLatin1Creds = NO;
@interface NGLdapConnection(Privates)
- (BOOL)_reinit;
LDAPInitialBindSpecific = [ud boolForKey:@"LDAPInitialBindSpecific"];
LDAPInitialBindDN = [[ud stringForKey:@"LDAPInitialBindDN"] copy];
LDAPInitialBindPW = [[ud stringForKey:@"LDAPInitialBindPW"] copy];
+ LDAPUseLatin1Creds = [ud boolForKey:@"LDAPUseLatin1Creds"];
}
- (BOOL)_reinit {
- if (self->handle) {
+ static int ldap_version3 = LDAP_VERSION3;
+ int rc;
+
+ if (self->handle != NULL) {
ldap_unbind(self->handle);
self->handle = NULL;
}
self->handle = ldap_init((char *)[self->hostName cString], self->port);
-
if (self->handle == NULL)
return NO;
-
+
+ /* setup options (must be done before the bind) */
+ rc =
+ ldap_set_option(self->handle, LDAP_OPT_PROTOCOL_VERSION, &ldap_version3);
+ if (rc != LDAP_OPT_SUCCESS)
+ [self logWithFormat:@"WARN: could not set protocol version to LDAPv3!"];
+
+ rc = ldap_set_option(self->handle, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) ;
+ if (rc != LDAP_OPT_SUCCESS)
+ [self logWithFormat:@"Note: could not disable LDAP referrals."];
+
return YES;
}
}
- (void)dealloc {
- if (self->handle) {
+ if (self->handle != NULL) {
if ([self isBound])
[self unbind];
else {
- (BOOL)bindWithMethod:(NSString *)_method
binddn:(NSString *)_login credentials:(NSString *)_cred
{
- int ldap_version3 = LDAP_VERSION3 ;
int method, err;
const char *l, *p;
-
+
if (self->handle == NULL)
[self _reinit];
return NO;
l = (char *)[_login UTF8String];
-#if ISOLATIN1_CREDENTIALS
- p = (char *)[_cred cString];
-#else
- p = (char *)[_cred UTF8String];
-#endif
+ p = LDAPUseLatin1Creds
+ ? (char *)[_cred cString]
+ : (char *)[_cred UTF8String];
+
err = (method == LDAP_AUTH_SIMPLE)
? ldap_simple_bind_s(self->handle, l, p)
: ldap_bind_s(self->handle, l, p, method);
if (err == LDAP_SUCCESS) {
- ldap_set_option(self->handle, LDAP_OPT_PROTOCOL_VERSION, &ldap_version3) ;
- ldap_set_option(self->handle, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) ;
self->flags.isBound = YES;
return YES;
}
if ((filter = [_q ldapFilterString]) == nil)
filter = @"(objectclass=*)";
- if (_attributes) {
+ if (_attributes != nil) {
unsigned i, acount;
acount = [_attributes count];
- attrs = calloc(acount + 1, sizeof(char *));
+ attrs = calloc(acount + 3, sizeof(char *));
for (i = 0; i < acount; i++)
attrs[i] = (char *)[[_attributes objectAtIndex:i] UTF8String];
+ attrs[i] = NULL;
}
else
attrs = NULL;
- if (LDAPDebugEnabled)
+ if (LDAPDebugEnabled) {
printf("%s: search with at base %s filter %s for attrs %s\n",
__PRETTY_FUNCTION__, [_base cString], [filter cString],
[[_attributes description] cString]);
-
+ }
+
msgid = ldap_search(self->handle,
(char *)[_base UTF8String],
_scope,
0);
/* free attributes */
- if (attrs) {
- free(attrs); attrs = NULL;
- }
+ if (attrs != NULL) free(attrs); attrs = NULL;
if (msgid == -1) {
/* trouble */
entry = [e nextObject];
- if ([e nextObject]) {
- NSLog(@"more than one search results in base search !!!");
+ if ([e nextObject] != nil) {
+ [self logWithFormat:@"WARN: more than one search results in base search!"];
/* consume all entries */
- while ([e nextObject])
+ while ([e nextObject] != nil) // TODO: can't we cancel the request?
;
}
return s;
}
-@end /* NGLdapConnection */
-
-@implementation NGLdapConnection(PlainPasswordCheck)
+/* PlainPasswordCheck */
+ (NSString *)uidAttributeName {
static NSString *uidAttr = nil;
if (uidAttr == nil) {
- uidAttr = [[[NSUserDefaults standardUserDefaults]
- stringForKey:@"LDAPLoginAttributeName"] copy];
- if ([uidAttr length] == 0) uidAttr = @"uid";
+ // TODO: can't we do this in +initialize? (maybe not if setup later by OGo)
+ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
+
+ uidAttr = [[ud stringForKey:@"LDAPLoginAttributeName"] copy];
+ if (![uidAttr isNotEmpty]) uidAttr = @"uid";
}
return uidAttr;
}
}
if (![self isBound]) {
didBind = NO;
- if (LDAPDebugEnabled)
- [self logWithFormat:@" attempt to do a simple, anonymous bind .."];
- NS_DURING
- if (LDAPInitialBindSpecific)
- didBind = [self bindWithMethod:@"simple" binddn:LDAPInitialBindDN credentials:LDAPInitialBindPW];
- else
+ NS_DURING {
+ if (LDAPInitialBindSpecific) {
+ // TODO: can't we just check whether the DN is set?
+ if (LDAPDebugEnabled) {
+ [self logWithFormat:
+ @" attempt to do a simple, authenticated bind "
+ @"(dn=%@,pwd=%s) ..",
+ LDAPInitialBindDN,
+ [LDAPInitialBindPW length] > 0 ? "yes":"no"];
+ }
+
+ didBind = [self bindWithMethod:@"simple" binddn:LDAPInitialBindDN
+ credentials:LDAPInitialBindPW];
+ }
+ else {
+ if (LDAPDebugEnabled)
+ [self logWithFormat:@" attempt to do a simple, anonymous bind .."];
+
didBind = [self bindWithMethod:@"simple" binddn:@"" credentials:@""];
+ }
+ }
NS_HANDLER
didBind = NO;
NS_ENDHANDLER;
didBind = YES;
if (LDAPDebugEnabled) [self logWithFormat:@" bound."];
}
+
filter = [NSString stringWithFormat:@"(%@=%@)",
[[self class] uidAttributeName],
_login];
- if (LDAPDebugEnabled) [self logWithFormat:@" search: '%@'", filter];
+ if (LDAPDebugEnabled)
+ [self logWithFormat:@" search: uid='%@': '%@'", _login, filter];
+
/* we only check the DN anyway .. */
attrs[0] = "objectclass";
attrs[1] = NULL;
(char *)[filter UTF8String],
attrs, 1,
&result) ;
- if ((ldap_search_result != LDAP_SUCCESS) && (ldap_search_result != LDAP_PARTIAL_RESULTS)) {
+ if ((ldap_search_result != LDAP_SUCCESS) &&
+ (ldap_search_result != LDAP_PARTIAL_RESULTS)) {
/* search failed */
if (didBind)
[self unbind];
- if (LDAPDebugEnabled) {
+ if (LDAPDebugEnabled)
[self logWithFormat:@" search failed"];
- }
+
return nil;
}
/* get DN of first entry */
if ((dn = ldap_get_dn(self->handle, entry)) == NULL) {
- /* couldn't get DN */
+ /* could not get DN */
if (didBind) [self unbind];
if (LDAPDebugEnabled) [self logWithFormat:@" got no DN for entry !"];
return nil;
}
+
strDN = nil;
NS_DURING {
strDN = [[[NSString alloc] initWithUTF8String:dn] autorelease];
if (strDN == nil) {
if (LDAPDebugEnabled) {
- [self debugWithFormat:
+ [self logWithFormat:
@"could not convert DN to UTF-8 string, try cString .."];
}
strDN = [[[NSString alloc] initWithCString:dn] autorelease];
}
- free(dn); dn = NULL;
+ if (dn != NULL) free(dn); dn = NULL;
- if (result) {
+ if (result != NULL) {
ldap_msgfree(result);
}
[self unbind];
- if (LDAPDebugEnabled) {
+
+ if (LDAPDebugEnabled)
[self logWithFormat:@" return DN %@", strDN];
- }
+
return strDN;
}
}
strDN = [self dnForLogin:_login baseDN:_baseDN];
- if (LDAPDebugEnabled) {
- [self logWithFormat:@" attempting to bind login %@ DN: %@ %s!",
- _login, strDN,
- [_pwd length] > 0 ? "(with password) " : "(empty password) "];
- }
-
- if (!strDN) {
+ if ([strDN length] == 0) {
if (LDAPDebugEnabled) {
[self logWithFormat:@" missing dn for login %@ atBaseDN %@",
_login, _baseDN];
}
return NO;
}
+
+ if (LDAPDebugEnabled) {
+ [self logWithFormat:@" attempting to bind login %@ DN: %@ %s!",
+ _login, strDN,
+ [_pwd length] > 0 ? "(with password) " : "(empty password) "];
+ }
+
/*
Now bind as the DN with the password supplied earlier...
Successful bind means the password was correct, otherwise the
if (!didBind) {
/* invalid login or password */
if (LDAPDebugEnabled)
- [self logWithFormat:@" could not simple bind DN '%@' !", strDN];
+ [self logWithFormat:@" simple bind failed for DN: '%@'", strDN];
[self unbind];
return NO;
return [ldap checkPassword:_pwd ofLogin:_login atBaseDN:_baseDN];
}
-@end /* NGLdapConnection(PlainPasswordCheck) */
+@end /* NGLdapConnection */