Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix check with krb constrained delegation #111

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ jobs:
name: Psalm static analysis

strategy:
fail-fast: false
matrix:
php-version:
- "7.2"
Expand Down
81 changes: 50 additions & 31 deletions src/KerberosApacheAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,35 +31,65 @@ class KerberosApacheAuth extends KerberosAuth implements IAuth {
/** @var string */
private $ticketPath = "";

// only working with specific library (mod_auth_kerb, krb5, smbclient) versions
/** @var bool */
private $saveTicketInMemory = false;

/** @var bool */
private $init = false;

/** @var string|false */
private $ticketName;

public function __construct() {
$this->ticketName = getenv("KRB5CCNAME");
}


/**
* Copy the ticket to a temporary location and use that ticket for authentication
*
* @return void
*/
public function copyTicket(): void {
if (!$this->checkTicket()) {
return;
}
$krb5 = new \KRB5CCache();
$krb5->open($this->ticketName);
$tmpFilename = tempnam("/tmp", "krb5cc_php_");
$tmpCacheFile = "FILE:" . $tmpFilename;
$krb5->save($tmpCacheFile);
$this->ticketPath = $tmpFilename;
$this->ticketName = $tmpCacheFile;
}

/**
* @param bool $saveTicketInMemory
* Pass the ticket to smbclient by memory instead of path
*
* @return void
*/
public function __construct(bool $saveTicketInMemory = false) {
$this->saveTicketInMemory = $saveTicketInMemory;
public function passTicketFromMemory(): void {
if (!$this->checkTicket()) {
return;
}
$krb5 = new \KRB5CCache();
$krb5->open($this->ticketName);
$this->ticketName = (string)$krb5->getName();
}

/**
* Check if a valid kerberos ticket is present
*
* @return bool
* @psalm-assert-if-true string $this->ticketName
*/
public function checkTicket(): bool {
//read apache kerberos ticket cache
$cacheFile = getenv("KRB5CCNAME");
if (!$cacheFile) {
if (!$this->ticketName) {
return false;
}

$krb5 = new \KRB5CCache();
$krb5->open($cacheFile);
return (bool)$krb5->isValid();
$krb5->open($this->ticketName);
/** @psalm-suppress MixedArgument */
return count($krb5->getEntries()) > 0;
}

private function init(): void {
Expand All @@ -75,28 +105,13 @@ private function init(): void {
}

//read apache kerberos ticket cache
$cacheFile = getenv("KRB5CCNAME");
if (!$cacheFile) {
if (!$this->checkTicket()) {
throw new Exception('No kerberos ticket cache environment variable (KRB5CCNAME) found.');
}

$krb5 = new \KRB5CCache();
$krb5->open($cacheFile);
if (!$krb5->isValid()) {
throw new Exception('Kerberos ticket cache is not valid.');
}


if ($this->saveTicketInMemory) {
putenv("KRB5CCNAME=" . (string)$krb5->getName());
} else {
//workaround: smbclient is not working with the original apache ticket cache.
$tmpFilename = tempnam("/tmp", "krb5cc_php_");
$tmpCacheFile = "FILE:" . $tmpFilename;
$krb5->save($tmpCacheFile);
$this->ticketPath = $tmpFilename;
putenv("KRB5CCNAME=" . $tmpCacheFile);
}
// note that even if the ticketname is the value we got from `getenv("KRB5CCNAME")` we still need to set the env variable ourselves
// this is because `getenv` also reads the variables passed from the SAPI (apache-php) and we need to set the variable in the OS's env
putenv("KRB5CCNAME=" . $this->ticketName);
}

public function getExtraCommandLineArguments(): string {
Expand All @@ -106,7 +121,11 @@ public function getExtraCommandLineArguments(): string {

public function setExtraSmbClientOptions($smbClientState): void {
$this->init();
parent::setExtraSmbClientOptions($smbClientState);
try {
parent::setExtraSmbClientOptions($smbClientState);
} catch (Exception $e) {
// suppress
}
}

public function __destruct() {
Expand Down