CVE-2015-5395: Cross-Site Request Forgery (CSRF) (CWE-352)
value: Cross-site request forgery (CSRF) vulnerability in SOGo before 3.1.0.
CWE description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
CVSS v3 base score: 8.8
Published: 2017-09-20T18:29Z
Repository: https://github.com/inverse-inc/sogo
Language: Objective-C
Files changed: NEWS, SoObjects/SOGo/SOGoSystemDefaults.h, SoObjects/SOGo/SOGoSystemDefaults.m, UI/Common/GNUmakefile, UI/Common/SOGoDirectAction.h, UI/Common/SOGoDirectAction.m, UI/Common/UIxFolderActions.h, UI/Common/UIxFolderActions.m, UI/Common/UIxObjectActions.h, UI/Common/UIxObjectActions.m, UI/Common/UIxParentFolderActions.h, UI/Common/UIxParentFolderActions.m, UI/Contacts/UIxContactActions.m, UI/Contacts/UIxContactsListActions.h, UI/Contacts/UIxContactsListActions.m, UI/MailPartViewers/UIxMailPartICalActions.h, UI/MailPartViewers/UIxMailPartICalActions.m, UI/MailerUI/UIxMailAccountActions.h, UI/MailerUI/UIxMailAccountActions.m, UI/MailerUI/UIxMailActions.h, UI/MailerUI/UIxMailActions.m, UI/MailerUI/UIxMailFolderActions.h, UI/MailerUI/UIxMailFolderActions.m, UI/MailerUI/UIxMailListActions.h, UI/MailerUI/UIxMailListActions.m, UI/MailerUI/UIxMailSourceView.h, UI/MailerUI/UIxMailSourceView.m, UI/MainUI/SOGoMicrosoftActiveSyncActions.m, UI/MainUI/SOGoRootPage.m, UI/MainUI/SOGoUserHomePage.m, UI/PreferencesUI/UIxJSONPreferences.h, UI/PreferencesUI/UIxJSONPreferences.m, UI/SOGoUI/UIxComponent.m, UI/Scheduler/UIxAppointmentActions.h, UI/Scheduler/UIxAppointmentActions.m, UI/Scheduler/UIxCalListingActions.h, UI/Scheduler/UIxCalListingActions.m, UI/Scheduler/UIxCalMainActions.h, UI/Scheduler/UIxCalMainActions.m, UI/WebServerResources/js/Common/Authentication.service.js
Commit date: 2016-04-26 11:07:22 -0400
Commit message: (feat) added AngularJS's XSRF support (#3246)

