Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

include/SugarOAuthServer.php (9 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*********************************************************************************
3
 * SugarCRM Community Edition is a customer relationship management program developed by
4
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5
6
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
7
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
8
 *
9
 * This program is free software; you can redistribute it and/or modify it under
10
 * the terms of the GNU Affero General Public License version 3 as published by the
11
 * Free Software Foundation with the addition of the following permission added
12
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
13
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
14
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
19
 * details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License along with
22
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
23
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24
 * 02110-1301 USA.
25
 *
26
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
27
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
28
 *
29
 * The interactive user interfaces in modified source and object code versions
30
 * of this program must display Appropriate Legal Notices, as required under
31
 * Section 5 of the GNU Affero General Public License version 3.
32
 *
33
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
34
 * these Appropriate Legal Notices must retain the display of the "Powered by
35
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
36
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
37
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
38
 ********************************************************************************/
39
40
41
require_once 'modules/OAuthTokens/OAuthToken.php';
42
require_once 'modules/OAuthKeys/OAuthKey.php';
43
/**
44
 * Sugar OAuth provider implementation
45
 * @api
46
 */
47
class SugarOAuthServer
48
{
49
    /**
50
     * OAuth token
51
     * @var OAuthToken
52
     */
53
    protected $token;
54
55
    /**
56
     * Check if everything is OK
57
     * @throws OAuthException
58
     */
59
    protected function check()
60
    {
61
        if(!function_exists('mhash') && !function_exists('hash_hmac')) {
62
            // define exception class
63
            throw new OAuthException("MHash extension required for OAuth support");
64
        }
65
    }
66
67
    /**
68
     * Is this functionality enabled?
69
     */
70
    public static function enabled()
71
    {
72
        return function_exists('mhash') || function_exists('hash_hmac');
73
    }
74
75
    /**
76
     * Find consumer by key
77
     * @param $provider
78
     */
79
    public function lookupConsumer($provider)
80
    {
81
        // check $provider->consumer_key
82
        // on unknown: Zend_Oauth_Provider::CONSUMER_KEY_UNKNOWN
83
        // on bad key: Zend_Oauth_Provider::CONSUMER_KEY_REFUSED
84
        $GLOBALS['log']->debug("OAUTH: lookupConsumer, key={$provider->consumer_key}");
85
        $consumer = OAuthKey::fetchKey($provider->consumer_key);
86
        if(!$consumer) {
87
            return Zend_Oauth_Provider::CONSUMER_KEY_UNKNOWN;
88
        }
89
        $provider->consumer_secret = $consumer->c_secret;
90
        $this->consumer = $consumer;
91
        return Zend_Oauth_Provider::OK;
92
    }
93
94
    /**
95
     * Check timestamps & nonces
96
     * @param OAuthProvider $provider
97
     */
98
    public function timestampNonceChecker($provider)
99
    {
100
        // FIXME: add ts/nonce verification
101
        if(empty($provider->nonce)) {
102
            return Zend_Oauth_Provider::BAD_NONCE;
103
        }
104
        if(empty($provider->timestamp)) {
105
            return Zend_Oauth_Provider::BAD_TIMESTAMP;
106
        }
107
        return OAuthToken::checkNonce($provider->consumer_key, $provider->nonce, $provider->timestamp);
0 ignored issues
show
The method checkNonce() does not seem to exist on object<OAuthToken>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
108
    }
109
110
    /**
111
     * Vefiry incoming token
112
     * @param OAuthProvider $provider
113
     */
114
    public function tokenHandler($provider)
115
    {
116
        $GLOBALS['log']->debug("OAUTH: tokenHandler, token={$provider->token}, verify={$provider->verifier}");
117
118
        $token = OAuthToken::load($provider->token);
0 ignored issues
show
The method load() does not seem to exist on object<OAuthToken>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
119
        if(empty($token)) {
120
            return Zend_Oauth_Provider::TOKEN_REJECTED;
121
        }
122
        if($token->consumer != $this->consumer->id) {
123
            return Zend_Oauth_Provider::TOKEN_REJECTED;
124
        }
125
        $GLOBALS['log']->debug("OAUTH: tokenHandler, found token=".var_export($token->id, true));
126
        if($token->tstate == OAuthToken::REQUEST) {
127
            if(!empty($token->verify) && $provider->verifier == $token->verify) {
128
                $provider->token_secret = $token->secret;
129
                $this->token = $token;
130
                return Zend_Oauth_Provider::OK;
131
            } else {
132
                return Zend_Oauth_Provider::TOKEN_USED;
133
            }
134
        }
135
        if($token->tstate == OAuthToken::ACCESS) {
136
            $provider->token_secret = $token->secret;
137
            $this->token = $token;
138
            return Zend_Oauth_Provider::OK;
139
        }
140
        return Zend_Oauth_Provider::TOKEN_REJECTED;
141
    }
142
143
    /**
144
     * Decode POST/GET via from_html()
145
     * @return array decoded data
146
     */
147
    protected function decodePostGet()
148
    {
149
        $data = $_GET;
150
        $data = array_merge($data, $_POST);
151
        foreach($data as $k => $v) {
152
            $data[$k] = from_html($v);
153
        }
154
        return $data;
155
    }
156
157
    /**
158
     * Create OAuth provider
159
     *
160
     * Checks current request for OAuth valitidy
161
     * @param bool $add_rest add REST endpoint as request path
0 ignored issues
show
There is no parameter named $add_rest. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
162
     */
163
    public function __construct($req_path = '')
164
    {
165
        $GLOBALS['log']->debug("OAUTH: __construct($req_path): ".var_export($_REQUEST, true));
166
        $this->check();
167
        $this->provider = new Zend_Oauth_Provider();
168
        try {
169
		    $this->provider->setConsumerHandler(array($this,'lookupConsumer'));
170
		    $this->provider->setTimestampNonceHandler(array($this,'timestampNonceChecker'));
171
		    $this->provider->setTokenHandler(array($this,'tokenHandler'));
172
	        if(!empty($req_path)) {
173
		        $this->provider->isRequestTokenEndpoint($req_path);  // No token needed for this end point
174
	        }
175
	    	$this->provider->checkOAuthRequest(null, $this->decodePostGet());
176
	    	if(mt_rand() % 10 == 0) {
177
	    	    // cleanup 1 in 10 times
178
	    	    OAuthToken::cleanup();
0 ignored issues
show
The method cleanup() does not seem to exist on object<OAuthToken>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
179
	    	}
180
        } catch(Exception $e) {
181
            $GLOBALS['log']->debug($this->reportProblem($e));
182
            throw $e;
183
        }
184
    }
185
186
    /**
187
     * Generate request token string
188
     * @return string
189
     */
190
    public function requestToken()
191
    {
192
        $GLOBALS['log']->debug("OAUTH: requestToken");
193
        $token = OAuthToken::generate();
0 ignored issues
show
The method generate() does not seem to exist on object<OAuthToken>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
194
        $token->setConsumer($this->consumer);
195
        $params = $this->provider->getOAuthParams();
196
        if(!empty($params['oauth_callback']) && $params['oauth_callback'] != 'oob') {
197
            $token->setCallbackURL($params['oauth_callback']);
198
        }
199
        $token->save();
200
        return $token->queryString();
201
    }
202
203
    /**
204
     * Generate access token string - must have validated request token
205
     * @return string
206
     */
207
    public function accessToken()
208
    {
209
        $GLOBALS['log']->debug("OAUTH: accessToken");
210
        if(empty($this->token) || $this->token->tstate != OAuthToken::REQUEST) {
211
            return null;
212
        }
213
        $this->token->invalidate();
0 ignored issues
show
The method invalidate() does not seem to exist on object<OAuthToken>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
214
        $token = OAuthToken::generate();
0 ignored issues
show
The method generate() does not seem to exist on object<OAuthToken>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
215
        $token->setState(OAuthToken::ACCESS);
216
        $token->setConsumer($this->consumer);
217
        // transfer user data from request token
218
        $token->copyAuthData($this->token);
219
        $token->save();
220
        return $token->queryString();
221
    }
222
223
    /**
224
     * Return authorization URL
225
     * @return string
226
     */
227
    public function authUrl()
228
    {
229
        return urlencode(rtrim($GLOBALS['sugar_config']['site_url'],'/')."/index.php?module=OAuthTokens&action=authorize");
230
    }
231
232
    /**
233
     * Fetch current token if it is authorized
234
     * @return OAuthToken|null
235
     */
236
    public function authorizedToken()
237
    {
238
        if($this->token->tstate == OAuthToken::ACCESS) {
239
            return $this->token;
240
        }
241
        return null;
242
    }
243
244
    /**
245
     * Fetch authorization data from current token
246
     * @return mixed Authorization data or null if none
247
     */
248
    public function authorization()
249
    {
250
        if($this->token->tstate == OAuthToken::ACCESS) {
251
            return $this->token->authdata;
252
        }
253
        return null;
254
    }
255
256
    /**
257
     * Report OAuth problem as string
258
     */
259
    public function reportProblem(Exception $e)
260
    {
261
        return $this->provider->reportProblem($e);
262
    }
263
}
264
265
if(!class_exists('OAuthException')) {
266
    // we will use this in case oauth extension is not loaded
267
    class OAuthException extends Exception {}
0 ignored issues
show
Comprehensibility Best Practice introduced by
The type OAuthException has been defined more than once; this definition is ignored, only the first definition in include/social/twitter/t.../twitteroauth/OAuth.php (L7-10) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
268
}