CVE-2015-5395 (Objective-C, published 2017-09-20T18:29Z)
Description: value: Cross-site request forgery (CSRF) vulnerability in SOGo before 3.1.0.
Severity: MEDIUM (CVSS v3 base score: 8.8)
Weakness: CWE-352 \u2014 Cross-Site Request Forgery (CSRF)
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.
Repository: https://github.com/inverse-inc/sogo
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 message: (feat) added AngularJS's XSRF support (#3246)


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/'});