Skip to content

Commit ff18f8b

Browse files
committed
also support saving the kerberos tickets in database
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent 8d53723 commit ff18f8b

File tree

7 files changed

+158
-11
lines changed

7 files changed

+158
-11
lines changed

.github/workflows/smb-kerberos.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,47 @@ jobs:
100100
FILEPATH=$(docker exec --user 33 apache ./occ log:file | grep "Log file:" | cut -d' ' -f3)
101101
echo "$FILEPATH:"
102102
docker exec --user 33 apache cat $FILEPATH
103+
104+
smb-kerberos-database-tests:
105+
runs-on: ubuntu-latest
106+
107+
if: ${{ github.repository_owner != 'nextcloud-gmbh' }}
108+
109+
name: smb-kerberos-sso
110+
111+
steps:
112+
- name: Checkout server
113+
uses: actions/checkout@v3
114+
with:
115+
submodules: true
116+
- name: Checkout user_saml
117+
uses: actions/checkout@v3
118+
with:
119+
repository: nextcloud/user_saml
120+
path: apps/user_saml
121+
ref: event-dispatcher
122+
- name: Pull images
123+
run: |
124+
docker pull ghcr.io/icewind1991/samba-krb-test-dc
125+
docker pull ghcr.io/icewind1991/samba-krb-test-apache
126+
docker pull ghcr.io/icewind1991/samba-krb-test-client
127+
docker tag ghcr.io/icewind1991/samba-krb-test-dc icewind1991/samba-krb-test-dc
128+
docker tag ghcr.io/icewind1991/samba-krb-test-apache icewind1991/samba-krb-test-apache
129+
docker tag ghcr.io/icewind1991/samba-krb-test-client icewind1991/samba-krb-test-client
130+
- name: Setup AD-DC
131+
run: |
132+
DC_IP=$(apps/files_external/tests/sso-setup/start-dc.sh)
133+
apps/files_external/tests/sso-setup/start-apache.sh $DC_IP $PWD -v $PWD/apps/files_external/tests/sso-setup/apache-session.conf:/etc/apache2/sites-enabled/000-default.conf
134+
echo "DC_IP=$DC_IP" >> $GITHUB_ENV
135+
- name: Set up Nextcloud
136+
run: |
137+
apps/files_external/tests/sso-setup/setup-sso-nc.sh smb::kerberos_sso_database
138+
- name: Test SSO
139+
run: |
140+
apps/files_external/tests/sso-setup/test-sso-smb-session.sh ${{ env.DC_IP }}
141+
- name: Show logs
142+
if: failure()
143+
run: |
144+
FILEPATH=$(docker exec --user 33 apache ./occ log:file | grep "Log file:" | cut -d' ' -f3)
145+
echo "$FILEPATH:"
146+
docker exec --user 33 apache cat $FILEPATH

3rdparty

Submodule 3rdparty updated 3582 files

apps/files_external/composer/composer/autoload_classmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
'OCA\\Files_External\\Lib\\Auth\\PublicKey\\RSAPrivateKey' => $baseDir . '/../lib/Lib/Auth/PublicKey/RSAPrivateKey.php',
5555
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosApacheAuth' => $baseDir . '/../lib/Lib/Auth/SMB/KerberosApacheAuth.php',
5656
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosAuth' => $baseDir . '/../lib/Lib/Auth/SMB/KerberosAuth.php',
57+
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosSsoDatabase' => $baseDir . '/../lib/Lib/Auth/SMB/KerberosSsoDatabase.php',
5758
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosSsoSession' => $baseDir . '/../lib/Lib/Auth/SMB/KerberosSsoSession.php',
5859
'OCA\\Files_External\\Lib\\Backend\\AmazonS3' => $baseDir . '/../lib/Lib/Backend/AmazonS3.php',
5960
'OCA\\Files_External\\Lib\\Backend\\Backend' => $baseDir . '/../lib/Lib/Backend/Backend.php',

