Monotone-Parent: 78e8177b7871651ba9b05f971e1b40376fb5e49d

Monotone-Revision: 8e4f10d6d171bd7c241c05d63d20efa7f2a66de4

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2009-09-11T14:38:43
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2009-09-11 14:38:43 +00:00
parent b5dfe674de
commit 7bb57b4692
15 changed files with 367 additions and 42 deletions

View File

@ -1,9 +1,17 @@
Alias /sogo.woa/WebServerResources/ \
/usr/GNUstep/System/Library/SOGo/WebServerResources/
Alias /SOGo.woa/WebServerResources/ \
/usr/GNUstep/System/Library/SOGo/WebServerResources/
Alias /SOGO.woa/WebServerResources/ \
Alias /SOGo/WebServerResources/ \
/usr/GNUstep/System/Library/SOGo/WebServerResources/
AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \
/usr/GNUstep/System/Library/SOGo/$1.SOGo/Resources/$2
## For Debian-based distributions, use the following instead of the above:
# Alias /SOGo.woa/WebServerResources/ \
# /usr/lib/GNUstep/SOGo/WebServerResources/
# Alias /SOGo/WebServerResources/ \
# /usr/lib/GNUstep/SOGo/WebServerResources/
# AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \
# /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2
<LocationMatch "^/SOGo/so/ControlPanel/Products/.*UI/Resources/.*jpg">
SetHandler default-handler
@ -25,20 +33,45 @@ Alias /SOGO.woa/WebServerResources/ \
SetHandler default-handler
</LocationMatch>
AliasMatch /SOGo/so/ControlPanel/Products/(.*)/Resources/(.*) \
/usr/GNUstep/System/Library/SOGo/$1.SOGo/Resources/$2
## Uncomment the following to enable proxy-side authentication, you will then
## need to set the "SOGoTrustProxyAuthentication" SOGo user default to YES and
## adjust the "x-webobjects-remote-user" proxy header in the "Proxy" section
## below.
#<Location /SOGo>
# AuthType XXX
# Require valid-user
# SetEnv proxy-nokeepalive 1
# Allow from all
#</Location>
ProxyRequests Off
SetEnv proxy-nokeepalive 1
ProxyPreserveHost On
ProxyPass /SOGo balancer://sogocluster/SOGo
<Proxy balancer://sogocluster>
BalancerMember http://127.0.0.1:20000 retry=1 max=1 timeout=120
# If you enable those, don't forget the enable the spawning of multiple SOGo
# processes. With Redhat-based distributions, this is done by setting the
# "PREFORK" variable in /etc/sysconfig/sogo to the amount of processes as
# value.
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
RequestHeader set "x-webobjects-remote-addr" "127.0.0.1"
RequestHeader set "x-webobjects-remote-host" "127.0.0.1"
## adjust the following to your configuration
RequestHeader set "x-webobjects-server-port" "443"
RequestHeader set "x-webobjects-server-name" "yourhostname"
RequestHeader set "x-webobjects-server-url" "https://yourhostname"
## When using proxy-side autentication, you need to uncomment and
## adjust the following line:
# RequestHeader set "x-webobjects-remote-user" "%{WEBAUTH_USER}e"
BalancerMember http://127.0.0.1:30000 retry=1 max=1 timeout=120
## If you enable those, don't forget the enable the spawning of multiple SOGo
## processes. With Redhat-based distributions, this is done by setting the
## "PREFORK" variable in /etc/sysconfig/sogo to the amount of processes.
## In Debian-based distributions, you should do the same in the
## /etc/default/sogo file instead.
# BalancerMember http://127.0.0.1:20001 retry=1 max=1 timeout=120
# BalancerMember http://127.0.0.1:20002 retry=1 max=1 timeout=120
ProxySet lbmethod=byrequests maxattempts=1
Order allow,deny
Allow from all
</Proxy>
SetEnv proxy-nokeepalive 1
ProxyRequests Off
ProxyPass /SOGo balancer://sogocluster/SOGo

View File

