Skip to content

Commit 7c05a7d

Browse files
authored
Merge pull request #45 from NottingHack/kerberosAuth
Implement Kerberos Auth methods and rename IdentityManager to Passwor…
2 parents c9fb267 + 0f59fc7 commit 7c05a7d

File tree

13 files changed

+249
-96
lines changed

13 files changed

+249
-96
lines changed
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44

55
use Illuminate\Support\Facades\Storage;
66

7-
class FileBasedIdentityManager implements IdentityManager
7+
class FileBasedPasswordStore implements PasswordStore
88
{
99
protected $usersFile;
1010
protected $users;
1111

1212
/**
13-
* FileBasedUserManager constructor.
13+
* FileBasedPasswordStore constructor.
1414
*/
15-
public function __construct($usersFile = 'users.json')
15+
public function __construct($app)
1616
{
17-
$this->usersFile = $usersFile;
17+
$config = $app['config']->get('passwordstore.filebased', []);
18+
$this->usersFile = $config['name'];
1819

1920
if (Storage::has($this->usersFile)) {
2021
$this->users = json_decode(Storage::get($this->usersFile), true);

app/HMS/Auth/HmsUserProvider.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212
*/
1313
class HmsUserProvider extends DoctrineUserProvider
1414
{
15-
/** @var IdentityManager */
16-
protected $identityManager;
15+
/** @var PasswordStore */
16+
protected $passwordStore;
1717

18-
public function __construct(Hasher $hasher, EntityManagerInterface $em, $entity, IdentityManager $identityManager)
18+
public function __construct(Hasher $hasher, EntityManagerInterface $em, $entity, PasswordStore $passwordStore)
1919
{
2020
// Note: $hasher is never used but required to construct DoctrineUserProvider (parent)
2121
parent::__construct($hasher, $em, $entity);
2222

23-
$this->identityManager = $identityManager;
23+
$this->passwordStore = $passwordStore;
2424
}
2525

2626
// overridden because getAuthIdentifier() on our User returns username rather than id
@@ -29,9 +29,9 @@ public function retrieveById($identifier)
2929
return $this->getRepository()->findOneBy(['username' => $identifier]);
3030
}
3131

32-
// overridden because we don't store the password on the user, we use an IdentityManager to check it instead
32+
// overridden because we don't store the password on the user, we use an PasswordStore to check it instead
3333
public function validateCredentials(IlluminateAuthenticatable $user, array $credentials)
3434
{
35-
return $this->identityManager->checkPassword($user->getAuthIdentifier(), $credentials['password']);
35+
return $this->passwordStore->checkPassword($user->getAuthIdentifier(), $credentials['password']);
3636
}
3737
}

app/HMS/Auth/KerberosIdentityManager.php

Lines changed: 0 additions & 64 deletions
This file was deleted.
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
<?php
2+
3+
namespace HMS\Auth;
4+
5+
6+
class KerberosPasswordStore implements PasswordStore
7+
{
8+
9+
/**
10+
* The KADM5 connection to use.
11+
* @var KADM5.
12+
*/
13+
private $__krbConn;
14+
15+
/**
16+
* The relm to use.
17+
* @var string
18+
*/
19+
private $__realm;
20+
21+
/**
22+
* If true, we're in debug mode and shouldn't actually take any action.
23+
* @var bool
24+
*/
25+
private $__debug;
26+
27+
/**
28+
* Constructor.
29+
*
30+
*/
31+
public function __construct($app)
32+
{
33+
$config = $app['config']->get('passwordstore.kerberos', []);
34+
35+
$this->__debug = $config['debug'];
36+
$this->__realm = $config['realm'];
37+
$this->__krbConn = new \KADM5($config['username'], $config['keytab'], true); // use keytab=true
38+
}
39+
40+
/**
41+
* Add a new identity with the specified username and password.
42+
*
43+
* @param string $username
44+
* @param string $password
45+
* @return void
46+
*/
47+
public function add($username, $password)
48+
{
49+
/* Just incase some smartarse appends /admin to their handle
50+
* in an attempt to become a krb admin... */
51+
if (stristr($username, '/admin') === false) {
52+
try {
53+
$princ = new \KADM5Principal(strtolower($username));
54+
$this->__krbConn->createPrincipal($princ, $password);
55+
} catch (\Exception $e) {
56+
if ($this->__debug) {
57+
echo "$e\n";
58+
}
59+
return false;
60+
}
61+
return true;
62+
} else {
63+
if ($this->__debug) {
64+
echo "Attempt to create admin user stopped.";
65+
}
66+
return false;
67+
}
68+
}
69+
70+
/**
71+
* Remove the specified identity.
72+
*
73+
* @param string $username
74+
* @return void
75+
*/
76+
public function remove($username)
77+
{
78+
try {
79+
$princ = $this->__krbConn->getPrincipal(strtolower($username));
80+
$princ->delete();
81+
} catch (\Exception $e) {
82+
if ($this->__debug) {
83+
echo "$e\n";
84+
}
85+
return false;
86+
}
87+
return true;
88+
}
89+
90+
/**
91+
* Check if a specified identity exists.
92+
*
93+
* @param string $username
94+
* @return boolean
95+
*/
96+
public function exists($username)
97+
{
98+
try {
99+
$this->__krbConn->getPrincipal(strtolower($username));
100+
} catch (\Exception $e) {
101+
if ($e->getMessage() == "Principal does not exist") {
102+
return false;
103+
} else {
104+
return null;
105+
}
106+
}
107+
return true;
108+
}
109+
110+
/**
111+
* Set the password for a specified identity.
112+
*
113+
* @param string $username
114+
* @param string $password
115+
* @return void
116+
*/
117+
public function setPassword($username, $password)
118+
{
119+
try {
120+
$princ = $this->__krbConn->getPrincipal(strtolower($username));
121+
$princ->changePassword($newpassword);
122+
} catch (\Exception $e) {
123+
if ($this->__debug) {
124+
echo "$e\n";
125+
}
126+
return false;
127+
}
128+
return true;
129+
}
130+
131+
/**
132+
* Check the password for a specified identity is correct.
133+
*
134+
* @param string $username
135+
* @param string $password
136+
* @return boolean
137+
*/
138+
public function checkPassword($username, $password)
139+
{
140+
$ticket = new \KRB5CCache();
141+
try {
142+
$ticket->initPassword(strtolower($username) . "@" . $this->__realm, $password);
143+
} catch (\Exception $e) {
144+
if ($this->__debug) {
145+
echo "$e\n";
146+
}
147+
return false;
148+
}
149+
return true;
150+
}
151+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
namespace HMS\Auth;
44

55
/**
6-
* An IdentityManager specifies operations for adding, removing and checking the credentials of an identity.
6+
* An PasswordStore specifies operations for adding, removing and checking the credentials of a users identity.
77
*
88
* @author Rob Hunt <rob.hunt@nottinghack.org.uk>
99
*/
10-
interface IdentityManager
10+
interface PasswordStore
1111
{
1212
/**
1313
* Add a new identity with the specified username and password.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace HMS\Auth;
4+
5+
use HMS\Auth\FileBassedPasswordStore;
6+
use HMS\Auth\KerberosPasswordStore;
7+
use Illuminate\Support\Manager;
8+
9+
class PasswordStoreManager extends Manager
10+
{
11+
12+
/**
13+
* Create an instance of the Kerberos driver
14+
*
15+
* @return KerberosPasswordStore
16+
*/
17+
protected function createKerberosDriver()
18+
{
19+
return new KerberosPasswordStore($this->app);
20+
}
21+
22+
/**
23+
* Create an instance of the FileBased driver
24+
*
25+
* @return FileBasedPasswordStore
26+
*/
27+
protected function createFileBasedDriver()
28+
{
29+
return new FileBasedPasswordStore($this->app);
30+
}
31+
32+
/**
33+
* Get the default driver
34+
*
35+
* @return string
36+
*/
37+
public function getDefaultDriver()
38+
{
39+
return $this->app['config']['passwordstore.driver'];
40+
}
41+
}

app/Http/Controllers/Auth/RegisterController.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace App\Http\Controllers\Auth;
44

5-
use HMS\Auth\IdentityManager;
5+
use HMS\Auth\PasswordStore;
66
use HMS\Entities\Role;
77
use HMS\Entities\User;
88

@@ -36,18 +36,18 @@ class RegisterController extends Controller
3636

3737
protected $userRepository;
3838
protected $roleRepository;
39-
protected $identityManager;
39+
protected $passwordStore;
4040

4141
/**
4242
* Create a new controller instance.
4343
*
4444
* @return void
4545
*/
46-
public function __construct(UserRepository $userRepository, RoleRepository $roleRepository, IdentityManager $identityManager)
46+
public function __construct(UserRepository $userRepository, RoleRepository $roleRepository, PasswordStore $passwordStore)
4747
{
4848
$this->userRepository = $userRepository;
4949
$this->roleRepository = $roleRepository;
50-
$this->identityManager = $identityManager;
50+
$this->passwordStore = $passwordStore;
5151
$this->middleware('guest');
5252
}
5353

@@ -85,7 +85,7 @@ protected function create(array $data)
8585

8686
// TODO: maybe consolidate these into a single call via a service?
8787
$this->userRepository->create($user);
88-
$this->identityManager->add($user->getUsername(), $data['password']);
88+
$this->passwordStore->add($user->getUsername(), $data['password']);
8989

9090
return $user;
9191
}

0 commit comments

Comments
 (0)