apps/files_external/composer/composer/autoload_static.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class ComposerStaticInitFiles_External
6969
'OCA\\Files_External\\Lib\\Auth\\PublicKey\\RSAPrivateKey' => __DIR__ . '/..' . '/../lib/Lib/Auth/PublicKey/RSAPrivateKey.php',
7070
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosApacheAuth' => __DIR__ . '/..' . '/../lib/Lib/Auth/SMB/KerberosApacheAuth.php',
7171
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosAuth' => __DIR__ . '/..' . '/../lib/Lib/Auth/SMB/KerberosAuth.php',
72+
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosSsoDatabase' => __DIR__ . '/..' . '/../lib/Lib/Auth/SMB/KerberosSsoDatabase.php',
7273
'OCA\\Files_External\\Lib\\Auth\\SMB\\KerberosSsoSession' => __DIR__ . '/..' . '/../lib/Lib/Auth/SMB/KerberosSsoSession.php',
7374
'OCA\\Files_External\\Lib\\Backend\\AmazonS3' => __DIR__ . '/..' . '/../lib/Lib/Backend/AmazonS3.php',
7475
'OCA\\Files_External\\Lib\\Backend\\Backend' => __DIR__ . '/..' . '/../lib/Lib/Backend/Backend.php',
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
5+
*
6+
* @author Robin Appelman <robin@icewind.nl>
7+
*
8+
* @license GNU AGPL version 3 or any later version
9+
*
10+
* This program is free software: you can redistribute it and/or modify
11+
* it under the terms of the GNU Affero General Public License as
12+
* published by the Free Software Foundation, either version 3 of the
13+
* License, or (at your option) any later version.
14+
*
15+
* This program is distributed in the hope that it will be useful,
16+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
* GNU Affero General Public License for more details.
19+
*
20+
* You should have received a copy of the GNU Affero General Public License
21+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
22+
*
23+
*/
24+
25+
namespace OCA\Files_External\Lib\Auth\SMB;
26+
27+
use Icewind\SMB\KerberosTicket;
28+
use OCA\Files_External\Lib\Auth\AuthMechanism;
29+
use OCA\Files_External\Lib\DefinitionParameter;
30+
use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
31+
use OCP\IL10N;
32+
use OCP\ISession;
33+
use OCP\IUser;
34+
use OCP\Security\ICredentialsManager;
35+
36+
class KerberosSsoDatabase extends AuthMechanism {
37+
private ICredentialsManager $credentialsManager;
38+
39+
public function __construct(IL10N $l, ICredentialsManager $credentialsManager) {
40+
$realm = new DefinitionParameter('default_realm', 'Default realm');
41+
$realm
42+
->setType(DefinitionParameter::VALUE_TEXT)
43+
->setFlag(DefinitionParameter::FLAG_OPTIONAL)
44+
->setTooltip($l->t('Kerberos default realm, defaults to "WORKGROUP"'));
45+
$this
46+
->setIdentifier('smb::kerberos_sso_database')
47+
->setScheme(self::SCHEME_SMB)
48+
->setText($l->t('Kerberos ticket SSO, save in database'))
49+
->addParameter($realm);
50+
$this->credentialsManager = $credentialsManager;
51+
}
52+
53+
public function getTicket(?IUser $user): KerberosTicket {
54+
if (!isset($user)) {
55+
throw new InsufficientDataForMeaningfulAnswerException('No kerberos ticket saved');
56+
}
57+
try {
58+
$envTicket = KerberosTicket::fromEnv();
59+
} catch (\Exception $e) {
60+
$envTicket = null;
61+
}
62+
if ($envTicket) {
63+
$this->credentialsManager->store($user->getUID(), 'kerberos_ticket', base64_encode($envTicket->save()));
64+
return $envTicket;
65+
}
66+
67+
$savedTicket = $this->credentialsManager->retrieve($user->getUID(), 'kerberos_ticket');
68+
if (!$savedTicket) {
69+
throw new InsufficientDataForMeaningfulAnswerException('No kerberos ticket saved');
70+
}
71+
return KerberosTicket::load(base64_decode($savedTicket));
72+
}
73+
}