@ -1,3 +1,36 @@
2009-09-11 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* UI/MainUI/SOGoUserHomePage.m (-logoffAction): adjusted to handle
the case where then authenticator doesn't handle authentication
cookies. In such cases, this method should theorically never be
invoked though.
* UI/Common/UIxPageFrame.m (-canLogoff): new bool accessor that
returns whether the current authenticator handles user
disconnection or not, in which case we hide the "logoff" link in
the UIxPageFrame.
* SoObjects/SOGo/SOGoCache.m (-registerUser:withName:): adjusted
method to take an additional "userName" parameter in order to
store users with the username used at login time rather than their
user id. This is especially useful when using indirect binds.
* SoObjects/SOGo/LDAPSource.m (-_qualifierForUIDFilter:): we
include the bindFields in the request if they are specified in the
configuration.
* Main/SOGo.m (-authenticatorInContext:): we no return an instance
of SOGoProxyAuthenticator if "SOGoTrustProxyAuthentication" is
set in the configuration.
* SoObjects/SOGo/SOGoProxyAuthenticator.[mh]: new class module
that defines an authenticator that unconditionnaly trusts and
handle authentication done proxy-side. SOGo uses that
authenticator when the "SOGoTrustProxyAuthentication" user default
is set. The username is taken from the "x-webobjects-remote-user"
http header, you may have to adapt your proxy configuration
accordingly.
2009-09-10 Francis Lachapelle <flachapelle@inverse.ca>
* UI/Scheduler/UIxComponentEditor.m ([UIxComponentEditor

View File

@ -48,6 +48,7 @@
#import <SoObjects/SOGo/SOGoCache.h>
#import <SoObjects/SOGo/SOGoDAVAuthenticator.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/SOGoProxyAuthenticator.h>
#import <SoObjects/SOGo/SOGoUserFolder.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoWebAuthenticator.h>
@ -67,6 +68,8 @@ static BOOL hasCheckedTables = NO;
static BOOL debugRequests = NO;
static BOOL debugLeaks = NO;
static BOOL trustProxyAuthentication;
#ifdef GNUSTEP_BASE_LIBRARY
static BOOL debugObjectAllocation = NO;
#endif
@ -120,6 +123,8 @@ static BOOL debugObjectAllocation = NO;
/* require Authenticated role for View and WebDAV */
[sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_View];
[sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_WebDAVAccess];
trustProxyAuthentication = [ud boolForKey: @"SOGoTrustProxyAuthentication"];
}
- (id) init
@ -269,10 +274,15 @@ static BOOL debugObjectAllocation = NO;
{
id authenticator;
if ([[context request] handledByDefaultHandler])
authenticator = [SOGoWebAuthenticator sharedSOGoWebAuthenticator];
if (trustProxyAuthentication)
authenticator = [SOGoProxyAuthenticator sharedSOGoProxyAuthenticator];
else
authenticator = [SOGoDAVAuthenticator sharedSOGoDAVAuthenticator];
{
if ([[context request] handledByDefaultHandler])
authenticator = [SOGoWebAuthenticator sharedSOGoWebAuthenticator];
else
authenticator = [SOGoDAVAuthenticator sharedSOGoDAVAuthenticator];
}
return authenticator;
}

View File

@ -45,6 +45,7 @@ SOGo_HEADER_FILES = \
\
SOGoAuthenticator.h \
SOGoDAVAuthenticator.h \
SOGoProxyAuthenticator.h \
SOGoWebAuthenticator.h \
SOGoWebDAVAclManager.h \
SOGoWebDAVValue.h \
@ -94,6 +95,7 @@ SOGo_OBJC_FILES = \
NSURL+DAV.m \
\
SOGoDAVAuthenticator.m \
SOGoProxyAuthenticator.m \
SOGoWebAuthenticator.m \
SOGoWebDAVAclManager.m \
SOGoWebDAVValue.m \

View File

@ -55,7 +55,8 @@
- (id) objectNamed: (NSString *) name
inContainer: (SOGoObject *) container;
- (void) registerUser: (SOGoUser *) user;
- (void) registerUser: (SOGoUser *) user
withName: (NSString *) userName;
- (id) userNamed: (NSString *) name;
- (NSMutableDictionary *) userAttributesForLogin: (NSString *) theLogin;

View File

@ -216,11 +216,12 @@ static NSLock *lock;
}
- (void) registerUser: (SOGoUser *) user
withName: (NSString *) userName
{
#if defined(THREADSAFE)
[lock lock];
#endif
[users setObject: user forKey: [user login]];
[users setObject: user forKey: userName];
#if defined(THREADSAFE)
[lock unlock];
#endif
@ -264,11 +265,11 @@ static NSLock *lock;
forLogin: (NSString *) theLogin
{
NSDictionary *d;
memcached_return rc;
const char *key;
char *s;
unsigned int len, vlen, flags;
unsigned int len, flags;
size_t vlen;
if (!handle)
return nil;

View File

@ -19,8 +19,8 @@
02111-1307, USA.
*/
#ifndef __Main_SOGoDAVAuthenticator_H__
#define __Main_SOGoDAVAuthenticator_H__
#ifndef _SOGoDAVAuthenticator_H__
#define _SOGoDAVAuthenticator_H__
#import <NGObjWeb/SoHTTPAuthenticator.h>
@ -50,4 +50,4 @@
@end
#endif /* __Main_SOGoDAVAuthenticator_H__ */
#endif /* _SOGoDAVAuthenticator_H__ */

View File

@ -27,7 +27,6 @@
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGLdap/NGLdapConnection.h>
#import "LDAPUserManager.h"
#import "SOGoPermissions.h"

View File

@ -0,0 +1,56 @@
/* SOGoProxyAuthenticator.h - this file is part of SOGo
*
* Copyright (C) 2009 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _SOGoProxyAuthenticator_H__
#define _SOGoProxyAuthenticator_H__
#import <Foundation/NSObject.h>
#import <NGObjWeb/SoHTTPAuthenticator.h>
#import "SOGoAuthenticator.h"
/*
SOGoProxyAuthenticator
This just overrides the login/pwd check method and always returns YES since
the password is already checked in Apache.
*/
@class NSUserDefaults;
@class NSString;
@class SOGoUser;
// @interface SOGoProxyAuthenticator : SoHTTPAuthenticator <SOGoAuthenticator>
@interface SOGoProxyAuthenticator : NSObject
{
NSString *authMethod;
}
+ (id) sharedSOGoProxyAuthenticator;
- (SOGoUser *) userInContext: (WOContext *) _ctx;
- (NSString *) passwordInContext: (WOContext *) context;
@end
#endif /* _SOGoProxyAuthenticator_H__ */

View File

@ -0,0 +1,166 @@
/* SOGoProxyAuthenticator.h - this file is part of SOGo
*
* Copyright (C) 2009 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSArray.h>
#import <Foundation/NSString.h>
#import <Foundation/NSUserDefaults.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
#import <NGExtensions/NSObject+Logs.h>
#import "LDAPUserManager.h"
#import "SOGoPermissions.h"
#import "SOGoUser.h"
#import "SOGoProxyAuthenticator.h"
@implementation SOGoProxyAuthenticator
+ (id) sharedSOGoProxyAuthenticator
{
static SOGoProxyAuthenticator *auth = nil;
if (!auth)
auth = [self new];
return auth;
}
- (id) init
{
NSUserDefaults *ud;
if ((self = [super init]))
{
ud = [NSUserDefaults standardUserDefaults];
authMethod = [ud stringForKey: @"SOGoAuthenticationMethod"];
if (!authMethod)
authMethod = [ud stringForKey: @"SOGoAuthentificationMethod"];
if (!authMethod)
{
authMethod = @"LDAP";
[self warnWithFormat:
@"authentication method automatically set to '%@'",
authMethod];
}
}
return self;
}
- (void) dealloc
{
[authMethod release];
[super dealloc];
}
- (BOOL) checkLogin: (NSString *) _login
password: (NSString *) _pwd
{
return YES;
}
/* create SOGoUser */
- (NSString *) checkCredentialsInContext: (WOContext *) context
{
NSString *remoteUser;
remoteUser = [[context request] headerForKey: @"x-webobjects-remote-user"];
return remoteUser;
}
- (WOResponse *) unauthorized: (NSString *) reason
inContext: (WOContext *) context
{
WOResponse *r;
if (![reason length])
reason = @"Unauthorized";
r = [context response];
[r setStatus: 403 /* unauthorized */];
[r setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"];
[r appendContentString: reason];
return r;
}
- (SOGoUser *) userInContext: (WOContext *) context
{
SOGoUser *user;
NSString *login;
login = [self checkCredentialsInContext: context];
if ([login length])
user = [SOGoUser userWithLogin: login
roles: [NSArray arrayWithObject:
SoRole_Authenticated]];
else
user = nil;
return user;
}
- (NSString *) passwordInContext: (WOContext *) context
{
return @"";
}
- (WOResponse *) preprocessCredentialsInContext: (WOContext *) context
{
WOResponse *r;
if ([self userInContext: context])
{
[context setObject: [NSArray arrayWithObject: SoRole_Authenticated]
forKey: @"SoAuthenticatedRoles"];
r = nil;
}
else
r = [self unauthorized: nil inContext: context];
return r;
}
- (BOOL) renderException: (NSException *) e
inContext: (WOContext *) context
{
BOOL rc;
if ([e httpStatus] == 401)
{
[self unauthorized: [e reason] inContext: context];
rc = YES;
}
else
rc = NO;
return rc;
}
@end /* SOGoProxyAuthenticator */

View File

@ -246,7 +246,7 @@ _timeValue (NSString *key)
if (user)
{
[user autorelease];
[cache registerUser: user];
[cache registerUser: user withName: newLogin];
}
}
if (newRoles)

View File

@ -25,9 +25,10 @@
#import <NGObjWeb/WOResourceManager.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoUserDefaults.h>
#import <SoObjects/SOGo/NSDictionary+Utilities.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserDefaults.h>
#import <SOGo/NSDictionary+Utilities.h>
#import <SOGo/SOGoWebAuthenticator.h>
#import "UIxPageFrame.h"
@ -389,6 +390,20 @@ static NSString *siteFavicon = nil;
&& [user isSuperUser]);
}
- (BOOL) canLogoff
{
BOOL canLogoff;
id auth;
auth = [[self clientObject] authenticatorInContext: context];
if ([auth respondsToSelector: @selector (cookieNameInContext:)])
canLogoff = ([[auth cookieNameInContext: context] length] > 0);
else
canLogoff = NO;
return canLogoff;
}
- (BOOL) userHasCalendarAccess
{
SOGoUser *user;

View File

@ -121,7 +121,8 @@ static NSArray *supportedLanguages = nil;
oldLocation = [[self clientObject] baseURLInContext: context];
response
= [self redirectToLocation: [NSString stringWithFormat: @"%@/%@",
oldLocation, login]];
oldLocation,
[login stringByEscapingURL]]];
}
return response;

