RequestProcessor::Initialize()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nop 0
dl 0
loc 11
rs 10
c 0
b 0
f 0
nc 2
1
<?php
2
3
/*
4
 * SPDX-License-Identifier: AGPL-3.0-only
5
 * SPDX-FileCopyrightText: Copyright 2007-2016 Zarafa Deutschland GmbH
6
 * SPDX-FileCopyrightText: Copyright 2020-2022 grommunio GmbH
7
 *
8
 * This file provides/loads the handlers for the different commands. The
9
 * request handlers are optimised so that as little as possible data is
10
 * kept-in-memory, and all output data is directly streamed to the client,
11
 * while also streaming input data from the client.
12
 */
13
14
abstract class RequestProcessor {
15
	protected static $backend;
16
	protected static $deviceManager;
17
	protected static $topCollector;
18
	protected static $decoder;
19
	protected static $encoder;
20
	protected static $userIsAuthenticated;
21
	protected static $specialHeaders;
22
	protected static $waitTime = 0;
23
24
	/**
25
	 * Authenticates the remote user
26
	 * The sent HTTP authentication information is used to on Backend->Logon().
27
	 * As second step the GET-User verified by Backend->Setup() for permission check
28
	 * Request::GetGETUser() is usually the same as the Request::GetAuthUser().
29
	 * If the GETUser is different from the AuthUser, the AuthUser MUST HAVE admin
30
	 * permissions on GETUsers data store. Only then the Setup() will be successful.
31
	 * This allows the user 'john' to do operations as user 'joe' if he has sufficient privileges.
32
	 *
33
	 * @throws AuthenticationRequiredException
34
	 */
35
	public static function Authenticate() {
36
		self::$userIsAuthenticated = false;
37
38
		// when a certificate is sent, allow authentication only as the certificate owner
39
		if (defined("CERTIFICATE_OWNER_PARAMETER") && isset($_SERVER[CERTIFICATE_OWNER_PARAMETER]) && strtolower((string) $_SERVER[CERTIFICATE_OWNER_PARAMETER]) != strtolower(Request::GetAuthUser())) {
0 ignored issues
show
Bug introduced by
It seems like Request::GetAuthUser() can also be of type boolean; however, parameter $string of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

39
		if (defined("CERTIFICATE_OWNER_PARAMETER") && isset($_SERVER[CERTIFICATE_OWNER_PARAMETER]) && strtolower((string) $_SERVER[CERTIFICATE_OWNER_PARAMETER]) != strtolower(/** @scrutinizer ignore-type */ Request::GetAuthUser())) {
Loading history...
40
			throw new AuthenticationRequiredException(sprintf("Access denied. Access is allowed only for the certificate owner '%s'", $_SERVER[CERTIFICATE_OWNER_PARAMETER]));
41
		}
42
43
		if (Request::GetImpersonatedUser() && strcasecmp(Request::GetAuthUser(), Request::GetImpersonatedUser()) !== 0) {
0 ignored issues
show
Bug introduced by
It seems like Request::GetImpersonatedUser() can also be of type boolean; however, parameter $string2 of strcasecmp() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

43
		if (Request::GetImpersonatedUser() && strcasecmp(Request::GetAuthUser(), /** @scrutinizer ignore-type */ Request::GetImpersonatedUser()) !== 0) {
Loading history...
Bug introduced by
It seems like Request::GetAuthUser() can also be of type boolean; however, parameter $string1 of strcasecmp() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

43
		if (Request::GetImpersonatedUser() && strcasecmp(/** @scrutinizer ignore-type */ Request::GetAuthUser(), Request::GetImpersonatedUser()) !== 0) {
Loading history...
44
			SLog::Write(LOGLEVEL_DEBUG, sprintf("RequestProcessor->Authenticate(): Impersonation active - authenticating: '%s' - impersonating '%s'", Request::GetAuthUser(), Request::GetImpersonatedUser()));
45
		}
46
47
		$backend = GSync::GetBackend();
48
		if ($backend->Logon(Request::GetAuthUser(), Request::GetAuthDomain(), Request::GetAuthPassword()) == false) {
49
			throw new AuthenticationRequiredException("Access denied. Username or password incorrect");
50
		}
51
52
		// mark this request as "authenticated"
53
		self::$userIsAuthenticated = true;
54
	}
55
56
	/**
57
	 * Indicates if the user was "authenticated".
58
	 *
59
	 * @return bool
60
	 */
61
	public static function isUserAuthenticated() {
62
		if (!isset(self::$userIsAuthenticated)) {
63
			return false;
64
		}
65
66
		return self::$userIsAuthenticated;
67
	}
68
69
	/**
70
	 * Initialize the RequestProcessor.
71
	 */
72
	public static function Initialize() {
73
		self::$backend = GSync::GetBackend();
74
		self::$deviceManager = GSync::GetDeviceManager(false);
75
		self::$topCollector = GSync::GetTopCollector();
76
77
		if (!GSync::CommandNeedsPlainInput(Request::GetCommandCode())) {
78
			self::$decoder = new WBXMLDecoder(Request::GetInputStream());
0 ignored issues
show
Bug introduced by
It seems like Request::GetInputStream() can also be of type boolean; however, parameter $input of WBXMLDecoder::__construct() does only seem to accept stream, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

78
			self::$decoder = new WBXMLDecoder(/** @scrutinizer ignore-type */ Request::GetInputStream());
Loading history...
79
		}
80
81
		self::$encoder = new WBXMLEncoder(Request::GetOutputStream(), Request::GetGETAcceptMultipart());
82
		self::$waitTime = 0;
83
	}
84
85
	/**
86
	 * Loads the command handler and processes a command sent from the mobile.
87
	 *
88
	 * @return bool
89
	 */
90
	public static function HandleRequest() {
91
		$handler = GSync::GetRequestHandlerForCommand(Request::GetCommandCode());
0 ignored issues
show
Bug introduced by
Request::GetCommandCode() of type boolean|string is incompatible with the type integer expected by parameter $commandCode of GSync::GetRequestHandlerForCommand(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

91
		$handler = GSync::GetRequestHandlerForCommand(/** @scrutinizer ignore-type */ Request::GetCommandCode());
Loading history...
92
93
		// if there is an error decoding wbxml, consume remaining data and include it in the WBXMLException
94
		try {
95
			if (!$handler->Handle(Request::GetCommandCode())) {
0 ignored issues
show
Bug introduced by
Request::GetCommandCode() of type boolean|string is incompatible with the type integer expected by parameter $commandCode of RequestProcessor::Handle(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

95
			if (!$handler->Handle(/** @scrutinizer ignore-type */ Request::GetCommandCode())) {
Loading history...
96
				throw new WBXMLException(sprintf("Unknown error in %s->Handle()", $handler::class));
97
			}
98
		}
99
		catch (Exception $ex) {
100
			// Log 10 KB of the WBXML data
101
			SLog::Write(LOGLEVEL_FATAL, "WBXML 10K debug data: " . Request::GetInputAsBase64(10240), false);
102
103
			throw $ex;
104
		}
105
106
		// also log WBXML in happy case
107
		if (SLog::IsWbxmlDebugEnabled()) {
108
			// Log 4 KB in the happy case
109
			SLog::Write(LOGLEVEL_WBXML, "WBXML-IN : " . Request::GetInputAsBase64(4096), false);
110
		}
111
112
		return true;
113
	}
114
115
	/**
116
	 * Returns any additional headers which should be sent to the mobile.
117
	 *
118
	 * @return array
119
	 */
120
	public static function GetSpecialHeaders() {
121
		if (!isset(self::$specialHeaders) || !is_array(self::$specialHeaders)) {
122
			return [];
123
		}
124
125
		return self::$specialHeaders;
126
	}
127
128
	/**
129
	 * Returns the amount of seconds RequestProcessor waited e.g. during Ping.
130
	 *
131
	 * @return int
132
	 */
133
	public static function GetWaitTime() {
134
		return self::$waitTime;
135
	}
136
137
	/**
138
	 * Handles a command.
139
	 *
140
	 * @param int $commandCode
141
	 *
142
	 * @return bool
143
	 */
144
	abstract public function Handle($commandCode);
145
}
146