Diff: diff --git a/NEWS b/NEWS
index 257414c10..8bf6284fe 100644
--- a/NEWS
+++ b/NEWS
@@ -3,10 +3,11 @@
 
 New features
  - [core] new database structure options to make SOGo use a total of nine tables
  - [core] new user-based rate-limiting support for all SOGo requests (#3188)
  - [web] toolbar of all-day events can be expanded to display all events
+ - [web] added AngularJS's XSRF support (#3246)
 
 Enhancements
  - [web] updated Angular Material to version 1.0.6
  - [web] added Lithuanan (lt) translation - thanks to Mantas Liobė
  - [web] we now "cc" delegates during invitation updates (#3195)
diff --git a/SoObjects/SOGo/SOGoSystemDefaults.h b/SoObjects/SOGo/SOGoSystemDefaults.h
index 58bdb8174..00a38d0ac 100644
--- a/SoObjects/SOGo/SOGoSystemDefaults.h
+++ b/SoObjects/SOGo/SOGoSystemDefaults.h
@@ -63,10 +63,11 @@
 - (BOOL) userCanChangePassword;
 - (BOOL) uixAdditionalPreferences;
 
 - (BOOL) uixDebugEnabled;
 - (BOOL) easDebugEnabled;
+- (BOOL) xsrfValidationEnabled;
 
 - (NSString *) pageTitle;
 - (NSString *) helpURL;
 
 - (NSArray *) supportedLanguages;
diff --git a/SoObjects/SOGo/SOGoSystemDefaults.m b/SoObjects/SOGo/SOGoSystemDefaults.m
index 51959e8ae..4ac596dd6 100644
--- a/SoObjects/SOGo/SOGoSystemDefaults.m
+++ b/SoObjects/SOGo/SOGoSystemDefaults.m
@@ -428,10 +428,22 @@ - (BOOL) uixDebugEnabled
 - (BOOL) easDebugEnabled
 {
   return [self boolForKey: @"SOGoEASDebugEnabled"];
 }
 
+- (BOOL) xsrfValidationEnabled
+{
+  id o;
+
+  if (!(o = [self objectForKey: @"SOGoXSRFValidationEnabled"]))
+    {
+      return YES;
+    }
+
+  return [o boolValue];
+}
+
 - (NSString *) pageTitle
 {
   return [self stringForKey: @"SOGoPageTitle"];
 }
 
diff --git a/UI/Common/GNUmakefile b/UI/Common/GNUmakefile
index 39e5a584f..58b4cfdc4 100644
--- a/UI/Common/GNUmakefile
+++ b/UI/Common/GNUmakefile
@@ -19,11 +19,11 @@ CommonUI_OBJC_FILES +=			\
 	UIxUserRightsEditor.m		\
 	\
 	UIxTopnavToolbar.m      	\
 	UIxToolbar.m			\
 	\
-	WODirectAction+SOGo.m		\
+	SOGoDirectAction.m		\
 
 CommonUI_RESOURCE_FILES += \
 	product.plist
 
 
diff --git a/UI/Common/WODirectAction+SOGo.h b/UI/Common/SOGoDirectAction.h
similarity index 91%
rename from UI/Common/WODirectAction+SOGo.h
rename to UI/Common/SOGoDirectAction.h
index aa4e5094c..27a0c65ae 100644
--- a/UI/Common/WODirectAction+SOGo.h
+++ b/UI/Common/SOGoDirectAction.h
@@ -1,8 +1,8 @@
-/* WODirectAction+SOGo.h - this file is part of SOGo
+/* SOGoDirectAction.h - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -24,11 +24,11 @@
 #import <NGObjWeb/WODirectAction.h>
 
 @class NSString;
 @class WOResponse, WOResourceManager;
 
-@interface WODirectAction (SOGoExtension)
+@interface SOGoDirectAction : WODirectAction
 
 - (WOResponse *) responseWithStatus: (unsigned int) status;
 - (WOResponse *) responseWithStatus: (unsigned int) status
 			  andString: (NSString *) contentString;
 - (WOResponse *) responseWithStatus: (unsigned int) status
diff --git a/UI/Common/WODirectAction+SOGo.m b/UI/Common/SOGoDirectAction.m
similarity index 81%
rename from UI/Common/WODirectAction+SOGo.m
rename to UI/Common/SOGoDirectAction.m
index 5055c2db1..73a1062fc 100644
--- a/UI/Common/WODirectAction+SOGo.m
+++ b/UI/Common/SOGoDirectAction.m
@@ -1,8 +1,8 @@
-/* WODirectAction+SOGo.m - this file is part of SOGo
+/* SOGoDirectAction - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -24,19 +24,23 @@
 #import <NGObjWeb/WOContext+SoObjects.h>
 #import <NGObjWeb/WOResponse.h>
 
 #import <SoObjects/SOGo/NSObject+Utilities.h>
 #import <SoObjects/SOGo/NSDictionary+Utilities.h>
+#import <SoObjects/SOGo/NSString+Crypto.h>
 #import <SoObjects/SOGo/NSString+Utilities.h>
+#import <SoObjects/SOGo/SOGoSession.h>
+#import <SoObjects/SOGo/SOGoSystemDefaults.h>
+#import <SoObjects/SOGo/SOGoWebAuthenticator.h>
 
 #import <NGExtensions/NSObject+Logs.h>
 
-#import "WODirectAction+SOGo.h"
+#import "SOGoDirectAction.h"
 
 static SoProduct      *commonProduct      = nil;
 
-@implementation WODirectAction (SOGoExtension)
+@implementation SOGoDirectAction
 
 + (void) initialize
 {
   if (commonProduct == nil)
     {
@@ -203,6 +207,36 @@ - (NSString *) urlForResourceFilename: (NSString *) filename
     url = @"";
 
   return url;
 }
 
+//
+// Protection against XSRF
+//
+- (id<WOActionResults>)performActionNamed:(NSString *)_actionName
+{
+  SOGoWebAuthenticator *auth;
+  NSString *value, *token;
+  NSArray *creds;
+
+  if (![[SOGoSystemDefaults sharedSystemDefaults] xsrfValidationEnabled])
+    return [super performActionNamed: _actionName];
+
+  // We grab the X-XSRF-TOKEN header
+  token = [[context request] headerForKey: @"X-XSRF-TOKEN"];
+
+  // We compare it with our session key
+  auth = [[WOApplication application]
+           authenticatorInContext: context];
+  value = [[context request]
+           cookieValueForKey: [auth cookieNameInContext: context]];
+  creds = [auth parseCredentials: value];
+
+  value = [SOGoSession valueForSessionKey: [creds lastObject]];
+
+  if ([token isEqualToString: [value asSHA1String]])
+    return [super performActionNamed: _actionName];
+
+  return nil;
+}
+
 @end
diff --git a/UI/Common/UIxFolderActions.h b/UI/Common/UIxFolderActions.h
index 194bf8625..495237f79 100644
--- a/UI/Common/UIxFolderActions.h
+++ b/UI/Common/UIxFolderActions.h
@@ -1,8 +1,8 @@
 /* UIxFolderActions.h - this file is part of SOGo
  *
- * Copyright (C) 2007-2014 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -28,11 +28,13 @@
 
 @class LDAPUserManager;
 @class SOGoGCSFolder;
 @class SOGoUserSettings;
 
-@interface UIxFolderActions : WODirectAction
+#include "SOGoDirectAction.h"
+
+@interface UIxFolderActions : SOGoDirectAction
 {
   SOGoGCSFolder *clientObject;
   LDAPUserManager *um;
   SOGoUserSettings *us;
   NSString *owner;
diff --git a/UI/Common/UIxFolderActions.m b/UI/Common/UIxFolderActions.m
index 7ed2987b7..acd43069d 100644
--- a/UI/Common/UIxFolderActions.m
+++ b/UI/Common/UIxFolderActions.m
@@ -1,8 +1,8 @@
 /* UIxFolderActions.m - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -40,12 +40,10 @@
 #import <Contacts/SOGoContactGCSFolder.h>
 #import <Contacts/SOGoContactSourceFolder.h>
 
 #import <Appointments/SOGoAppointmentFolder.h>
 
-#import "WODirectAction+SOGo.h"
-
 #import "UIxFolderActions.h"
 
 @implementation UIxFolderActions
 
 - (void) _setupContext
diff --git a/UI/Common/UIxObjectActions.h b/UI/Common/UIxObjectActions.h
index 314a9747b..c0f19c04e 100644
--- a/UI/Common/UIxObjectActions.h
+++ b/UI/Common/UIxObjectActions.h
@@ -1,10 +1,8 @@
 /* UIxObjectActions.h - this file is part of SOGo
  *
- * Copyright (C) 2007 Inverse inc.
- *
- * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ * Copyright (C) 2007-2016 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.
@@ -21,14 +19,15 @@
  */
 
 #ifndef UIXOBJECTACTIONS_H
 #define UIXOBJECTACTIONS_H
 
+#include "SOGoDirectAction.h"
 
 @class WOResponse;
 
-@interface UIxObjectActions : WODirectAction
+@interface UIxObjectActions : SOGoDirectAction
 
 - (WOResponse *) addUserInAclsAction;
 
 @end
 
diff --git a/UI/Common/UIxObjectActions.m b/UI/Common/UIxObjectActions.m
index 602f039d6..19042f5d3 100644
--- a/UI/Common/UIxObjectActions.m
+++ b/UI/Common/UIxObjectActions.m
@@ -28,12 +28,10 @@
 
 #import <SoObjects/SOGo/SOGoContentObject.h>
 
 #import <SOGo/NSDictionary+Utilities.h>
 
-#import "WODirectAction+SOGo.h"
-
 #import "UIxObjectActions.h"
 
 @implementation UIxObjectActions
 
 /**
diff --git a/UI/Common/UIxParentFolderActions.h b/UI/Common/UIxParentFolderActions.h
index 9b6d4cfce..23e58483d 100644
--- a/UI/Common/UIxParentFolderActions.h
+++ b/UI/Common/UIxParentFolderActions.h
@@ -1,10 +1,8 @@
 /* UIxParentFolderActions.h - this file is part of SOGo
  *
- * Copyright (C) 2007 Inverse inc.
- *
- * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ * Copyright (C) 2007-2016 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.
@@ -21,10 +19,11 @@
  */
 
 #ifndef UIXPARENTFOLDERACTIONS_H
 #define UIXPARENTFOLDERACTIONS_H
 
+#include "SOGoDirectAction.h"
 
-@interface UIxParentFolderActions : WODirectAction
+@interface UIxParentFolderActions : SOGoDirectAction
 @end
 
 #endif /* UIXPARENTFOLDERACTIONS_H */
diff --git a/UI/Common/UIxParentFolderActions.m b/UI/Common/UIxParentFolderActions.m
index d1bb60342..6669e3e71 100644
--- a/UI/Common/UIxParentFolderActions.m
+++ b/UI/Common/UIxParentFolderActions.m
@@ -1,8 +1,8 @@
 /* UIxParentFolderActions.m - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -27,12 +27,10 @@
 #import <SoObjects/SOGo/SOGoParentFolder.h>
 
 #import <SOGo/NSDictionary+Utilities.h>
 #import <SOGo/NSString+Utilities.h>
 
-#import <UI/Common/WODirectAction+SOGo.h>
-
 #import "UIxParentFolderActions.h"
 
 @implementation UIxParentFolderActions
 
 /**
diff --git a/UI/Contacts/UIxContactActions.m b/UI/Contacts/UIxContactActions.m
index fa50fe1db..1d50d8f2b 100644
--- a/UI/Contacts/UIxContactActions.m
+++ b/UI/Contacts/UIxContactActions.m
@@ -1,10 +1,8 @@
 /* UIxContactActions.m - this file is part of SOGo
  *
- * Copyright (C) 2010 Inverse inc.
- *
- * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ * Copyright (C) 2010-2016 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.
@@ -28,11 +26,11 @@
 
 #import <NGCards/NGVCard.h>
 
 #import <Contacts/SOGoContactGCSEntry.h>
 
-#import <Common/WODirectAction+SOGo.h>
+#import <Common/SOGoDirectAction.h>
 
 @interface NGVCard (SOGoActionCategory)
 
 - (BOOL) addOrRemove: (BOOL) set
             category: (NSString *) newCategory;
@@ -78,11 +76,11 @@ - (BOOL) addOrRemove: (BOOL) set
   return modified;
 }
 
 @end
 
-@interface UIxContactActions : WODirectAction
+@interface UIxContactActions : SOGoDirectAction
 
 - (WOResponse *) setCategoryAction;
 - (WOResponse *) unsetCategoryAction;
 
 @end
diff --git a/UI/Contacts/UIxContactsListActions.h b/UI/Contacts/UIxContactsListActions.h
index cd0e33dac..f775c6676 100644
--- a/UI/Contacts/UIxContactsListActions.h
+++ b/UI/Contacts/UIxContactsListActions.h
@@ -1,36 +1,37 @@
 /*
- Copyright (C) 2004-2005 SKYRIX Software AG
- 
- This file is part of OpenGroupware.org.
- 
- OGo is free software; you can redistribute it and/or modify it under
- the terms of the GNU Lesser General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
- 
- OGo 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 Lesser General Public
- License for more details.
- 
- You should have received a copy of the GNU Lesser General Public
- License along with OGo; see the file COPYING.  If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
+  Copyright (C) 2006-2016 Inverse inc.
+
+  This file is part of SOGo.
+
+  SOGo is free software; you can redistribute it and/or modify it under
+  the terms of the GNU Lesser General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  SOGo 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 Lesser General Public
+  License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with SOGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
 */
 
 #ifndef __UIxContactsListActions_H__
 #define __UIxContactsListActions_H__
 
+#import <Common/SOGoDirectAction.h>
 
 @class NSDictionary;
 @class NSString;
 
 @protocol SOGoContactObject;
 
-@interface UIxContactsListActions : WODirectAction
+@interface UIxContactsListActions : SOGoDirectAction
 {
   NSDictionary *currentContact;
 
   NSArray *contactInfos;
   NSArray *sortedIDs;
diff --git a/UI/Contacts/UIxContactsListActions.m b/UI/Contacts/UIxContactsListActions.m
index d3577e1f4..8266e7ab8 100644
--- a/UI/Contacts/UIxContactsListActions.m
+++ b/UI/Contacts/UIxContactsListActions.m
@@ -35,13 +35,10 @@
 #import <NGExtensions/NSNull+misc.h>
 
 #import <EOControl/EOQualifier.h>
 #import <EOControl/EOSortOrdering.h>
 
-#import <Common/WODirectAction+SOGo.h>
-
-
 #import <SOGo/SOGoUser.h>
 #import <SOGo/SOGoUserSettings.h>
 
 #import <SoObjects/Contacts/SOGoContactGCSEntry.h>
 #import <SoObjects/Contacts/SOGoContactGCSFolder.h>
diff --git a/UI/MailPartViewers/UIxMailPartICalActions.h b/UI/MailPartViewers/UIxMailPartICalActions.h
index a0299402e..620e6075a 100644
--- a/UI/MailPartViewers/UIxMailPartICalActions.h
+++ b/UI/MailPartViewers/UIxMailPartICalActions.h
@@ -1,10 +1,8 @@
 /* UIxMailPartICalActions.h - this file is part of SOGo
  *
- * Copyright (C) 2007 Inverse inc.
- *
- * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ * Copyright (C) 2007-2016 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.
@@ -21,16 +19,17 @@
  */
 
 #ifndef UIXMAILPARTICALACTIONS_H
 #define UIXMAILPARTICALACTIONS_H
 
-
 @class iCalCalendar;
 @class SOGoMailBodyPart;
 @class WOResponse;
 
-@interface UIxMailPartICalActions : WODirectAction
+#import <UI/Common/SOGoDirectAction.h>
+
+@interface UIxMailPartICalActions : SOGoDirectAction
 
 - (WOResponse *) acceptAction;
 - (WOResponse *) declineAction;
 - (WOResponse *) tentativeAction;
 - (WOResponse *) delegateAction;
diff --git a/UI/MailPartViewers/UIxMailPartICalActions.m b/UI/MailPartViewers/UIxMailPartICalActions.m
index b7c15267f..2fecb3ab5 100644
--- a/UI/MailPartViewers/UIxMailPartICalActions.m
+++ b/UI/MailPartViewers/UIxMailPartICalActions.m
@@ -1,8 +1,8 @@
 /* UIxMailPartICalActions.m - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -30,12 +30,10 @@
 #import <NGExtensions/NSNull+misc.h>
 #import <NGExtensions/NSObject+Logs.h>
 
 #import <NGCards/iCalCalendar.h>
 
-#import <UI/Common/WODirectAction+SOGo.h>
-
 #import <NGImap4/NGImap4EnvelopeAddress.h>
 
 #import <Appointments/iCalEvent+SOGo.h>
 #import <Appointments/iCalPerson+SOGo.h>
 #import <Appointments/SOGoAppointmentObject.h>
@@ -237,11 +235,10 @@ - (WOResponse *) _changePartStatusAction: (NSString *) newStatus
                             withDelegate: (iCalPerson *) delegate
 {
   WOResponse *response;
   SOGoAppointmentObject *eventObject;
   iCalEvent *chosenEvent;
-  //NSException *ex;
 
   chosenEvent = [self _setupChosenEventAndEventObject: &eventObject];
   if (chosenEvent)
     {
       response = (WOResponse*)[eventObject changeParticipationStatus: newStatus
diff --git a/UI/MailerUI/UIxMailAccountActions.h b/UI/MailerUI/UIxMailAccountActions.h
index 4dfc9b457..8f54aac89 100644
--- a/UI/MailerUI/UIxMailAccountActions.h
+++ b/UI/MailerUI/UIxMailAccountActions.h
@@ -1,8 +1,8 @@
 /* UIxMailAccountActions.h - this file is part of SOGo
  *
- * Copyright (C) 2007-2013 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -19,14 +19,15 @@
  */
 
 #ifndef UIXMAILACCOUNTACTIONS_H
 #define UIXMAILACCOUNTACTIONS_H
 
+#import <UI/Common/SOGoDirectAction.h>
 
 @class WOResponse;
 
-@interface UIxMailAccountActions : WODirectAction
+@interface UIxMailAccountActions : SOGoDirectAction
 {
 }
 
 - (WOResponse *) listMailboxesAction;
 
diff --git a/UI/MailerUI/UIxMailAccountActions.m b/UI/MailerUI/UIxMailAccountActions.m
index ecc739855..af7e94ce7 100644
--- a/UI/MailerUI/UIxMailAccountActions.m
+++ b/UI/MailerUI/UIxMailAccountActions.m
@@ -1,8 +1,8 @@
 /* UIxMailAccountActions.m - this file is part of SOGo
  *
- * Copyright (C) 2007-2014 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -32,12 +32,10 @@
 #import <SOGo/NSObject+Utilities.h>
 #import <SOGo/NSString+Utilities.h>
 #import <SOGo/SOGoDomainDefaults.h>
 #import <SOGo/SOGoUser.h>
 
-#import "../Common/WODirectAction+SOGo.h"
-
 #import "UIxMailAccountActions.h"
 
 @implementation UIxMailAccountActions
 
 - (WOResponse *) listMailboxesAction
diff --git a/UI/MailerUI/UIxMailActions.h b/UI/MailerUI/UIxMailActions.h
index e2d92cd7a..7cfdecce1 100644
--- a/UI/MailerUI/UIxMailActions.h
+++ b/UI/MailerUI/UIxMailActions.h
@@ -1,8 +1,8 @@
 /* UIxMailActions.h - this file is part of SOGo
  *
- * Copyright (C) 2007-2013 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -19,10 +19,11 @@
  */
 
 #ifndef UIXMAILACTIONS_H
 #define UIXMAILACTIONS_H
 
+#import <UI/Common/SOGoDirectAction.h>
 
-@interface UIxMailActions : WODirectAction
+@interface UIxMailActions : SOGoDirectAction
 @end
 
 #endif /* UIXMAILACTIONS_H */
diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m
index 7263b4ce6..688b22073 100644
--- a/UI/MailerUI/UIxMailActions.m
+++ b/UI/MailerUI/UIxMailActions.m
@@ -35,12 +35,10 @@
 #import <SoObjects/SOGo/NSString+Utilities.h>
 #import <SoObjects/SOGo/SOGoUser.h>
 #import <SoObjects/SOGo/SOGoUserSettings.h>
 #import <SoObjects/SOGo/SOGoUserDefaults.h>
 
-#import "../Common/WODirectAction+SOGo.h"
-
 #import "UIxMailActions.h"
 
 @implementation UIxMailActions
 
 - (WOResponse *) replyToAll: (BOOL) toAll
diff --git a/UI/MailerUI/UIxMailFolderActions.h b/UI/MailerUI/UIxMailFolderActions.h
index 42c0dc84b..685b1f2f1 100644
--- a/UI/MailerUI/UIxMailFolderActions.h
+++ b/UI/MailerUI/UIxMailFolderActions.h
@@ -19,14 +19,15 @@
  */
 
 #ifndef UIXMAILFOLDERACTIONS_H
 #define UIXMAILFOLDERACTIONS_H
 
+#import <UI/Common/SOGoDirectAction.h>
 
 @class WOResponse;
 
-@interface UIxMailFolderActions : WODirectAction
+@interface UIxMailFolderActions : SOGoDirectAction
 
 - (id <WOActionResults>) createFolderAction;
 - (WOResponse *) renameFolderAction;
 - (WOResponse *) deleteAction;
 - (WOResponse *) batchDeleteAction;
diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m
index 56fcc7330..36081cf1e 100644
--- a/UI/MailerUI/UIxMailFolderActions.m
+++ b/UI/MailerUI/UIxMailFolderActions.m
@@ -36,12 +36,10 @@
 #import <SOGo/NSString+Utilities.h>
 #import <SOGo/SOGoDomainDefaults.h>
 #import <SOGo/SOGoUser.h>
 #import <SOGo/SOGoUserSettings.h>
 
-#import <UI/Common/WODirectAction+SOGo.h>
-
 #import "UIxMailFolderActions.h"
 
 @implementation UIxMailFolderActions
 
 /**
@@ -223,11 +221,10 @@ - (WOResponse *) deleteAction
   NSDictionary *jsonResponse;
   NSURL *srcURL, *destURL;
   SOGoUserSettings *us;
   WOResponse *response;
   NSException *error;
-
   BOOL moved;
 
   co = [self clientObject];
   moved = YES;
 
@@ -378,24 +375,24 @@ - (WOResponse *) saveMessagesAction
   co = [self clientObject];
   value = [[context request] formValueForKey: @"uid"];
   response = nil;
 
   if ([value length] > 0)
-  {
-    uids = [value componentsSeparatedByString: @","];
-    response = [co archiveUIDs: uids
-                inArchiveNamed: [self labelForKey: @"Saved Messages.zip" inContext: context]
-                     inContext: context];
-    if (!response)
-      response = [self responseWith204];
-  }
+    {
+      uids = [value componentsSeparatedByString: @","];
+      response = [co archiveUIDs: uids
+                  inArchiveNamed: [self labelForKey: @"Saved Messages.zip" inContext: context]
+                       inContext: context];
+      if (!response)
+        response = [self responseWith204];
+    }
   else
-  {
-    jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'uid' parameter." inContext: context]
-                                               forKey: @"message"];
-    response = [self responseWithStatus: 500 andJSONRepresentation: jsonResponse];
-  }
+    {
+      jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'uid' parameter." inContext: context]
+                                                 forKey: @"message"];
+      response = [self responseWithStatus: 500 andJSONRepresentation: jsonResponse];
+    }
 
   return response;
 }
 
 - (id) markFolderReadAction
diff --git a/UI/MailerUI/UIxMailListActions.h b/UI/MailerUI/UIxMailListActions.h
index c85ab9fbd..2f7af144b 100644
--- a/UI/MailerUI/UIxMailListActions.h
+++ b/UI/MailerUI/UIxMailListActions.h
@@ -1,8 +1,7 @@
 /*
-  Copyright (C) 2004-2005 SKYRIX Software AG
-  Copyright (C) 2004-2014 Inverse inc
+  Copyright (C) 2004-2016 Inverse inc
 
   This file is part of SOGo.
 
   SOGo is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
@@ -21,17 +20,18 @@
 */
   
 #ifndef UIXMAILLISTACTIONS_H
 #define UIXMAILLISTACTIONS_H
 
-
 @class NSDictionary;
 @class EOQualifier;
 @class SOGoDateFormatter;
 @class UIxMailSizeFormatter;
 
-@interface UIxMailListActions : WODirectAction
+#import <UI/Common/SOGoDirectAction.h>
+
+@interface UIxMailListActions : SOGoDirectAction
 {
   NSArray *sortedUIDs; /* we always need to retrieve all anyway! */
   NSArray *messages;
   NSCalendarDate *now;
   id message;
diff --git a/UI/MailerUI/UIxMailListActions.m b/UI/MailerUI/UIxMailListActions.m
index b15281fb2..a524ecd8c 100644
--- a/UI/MailerUI/UIxMailListActions.m
+++ b/UI/MailerUI/UIxMailListActions.m
@@ -56,11 +56,10 @@
 #import <SOGo/SOGoUser.h>
 #import <SOGo/SOGoUserDefaults.h>
 #import <SOGo/SOGoUserSettings.h>
 #import <SOGo/WOResourceManager+SOGo.h>
 
-#import <UI/Common/WODirectAction+SOGo.h>
 #import <UI/MailPartViewers/UIxMailSizeFormatter.h>
 
 #import "WOContext+UIxMailer.h"
 #import "UIxMailFormatter.h"
 
diff --git a/UI/MailerUI/UIxMailSourceView.h b/UI/MailerUI/UIxMailSourceView.h
index 0b60fa6e6..41e1757b3 100644
--- a/UI/MailerUI/UIxMailSourceView.h
+++ b/UI/MailerUI/UIxMailSourceView.h
@@ -1,8 +1,8 @@
 /* UIxMailSourceView.h - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -19,12 +19,13 @@
  */
 
 #ifndef UIXMAILSOURCEVIEW_H
 #define UIXMAILSOURCEVIEW_H
 
+#import <UI/Common/SOGoDirectAction.h>
 
-@interface UIxMailSourceView : WODirectAction
+@interface UIxMailSourceView : SOGoDirectAction
 
 @end
 
 
 #endif /* UIXMAILSOURCEVIEW_H */
diff --git a/UI/MailerUI/UIxMailSourceView.m b/UI/MailerUI/UIxMailSourceView.m
index cadb46140..6dd05c367 100644
--- a/UI/MailerUI/UIxMailSourceView.m
+++ b/UI/MailerUI/UIxMailSourceView.m
@@ -1,8 +1,8 @@
 /* UIxMailSourceView.m - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -21,12 +21,10 @@
 #import <NGObjWeb/WOResponse.h>
 #import <NGExtensions/NSString+misc.h>
 
 #import <SoObjects/Mailer/SOGoMailObject.h>
 
-#import <UI/Common/WODirectAction+SOGo.h>
-
 #import "UIxMailSourceView.h"
 
 @implementation UIxMailSourceView
 
 - (WOResponse *) viewSourceAction
diff --git a/UI/MainUI/SOGoMicrosoftActiveSyncActions.m b/UI/MainUI/SOGoMicrosoftActiveSyncActions.m
index 5761d65ff..4b1e25748 100644
--- a/UI/MainUI/SOGoMicrosoftActiveSyncActions.m
+++ b/UI/MainUI/SOGoMicrosoftActiveSyncActions.m
@@ -1,7 +1,7 @@
 /*
-  Copyright (C) 2014 Inverse inc. 
+  Copyright (C) 2014-2016 Inverse inc.
 
   This file is part of SOGo.
 
   SOGo is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
@@ -21,14 +21,15 @@
 
 
 #import <SOGo/SOGoCache.h>
 #import <SOGo/NSObject+Utilities.h>
 
-#import <NGObjWeb/NSException+HTTP.h>
 #import <NGObjWeb/WOContext.h>
+#import <NGObjWeb/WODirectAction.h>
+#import <NGObjWeb/NSException+HTTP.h>
+#import <NGObjWeb/WOResponse.h>
 
-#import <Common/WODirectAction+SOGo.h>
 #import <ActiveSync/SOGoActiveSyncDispatcher.h>
 
 @interface SOGoMicrosoftActiveSyncActions : WODirectAction
 @end
 
@@ -45,11 +46,13 @@ - (WOResponse *) microsoftServerActiveSyncAction
   NSException *ex;
   id dispatcher;
   Class clazz;
 
   request = (WORequest *)[context request];
-  response = [self responseWithStatus: 200];
+  response = [context response];
+  [response setStatus: 200];
+  [response setHeader: @"text/plain; charset=utf-8"  forKey: @"content-type"];
 
   bundle = [NSBundle bundleForClass: NSClassFromString(@"ActiveSyncProduct")];
   clazz = [bundle classNamed: @"SOGoActiveSyncDispatcher"];
   dispatcher = [[clazz alloc] init];
 
diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m
index 9348da2f9..ec821a042 100644
--- a/UI/MainUI/SOGoRootPage.m
+++ b/UI/MainUI/SOGoRootPage.m
@@ -34,10 +34,11 @@
 #import <NGExtensions/NSString+misc.h>
 #import <NGExtensions/NSObject+Logs.h>
 
 #import <Appointments/SOGoAppointmentFolders.h>
 
+#import <SOGo/NSString+Crypto.h>
 #import <SOGo/NSString+Utilities.h>
 #import <SOGo/SOGoBuild.h>
 #import <SOGo/SOGoCache.h>
 #import <SOGo/SOGoCASSession.h>
 #if defined(SAML2_CONFIG)
@@ -168,18 +169,18 @@ - (WOResponse *) _responseWithLDAPPolicyError: (int) error
 //
 - (id <WOActionResults>) connectAction
 {
   WOResponse *response;
   WORequest *request;
-  WOCookie *authCookie;
+  WOCookie *authCookie, *xsrfCookie;
   SOGoWebAuthenticator *auth;
   SOGoAppointmentFolders *calendars;
   SOGoUserDefaults *ud;
   SOGoUser *loggedInUser;
   NSDictionary *params;
   NSString *username, *password, *language, *domain, *remoteHost;
-  NSArray *supportedLanguages;
+  NSArray *supportedLanguages, *creds;
   
   SOGoPasswordPolicyError err;
   int expire, grace;
   BOOL rememberLogin, b;
   
@@ -230,10 +231,17 @@ - (WOResponse *) _responseWithLDAPPolicyError: (int) error
       authCookie = [auth cookieWithUsername: username
                                 andPassword: password
                                   inContext: context];
       [response addCookie: authCookie];
 
+      // We prepare the XSRF protection cookie
+      creds = [auth parseCredentials: [authCookie value]];
+      xsrfCookie = [WOCookie cookieWithName: @"XSRF-TOKEN"
+                                      value: [[SOGoSession valueForSessionKey: [creds lastObject]] asSHA1String]];
+      [xsrfCookie setPath: [NSString stringWithFormat: @"/%@/", [[context request] applicationName]]];
+      [response addCookie: xsrfCookie];
+
       supportedLanguages = [[SOGoSystemDefaults sharedSystemDefaults]
                              supportedLanguages];
       loggedInUser = [SOGoUser userWithLogin: username];
       [context setActiveUser: loggedInUser];
       if (language && [supportedLanguages containsObject: language])
@@ -538,12 +546,12 @@ - (NSString *) version
 }
 
 - (WOResponse *) changePasswordAction
 {
   NSString *username, *domain, *password, *newPassword, *value;
+  WOCookie *authCookie, *xsrfCookie;
   NSDictionary *message;
-  WOCookie *authCookie;
   NSArray *creds;
   SOGoUserManager *um;
   SOGoPasswordPolicyError error;
   SOGoSystemDefaults *sd;
   SOGoWebAuthenticator *auth;
@@ -590,10 +598,16 @@ - (WOResponse *) changePasswordAction
       response = [self responseWith204];
       authCookie = [auth cookieWithUsername: username
                                 andPassword: newPassword
                                   inContext: context];
       [response addCookie: authCookie];
+
+      // We update the XSRF protection cookie
+      creds = [auth parseCredentials: [authCookie value]];
+      xsrfCookie = [WOCookie cookieWithName: @"XSRF-TOKEN"
+                                      value: [[SOGoSession valueForSessionKey: [creds lastObject]] asSHA1String]];
+      [response addCookie: xsrfCookie];
     }
   else
     response = [self _responseWithLDAPPolicyError: error];
 
   return response;
diff --git a/UI/MainUI/SOGoUserHomePage.m b/UI/MainUI/SOGoUserHomePage.m
index 7770e9e07..e6cf4bfb7 100644
--- a/UI/MainUI/SOGoUserHomePage.m
+++ b/UI/MainUI/SOGoUserHomePage.m
@@ -453,12 +453,12 @@ - (WOCookie *) _logoutCookieWithDate: (NSCalendarDate *) date
   return cookie;
 }
 
 - (id <WOActionResults>) logoffAction
 {
-  SOGoWebAuthenticator *auth;
   NSString *userName, *value;
+  SOGoWebAuthenticator *auth;
   WOResponse *response;
   NSCalendarDate *date;
   WOCookie *cookie;
   NSArray *creds;
    
@@ -484,10 +484,16 @@ - (WOCookie *) _logoutCookieWithDate: (NSCalendarDate *) date
 
   cookie = [self _logoutCookieWithDate: date];
   if (cookie)
     [response addCookie: cookie];
 
+  // We remove the XSRF cookie
+  cookie = [WOCookie cookieWithName: @"XSRF-TOKEN"  value: @"discard"];
+  [cookie setPath: [NSString stringWithFormat: @"/%@/", [[context request] applicationName]]];
+  [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, post-check=0, pre-check=0"
                forKey: @"Cache-Control"];
   [response setHeader: @"no-cache" forKey: @"Pragma"];
diff --git a/UI/PreferencesUI/UIxJSONPreferences.h b/UI/PreferencesUI/UIxJSONPreferences.h
index f095254fc..42d4353f5 100644
--- a/UI/PreferencesUI/UIxJSONPreferences.h
+++ b/UI/PreferencesUI/UIxJSONPreferences.h
@@ -1,8 +1,8 @@
 /* UIxJSONPreferences.h - this file is part of SOGo
  *
- * Copyright (C) 2007-2015 Inverse inc.
+ * Copyright (C) 2007-2016 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.
@@ -19,11 +19,12 @@
  */
 
 #ifndef UIXJSONPREFERENCES_H
 #define UIXJSONPREFERENCES_H
 
+#import <UI/Common/SOGoDirectAction.h>
 
-@interface UIxJSONPreferences : WODirectAction
+@interface UIxJSONPreferences : SOGoDirectAction
 
 @end
 
 #endif /* UIXJSONSETTINGS_H */
diff --git a/UI/PreferencesUI/UIxJSONPreferences.m b/UI/PreferencesUI/UIxJSONPreferences.m
index 8d639ab88..41288018d 100644
--- a/UI/PreferencesUI/UIxJSONPreferences.m
+++ b/UI/PreferencesUI/UIxJSONPreferences.m
@@ -33,12 +33,10 @@
 #import <SOGo/SOGoUserSettings.h>
 #import <SOGo/SOGoUserProfile.h>
 #import <SOGo/WOResourceManager+SOGo.h>
 #import <Mailer/SOGoMailLabel.h>
 
-#import <UI/Common/WODirectAction+SOGo.h>
-
 #import "UIxJSONPreferences.h"
 
 static SoProduct *preferencesProduct = nil;
 
 @implementation UIxJSONPreferences
diff --git a/UI/SOGoUI/UIxComponent.m b/UI/SOGoUI/UIxComponent.m
index c4606f13f..c23db4bb1 100644
--- a/UI/SOGoUI/UIxComponent.m
+++ b/UI/SOGoUI/UIxComponent.m
@@ -32,15 +32,18 @@
 #import <NGExtensions/NSURL+misc.h>
 
 #import <SOGo/NSCalendarDate+SOGo.h>
 #import <SOGo/NSDictionary+Utilities.h>
 #import <SOGo/NSObject+Utilities.h>
+#import <SOGo/NSString+Crypto.h>
 #import <SOGo/NSString+Utilities.h>
 #import <SOGo/SOGoBuild.h>
+#import <SOGo/SOGoSession.h>
 #import <SOGo/SOGoSystemDefaults.h>
 #import <SOGo/SOGoUser.h>
 #import <SOGo/SOGoUserFolder.h>
+#import <SOGo/SOGoWebAuthenticator.h>
 #import <SOGo/WOContext+SOGo.h>
 #import <SOGo/WOResourceManager+SOGo.h>
 
 #import "UIxJSClose.h"
 
@@ -761,6 +764,44 @@ - (BOOL) isUIxDebugEnabled
   sd = [SOGoSystemDefaults sharedSystemDefaults];
 
   return [sd uixDebugEnabled];
 }
 
+//
+// Protection against XSRF
+//
+- (id<WOActionResults>)performActionNamed:(NSString *)_actionName
+{
+  SOGoWebAuthenticator *auth;
+  NSString *value, *token;
+  NSArray *creds;
+
+  if (![[SOGoSystemDefaults sharedSystemDefaults] xsrfValidationEnabled])
+    return [super performActionNamed: _actionName];
+
+  // If the action is 'connect' (or 'logoff'), we let it go as the token
+  // needs to be created (or destroyed) during the session initialization
+  if ([_actionName isEqualToString: @"connect"] ||
+      [_actionName isEqualToString: @"logoff"])
+    {
+      return [super performActionNamed: _actionName];
+    }
+
+  // We grab the X-XSRF-TOKEN header
+  token = [[context request] headerForKey: @"X-XSRF-TOKEN"];
+
+  // We compare it with our session key
+  auth = [[WOApplication application]
+           authenticatorInContext: context];
+  value = [[context request]
+           cookieValueForKey: [auth cookieNameInContext: context]];
+  creds = [auth parseCredentials: value];
+
+  value = [SOGoSession valueForSessionKey: [creds lastObject]];
+
+  if ([token isEqualToString: [value asSHA1String]])
+    return [super performActionNamed: _actionName];
+
+  return nil;
+}
+
 @end /* UIxComponent */
diff --git a/UI/Scheduler/UIxAppointmentActions.h b/UI/Scheduler/UIxAppointmentActions.h
index a50346d9c..fa012e411 100644
--- a/UI/Scheduler/UIxAppointmentActions.h
+++ b/UI/Scheduler/UIxAppointmentActions.h
@@ -19,11 +19,12 @@
  */
 
 #ifndef UIXAPPOINTMENTACTIONS_H
 #define UIXAPPOINTMENTACTIONS_H
 
+#import <Common/SOGoDirectAction.h>
 
-@interface UIxAppointmentActions : WODirectAction
+@interface UIxAppointmentActions : SOGoDirectAction
 
 @end
 
 #endif /* UIXAPPOINTMENTACTIONS_H */
diff --git a/UI/Scheduler/UIxAppointmentActions.m b/UI/Scheduler/UIxAppointmentActions.m
index cd47098c7..8f16ba980 100644
--- a/UI/Scheduler/UIxAppointmentActions.m
+++ b/UI/Scheduler/UIxAppointmentActions.m
@@ -38,12 +38,10 @@
 #import <Appointments/iCalEvent+SOGo.h>
 #import <Appointments/SOGoAppointmentObject.h>
 #import <Appointments/SOGoAppointmentFolder.h>
 #import <Appointments/SOGoAppointmentFolders.h>
 
-#import <Common/WODirectAction+SOGo.h>
-
 #import "UIxAppointmentActions.h"
 
 @implementation UIxAppointmentActions
 
 - (WOResponse *) adjustAction
diff --git a/UI/Scheduler/UIxCalListingActions.h b/UI/Scheduler/UIxCalListingActions.h
index f57df5c77..b4aec4ffb 100644
--- a/UI/Scheduler/UIxCalListingActions.h
+++ b/UI/Scheduler/UIxCalListingActions.h
@@ -1,8 +1,8 @@
 /* UIxCalListingActions.h - this file is part of SOGo
  *
- * Copyright (C) 2006-2015 Inverse inc.
+ * Copyright (C) 2006-2016 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.
@@ -19,11 +19,11 @@
  */
 
 #ifndef UIXCALLISTINGACTIONVIEW_H
 #define UIXCALLISTINGACTIONVIEW_H
 
-#import <Common/WODirectAction+SOGo.h>
+#import <Common/SOGoDirectAction.h>
 
 @class NSCalendarDate;
 @class NSMutableDictionary;
 @class NSString;
 @class NSTimeZone;
@@ -31,11 +31,11 @@
 @class SOGoDateFormatter;
 
 @class WOResponse;
 @class WORequest;
 
-@interface UIxCalListingActions : WODirectAction
+@interface UIxCalListingActions : SOGoDirectAction
 {
   NSMutableDictionary *componentsData;
   NSCalendarDate *startDate;
   NSCalendarDate *endDate;
   NSCalendarDate *now;
diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m
index 635008b0e..35208333d 100644
--- a/UI/Scheduler/UIxCalListingActions.m
+++ b/UI/Scheduler/UIxCalListingActions.m
@@ -45,12 +45,10 @@
 #import <SOGo/NSObject+Utilities.h>
 #import <SOGo/WOResourceManager+SOGo.h>
 #import <Appointments/SOGoAppointmentFolders.h>
 #import <Appointments/SOGoWebAppointmentFolder.h>
 
-#import <UI/Common/WODirectAction+SOGo.h>
-
 #import "NSArray+Scheduler.h"
 
 #import "UIxCalListingActions.h"
 
 static NSArray *eventsFields = nil;
@@ -636,11 +634,11 @@ - (WOResponse *) alarmsListAction
   SOGoAppointmentFolders *clientObject;
   NSMutableArray *allAlarms;
   NSDictionary *data;
   NSEnumerator *folders;
   unsigned int browserTime, laterTime;
-  
+
   // We look for alarms in the next 48 hours
   browserTime = [[[context request] formValueForKey: @"browserTime"] intValue];
   laterTime = browserTime + 60*60*48;
   clientObject = [self clientObject];
   allAlarms = [NSMutableArray array];
@@ -777,11 +775,11 @@ - (WOResponse *) eventsListAction
   NSEnumerator *events;
   NSMutableArray *fields, *newEvents, *newEvent;
   unsigned int interval;
   BOOL isAllDay;
   NSString *sort, *ascending;
-  
+
   [self _setupContext];
   [self saveFilterValue: @"EventsFilterState"];
   [self saveSortValue: @"EventsSortingState"];
   
   newEvents = [NSMutableArray array];
@@ -1315,11 +1313,11 @@ - (WOResponse *) eventsBlocksAction
   NSMutableArray *allDayBlocks, *blocks, *currentDay, *eventsForCalendar, *eventsByCalendars;
   NSNumber *eventNbr;
   NSString *calendarName, *calendarId;
   BOOL isAllDay;
   int i, j;
-  
+
   [self _setupContext];
   
   events = [self _fetchFields: eventsFields forComponentOfType: @"vevent"];
   
   if ([currentView isEqualToString: @"multicolumndayview"])
@@ -1484,11 +1482,11 @@ - (WOResponse *) tasksListAction
   unsigned int endDateStamp;
   BOOL showCompleted;
   int statusCode;
   int startSecs;
   int endsSecs;
-  
+
   filteredTasks = [NSMutableArray array];
   
   [self _setupContext];
   [self saveFilterValue: @"TasksFilterState"];
   [self saveSortValue: @"TasksSortingState"];
@@ -1571,13 +1569,12 @@ - (WOResponse *) activeTasksAction
 {
   NSMutableDictionary *activeTasksByCalendars;
   SOGoAppointmentFolder *folder;
   SOGoAppointmentFolders *co;
   NSArray *folders;
-  
   int i;
-  
+
   co = [self clientObject];
   folders = [co subFolders];
   activeTasksByCalendars = [NSMutableDictionary dictionaryWithCapacity: [folders count]];
 
   for (i = 0; i < [folders count]; i++)
diff --git a/UI/Scheduler/UIxCalMainActions.h b/UI/Scheduler/UIxCalMainActions.h
index 36ba4fbf3..53fdc451a 100644
--- a/UI/Scheduler/UIxCalMainActions.h
+++ b/UI/Scheduler/UIxCalMainActions.h
@@ -1,8 +1,8 @@
 /* UIxCalMainActions.h - this file is part of SOGo
  *
- * Copyright (C) 2009-2013 Inverse inc.
+ * Copyright (C) 2009-2016 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.
@@ -19,12 +19,12 @@
  */
 
 #ifndef UIXCALMAINACTIONS_H
 #define UIXCALMAINACTIONS_H
 
-#import <Common/WODirectAction+SOGo.h>
+#import <Common/SOGoDirectAction.h>
 
-@interface UIxCalMainActions : WODirectAction
+@interface UIxCalMainActions : SOGoDirectAction
 
 @end
 
 #endif /* UIXCALMAINACTIONS_H */
diff --git a/UI/Scheduler/UIxCalMainActions.m b/UI/Scheduler/UIxCalMainActions.m
index d76490a82..f20387c17 100644
--- a/UI/Scheduler/UIxCalMainActions.m
+++ b/UI/Scheduler/UIxCalMainActions.m
@@ -1,8 +1,8 @@
 /* UIxCalMainActions.m - this file is part of SOGo
  *
- * Copyright (C) 2009-2015 Inverse inc.
+ * Copyright (C) 2009-2016 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.
diff --git a/UI/WebServerResources/js/Common/Authentication.service.js b/UI/WebServerResources/js/Common/Authentication.service.js
index 5401fd99e..f1a883f9a 100644
--- a/UI/WebServerResources/js/Common/Authentication.service.js
+++ b/UI/WebServerResources/js/Common/Authentication.service.js
@@ -149,15 +149,21 @@
           return d.promise;
         }, // login: function(data) { ...
 
         changePassword: function(newPassword) {
           var d = $q.defer(),
-              loginCookie = readLoginCookie();
+              loginCookie = readLoginCookie(),
+              xsrfCookie = $cookies.get('XSRF-TOKEN');
+
+          $cookies.remove('XSRF-TOKEN', {path: '/SOGo/'});
 
           $http({
             method: 'POST',
             url: '/SOGo/so/changePassword',
+            headers: {
+              'X-XSRF-TOKEN' : xsrfCookie
+            },
             data: {
               userName: loginCookie[0],
               password: loginCookie[1],
               newPassword: newPassword }
           }).then(d.resolve, function(response) {
@@ -184,10 +190,12 @@
             } else {
               error = l("Unhandled policy error: %{0}").formatted(perr);
               perr = passwordPolicyConfig.PolicyPasswordUnknown;
             }
 
+            // Restore the cookie
+            $cookies.put('XSRF-TOKEN', xsrfCookie, {path: '/SOGo/'});
             d.reject(error);
           });
           return d.promise;
         }
       };

Vulnerable code: 	WODirectAction+SOGo.m		\
/* WODirectAction+SOGo.h - this file is part of SOGo
 * Copyright (C) 2007-2015 Inverse inc.
@interface WODirectAction (SOGoExtension)
/* WODirectAction+SOGo.m - this file is part of SOGo
 * Copyright (C) 2007-2015 Inverse inc.
#import "WODirectAction+SOGo.h"
@implementation WODirectAction (SOGoExtension)
 * Copyright (C) 2007-2014 Inverse inc.
@interface UIxFolderActions : WODirectAction
 * Copyright (C) 2007-2015 Inverse inc.
#import "WODirectAction+SOGo.h"

 * Copyright (C) 2007 Inverse inc.
 *
 * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
@interface UIxObjectActions : WODirectAction
#import "WODirectAction+SOGo.h"

 * Copyright (C) 2007 Inverse inc.
 *
 * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
@interface UIxParentFolderActions : WODirectAction
 * Copyright (C) 2007-2015 Inverse inc.
#import <UI/Common/WODirectAction+SOGo.h>

 * Copyright (C) 2010 Inverse inc.
 *
 * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
#import <Common/WODirectAction+SOGo.h>
@interface UIxContactActions : WODirectAction
 Copyright (C) 2004-2005 SKYRIX Software AG
 
 This file is part of OpenGroupware.org.
 
 OGo is free software; you can redistribute it and/or modify it under
 the terms of the GNU Lesser General Public License as published by the
 Free Software Foundation; either version 2, or (at your option) any
 later version.
 
 OGo 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 Lesser General Public
 License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with OGo; see the file COPYING.  If not, write to the
 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.
@interface UIxContactsListActions : WODirectAction
#import <Common/WODirectAction+SOGo.h>


 * Copyright (C) 2007 Inverse inc.
 *
 * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>

@interface UIxMailPartICalActions : WODirectAction
 * Copyright (C) 2007-2015 Inverse inc.
#import <UI/Common/WODirectAction+SOGo.h>

  //NSException *ex;
 * Copyright (C) 2007-2013 Inverse inc.
@interface UIxMailAccountActions : WODirectAction
 * Copyright (C) 2007-2014 Inverse inc.
#import "../Common/WODirectAction+SOGo.h"

 * Copyright (C) 2007-2013 Inverse inc.
@interface UIxMailActions : WODirectAction
#import "../Common/WODirectAction+SOGo.h"

@interface UIxMailFolderActions : WODirectAction
#import <UI/Common/WODirectAction+SOGo.h>


  {
    uids = [value componentsSeparatedByString: @","];
    response = [co archiveUIDs: uids
                inArchiveNamed: [self labelForKey: @"Saved Messages.zip" inContext: context]
                     inContext: context];
    if (!response)
      response = [self responseWith204];
  }
  {
    jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'uid' parameter." inContext: context]
                                               forKey: @"message"];
    response = [self responseWithStatus: 500 andJSONRepresentation: jsonResponse];
  }
  Copyright (C) 2004-2005 SKYRIX Software AG
  Copyright (C) 2004-2014 Inverse inc

@interface UIxMailListActions : WODirectAction
#import <UI/Common/WODirectAction+SOGo.h>
 * Copyright (C) 2007-2015 Inverse inc.
@interface UIxMailSourceView : WODirectAction
 * Copyright (C) 2007-2015 Inverse inc.
#import <UI/Common/WODirectAction+SOGo.h>

  Copyright (C) 2014 Inverse inc. 
#import <NGObjWeb/NSException+HTTP.h>
#import <Common/WODirectAction+SOGo.h>
  response = [self responseWithStatus: 200];
  WOCookie *authCookie;
  NSArray *supportedLanguages;
  WOCookie *authCookie;
  SOGoWebAuthenticator *auth;
 * Copyright (C) 2007-2015 Inverse inc.
@interface UIxJSONPreferences : WODirectAction
#import <UI/Common/WODirectAction+SOGo.h>

@interface UIxAppointmentActions : WODirectAction
#import <Common/WODirectAction+SOGo.h>

 * Copyright (C) 2006-2015 Inverse inc.
#import <Common/WODirectAction+SOGo.h>
@interface UIxCalListingActions : WODirectAction
#import <UI/Common/WODirectAction+SOGo.h>

  
  
  
  
  
  
 * Copyright (C) 2009-2013 Inverse inc.
#import <Common/WODirectAction+SOGo.h>
@interface UIxCalMainActions : WODirectAction
 * Copyright (C) 2009-2015 Inverse inc.
              loginCookie = readLoginCookie();
Fixed code:  - [web] added AngularJS's XSRF support (#3246)
- (BOOL) xsrfValidationEnabled;
- (BOOL) xsrfValidationEnabled
{
  id o;

  if (!(o = [self objectForKey: @"SOGoXSRFValidationEnabled"]))
    {
      return YES;
    }

  return [o boolValue];
}

	SOGoDirectAction.m		\
/* SOGoDirectAction.h - this file is part of SOGo
 * Copyright (C) 2007-2016 Inverse inc.
@interface SOGoDirectAction : WODirectAction
/* SOGoDirectAction - this file is part of SOGo
 * Copyright (C) 2007-2016 Inverse inc.
#import <SoObjects/SOGo/NSString+Crypto.h>
#import <SoObjects/SOGo/SOGoSession.h>
#import <SoObjects/SOGo/SOGoSystemDefaults.h>
#import <SoObjects/SOGo/SOGoWebAuthenticator.h>
#import "SOGoDirectAction.h"
@implementation SOGoDirectAction
//
// Protection against XSRF
//
- (id<WOActionResults>)performActionNamed:(NSString *)_actionName
{
  SOGoWebAuthenticator *auth;
  NSString *value, *token;
  NSArray *creds;

  if (![[SOGoSystemDefaults sharedSystemDefaults] xsrfValidationEnabled])
    return [super performActionNamed: _actionName];

  // We grab the X-XSRF-TOKEN header
  token = [[context request] headerForKey: @"X-XSRF-TOKEN"];

  // We compare it with our session key
  auth = [[WOApplication application]
           authenticatorInContext: context];
  value = [[context request]
           cookieValueForKey: [auth cookieNameInContext: context]];
  creds = [auth parseCredentials: value];

  value = [SOGoSession valueForSessionKey: [creds lastObject]];

  if ([token isEqualToString: [value asSHA1String]])
    return [super performActionNamed: _actionName];

  return nil;
}

 * Copyright (C) 2007-2016 Inverse inc.
#include "SOGoDirectAction.h"

@interface UIxFolderActions : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
 * Copyright (C) 2007-2016 Inverse inc.
#include "SOGoDirectAction.h"
@interface UIxObjectActions : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
#include "SOGoDirectAction.h"
@interface UIxParentFolderActions : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
 * Copyright (C) 2010-2016 Inverse inc.
#import <Common/SOGoDirectAction.h>
@interface UIxContactActions : SOGoDirectAction
  Copyright (C) 2006-2016 Inverse inc.

  This file is part of SOGo.

  SOGo is free software; you can redistribute it and/or modify it under
  the terms of the GNU Lesser General Public License as published by the
  Free Software Foundation; either version 2, or (at your option) any
  later version.

  SOGo 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 Lesser General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with SOGo; see the file COPYING.  If not, write to the
  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  02111-1307, USA.
#import <Common/SOGoDirectAction.h>
@interface UIxContactsListActions : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
#import <UI/Common/SOGoDirectAction.h>

@interface UIxMailPartICalActions : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
 * Copyright (C) 2007-2016 Inverse inc.
#import <UI/Common/SOGoDirectAction.h>
@interface UIxMailAccountActions : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
 * Copyright (C) 2007-2016 Inverse inc.
#import <UI/Common/SOGoDirectAction.h>
@interface UIxMailActions : SOGoDirectAction
#import <UI/Common/SOGoDirectAction.h>
@interface UIxMailFolderActions : SOGoDirectAction
    {
      uids = [value componentsSeparatedByString: @","];
      response = [co archiveUIDs: uids
                  inArchiveNamed: [self labelForKey: @"Saved Messages.zip" inContext: context]
                       inContext: context];
      if (!response)
        response = [self responseWith204];
    }
    {
      jsonResponse = [NSDictionary dictionaryWithObject: [self labelForKey: @"Missing 'uid' parameter." inContext: context]
                                                 forKey: @"message"];
      response = [self responseWithStatus: 500 andJSONRepresentation: jsonResponse];
    }
  Copyright (C) 2004-2016 Inverse inc
#import <UI/Common/SOGoDirectAction.h>

@interface UIxMailListActions : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
#import <UI/Common/SOGoDirectAction.h>
@interface UIxMailSourceView : SOGoDirectAction
 * Copyright (C) 2007-2016 Inverse inc.
  Copyright (C) 2014-2016 Inverse inc.
#import <NGObjWeb/WODirectAction.h>
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOResponse.h>
  response = [context response];
  [response setStatus: 200];
  [response setHeader: @"text/plain; charset=utf-8"  forKey: @"content-type"];
#import <SOGo/NSString+Crypto.h>
  WOCookie *authCookie, *xsrfCookie;
  NSArray *supportedLanguages, *creds;
      // We prepare the XSRF protection cookie
      creds = [auth parseCredentials: [authCookie value]];
      xsrfCookie = [WOCookie cookieWithName: @"XSRF-TOKEN"
                                      value: [[SOGoSession valueForSessionKey: [creds lastObject]] asSHA1String]];
      [xsrfCookie setPath: [NSString stringWithFormat: @"/%@/", [[context request] applicationName]]];
      [response addCookie: xsrfCookie];

  WOCookie *authCookie, *xsrfCookie;

      // We update the XSRF protection cookie
      creds = [auth parseCredentials: [authCookie value]];
      xsrfCookie = [WOCookie cookieWithName: @"XSRF-TOKEN"
                                      value: [[SOGoSession valueForSessionKey: [creds lastObject]] asSHA1String]];
      [response addCookie: xsrfCookie];
  SOGoWebAuthenticator *auth;
  // We remove the XSRF cookie
  cookie = [WOCookie cookieWithName: @"XSRF-TOKEN"  value: @"discard"];
  [cookie setPath: [NSString stringWithFormat: @"/%@/", [[context request] applicationName]]];
  [cookie setExpires: [date yesterday]];
  [response addCookie: cookie];

 * Copyright (C) 2007-2016 Inverse inc.
#import <UI/Common/SOGoDirectAction.h>
@interface UIxJSONPreferences : SOGoDirectAction
#import <SOGo/NSString+Crypto.h>
#import <SOGo/SOGoSession.h>
#import <SOGo/SOGoWebAuthenticator.h>
//
// Protection against XSRF
//
- (id<WOActionResults>)performActionNamed:(NSString *)_actionName
{
  SOGoWebAuthenticator *auth;
  NSString *value, *token;
  NSArray *creds;

  if (![[SOGoSystemDefaults sharedSystemDefaults] xsrfValidationEnabled])
    return [super performActionNamed: _actionName];

  // If the action is 'connect' (or 'logoff'), we let it go as the token
  // needs to be created (or destroyed) during the session initialization
  if ([_actionName isEqualToString: @"connect"] ||
      [_actionName isEqualToString: @"logoff"])
    {
      return [super performActionNamed: _actionName];
    }

  // We grab the X-XSRF-TOKEN header
  token = [[context request] headerForKey: @"X-XSRF-TOKEN"];

  // We compare it with our session key
  auth = [[WOApplication application]
           authenticatorInContext: context];
  value = [[context request]
           cookieValueForKey: [auth cookieNameInContext: context]];
  creds = [auth parseCredentials: value];

  value = [SOGoSession valueForSessionKey: [creds lastObject]];

  if ([token isEqualToString: [value asSHA1String]])
    return [super performActionNamed: _actionName];

  return nil;
}

#import <Common/SOGoDirectAction.h>
@interface UIxAppointmentActions : SOGoDirectAction
 * Copyright (C) 2006-2016 Inverse inc.
#import <Common/SOGoDirectAction.h>
@interface UIxCalListingActions : SOGoDirectAction





 * Copyright (C) 2009-2016 Inverse inc.
#import <Common/SOGoDirectAction.h>
@interface UIxCalMainActions : SOGoDirectAction
 * Copyright (C) 2009-2016 Inverse inc.
              loginCookie = readLoginCookie(),
              xsrfCookie = $cookies.get('XSRF-TOKEN');

          $cookies.remove('XSRF-TOKEN', {path: '/SOGo/'});
            headers: {
              'X-XSRF-TOKEN' : xsrfCookie
            },
            // Restore the cookie
            $cookies.put('XSRF-TOKEN', xsrfCookie, {path: '/SOGo/'});