View File

@ -270,7 +270,7 @@ static NSString *LDAPContactInfoAttribute = nil;
SOGoWebAuthenticator *auth;
id container;
NSCalendarDate *date;
NSString *userName;
NSString *userName, *cookieName;
container = [[self clientObject] container];
@ -281,21 +281,27 @@ static NSString *LDAPContactInfoAttribute = nil;
[response setStatus: 302];
[response setHeader: [container baseURLInContext: context]
forKey: @"location"];
auth = [[self clientObject] authenticatorInContext: context];
date = [NSCalendarDate calendarDate];
[date setTimeZone: [NSTimeZone timeZoneWithAbbreviation: @"GMT"]];
cookie = [WOCookie cookieWithName: [auth cookieNameInContext: context]
value: @"discard"];
[cookie setPath: @"/"];
[cookie setExpires: [date yesterday]];
[response addCookie: cookie];
auth = [[self clientObject] authenticatorInContext: context];
if ([auth respondsToSelector: @selector (cookieNameInContext:)])
cookieName = [auth cookieNameInContext: context];
else
cookieName = nil;
if (cookieName)
{
cookie = [WOCookie cookieWithName: cookieName value: @"discard"];
[cookie setPath: @"/"];
[cookie setExpires: [date yesterday]];
[response addCookie: cookie];
}
[response setHeader: [date rfc822DateString] forKey: @"Last-Modified"];
[response setHeader: @"no-store, no-cache, must-revalidate, max-age=0"
forKey: @"Cache-Control"];
[response setHeader: @"post-check=0, pre-check=0" forKey: @"Cache-Control"];
[response setHeader: @"no-store, no-cache, must-revalidate."
@" max-age=0, post-check=0, pre-check=0"
forKey: @"Cache-Control"];
[response setHeader: @"no-cache" forKey: @"Pragma"];
return response;

View File

@ -46,8 +46,10 @@
><var:if condition="context.isUIxDebugEnabled"
><div id="logConsole"><!-- space --></div></var:if>
<div id="linkBanner" class="linkbanner">
<a id="logoff" var:href="logoffPath"
><var:string label:value="Disconnect" /></a>
<var:if condition="canLogoff"
><a id="logoff" var:href="logoffPath"
><var:string label:value="Disconnect" /></a
></var:if>
<var:if condition="userHasCalendarAccess">
<var:if condition="isCalendar">
<span class="active"><var:string label:value="Calendar"