Skip to content

Commit 12432c3

Browse files
committed
feat: add resolveUid method to IdentifyMethodService
Add method to resolve user identifiers from certificate chain data, supporting multiple fallback strategies and email-to-account resolution. Signed-off-by: Vitor Mattos <[email protected]>
1 parent b31841c commit 12432c3

1 file changed

Lines changed: 66 additions & 0 deletions

File tree

lib/Service/IdentifyMethodService.php

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use OCA\Libresign\Service\IdentifyMethod\Xmpp;
2323
use OCP\IConfig;
2424
use OCP\IL10N;
25+
use OCP\IUserManager;
2526

2627
class IdentifyMethodService {
2728
public const IDENTIFY_ACCOUNT = 'account';
@@ -56,6 +57,7 @@ public function __construct(
5657
private IConfig $config,
5758
private IdentifyMethodMapper $identifyMethodMapper,
5859
private IL10N $l10n,
60+
private IUserManager $userManager,
5961
private Account $account,
6062
private Email $email,
6163
private Signal $signal,
@@ -283,4 +285,68 @@ public function getIdentifyMethodsSettings(): array {
283285
}
284286
return $this->identifyMethodsSettings;
285287
}
288+
289+
/**
290+
* Resolve UID from certificate chain data
291+
*
292+
* Extracts and resolves the identifier from certificate subject or extensions.
293+
* Supports fallbacks for older LibreSign versions and converts to standard
294+
* identifier format (account:uid or email:value).
295+
*
296+
* @param array $chainArr Certificate chain array with subject and extensions
297+
* @param string $host Host domain for email matching
298+
* @return string|null Resolved identifier in format "type:value" or null
299+
*/
300+
public function resolveUid(array $chainArr, string $host): ?string {
301+
if (!empty($chainArr['subject']['UID'])) {
302+
return $chainArr['subject']['UID'];
303+
}
304+
if (!empty($chainArr['subject']['CN'])) {
305+
$cn = $chainArr['subject']['CN'];
306+
if (is_array($cn)) {
307+
$cn = $cn[0];
308+
}
309+
if (preg_match('/^(?<key>.*):(?<value>.*), /', (string)$cn, $matches)) {
310+
return $matches['key'] . ':' . $matches['value'];
311+
}
312+
}
313+
if (!empty($chainArr['extensions']['subjectAltName'])) {
314+
$subjectAltName = $chainArr['extensions']['subjectAltName'];
315+
if (is_array($subjectAltName)) {
316+
$subjectAltName = $subjectAltName[0];
317+
}
318+
preg_match('/^(?<key>(email|account)):(?<value>.*)$/', (string)$subjectAltName, $matches);
319+
if ($matches) {
320+
if (str_ends_with($matches['value'], $host)) {
321+
$uid = str_replace('@' . $host, '', $matches['value']);
322+
$userFound = $this->userManager->get($uid);
323+
if ($userFound) {
324+
return 'account:' . $uid;
325+
} else {
326+
$userFound = $this->userManager->getByEmail($matches['value']);
327+
if ($userFound) {
328+
$userFound = current($userFound);
329+
return 'account:' . $userFound->getUID();
330+
} else {
331+
return 'email:' . $matches['value'];
332+
}
333+
}
334+
} else {
335+
$userFound = $this->userManager->getByEmail($matches['value']);
336+
if ($userFound) {
337+
$userFound = current($userFound);
338+
return 'account:' . $userFound->getUID();
339+
} else {
340+
$userFound = $this->userManager->get($matches['value']);
341+
if ($userFound) {
342+
return 'account:' . $userFound->getUID();
343+
} else {
344+
return $matches['key'] . ':' . $matches['value'];
345+
}
346+
}
347+
}
348+
}
349+
}
350+
return null;
351+
}
286352
}

0 commit comments

Comments
 (0)