Bug fixes for #2378 and #2377 and documentation improvements

pull/67/head
Ludovic Marcotte 2014-11-26 15:09:30 -05:00
parent 5a5464dc61
commit be608dc76c
7 changed files with 170 additions and 15 deletions

View File

@ -425,25 +425,31 @@ Defaults to `YES` when unset.
|The location of the SSL private key file on the filesystem that is used
by SOGo to sign and encrypt communications with the SAML2 identity
provider. This file must be generated for each running SOGo service
(rather than host).
(rather than host). Make sure this file is readable by the SOGo user.
|S |SOGoSAML2CertiticateLocation
|The location of the SSL certificate file. This file must be generated
for each running SOGo service.
for each running SOGo service. Make sure this file is readable by the SOGo user.
|S |SOGoSAML2IdpMetadataLocation
|The location of the metadata file that describes the services available
on the SAML2 identify provider.
on the SAML2 identify provider. The content of this file is usually generated
directly by your SAML 2.0 IdP solution. For example, using SimpleSAMLphp, you
can get the metadata directly from https://MYSERVER/simplesaml/saml2/idp/metadata.php
Make sure this file is readable by the SOGo user.
|S |SOGoSAML2IdpPublicKeyLocation
|The location of the SSL public key file on the filesystem that is used
by SOGo to sign and encrypt communications with the SAML2 identity
provider. This file should be part of the setup of your identity
provider.
provider. Make sure this file is readable by the SOGo user.
|S |SOGoSAML2IdpCertificateLocation
|The location of the SSL certificate file. This file should be part of
the setup of your identity provider.
the setup of your identity provider. Make sure this file is readable by the SOGo user.
|S |SOGoSAML2LoginAttribute
|The attribute provided by the IdP to identify the user in SOGo.
|S |SOGoSAML2LogoutEnabled
|Boolean value indicated whether the "Logout" link is enabled when using
@ -1230,13 +1236,32 @@ documentation of your identity provider and the SAML2 configuration keys
that are listed above for proper setup. Once a SOGo instance is
configured properly, the metadata for that instance can be retrieved
from `http://<hostname>/SOGo/saml2-metadata` for registration with the
identity provider.
identity provider. SOGo will dynamically generate the metadata based on
the SOGoSAML2CertificateLocation's content and the SOGo server name.
When using SimpleSAMLphp, make sure the convert OID to names by modifying your
`metadata/saml20-idp-hosted.php` to contain something like this:
----
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
'authproc' => array(
100 => array('class' => 'core:AttributeMap', 'oid2name'),
),
----
If you want to test the IdP-initiated logout using SimpleSAMLphp, you can do so by opening
the following URL:
----
https://idp.example.org/simplesaml/saml2/idp/SingleLogoutService.php?ReturnTo=www.sogo.nu
----
In order to relay authentication information to your IMAP server and if
you make use of the CrudeSAML SASL plugin, you need to make sure that
_NGImap4AuthMechanism_ is configured to use the `SAML` mechanism. If you
make use of the CrudeSAML PAM plugin, this value may be left empty.
Database Configuration
~~~~~~~~~~~~~~~~~~~~~~

7
NEWS
View File

