Completed
Pull Request — master (#2198)
by Thomas
06:00
created

OC_User_SMB::checkPassword()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 3
nop 2
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright (c) 2012 Robin Appelman <[email protected]>
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later.
6
 * See the COPYING-README file.
7
 */
8
9
/**
10
 * User authentication via samba (smbclient)
11
 *
12
 * @category Apps
13
 * @package  UserExternal
14
 * @author   Robin Appelman <[email protected]>
15
 * @license  http://www.gnu.org/licenses/agpl AGPL
16
 * @link     http://github.com/owncloud/apps
17
 */
18
class OC_User_SMB extends \OCA\user_external\Base{
19
	private $host;
20
21
	const SMBCLIENT = 'smbclient -L';
22
	const LOGINERROR = 'NT_STATUS_LOGON_FAILURE';
23
24
	/**
25
	 * Create new samba authentication provider
26
	 *
27
	 * @param string $host Hostname or IP of windows machine
28
	 */
29
	public function __construct($host) {
30
		parent::__construct($host);
31
		$this->host=$host;
32
	}
33
34
	/**
35
	 * @param string $uid
36
	 * @param string $password
37
	 * @return bool
38
	 */
39
	private function tryAuthentication($uid, $password) {
40
		$uidEscaped = escapeshellarg($uid);
41
		$password = escapeshellarg($password);
42
		$command = self::SMBCLIENT.' '.escapeshellarg('//' . $this->host . '/dummy').' -U'.$uidEscaped.'%'.$password;
43
		$lastline = exec($command, $output, $retval);
44
		if ($retval === 127) {
45
			OCP\Util::writeLog(
46
				'user_external', 'ERROR: smbclient executable missing',
47
				OCP\Util::ERROR
48
			);
49
			return false;
50
		} else if (strpos($lastline, self::LOGINERROR) !== false) {
51
			//normal login error
52
			return false;
53
		} else if (strpos($lastline, 'NT_STATUS_BAD_NETWORK_NAME') !== false) {
54
			//login on minor error
55
			goto login;
56
		} else if ($retval != 0) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $retval of type integer|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
57
			//some other error
58
			OCP\Util::writeLog(
59
				'user_external', 'ERROR: smbclient error: ' . trim($lastline),
60
				OCP\Util::ERROR
61
			);
62
			return false;
63
		} else {
64
			login:
65
			return $uid;
66
		}
67
	}
68
69
	/**
70
	 * Check if the password is correct without logging in the user
71
	 *
72
	 * @param string $uid      The username
73
	 * @param string $password The password
74
	 *
75
	 * @return true/false
0 ignored issues
show
Documentation introduced by
The doc-type true/false could not be parsed: Unknown type name "true/false" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
76
	 */
77
	public function checkPassword($uid, $password) {
78
		// Check with an invalid password, if the user authenticates then fail
79
		$attemptWithInvalidPassword = $this->tryAuthentication($uid, base64_encode($password));
80
		if(is_string($attemptWithInvalidPassword)) {
81
			return false;
82
		}
83
84
		// Check with valid password
85
		$attemptWithValidPassword = $this->tryAuthentication($uid, $password);
86
		if(is_string($attemptWithValidPassword)) {
87
			$this->storeUser($uid);
88
			return $uid;
89
		}
90
91
		return false;
92
	}
93
}
94
95