apps/files_external/lib/Lib/Backend/SMB.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
use OCA\Files_External\Lib\Auth\AuthMechanism;
3535
use OCA\Files_External\Lib\Auth\Password\Password;
3636
use OCA\Files_External\Lib\Auth\SMB\KerberosApacheAuth as KerberosApacheAuthMechanism;
37+
use OCA\Files_External\Lib\Auth\SMB\KerberosSsoDatabase;
3738
use OCA\Files_External\Lib\Auth\SMB\KerberosSsoSession;
3839
use OCA\Files_External\Lib\DefinitionParameter;
3940
use OCA\Files_External\Lib\InsufficientDataForMeaningfulAnswerException;
@@ -91,6 +92,13 @@ public function manipulateStorageConfig(StorageConfig &$storage, IUser $user = n
9192
case 'smb::kerberos':
9293
$smbAuth = new KerberosAuth();
9394
break;
95+
case 'smb::kerberos_sso_database':
96+
if (!$auth instanceof KerberosSsoDatabase) {
97+
throw new \InvalidArgumentException('invalid authentication backend');
98+
}
99+
$smbAuth = new KerberosAuth();
100+
$smbAuth->setTicket($auth->getTicket($user));
101+
break;
94102
case 'smb::kerberos_sso_session':
95103
if (!$auth instanceof KerberosSsoSession) {
96104
throw new \InvalidArgumentException('invalid authentication backend');

apps/files_external/lib/Lib/TicketSaveMiddleware.php

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,47 +25,67 @@
2525

2626
use Icewind\SMB\KerberosTicket;
2727
use OCA\Files_External\Controller\UserGlobalStoragesController;
28+
use OCA\Files_External\Lib\Auth\SMB\KerberosSsoDatabase;
2829
use OCA\Files_External\Lib\Auth\SMB\KerberosSsoSession;
2930
use OCA\Files_External\Service\UserGlobalStoragesService;
3031
use OCP\AppFramework\Http\Response;
3132
use OCP\AppFramework\Middleware;
3233
use OCP\ISession;
34+
use OCP\IUser;
3335
use OCP\IUserSession;
36+
use OCP\Security\ICredentialsManager;
3437

3538
class TicketSaveMiddleware extends Middleware {
39+
const SAVE_SESSION = 1;
40+
const SAVE_DB = 2;
41+
3642
private ISession $session;
3743
private IUserSession $userSession;
3844
private UserGlobalStoragesService $storagesService;
45+
private ICredentialsManager $credentialsManager;
3946

4047
public function __construct(
4148
ISession $session,
49+
ICredentialsManager $credentialsManager,
4250
IUserSession $userSession,
4351
UserGlobalStoragesService $storagesService
4452
) {
4553
$this->session = $session;
54+
$this->credentialsManager = $credentialsManager;
4655
$this->userSession = $userSession;
4756
$this->storagesService = $storagesService;
4857
}
4958

5059
public function afterController($controller, $methodName, Response $response) {
60+
$user = $this->userSession->getUser();
61+
if (!$user) {
62+
return $response;
63+
}
5164
$ticket = KerberosTicket::fromEnv();
52-
if ($ticket && $ticket->isValid() && $this->needToSaveTicket()) {
53-
$this->session->set('kerberos_ticket', base64_encode($ticket->save()));
65+
if ($ticket && $ticket->isValid()) {
66+
$save = $this->needToSaveTicket($user);
67+
if ($save & self::SAVE_SESSION) {
68+
$this->session->set('kerberos_ticket', base64_encode($ticket->save()));
69+
}
70+
if ($save & self::SAVE_DB) {
71+
$this->credentialsManager->store($user->getUID(), 'kerberos_ticket', base64_encode($ticket->save()));
72+
}
5473
}
5574
return $response;
5675
}
5776

58-
private function needToSaveTicket(): bool {
59-
$user = $this->userSession->getUser();
60-
if (!$user) {
61-
return false;
62-
}
77+
private function needToSaveTicket(IUser $user): int {
78+
$save = 0;
6379
$storages = $this->storagesService->getAllStoragesForUser($user);
6480
foreach ($storages as $storage) {
65-
if ($storage->getAuthMechanism() instanceof KerberosSsoSession) {
66-
return true;
81+
$auth = $storage->getAuthMechanism();
82+
if ($auth instanceof KerberosSsoSession) {
83+
$save = $save | self::SAVE_SESSION;
84+
}
85+
if ($auth instanceof KerberosSsoDatabase) {
86+
$save = $save | self::SAVE_DB;
6787
}
6888
}
69-
return false;
89+
return $save;
7090
}
7191
}

0 commit comments

Comments
 (0)