@ -1,8 +1,13 @@
2.2.11 (2014-xx-xx)
-------------------
Enhancements
- Improved the SAML2 documentation
Bug fixes
- Now possible to specify the username attribute for SAML2 (SOGoSAML2LoginAttribute)
- Now possible to specify the username attribute for SAML2 (SOGoSAML2LoginAttribute) (#2381)
- Added support for IdP-initiated SAML2 logout (#2377)
- We now generate SAML2 metadata on the fly (#2378)
2.2.10 (2014-11-21)
-------------------

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EntityDescriptor
entityID="%{base_url}/saml2-metadata"
xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<SPSSODescriptor
AuthnRequestsSigned="true"
WantAssertionsSigned="true"
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>%{certificate}</ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor><KeyDescriptor use="encryption"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data>%{certificate}<ds:X509Certificate></ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor>
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
Location="%{base_url}/saml2-sls" />
<SingleLogoutService
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
Location="%{base_url}/saml2-sls" />
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<AssertionConsumerService
index="0"
isDefault="true"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
Location="%{base_url}/saml2-signon-post" />
<AssertionConsumerService
index="1"
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
Location="%{base_url}/saml2/artifactResponse" />
</SPSSODescriptor>
</EntityDescriptor>

View File

@ -39,7 +39,9 @@
NSString *assertion;
}
+ (NSString *) metadataInContext: (WOContext *) context;
+ (NSString *) metadataInContext: (WOContext *) context
certificate: (NSString *) certificate;
+ (NSString *) authenticationURLInContext: (WOContext *) context;
+ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context;

View File

@ -46,6 +46,28 @@
#import "SOGoSAML2Session.h"
@interface NSString (SOGoCertificateExtension)
- (NSString *) cleanedUpCertificate;
@end
@implementation NSString (SOGoCertificateExtension)
- (NSString *) cleanedUpCertificate
{
NSMutableArray *a;
a = [NSMutableArray arrayWithArray: [self componentsSeparatedByString: @"\n"]];
[a removeObjectAtIndex: 0];
[a removeLastObject];
[a removeLastObject];
return [a componentsJoinedByString: @""];
}
@end
@interface WOContext (SOGoSAML2Extension)
- (NSString *) SAML2ServerURLString;
@ -117,7 +139,9 @@ LassoServerInContext (WOContext *context)
format: @"certificate file '%@' could not be read",
filename];
metadata = [SOGoSAML2Session metadataInContext: context];
metadata = [SOGoSAML2Session metadataInContext: context
certificate: certContent];
/* FIXME: enable key password in config ? */
server = lasso_server_new_from_buffers ([metadata UTF8String],
[keyContent UTF8String],
@ -179,8 +203,10 @@ LassoServerInContext (WOContext *context)
}
+ (NSString *) metadataInContext: (WOContext *) context
certificate: (NSString *) certificate
{
NSString *metadata, *serverURLString, *filename;
NSString *serverURLString, *filename;
NSMutableString *metadata;
NSBundle *bundle;
bundle = [NSBundle bundleForClass: self];
@ -188,9 +214,16 @@ LassoServerInContext (WOContext *context)
if (filename)
{
serverURLString = [context SAML2ServerURLString];
metadata = [[NSString stringWithContentsOfFile: filename]
stringByReplacingString: @"%{base_url}"
withString: serverURLString];
metadata = [NSMutableString stringWithContentsOfFile: filename];
[metadata replaceOccurrencesOfString: @"%{base_url}"
withString: serverURLString
options: 0
range: NSMakeRange(0, [metadata length])];
[metadata replaceOccurrencesOfString: @"%{certificate}"
withString: [certificate cleanedUpCertificate]
options: 0
range: NSMakeRange(0, [metadata length])];
}
else
metadata = nil;

View File

@ -33,6 +33,8 @@
#import <NGExtensions/NSString+misc.h>
#import <SOGo/SOGoSAML2Session.h>
#import <SOGo/SOGoSession.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoWebAuthenticator.h>
@interface SOGoSAML2Actions : WODirectAction
@ -42,20 +44,76 @@
- (WOResponse *) saml2MetadataAction
{
NSString *metadata, *certContent;
SOGoSystemDefaults *sd;
WOResponse *response;
NSString *metadata;
response = [context response];
[response setHeader: @"application/xml; charset=utf-8"
forKey: @"content-type"];
metadata = [SOGoSAML2Session metadataInContext: context];
sd = [SOGoSystemDefaults sharedSystemDefaults];
certContent = [NSString stringWithContentsOfFile: [sd SAML2CertificateLocation]];
metadata = [SOGoSAML2Session metadataInContext: context
certificate: certContent];
[response setContentEncoding: NSUTF8StringEncoding];
[response appendContentString: metadata];
return response;
}
- (WOResponse *) saml2SingleLogoutServiceAction
{
NSString *userName, *value, *cookieName;
SOGoWebAuthenticator *auth;
WOResponse *response;
NSCalendarDate *date;
WOCookie *cookie;
NSArray *creds;
userName = [[context activeUser] login];
[self logWithFormat: @"SAML2 IdP-initiated SLO for user '%@'", userName];
response = [context response];
if ([userName isEqualToString: @"anonymous"])
return response;
cookie = nil;
date = [NSCalendarDate calendarDate];
[date setTimeZone: [NSTimeZone timeZoneWithAbbreviation: @"GMT"]];
// We cleanup the memecached/database session cache. We do this before
// invoking _logoutCookieWithDate: in order to obtain its value.
auth = [[SoApplication application] authenticatorInContext: context];
if ([auth respondsToSelector: @selector (cookieNameInContext:)])
{
cookieName = [auth cookieNameInContext: context];
value = [[context request] cookieValueForKey: cookieName];
creds = [auth parseCredentials: value];
if ([creds count] > 1)
[SOGoSession deleteValueForSessionKey: [creds objectAtIndex: 1]];
if ([cookieName length])
{
cookie = [WOCookie cookieWithName: cookieName value: @"discard"];
[cookie setPath: [NSString stringWithFormat: @"/%@/", [[context request] applicationName]]];
[cookie setExpires: [date yesterday]];
}
}
if (cookie)
[response addCookie: cookie];
return response;
}
- (WOCookie *) _authLocationResetCookieWithName: (NSString *) cookieName
{
WOCookie *locationCookie;

View File

@ -133,6 +133,11 @@
actionClass = "SOGoSAML2Actions";
actionName = "saml2SignOnPOST";
};
saml2-sls = {
protectedBy = "<public>";
actionClass = "SOGoSAML2Actions";
actionName = "saml2SingleLogoutService";
};
/* saml2-signon-redirect = {
protectedBy = "<public>";
actionClass = "SOGoSAML2Actions";