Merge to 2.2.11

This commit is contained in:
Ludovic Marcotte
2014-12-09 09:09:58 -05:00
37 changed files with 1153 additions and 148 deletions
+5 -8
View File
@@ -86,15 +86,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
return nil;
}
data = [[NSData alloc] initWithBytes: xml length: xml_len];
data = [NSData dataWithBytesNoCopy: xml length: xml_len freeWhenDone: YES];
#if WBXMLDEBUG
[data writeToFile: @"/tmp/protocol.decoded" atomically: YES];
#endif
free(xml);
return AUTORELEASE(data);
return data;
}
@@ -138,15 +136,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
return nil;
}
data = [[NSData alloc] initWithBytes: wbxml length: wbxml_len];
data = [NSData dataWithBytesNoCopy: wbxml length: wbxml_len freeWhenDone: YES];
#if WBXMLDEBUG
[data writeToFile: @"/tmp/protocol.encoded" atomically: YES];
#endif
free(wbxml);
wbxml_conv_xml2wbxml_destroy(conv);
return AUTORELEASE(data);
return data;
}
@end
+4
View File
@@ -155,6 +155,10 @@ static NSArray *easCommandParameters = nil;
const char* qs_bytes;
queryString = [[components objectAtIndex: 0] dataByDecodingBase64];
if (![queryString length])
return nil;
qs_bytes = (const char*)[queryString bytes];
if (!easCommandCodes)
+41 -17
View File
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#import "SOGoActiveSyncDispatcher+Sync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSNull.h>
#import <Foundation/NSProcessInfo.h>
@@ -114,22 +115,26 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
forKey: (NSString *) theFolderKey
{
SOGoCacheGCSObject *o;
NSDictionary *values;
NSString *key;
key = [NSString stringWithFormat: @"%@+%@", [context objectForKey: @"DeviceId"], theFolderKey];
values = [theFolderMetadata copy];
o = [SOGoCacheGCSObject objectWithName: key inContainer: nil];
[o setObjectType: ActiveSyncFolderCacheObject];
[o setTableUrl: [self folderTableURL]];
[o reloadIfNeeded];
//[o reloadIfNeeded];
[[o properties] removeObjectForKey: @"SyncKey"];
[[o properties] removeObjectForKey: @"SyncCache"];
[[o properties] removeObjectForKey: @"DateCache"];
[[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
[[o properties] addEntriesFromDictionary: theFolderMetadata];
[[o properties] addEntriesFromDictionary: values];
[o save];
[values release];
}
- (NSMutableDictionary *) _folderMetadataForKey: (NSString *) theFolderKey
@@ -534,6 +539,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
NSMutableDictionary *folderMetadata, *dateCache, *syncCache;
NSAutoreleasePool *pool;
NSMutableString *s;
BOOL more_available;
@@ -635,6 +641,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
allComponents = [theCollection syncTokenFieldsWithProperties: nil matchingSyncToken: theSyncKey fromDate: theFilterType];
allComponents = [allComponents sortedArrayUsingDescriptors: [NSArray arrayWithObjects: [[NSSortDescriptor alloc] initWithKey: @"c_lastmodified" ascending:YES], nil]];
// Check for the WindowSize
max = [allComponents count];
@@ -643,14 +650,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
for (i = 0; i < max; i++)
{
pool = [[NSAutoreleasePool alloc] init];
// Check for the WindowSize and slice accordingly
if (return_count >= theWindowSize)
{
more_available = YES;
// -1 to make sure that we miss no event in case there are more with the same c_lastmodified
*theLastServerKey = [NSString stringWithFormat: @"%d", [[component objectForKey: @"c_lastmodified"] intValue] - 1];
*theLastServerKey = [[NSString alloc] initWithFormat: @"%d", [[component objectForKey: @"c_lastmodified"] intValue] - 1];
DESTROY(pool);
break;
}
@@ -747,6 +757,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendString: @"</Add>"];
return_count++;
DESTROY(pool);
}
} // for ...
@@ -763,6 +775,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[self _setFolderMetadata: folderMetadata
forKey: [NSString stringWithFormat: @"%@/%@", component_name, [theCollection nameInContainer]]];
RELEASE(*theLastServerKey);
}
break;
case ActiveSyncMailFolder:
@@ -830,6 +844,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
for (; k < [allCacheObjects count]; k++)
{
pool = [[NSAutoreleasePool alloc] init];
// Check for the WindowSize and slice accordingly
if (return_count >= theWindowSize)
{
@@ -837,8 +853,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
more_available = YES;
lastSequence = ([[aCacheObject sequence] isEqual: [NSNull null]] ? @"1" : [aCacheObject sequence]);
*theLastServerKey = [NSString stringWithFormat: @"%@-%@", [aCacheObject uid], lastSequence];
*theLastServerKey = [[NSString alloc] initWithFormat: @"%@-%@", [aCacheObject uid], lastSequence];
//NSLog(@"Reached windowSize - lastUID will be: %@", *theLastServerKey);
DESTROY(pool);
break;
}
@@ -919,7 +936,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
}
}
DESTROY(pool);
} // for (; k < ...)
if (more_available)
{
@@ -933,6 +951,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
[self _setFolderMetadata: folderMetadata forKey: [self _getNameInCache: theCollection withType: theFolderType]];
RELEASE(*theLastServerKey);
} // default:
break;
} // switch (folderType) ...
@@ -1050,11 +1070,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
// Collection not found - next folderSync will do the cleanup
//NSLog(@"Sync Collection not found %@ %@", collectionId, realCollectionId);
[theBuffer appendString: @"<Collection>"];
[theBuffer appendFormat: @"<SyncKey>%@</SyncKey>", syncKey];
[theBuffer appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
[theBuffer appendFormat: @"<Status>%d</Status>", 8];
[theBuffer appendString: @"</Collection>"];
//Outlook doesn't like following response
//[theBuffer appendString: @"<Collection>"];
//[theBuffer appendFormat: @"<SyncKey>%@</SyncKey>", syncKey];
//[theBuffer appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
//[theBuffer appendFormat: @"<Status>%d</Status>", 8];
//[theBuffer appendString: @"</Collection>"];
return;
}
@@ -1097,7 +1118,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*changeDetected = YES;
if (!([[self _folderMetadataForKey: [self _getNameInCache: collection withType: folderType]] objectForKey: @"displayName"]))
status = 13; // need folderSync
status = 12; // need folderSync
else
status = 3; // do a complete resync
}
@@ -1118,11 +1139,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[self processSyncGetChanges: theDocumentElement
inCollection: collection
withWindowSize: windowSize
//withWindowSize: 5
withSyncKey: syncKey
withFolderType: folderType
withFilterType: [NSCalendarDate dateFromFilterType: [[(id)[theDocumentElement getElementsByTagName: @"FilterType"] lastObject] textValue]]
//withFilterType: [NSCalendarDate dateFromFilterType: @"7"]
inBuffer: changeBuffer
lastServerKey: &lastServerKey];
}
@@ -1309,7 +1328,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
BOOL changeDetected;
// We initialize our output buffer
output = [NSMutableString string];
output = [[NSMutableString alloc] init];
[output appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[output appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
@@ -1365,8 +1384,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[output appendString: s];
[output appendString: @"</Collections></Sync>"];
d = [[output dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
// Avoid overloading the autorelease pool here, as Sync command can
// generate fairly large responses.
d = [output dataUsingEncoding: NSUTF8StringEncoding];
RELEASE(output);
d = [d xml2wbxml];
[theResponse setContent: d];
}
+108 -13
View File
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SOGoActiveSyncDispatcher.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSProcessInfo.h>
#import <Foundation/NSTimeZone.h>
@@ -129,6 +130,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@interface SOGoActiveSyncDispatcher (Sync)
- (NSMutableDictionary *) _folderMetadataForKey: (NSString *) theFolderKey;
- (void) _setFolderMetadata: (NSDictionary *) theFolderMetadata forKey: (NSString *) theFolderKey;
@end
@@ -906,6 +908,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[o reloadIfNeeded];
[[o properties ] setObject: [[folderMetadata objectForKey: @"path"] substringFromIndex: 1] forKey: @"displayName"];
// clean cache content to avoid stale data
[[o properties] removeObjectForKey: @"SyncKey"];
[[o properties] removeObjectForKey: @"SyncCache"];
[[o properties] removeObjectForKey: @"DateCache"];
[[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
[o save];
command_count++;
@@ -949,11 +958,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Decide between add and change
if (![[o properties ] objectForKey: @"displayName"] || first_sync)
operation = @"Add";
operation = @"Add";
else if (![[[o properties ] objectForKey: @"displayName"] isEqualToString: [[folders objectAtIndex:fi] displayName]])
operation = @"Update";
else
operation = nil;
operation = @"Update";
else
operation = nil;
if (operation)
{
@@ -981,6 +990,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[o setTableUrl: [self folderTableURL]];
[o reloadIfNeeded];
[[o properties ] setObject: [[folders objectAtIndex:fi] displayName] forKey: @"displayName"];
if ([operation isEqualToString: @"Add"])
{
// clean cache content to avoid stale data
[[o properties] removeObjectForKey: @"SyncKey"];
[[o properties] removeObjectForKey: @"SyncCache"];
[[o properties] removeObjectForKey: @"DateCache"];
[[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
}
[o save];
}
else
@@ -992,6 +1012,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
command_count++;
[[o properties ] setObject: [[folders objectAtIndex:fi] displayName] forKey: @"displayName"];
if ([operation isEqualToString: @"Add"])
{
// clean cache content to avoid stale data
[[o properties] removeObjectForKey: @"SyncKey"];
[[o properties] removeObjectForKey: @"SyncCache"];
[[o properties] removeObjectForKey: @"DateCache"];
[[o properties] removeObjectForKey: @"MoreAvailable"];
[[o properties] removeObjectForKey: @"SuccessfulMoveItemsOps"];
}
[o save];
}
}
@@ -1397,7 +1428,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- (void) processMoveItems: (id <DOMElement>) theDocumentElement
inResponse: (WOResponse *) theResponse
{
NSString *srcMessageId, *srcFolderId, *dstFolderId, *dstMessageId;
NSString *srcMessageId, *srcFolderId, *dstFolderId, *dstMessageId, *nameInCache, *currentFolder;
NSMutableDictionary *folderMetadata, *prevSuccessfulMoveItemsOps, *newSuccessfulMoveItemsOps;
SOGoMicrosoftActiveSyncFolderType srcFolderType, dstFolderType;
id <DOMElement> aMoveOperation;
NSArray *moveOperations;
@@ -1406,6 +1438,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
NSData *d;
int i;
currentFolder = nil;
moveOperations = (id)[theDocumentElement getElementsByTagName: @"Move"];
s = [NSMutableString string];
@@ -1421,6 +1455,19 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
srcMessageId = [[(id)[aMoveOperation getElementsByTagName: @"SrcMsgId"] lastObject] textValue];
srcFolderId = [[[(id)[aMoveOperation getElementsByTagName: @"SrcFldId"] lastObject] textValue] realCollectionIdWithFolderType: &srcFolderType];
dstFolderId = [[[(id)[aMoveOperation getElementsByTagName: @"DstFldId"] lastObject] textValue] realCollectionIdWithFolderType: &dstFolderType];
if (srcFolderType == ActiveSyncMailFolder)
nameInCache = [NSString stringWithFormat: @"folder%@", [[[[(id)[aMoveOperation getElementsByTagName: @"SrcFldId"] lastObject] textValue] stringByUnescapingURL] substringFromIndex: 5]];
else
nameInCache = [[[(id)[aMoveOperation getElementsByTagName: @"SrcFldId"] lastObject] textValue] stringByUnescapingURL];
if (![nameInCache isEqualToString: currentFolder])
{
folderMetadata = [self _folderMetadataForKey: nameInCache];
prevSuccessfulMoveItemsOps = [folderMetadata objectForKey: @"SuccessfulMoveItemsOps"];
newSuccessfulMoveItemsOps = [NSMutableDictionary dictionary] ;
currentFolder = nameInCache;
}
[s appendString: @"<Response>"];
@@ -1463,8 +1510,31 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (!dstMessageId)
{
// FIXME: should we return 1 or 2 here?
[s appendFormat: @"<Status>%d</Status>", 2];
// Our destination message ID doesn't exist OR even our source message ID doesn't.
// This can happen if you Move items from your EAS client and immediately closes it
// before the server had the time to receive or process the query. Then, if that message
// is moved away by an other client behing the EAS' client back, it obvisouly won't find it.
// The issue the "result" will still be a success, but in fact, it's a failure. Cyrus generates
// this kind of query/response for an 'unkknown' message UID (696969) when trying to copy it
// over to the folder "Trash".
//
// 3 uid copy 696969 "Trash"
// 3 OK Completed
//
// See http://msdn.microsoft.com/en-us/library/gg651088(v=exchg.80).aspx for Status response codes.
//
if ([prevSuccessfulMoveItemsOps objectForKey: srcMessageId])
{
// Previous move failed operation but we can recover the dstMessageId from previous request
[s appendFormat: @"<SrcMsgId>%@</SrcMsgId>", srcMessageId];
[s appendFormat: @"<DstMsgId>%@</DstMsgId>", [prevSuccessfulMoveItemsOps objectForKey: srcMessageId]];
[s appendFormat: @"<Status>%d</Status>", 3];
[newSuccessfulMoveItemsOps setObject: [prevSuccessfulMoveItemsOps objectForKey: srcMessageId] forKey: srcMessageId];
}
else
{
[s appendFormat: @"<Status>%d</Status>", 1];
}
}
else
{
@@ -1493,6 +1563,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<SrcMsgId>%@</SrcMsgId>", srcMessageId];
[s appendFormat: @"<DstMsgId>%@</DstMsgId>", dstMessageId];
[s appendFormat: @"<Status>%d</Status>", 3];
// Save dstMessageId in cache - it will help to recover if the request fails before the response can be sent to client
[newSuccessfulMoveItemsOps setObject: dstMessageId forKey: srcMessageId];
}
}
@@ -1536,11 +1609,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[s appendFormat: @"<SrcMsgId>%@</SrcMsgId>", srcMessageId];
[s appendFormat: @"<DstMsgId>%@</DstMsgId>", newUID];
[s appendFormat: @"<Status>%d</Status>", 3];
// Save dstMessageId in cache - it will help to recover if the request fails before the response can be sent to client
[newSuccessfulMoveItemsOps setObject: newUID forKey: srcMessageId];
}
else
{
[s appendFormat: @"<SrcMsgId>%@</SrcMsgId>", srcMessageId];
[s appendFormat: @"<Status>%d</Status>", 1];
if ([prevSuccessfulMoveItemsOps objectForKey: srcMessageId])
{
// Move failed but we can recover the dstMessageId from previous request
[s appendFormat: @"<SrcMsgId>%@</SrcMsgId>", srcMessageId];
[s appendFormat: @"<DstMsgId>%@</DstMsgId>", [prevSuccessfulMoveItemsOps objectForKey: srcMessageId] ];
[s appendFormat: @"<Status>%d</Status>", 3];
[newSuccessfulMoveItemsOps setObject: [prevSuccessfulMoveItemsOps objectForKey: srcMessageId] forKey: srcMessageId];
}
else
{
[s appendFormat: @"<SrcMsgId>%@</SrcMsgId>", srcMessageId];
[s appendFormat: @"<Status>%d</Status>", 1];
}
}
}
else
@@ -1557,6 +1644,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
}
[s appendString: @"</Response>"];
[folderMetadata removeObjectForKey: @"SuccessfulMoveItemsOps"];
[folderMetadata setObject: newSuccessfulMoveItemsOps forKey: @"SuccessfulMoveItemsOps"];
[self _setFolderMetadata: folderMetadata forKey: nameInCache];
}
[s appendString: @"</MoveItems>"];
@@ -2329,21 +2420,23 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
context: (id) theContext
{
id <DOMElement> documentElement;
NSAutoreleasePool *pool;
id builder, dom;
SEL aSelector;
NSString *cmdName, *deviceId;
NSData *d;
pool = [[NSAutoreleasePool alloc] init];
ASSIGN(context, theContext);
// Get the device ID, device type and "stash" them
deviceId = [[theRequest uri] deviceId];
[context setObject: deviceId forKey: @"DeviceId"];
[context setObject: [[theRequest uri] deviceType] forKey: @"DeviceType"];
[context setObject: [[theRequest uri] attachmentName] forKey: @"AttachmentName"];
cmdName = [[theRequest uri] command];
// We make sure our cache table exists
@@ -2379,6 +2472,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
d = [[theRequest content] wbxml2xml];
}
documentElement = nil;
if (!d)
@@ -2414,8 +2508,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[theResponse setHeader: @"Sync,SendMail,SmartForward,SmartReply,GetAttachment,GetHierarchy,CreateCollection,DeleteCollection,MoveCollection,FolderSync,FolderCreate,FolderDelete,FolderUpdate,MoveItems,GetItemEstimate,MeetingResponse,Search,Settings,Ping,ItemOperations,ResolveRecipients,ValidateCert" forKey: @"MS-ASProtocolCommands"];
[theResponse setHeader: @"2.0,2.1,2.5,12.0,12.1,14.0,14.1" forKey: @"MS-ASProtocolVersions"];
RELEASE(context);
RELEASE(context);
RELEASE(pool);
return nil;
}
+1 -9
View File
@@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SOGoMailObject+ActiveSync.h"
#import <Foundation/NSArray.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
@@ -511,7 +510,6 @@ struct GlobalObjectId {
//
- (NSString *) activeSyncRepresentationInContext: (WOContext *) _context
{
NSAutoreleasePool *pool;
NSData *d, *globalObjId;
NSArray *attachmentKeys;
NSMutableString *s;
@@ -704,10 +702,6 @@ struct GlobalObjectId {
// Body - namespace 17
preferredBodyType = [[context objectForKey: @"BodyPreferenceType"] intValue];
// Make use of a local pool here as _preferredBodyDataUsingType:nativeType: will consume
// a significant amout of RAM and file descriptors
pool = [[NSAutoreleasePool alloc] init];
nativeBodyType = 1;
d = [self _preferredBodyDataUsingType: preferredBodyType nativeType: &nativeBodyType];
@@ -747,9 +741,7 @@ struct GlobalObjectId {
}
[s appendString: @"</Body>"];
}
DESTROY(pool);
// Attachments -namespace 16
attachmentKeys = [self fetchFileAttachmentKeys];
if ([attachmentKeys count])
+13 -1
View File
@@ -26,12 +26,23 @@ Alias /SOGo/WebServerResources/ \
## need to set the "SOGoTrustProxyAuthentication" SOGo user default to YES and
## adjust the "x-webobjects-remote-user" proxy header in the "Proxy" section
## below.
#
## For full proxy-side authentication:
#<Location /SOGo>
# AuthType XXX
# Require valid-user
# SetEnv proxy-nokeepalive 1
# Allow from all
#</Location>
#
## For proxy-side authentication only for CardDAV and GroupDAV from external
## clients:
#<Location /SOGo/dav>
# AuthType XXX
# Require valid-user
# SetEnv proxy-nokeepalive 1
# Allow from all
#</Location>
ProxyRequests Off
SetEnv proxy-nokeepalive 1
@@ -64,7 +75,8 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0
## When using proxy-side autentication, you need to uncomment and
## adjust the following line:
# RequestHeader set "x-webobjects-remote-user" "%{REMOTE_USER}e"
RequestHeader unset "x-webobjects-remote-user"
# RequestHeader set "x-webobjects-remote-user" "%{REMOTE_USER}e" env=REMOTE_USER
RequestHeader set "x-webobjects-server-protocol" "HTTP/1.0"
+247
View File
@@ -1,3 +1,250 @@
commit aac6b22ab56f594e2c796d015e949549bf22e517
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Dec 9 09:08:54 2014 -0500
Preparation for the release
M Documentation/docinfo.xml
M Documentation/includes/global-attributes.asciidoc
M NEWS
M Version
commit 39e8f055d702e0d33da6af130403e1fd0287c102
Author: Jens Erat <email@jenserat.de>
Date: Tue Dec 9 13:23:21 2014 +0100
Added information on common configuration issues
A very common issue (watching the mailing list) is not wrapping the
whole configuration in a dictionary. SOGo is not very helpful at
debugging broken configuration files, thus hinting `plparse` already
installed with the GNUstep runtime.
M Documentation/SOGoInstallationGuide.asciidoc
commit 64637d842b9b4979324e98d057909d57c86eb9ec
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Dec 9 07:21:34 2014 -0500
Prevent compilation failures with old gcc versions
M Tools/SOGoToolManageEAS.m
commit 4e6214d6fcaa278f4039765de2b74fd862ced228
Author: Jens Erat <email@jenserat.de>
Date: Tue Dec 9 13:11:03 2014 +0100
Fixed ActiveSync URL in documentation
M Documentation/SOGoInstallationGuide.asciidoc
commit 12788c847d5ba3d609848bf52589b4c7f3907595
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Dec 8 10:45:34 2014 -0500
New sogo-tool feature to manage EAS data
M ActiveSync/SOGoActiveSyncDispatcher+Sync.m
M ActiveSync/SOGoActiveSyncDispatcher.m
M NEWS
M Tools/GNUmakefile
A Tools/SOGoToolManageEAS.m
commit 2b95dd2c0a04b28839a721cb3ba40c674f3981b5
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Dec 8 10:29:23 2014 -0500
Avoid generating GUID for "Other user"/"Shared" folders
M SoObjects/Mailer/SOGoMailAccount.m
commit 9e14a37cb81cf1dce955e5e16440fe413e4f656a
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Mon Dec 8 10:25:37 2014 -0500
Improvements over fixes for #2982
M ActiveSync/SOGoActiveSyncDispatcher+Sync.m
M ActiveSync/SOGoActiveSyncDispatcher.m
commit ae0cbfe6a61610acfe3b3325e6cc9ef58332f6b4
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Fri Dec 5 13:52:10 2014 -0500
Fix for bug #2982
M ActiveSync/SOGoActiveSyncDispatcher.m
M NEWS
commit 3f3673cf5ad2691c04f975dc58a58173e7c6c2ee
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Dec 4 17:59:17 2014 -0500
Added SOGoSAML2LogoutURL
M Documentation/SOGoInstallationGuide.asciidoc
M SoObjects/SOGo/SOGoSystemDefaults.h
M SoObjects/SOGo/SOGoSystemDefaults.m
M UI/MainUI/SOGoSAML2Actions.m
commit 9ef4d1f551bcfe597395bc7d9ec7bef2ef3e9a0f
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Dec 4 12:21:23 2014 -0500
Fix for bug #3010
M NEWS
M UI/MainUI/SOGoUserHomePage.m
commit fe9ad9c6e9b43fa276f6e71972ffd9823e4df9de
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Dec 4 11:27:10 2014 -0500
Radically reduced EAS memory usage
M ActiveSync/NSData+ActiveSync.m
M ActiveSync/SOGoActiveSyncDispatcher+Sync.m
M ActiveSync/SOGoActiveSyncDispatcher.m
M ActiveSync/SOGoMailObject+ActiveSync.m
M NEWS
M SoObjects/SOGo/SOGoCacheGCSObject.m
commit 47094b6d91c6375bb48160b355c643a628c139be
Author: extrafu <lmarcotte@inverse.ca>
Date: Tue Dec 2 19:33:54 2014 -0500
Update SOGoSAML2Metadata.xml
Fixed XML template generation.
M SoObjects/SOGo/SOGoSAML2Metadata.xml
commit 9ffa32eebdcc5d3b102aa4d86a93590684800cdc
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Sun Nov 30 17:35:39 2014 -0500
Enable SAML support on all Debian-based distro
M packaging/debian-multiarch/control
M packaging/debian-multiarch/rules
M packaging/debian/control
M packaging/debian/control-squeeze
M packaging/debian/rules
commit 1b715e0812dba3d9f2c4d3f2daa0cbd4313f8def
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Thu Nov 27 11:37:08 2014 -0500
We now handle correctly the SOGo logout when using SAML (#2376 and #2379)
M Documentation/SOGoInstallationGuide.asciidoc
M NEWS
M SoObjects/SOGo/SOGoCASSession.h
M SoObjects/SOGo/SOGoCASSession.m
M SoObjects/SOGo/SOGoCache.h
M SoObjects/SOGo/SOGoCache.m
M SoObjects/SOGo/SOGoSAML2Session.h
M SoObjects/SOGo/SOGoSAML2Session.m
M SoObjects/SOGo/SOGoWebAuthenticator.m
M UI/MainUI/SOGoSAML2Actions.m
M UI/MainUI/SOGoUserHomePage.m
commit c3715c94857efa77e1e38b814e0f0ee09cc9c678
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Nov 26 15:27:36 2014 -0500
Added additional bugfix for #2982
M ActiveSync/SOGoActiveSyncDispatcher+Sync.m
commit be608dc76c7217c62152e869ab17c9b237a4e99a
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Nov 26 15:09:30 2014 -0500
Bug fixes for #2378 and #2377 and documentation improvements
M Documentation/SOGoInstallationGuide.asciidoc
M NEWS
A SoObjects/SOGo/SOGoSAML2Metadata.xml
M SoObjects/SOGo/SOGoSAML2Session.h
M SoObjects/SOGo/SOGoSAML2Session.m
M UI/MainUI/SOGoSAML2Actions.m
M UI/MainUI/product.plist
commit 5a5464dc610cddb87b9c07e97699c24a767f5ed7
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Nov 26 13:24:04 2014 -0500
An other fix for #2930
M UI/MainUI/SOGoUserHomePage.m
commit 89917c941caf9f7c4ca18e498bba06298f7f26f6
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Nov 26 13:01:50 2014 -0500
New entry for bug #2381
M NEWS
commit 913a75f410d8e4409960e59c110f707ffad47371
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Wed Nov 26 13:00:47 2014 -0500
Fix for bug #
M SoObjects/SOGo/SOGoCache.m
M SoObjects/SOGo/SOGoSAML2Session.h
M SoObjects/SOGo/SOGoSAML2Session.m
M SoObjects/SOGo/SOGoSession.h
M SoObjects/SOGo/SOGoSession.m
M SoObjects/SOGo/SOGoSystemDefaults.h
M SoObjects/SOGo/SOGoSystemDefaults.m
commit 20e728afac25c9930af97eb2d1fb7519d415c853
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Nov 25 17:28:12 2014 -0500
Remove unnecessary comments
M SoObjects/SOGo/SOGoCache.m
commit 5f14bc11011394ff6f1333880320eec7ceb675af
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Tue Nov 25 17:27:03 2014 -0500
Report the correct preference keys
M SoObjects/SOGo/SOGoSAML2Session.m
commit b0633ba1f454b9b09d646ff0b512f5d13a0f236e
Author: Robin McCorkell <rmccorkell@karoshi.org.uk>
Date: Tue Jun 18 17:50:28 2013 +0200
Add check for remote_user variable for trusted proxy auth
If trusted proxy authentication is on, yet the proxy did not authenticate the
user, then the default authentication method is used instead of returning 'Unauthorized'.
M Apache/SOGo.conf
M Main/SOGo.m
commit bb227443ed632cb03cba58e24259510c9686e1d2
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Sat Nov 22 08:14:31 2014 -0500
Check lenght of string before trying to use parameters
M ActiveSync/NSString+ActiveSync.m
commit efff32e44d1b6df1dfe03f81bbd0e1f449a8fbb2
Author: Ludovic Marcotte <lmarcotte@inverse.ca>
Date: Fri Nov 21 09:13:11 2014 -0500
Update ChangeLog
M ChangeLog
commit f7f78eaba6ac5304df937f5b26f5d21979657787
Author: Francis Lachapelle <flachapelle@inverse.ca>
Date: Fri Nov 21 09:07:39 2014 -0500
+45 -8
View File
@@ -273,6 +273,11 @@ is not required, only recommended. Block comments are delimited by `/*`
and `*/` and can span multiple lines while line comments must start with
`//`.
The configuration must be contained in a root dictionary, thus be completely
wrapped within curly brackets `{ [configuration] }`. If SOGo refuses to
start due to syntax errors in its configuration file, `plparse` is helpful
for finding these, as it indicates the line containing the problem.
Preferences Hierarchy
~~~~~~~~~~~~~~~~~~~~~
@@ -425,29 +430,42 @@ 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
SAML2 as authentication mechanism.
SAML2 as authentication mechanism. When using this feature, SOGo will invoke
the IdP to proceed with the logout procedure. When the user clicks on the logout
button, a redirection will be made to the IdP to trigger the logout.
|S |SOGoSAML2LogoutURL
|The URL to which redirect the user after the "Logout" link is clicked.
SOGoSAML2LogoutEnabled must be set to YES. If unset, the user will be
redirected to a blank page.
|D |SOGoTimeZone
|Parameter used to set a default time zone for users. The default
@@ -1230,13 +1248,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
~~~~~~~~~~~~~~~~~~~~~~
@@ -2524,7 +2561,7 @@ any mobile devices that support Microsoft ActiveSync. Microsoft Outlook
2013 is also supported.
The Microsoft ActiveSync server URL is generally something
like: `http://localhost/Microsoft-Active-Sync`.
like: `http://localhost/Microsoft-Server-ActiveSync`.
Upgrading
---------
+3 -3
View File
@@ -1,7 +1,7 @@
<!-- TODO have the build system take care of this -->
<releaseinfo>Version 2.2.10 - November 2014</releaseinfo>
<subtitle>for version 2.2.10</subtitle>
<date>2014-11-21</date>
<releaseinfo>Version 2.2.11 - December 2014</releaseinfo>
<subtitle>for version 2.2.11</subtitle>
<date>2014-12-09</date>
<legalnotice>
<para>Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".</para>
@@ -13,6 +13,6 @@
// TODO have the build system take care of this
:release_version: 2.2.10
:release_version: 2.2.11
// vim: set syntax=asciidoc tabstop=2 shiftwidth=2 expandtab:
+1 -1
View File
@@ -283,7 +283,7 @@ static BOOL debugLeaks;
{
id authenticator;
if (trustProxyAuthentication)
if (trustProxyAuthentication && [[context request] headerForKey: @"x-webobjects-remote-user"])
authenticator = [SOGoProxyAuthenticator sharedSOGoProxyAuthenticator];
else
{
+18
View File
@@ -1,3 +1,21 @@
2.2.11 (2014-12-09)
-------------------
New features
- sogo-tool can now be used to manage EAS metadata for all devices
Enhancements
- Improved the SAML2 documentation
- Radically reduced AES memory usage
Bug fixes
- 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)
- We now handle correctly the SOGo logout when using SAML (#2376 and #2379)
- Fixed freebusy lookups going off bounds for resources (#3010)
- Fixed EAS clients moving mails between folders but disconnecting before receiving server's response (#2982)
2.2.10 (2014-11-21)
-------------------
+12 -2
View File
@@ -664,7 +664,7 @@ static NSString *inboxFolderName = @"INBOX";
- (NSDictionary *) imapFolderGUIDs
{
NSDictionary *result, *nresult, *folderData;
NSDictionary *result, *nresult, *namespaceDict;
NSMutableDictionary *folders;
NGImap4Client *client;
SOGoUserDefaults *ud;
@@ -684,16 +684,26 @@ static NSString *inboxFolderName = @"INBOX";
folders = [NSMutableDictionary dictionary];
client = [[self imap4Connection] client];
namespaceDict = [client namespace];
result = [client annotation: @"*" entryName: @"/comment" attributeName: @"value.priv"];
e = [folderList objectEnumerator];
while (object = [e nextObject])
while ((object = [e nextObject]))
{
guid = [[[[result objectForKey: @"FolderList"] objectForKey: [object substringFromIndex: 1]] objectForKey: @"/comment"] objectForKey: @"value.priv"];
if (!guid)
{
// Don't generate a GUID for "Other users" and "Shared" namespace folders - user foldername instead
if ([[object substringFromIndex: 1] isEqualToString: [[[[namespaceDict objectForKey: @"other users"] lastObject] objectForKey: @"prefix"] substringFromIndex: 1]] ||
[[object substringFromIndex: 1] isEqualToString: [[[[namespaceDict objectForKey: @"shared"] lastObject] objectForKey: @"prefix"] substringFromIndex: 1]])
{
[folders setObject: [NSString stringWithFormat: @"folder%@", [object substringFromIndex: 1]] forKey: [NSString stringWithFormat: @"folder%@", [object substringFromIndex: 1]]];
continue;
}
guid = [[NSProcessInfo processInfo] globallyUniqueString];
nresult = [client annotation: [object substringFromIndex: 1] entryName: @"/comment" attributeName: @"value.priv" attributeValue: guid];
+1 -3
View File
@@ -1,8 +1,6 @@
/* SOGoCASSession.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2010-2014 Inverse inc.
*
* 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
+1 -3
View File
@@ -1,8 +1,6 @@
/* SOGoCASSession.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2010-2014 Inverse inc.
*
* 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
+1
View File
@@ -132,6 +132,7 @@
- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier;
- (void) setSaml2LoginDumps: (NSDictionary *) dump
forIdentifier: (NSString *) identifier;
- (void) removeSAML2LoginDumpsForIdentifier: (NSString *) identifier;
//
// ACL caching support
+16 -5
View File
@@ -31,8 +31,8 @@
* <uid>+defaults value = NSDictionary instance > user's defaults
* <uid>+settings value = NSDictionary instance > user's settings
* <uid>+attributes value = NSMutableDictionary instance > user's LDAP attributes
* <uid>+failedlogins value =
* <uid>+messagesubmissions value =
* <uid>+failedlogins value = NSDictionary instance holding the failed count and the date of the first failed authentication
* <uid>+messagesubmissions value = NSDictionary instance holding the number of messages sent, and number of recipients
* <uid>+dn value = NSString instance > cached user's DN
* <object path>+acl value = NSDictionary instance > ACLs on an object at specified path
* <groupname>+<domain> value = NSString instance (array components separated by ",") or group member logins for a specific group in domain
@@ -40,8 +40,7 @@
* cas-ticket:< > value =
* cas-pgtiou:< > value =
* session:< > value =
* <uid>+failedlogins value = NSDictionary instance holding the failed count and the date of the first failed authentication
* <uid>+messagesubmissions value = NSDictionary instance holding the number of messages sent, and number of recipients
* saml2-login:< > value =
*/
@@ -674,11 +673,13 @@ static memcached_st *handle = NULL;
{
key = [NSString stringWithFormat: @"cas-ticket:%@", ticket];
[self removeValueForKey: key];
[self debugWithFormat: @"Removed session: %@", session];
[self debugWithFormat: @"Removed CAS session: %@", session];
}
}
//
// SAML2 support
//
- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier
{
NSString *key, *jsonString;
@@ -699,6 +700,16 @@ static memcached_st *handle = NULL;
[self setValue: [dump jsonRepresentation] forKey: key];
}
- (void) removeSAML2LoginDumpsForIdentifier: (NSString *) identifier
{
NSString *key;
key = [NSString stringWithFormat: @"saml2-login:%@", identifier];
[self removeValueForKey: key];
[self debugWithFormat: @"Removed SAML2 session for identifier: %@", identifier];
}
//
// ACL caching code
//
+20
View File
@@ -36,6 +36,7 @@
#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NSNull+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/NSObject+Utilities.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoDomainDefaults.h>
@@ -96,10 +97,29 @@ static EOAttribute *textColumn = nil;
- (void) dealloc
{
//NSLog(@"SOGoCacheGCSObject: -dealloc for name: %@", nameInContainer);
[tableUrl release];
[super dealloc];
}
+ (id) objectWithName: (NSString *) key inContainer: (id) theContainer
{
SOGoCache *cache;
id o;
cache = [SOGoCache sharedCache];
o = [cache objectNamed: key inContainer: theContainer];
if (!o)
{
o = [super objectWithName: key inContainer: theContainer];
//NSLog(@"Caching object with key: %@", key);
[cache registerObject: o withName: key inContainer: theContainer];
}
return o;
}
- (void) setTableUrl: (NSURL *) newTableUrl
{
ASSIGN (tableUrl, newTableUrl);
+27
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><ds:X509Certificate>%{certificate}</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>
+10 -4
View File
@@ -1,8 +1,6 @@
/* SOGoSAML2Session.h - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2012-2014 Inverse inc.
*
* 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
@@ -39,9 +37,15 @@
NSString *login;
NSString *identifier;
NSString *assertion;
NSString *identity;
NSString *session;
}
+ (NSString *) metadataInContext: (WOContext *) context;
+ (LassoServer *) lassoServerInContext: (WOContext *) context;
+ (NSString *) metadataInContext: (WOContext *) context
certificate: (NSString *) certificate;
+ (NSString *) authenticationURLInContext: (WOContext *) context;
+ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context;
@@ -54,6 +58,8 @@
- (NSString *) login;
- (NSString *) identifier;
- (NSString *) assertion;
- (NSString *) identity;
- (NSString *) session;
@end
+111 -37
View File
@@ -1,8 +1,6 @@
/* SOGoSAML2Session.m - this file is part of SOGo
*
* Copyright (C) 2012 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2012-2014 Inverse inc.
*
* 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
@@ -48,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;
@@ -85,8 +105,7 @@ static NSMapTable *serverTable = nil;
lasso_init ();
}
static LassoServer *
LassoServerInContext (WOContext *context)
+ (LassoServer *) lassoServerInContext: (WOContext *) context
{
NSString *urlString, *metadata, *filename, *keyContent, *certContent,
*idpKeyFilename, *idpCertFilename;
@@ -102,7 +121,7 @@ LassoServerInContext (WOContext *context)
filename = [sd SAML2PrivateKeyLocation];
if (!filename)
[NSException raise: NSInvalidArgumentException
format: @"'SAML2PrivateKeyLocation' not set"];
format: @"'SOGoSAML2PrivateKeyLocation' not set"];
keyContent = [NSString stringWithContentsOfFile: filename];
if (!keyContent)
[NSException raise: NSGenericException
@@ -112,14 +131,16 @@ LassoServerInContext (WOContext *context)
filename = [sd SAML2CertificateLocation];
if (!filename)
[NSException raise: NSInvalidArgumentException
format: @"'SAML2CertificateLocation' not set"];
format: @"'SOGoSAML2CertificateLocation' not set"];
certContent = [NSString stringWithContentsOfFile: filename];
if (!certContent)
[NSException raise: NSGenericException
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],
@@ -148,7 +169,7 @@ LassoServerInContext (WOContext *context)
NSString *url;
GList *providers;
server = LassoServerInContext (context);
server = [SOGoSAML2Session lassoServerInContext: context];
tempLogin = lasso_login_new (server);
providers = g_hash_table_get_keys (server->providers);
@@ -181,8 +202,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];
@@ -190,9 +213,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;
@@ -208,6 +238,8 @@ LassoServerInContext (WOContext *context)
login = nil;
identifier = nil;
assertion = nil;
identity = nil;
session = nil;
}
return self;
@@ -215,7 +247,6 @@ LassoServerInContext (WOContext *context)
- (void) _updateDataFromLogin
{
// LassoSamlp2Response *response;
LassoSaml2Assertion *saml2Assertion;
GList *statementList, *attributeList;
LassoSaml2AttributeStatement *statement;
@@ -223,10 +254,15 @@ LassoServerInContext (WOContext *context)
LassoSaml2AttributeValue *value;
LassoMiscTextNode *textNode;
LassoSaml2NameID *nameIdentifier;
SOGoSystemDefaults *sd;
NSString *loginAttribue;
gchar *dump;
saml2Assertion
= LASSO_SAML2_ASSERTION (lasso_login_get_assertion (lassoLogin));
saml2Assertion = LASSO_SAML2_ASSERTION (lasso_login_get_assertion (lassoLogin));
sd = [SOGoSystemDefaults sharedSystemDefaults];
loginAttribue = [sd SAML2LoginAttribute];
if (saml2Assertion)
{
/* deduce user login */
@@ -241,22 +277,42 @@ LassoServerInContext (WOContext *context)
while (!login && attributeList)
{
attribute = LASSO_SAML2_ATTRIBUTE (attributeList->data);
if (strcmp (attribute->Name, "uid") == 0)
if (loginAttribue && (strcmp (attribute->Name, [loginAttribue UTF8String]) == 0))
{
value = LASSO_SAML2_ATTRIBUTE_VALUE (attribute->AttributeValue->data);
textNode = value->any->data;
// If we got an @ sign in the value, it's most likely an email address
// so we'll ask SOGoUserManager about this
login = [NSString stringWithUTF8String: textNode->content];
if ([login rangeOfString: @"@"].location != NSNotFound)
{
login = [[SOGoUserManager sharedUserManager] getUIDForEmail: login];
}
[login retain];
}
else if (strcmp (attribute->Name, "mail") == 0)
else if (!loginAttribue)
{
value = LASSO_SAML2_ATTRIBUTE_VALUE (attribute->AttributeValue->data);
textNode = value->any->data;
login = [[SOGoUserManager sharedUserManager] getUIDForEmail: [NSString stringWithUTF8String: textNode->content]];
[login retain];
// We fallback on "standard" attributes such as "uid" and "mail"
if (strcmp (attribute->Name, "uid") == 0)
{
value = LASSO_SAML2_ATTRIBUTE_VALUE (attribute->AttributeValue->data);
textNode = value->any->data;
login = [NSString stringWithUTF8String: textNode->content];
[login retain];
}
else if (strcmp (attribute->Name, "mail") == 0)
{
value = LASSO_SAML2_ATTRIBUTE_VALUE (attribute->AttributeValue->data);
textNode = value->any->data;
login = [[SOGoUserManager sharedUserManager] getUIDForEmail: [NSString stringWithUTF8String: textNode->content]];
[login retain];
}
}
else
attributeList = attributeList->next;
attributeList = attributeList->next;
}
statementList = statementList->next;
}
@@ -295,7 +351,7 @@ LassoServerInContext (WOContext *context)
if ((self = [self init]))
{
server = LassoServerInContext (context);
server = [SOGoSAML2Session lassoServerInContext: context];
lassoLogin = lasso_login_new (server);
if (saml2Dump)
{
@@ -303,12 +359,17 @@ LassoServerInContext (WOContext *context)
ASSIGN (login, [saml2Dump objectForKey: @"login"]);
ASSIGN (identifier, [saml2Dump objectForKey: @"identifier"]);
ASSIGN (assertion, [saml2Dump objectForKey: @"assertion"]);
dump = [[saml2Dump objectForKey: @"identity"] UTF8String];
ASSIGN(identity, [saml2Dump objectForKey: @"identity"]);
dump = [identity UTF8String];
if (dump)
lasso_profile_set_identity_from_dump (profile, dump);
dump = [[saml2Dump objectForKey: @"session"] UTF8String];
ASSIGN (session, [saml2Dump objectForKey: @"session"]);
dump = [session UTF8String];
if (dump)
lasso_profile_set_session_from_dump (profile, dump);
lasso_login_accept_sso (lassoLogin);
// if (rc)
// [NSException raiseSAML2Exception: rc];
@@ -326,6 +387,9 @@ LassoServerInContext (WOContext *context)
[login release];
[identifier release];
[assertion release];
[identity release];
[session release];
[super dealloc];
}
@@ -378,13 +442,23 @@ LassoServerInContext (WOContext *context)
return assertion;
}
- (NSString *) identity
{
return identity;
}
- (NSString *) session
{
return session;
}
- (void) processAuthnResponse: (NSString *) authnResponse
{
lasso_error_t rc;
gchar *responseData, *dump;
LassoProfile *profile;
LassoIdentity *identity;
LassoSession *session;
LassoIdentity *lasso_identity;
LassoSession *lasso_session;
NSString *nsDump;
NSMutableDictionary *saml2Dump;
@@ -408,22 +482,22 @@ LassoServerInContext (WOContext *context)
profile = LASSO_PROFILE (lassoLogin);
session = lasso_profile_get_session (profile);
if (session)
lasso_session = lasso_profile_get_session (profile);
if (lasso_session)
{
dump = lasso_session_dump (session);
dump = lasso_session_dump (lasso_session);
nsDump = [NSString stringWithUTF8String: dump];
[saml2Dump setObject: nsDump forKey: @"session"];
lasso_session_destroy (session);
lasso_session_destroy (lasso_session);
}
identity = lasso_profile_get_identity (profile);
if (identity)
lasso_identity = lasso_profile_get_identity (profile);
if (lasso_identity)
{
dump = lasso_identity_dump (identity);
dump = lasso_identity_dump (lasso_identity);
nsDump = [NSString stringWithUTF8String: dump];
[saml2Dump setObject: nsDump forKey: @"identity"];
lasso_identity_destroy (identity);
lasso_identity_destroy (lasso_identity);
}
[[SOGoCache sharedCache] setSaml2LoginDumps: saml2Dump
+1 -4
View File
@@ -1,9 +1,6 @@
/* SOGoSession.h - this file is part of SOGo
*
* Copyright (C) 2010-2011 Inverse inc.
*
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
* Francis Lachapelle <flachapelle@inverse.ca>
* Copyright (C) 2010-2014 Inverse inc.
*
* 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
+1 -5
View File
@@ -1,10 +1,6 @@
/* SOGoSession.m - this file is part of SOGo
*
* Copyright (C) 2010-2011 Inverse inc.
*
* Author: Ludovic Marcotte <lmarcotte@inverse.ca>
* Francis Lachapelle <flachapelle@inverse.ca>
* Copyright (C) 2010-2014 Inverse inc.
*
* 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
+2
View File
@@ -80,7 +80,9 @@
- (NSString *) SAML2IdpMetadataLocation;
- (NSString *) SAML2IdpPublicKeyLocation;
- (NSString *) SAML2IdpCertificateLocation;
- (NSString *) SAML2LoginAttribute;
- (BOOL) SAML2LogoutEnabled;
- (NSString *) SAML2LogoutURL;
- (BOOL) enablePublicAccess;
+10
View File
@@ -511,6 +511,16 @@ _injectConfigurationFromFile (NSMutableDictionary *defaultsDict,
return [self boolForKey: @"SOGoSAML2LogoutEnabled"];
}
- (NSString *) SAML2LogoutURL
{
return [self stringForKey: @"SOGoSAML2LogoutURL"];
}
- (NSString *) SAML2LoginAttribute
{
return [self stringForKey: @"SOGoSAML2LoginAttribute"];
}
- (BOOL) enablePublicAccess
{
return [self boolForKey: @"SOGoEnablePublicAccess"];
+1 -1
View File
@@ -1,6 +1,6 @@
/* SOGoWebAuthenticator.m - this file is part of SOGo
*
* Copyright (C) 2007-2013 Inverse inc.
* Copyright (C) 2007-2014 Inverse inc.
*
* 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
+2 -1
View File
@@ -22,7 +22,8 @@ $(SOGO_TOOL)_OBJC_FILES += \
SOGoToolRemoveDoubles.m \
SOGoToolRenameUser.m \
SOGoToolRestore.m \
SOGoToolUserPreferences.m
SOGoToolUserPreferences.m \
SOGoToolManageEAS.m
TOOL_NAME += $(SOGO_TOOL)
###
+290
View File
@@ -0,0 +1,290 @@
/* SOGoToolManageEAS.m - this file is part of SOGo
*
* Copyright (C) 2014 Inverse inc.
*
* 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/NSCharacterSet.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSURL.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOApplication.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoProductLoader.h>
#import "SOGo/SOGoCredentialsFile.h"
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserFolder.h>
#import <SOGo/SOGoUserDefaults.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoUserSettings.h>
#import <Mailer/SOGoMailAccounts.h>
#import <Mailer/SOGoMailAccount.h>
#import <SOGo/SOGoCacheGCSObject.h>
#import "SOGoTool.h"
typedef enum
{
ManageEASUnknown = -1,
ManageEASListDevices = 0,
ManageEASListFolders = 2,
ManageEASResetDevice = 3,
ManageEASRestFolder = 4,
} SOGoManageEASCommand;
@interface SOGoToolManageEAS : SOGoTool
@end
@implementation SOGoToolManageEAS
+ (void) initialize
{
}
+ (NSString *) command
{
return @"manage-eas";
}
+ (NSString *) description
{
return @"manage EAS folders";
}
- (void) usage
{
fprintf (stderr, "manage-eas listdevices|resetdevice|resetfolder user <devinceId | folderId> \n\n"
" user the user of whom to reset the whole device or a single folder\n"
" Examples:\n"
" sogo-tool manage-eas listdevices janedoe\n"
" sogo-tool manage-eas listfolders janedoe androidc316986417\n"
" sogo-tool manage-eas resetdevice janedoe androidc316986417\n"
" sogo-tool manage-eas resetfolder janedow androidc316986417+folderlala-dada-sasa_7a13_1a2386e0_e\n") ;
}
- (SOGoManageEASCommand) _cmdFromString: (NSString *) theString
{
if ([theString length] > 2)
{
if ([theString caseInsensitiveCompare: @"listdevices"] == NSOrderedSame)
return ManageEASListDevices;
else if ([theString caseInsensitiveCompare: @"listfolders"] == NSOrderedSame)
return ManageEASListFolders;
else if ([theString caseInsensitiveCompare: @"resetdevice"] == NSOrderedSame)
return ManageEASResetDevice;
else if ([theString caseInsensitiveCompare: @"resetfolder"] == NSOrderedSame)
return ManageEASRestFolder;
}
return ManageEASUnknown;
}
- (BOOL) run
{
NSString *userId;
SOGoManageEASCommand cmd;
SOGoCacheGCSObject *oc, *foc;
NSString *urlString, *ocFSTableName, *deviceId;
NSURL *folderTableURL;
NSMutableArray *parts;
NSArray *entries;
id cacheEntry;
BOOL rc;
int i, max;
max = [sanitizedArguments count];
rc = NO;
if (max > 1)
{
SOGoUser *user;
cmd = [self _cmdFromString: [sanitizedArguments objectAtIndex: 0]];
userId = [sanitizedArguments objectAtIndex: 1];
user = [SOGoUser userWithLogin: userId];
if (![user loginInDomain])
return NO;
urlString = [[user domainDefaults] folderInfoURL];
parts = [[urlString componentsSeparatedByString: @"/"]
mutableCopy];
[parts autorelease];
if ([parts count] == 5)
{
/* If "OCSFolderInfoURL" is properly configured, we must have 5
parts in this url. We strip the '-' character in case we have
this in the domain part - like foo@bar-zot.com */
ocFSTableName = [NSString stringWithFormat: @"sogo_cache_folder_%@",
[[[user loginInDomain] asCSSIdentifier]
stringByReplacingOccurrencesOfString: @"-"
withString: @"_"]];
[parts replaceObjectAtIndex: 4 withObject: ocFSTableName];
folderTableURL
= [NSURL URLWithString: [parts componentsJoinedByString: @"/"]];
[folderTableURL retain];
}
switch (cmd)
{
case ManageEASListDevices:
oc = [SOGoCacheGCSObject objectWithName: @"0" inContainer: nil];
[oc setObjectType: ActiveSyncGlobalCacheObject];
[oc setTableUrl: folderTableURL];
entries = [oc cacheEntriesForDeviceId: nil newerThanVersion: -1];
for (i = 0; i < [entries count]; i++)
{
cacheEntry = [entries objectAtIndex: i];
fprintf(stdout,"%s\n", [[cacheEntry substringFromIndex: 1] UTF8String]);
}
rc = YES;
break;
case ManageEASListFolders:
if (max > 2)
{
/* value specified on command line */
deviceId = [sanitizedArguments objectAtIndex: 2];
oc = [SOGoCacheGCSObject objectWithName: @"0" inContainer: nil];
[oc setObjectType: ActiveSyncFolderCacheObject];
[oc setTableUrl: folderTableURL];
entries = [oc cacheEntriesForDeviceId: deviceId newerThanVersion: -1];
for (i = 0; i < [entries count]; i++)
{
cacheEntry = [entries objectAtIndex: i];
fprintf(stdout,"Folder Key: %s\n", [[cacheEntry substringFromIndex: 1] UTF8String]);
foc = [SOGoCacheGCSObject objectWithName: [cacheEntry substringFromIndex: 1] inContainer: nil];
[foc setObjectType: ActiveSyncFolderCacheObject];
[foc setTableUrl: folderTableURL];
[foc reloadIfNeeded];
fprintf(stdout, " Folder Name: %s\n\n", [[[foc properties] objectForKey: @"displayName"] UTF8String]);
if (verbose)
fprintf(stdout, " metadata Name: %s\n\n", [[[foc properties] description] UTF8String]);
}
rc = YES;
}
else
{
fprintf(stderr, "\nERROR: deviceId not specified\n\n");
}
break;
case ManageEASResetDevice:
if (max > 2)
{
/* value specified on command line */
deviceId = [sanitizedArguments objectAtIndex: 2];
oc = [SOGoCacheGCSObject objectWithName: deviceId inContainer: nil];
[oc setObjectType: ActiveSyncGlobalCacheObject];
[oc setTableUrl: folderTableURL];
[oc reloadIfNeeded];
if ([oc isNew]) {
fprintf(stderr, "ERROR: Device with ID '%s' not found\n", [deviceId UTF8String]);
return rc;
}
NSMutableString *sql;
sql = [NSMutableString stringWithFormat: @"DELETE FROM %@" @" WHERE c_path like '/%@'", [oc tableName], deviceId];
[oc performBatchSQLQueries: [NSArray arrayWithObject: sql]];
rc = YES;
}
else
{
fprintf(stderr, "\nERROR: deviceId not specified\n\n");
}
break;
case ManageEASRestFolder:
if (max > 2)
{
/* value specified on command line */
deviceId = [sanitizedArguments objectAtIndex: 2];
//if ([deviceId rangeOfString: @"+"].location == NSNotFound) {
// fprintf(stderr, "ERROR: Deviceid invalid folder \"%@\" not found\n", deviceId);
// return rc;
//}
oc = [SOGoCacheGCSObject objectWithName: deviceId inContainer: nil];
[oc setObjectType: ActiveSyncFolderCacheObject];
[oc setTableUrl: folderTableURL];
[oc reloadIfNeeded];
if ([oc isNew]) {
fprintf(stderr, "ERROR: Folder with ID \"%s\" not found\n", [deviceId UTF8String]);
return rc;
}
[[oc properties] removeObjectForKey: @"SyncKey"];
[[oc properties] removeObjectForKey: @"SyncCache"];
[[oc properties] removeObjectForKey: @"DateCache"];
[[oc properties] removeObjectForKey: @"MoreAvailable"];
[oc save];
rc = YES;
}
else
{
fprintf(stderr, "\nERROR: folderId not specified\n\n");
}
break;
case ManageEASUnknown:
break;
}
}
if (!rc)
{
[self usage];
}
return rc;
}
@end
+85 -2
View File
@@ -32,7 +32,10 @@
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSString+misc.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoSAML2Session.h>
#import <SOGo/SOGoSession.h>
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoWebAuthenticator.h>
@interface SOGoSAML2Actions : WODirectAction
@@ -42,20 +45,100 @@
- (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, *domain, *username, *password;
SOGoWebAuthenticator *auth;
SOGoSystemDefaults *sd;
WOResponse *response;
NSCalendarDate *date;
WOCookie *cookie;
NSArray *creds;
userName = [[context activeUser] login];
[self logWithFormat: @"SAML2 IdP-initiated SLO for user '%@'", userName];
sd = [SOGoSystemDefaults sharedSystemDefaults];
response = [context response];
if ([sd SAML2LogoutURL])
{
[response setStatus: 302];
[response setHeader: [sd SAML2LogoutURL] forKey: @"location"];
}
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];
// We first delete our memcached entry
value = [SOGoSession valueForSessionKey: [creds lastObject]];
domain = nil;
[SOGoSession decodeValue: value
usingKey: [creds objectAtIndex: 0]
login: &username
domain: &domain
password: &password];
[[SOGoCache sharedCache] removeSAML2LoginDumpsForIdentifier: password];
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;
+59 -10
View File
@@ -33,7 +33,12 @@
#import <NGExtensions/NSObject+Logs.h>
#import <Appointments/SOGoFreeBusyObject.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoCASSession.h>
#if defined(SAML2_CONFIG)
#import <SOGo/SOGoSAML2Session.h>
#endif
#import <SOGo/SOGoUserManager.h>
#import <SOGo/SOGoWebAuthenticator.h>
#import <SOGo/SOGoUser.h>
@@ -216,21 +221,22 @@
interval = [endDate timeIntervalSinceDate: startDate] + 60;
// Slices of 15 minutes. The +4 is to take into account that we can
// have a timezone change during the freebusy lookup.
intervals = interval / intervalSeconds + 4;
// Slices of 15 minutes. The +8 is to take into account that we can
// have a timezone change during the freebusy lookup. We have +4 at the
// beginning and +4 at the end.
intervals = interval / intervalSeconds + 8;
// Build a bit string representation of the freebusy data for the period
freeBusyItems = NSZoneCalloc (NULL, intervals, sizeof (int));
[self _fillFreeBusyItems: freeBusyItems
count: intervals
[self _fillFreeBusyItems: (freeBusyItems+4)
count: (intervals-4)
withRecords: [fb fetchFreeBusyInfosFrom: start to: end forContact: uid]
fromStartDate: startDate
toEndDate: endDate];
// Convert bit string to a NSArray
// Convert bit string to a NSArray. We also skip by the default the non-requested information.
freeBusy = [NSMutableArray arrayWithCapacity: intervals];
for (count = 0; count < intervals; count++)
for (count = 4; count < (intervals-4); count++)
{
[freeBusy addObject: [NSString stringWithFormat: @"%d", *(freeBusyItems + count)]];
}
@@ -299,14 +305,57 @@
sd = [SOGoSystemDefaults sharedSystemDefaults];
if ([[sd authenticationType] isEqualToString: @"cas"])
redirectURL = [SOGoCASSession CASURLWithAction: @"logout"
andParameters: nil];
{
redirectURL = [SOGoCASSession CASURLWithAction: @"logout"
andParameters: nil];
}
#if defined(SAML2_CONFIG)
else if ([[sd authenticationType] isEqualToString: @"saml2"])
{
NSString *username, *password, *domain, *value;
SOGoSAML2Session *saml2Session;
SOGoWebAuthenticator *auth;
LassoServer *server;
LassoLogout *logout;
NSArray *creds;
auth = [[self clientObject] authenticatorInContext: context];
value = [[context request] cookieValueForKey: [auth cookieNameInContext: context]];
creds = [auth parseCredentials: value];
value = [SOGoSession valueForSessionKey: [creds lastObject]];
domain = nil;
[SOGoSession decodeValue: value
usingKey: [creds objectAtIndex: 0]
login: &username
domain: &domain
password: &password];
saml2Session = [SOGoSAML2Session SAML2SessionWithIdentifier: password
inContext: context];
server = [SOGoSAML2Session lassoServerInContext: context];
logout = lasso_logout_new(server);
lasso_profile_set_session_from_dump(LASSO_PROFILE(logout), [[saml2Session session] UTF8String]);
lasso_profile_set_identity_from_dump(LASSO_PROFILE(logout), [[saml2Session session] UTF8String]);
lasso_logout_init_request(logout, NULL, LASSO_HTTP_METHOD_REDIRECT);
lasso_logout_build_request_msg(logout);
redirectURL = [NSString stringWithFormat: @"%s", LASSO_PROFILE(logout)->msg_url];
// We destroy our cache entry, the session will be taken care by the caller
[[SOGoCache sharedCache] removeSAML2LoginDumpsForIdentifier: password];
}
#endif
else
{
container = [[self clientObject] container];
redirectURL = [container baseURLInContext: context];
}
return redirectURL;
}
+5
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";
+1 -1
View File
@@ -4,4 +4,4 @@
MAJOR_VERSION=2
MINOR_VERSION=2
SUBMINOR_VERSION=10
SUBMINOR_VERSION=11
+2 -2
View File
@@ -1,7 +1,7 @@
Source: sogo
Priority: optional
Maintainer: Inverse Support <support@inverse.ca>
Build-Depends: debhelper (>= 8.0.0), gobjc | objc-compiler, libgnustep-base-dev, libsope-appserver4.9-dev, libsope-core4.9-dev, libsope-gdl1-4.9-dev, libsope-ldap4.9-dev, libsope-mime4.9-dev, libsope-xml4.9-dev, libmemcached-dev, libxml2-dev, libsbjson-dev, libssl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libmapi-dev, libmapistore-dev, libmapiproxy-dev, libwbxml2-dev (>= 0.11.2)
Build-Depends: debhelper (>= 8.0.0), gobjc | objc-compiler, libgnustep-base-dev, libsope-appserver4.9-dev, libsope-core4.9-dev, libsope-gdl1-4.9-dev, libsope-ldap4.9-dev, libsope-mime4.9-dev, libsope-xml4.9-dev, libmemcached-dev, libxml2-dev, libsbjson-dev, libssl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libmapi-dev, libmapistore-dev, libmapiproxy-dev, libwbxml2-dev (>= 0.11.2), liblasso3-dev (>= 2.3.5)
Section: web
Standards-Version: 3.9.2
@@ -10,7 +10,7 @@ Pre-Depends: ${misc:Pre-Depends}
Multi-Arch: same
Section: web
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make, libcurl3, zip
Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make, libcurl3, zip, liblasso3 (>= 2.3.5)
Recommends: memcached
Suggests: nginx
Description: a modern and scalable groupware
+3 -1
View File
@@ -6,12 +6,14 @@ export DH_VERBOSE=1
DESTDIR=$(CURDIR)/debian/tmp
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
SAML2_CONFIG=--enable-saml2
include /etc/GNUstep/GNUstep.conf
include /usr/share/GNUstep/Makefiles/common.make
config.make: configure
dh_testdir
./configure --prefix=$(GNUSTEP_SYSTEM_ROOT)
./configure --prefix=$(GNUSTEP_SYSTEM_ROOT) $(SAML2_CONFIG)
#Architecture
build: build-arch
+2 -2
View File
@@ -1,14 +1,14 @@
Source: sogo
Priority: optional
Maintainer: Inverse Support <support@inverse.ca>
Build-Depends: debhelper (>= 7.0.15), gobjc | objc-compiler, libgnustep-base-dev, libsope-appserver4.9-dev, libsope-core4.9-dev, libsope-gdl1-4.9-dev, libsope-ldap4.9-dev, libsope-mime4.9-dev, libsope-xml4.9-dev, libmemcached-dev, libxml2-dev, libsbjson-dev, libssl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libwbxml2-dev (>= 0.11.2)
Build-Depends: debhelper (>= 7.0.15), gobjc | objc-compiler, libgnustep-base-dev, libsope-appserver4.9-dev, libsope-core4.9-dev, libsope-gdl1-4.9-dev, libsope-ldap4.9-dev, libsope-mime4.9-dev, libsope-xml4.9-dev, libmemcached-dev, libxml2-dev, libsbjson-dev, libssl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libwbxml2-dev (>= 0.11.2), liblasso3-dev (>= 2.3.5)
Section: web
Standards-Version: 3.9.1
Package: sogo
Section: web
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make, libcurl3, zip
Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make, libcurl3, zip, liblasso3 (>= 2.3.5)
Recommends: memcached
Suggests: nginx
Description: a modern and scalable groupware
+2 -2
View File
@@ -1,14 +1,14 @@
Source: sogo
Priority: optional
Maintainer: Inverse Support <support@inverse.ca>
Build-Depends: debhelper (>= 7.0.15), gobjc | objc-compiler, libgnustep-base-dev, libsope-appserver4.9-dev, libsope-core4.9-dev, libsope-gdl1-4.9-dev, libsope-ldap4.9-dev, libsope-mime4.9-dev, libsope-xml4.9-dev, libmemcached-dev, libxml2-dev, libsbjson-dev, libssl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libmapi-dev, libmapistore-dev, libmapiproxy-dev, libwbxml2-dev
Build-Depends: debhelper (>= 7.0.15), gobjc | objc-compiler, libgnustep-base-dev, libsope-appserver4.9-dev, libsope-core4.9-dev, libsope-gdl1-4.9-dev, libsope-ldap4.9-dev, libsope-mime4.9-dev, libsope-xml4.9-dev, libmemcached-dev, libxml2-dev, libsbjson-dev, libssl-dev, libcurl4-openssl-dev | libcurl4-gnutls-dev, libmapi-dev, libmapistore-dev, libmapiproxy-dev, libwbxml2-dev, liblasso3-dev (>= 2.3.5)
Section: web
Standards-Version: 3.9.1
Package: sogo
Section: web
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make, libcurl3
Depends: ${shlibs:Depends}, ${misc:Depends}, tmpreaper, sope4.9-libxmlsaxdriver, sope4.9-db-connector, gnustep-make, libcurl3, liblasso3 (>= 2.3.5)
Recommends: memcached
Suggests: nginx
Description: a modern and scalable groupware
+1 -2
View File
@@ -6,9 +6,8 @@ export DH_VERBOSE=1
DESTDIR=$(CURDIR)/debian/tmp
DIST_CODENAME=$(shell lsb_release -cs)
# NOTYET
#ifeq ($(DIST_CODENAME), squeeze)
# SAML2_CONFIG=--enable-saml2
SAML2_CONFIG=--enable-saml2
#endif
include /etc/GNUstep/GNUstep.conf