mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-17 01:54:49 +00:00
System: Trust: Certificates - work in progress for https://github.com/opnsense/core/issues/7248
* add certificate purpose according to rfc3280 * add info button for raw (readable) certificate and csr output
This commit is contained in:
parent
dbd80f33f5
commit
875fb5d8b3
@ -141,7 +141,9 @@ class CertController extends ApiMutableModelControllerBase
|
||||
$filter_funct = function ($record) use ($carefs) {
|
||||
return empty($carefs) || array_intersect(explode(',', $record->caref), $carefs);
|
||||
};
|
||||
return $this->searchBase('cert', ['descr', 'caref', 'name', 'valid_from', 'valid_to'], null, $filter_funct);
|
||||
return $this->searchBase(
|
||||
'cert', ['descr', 'caref', 'rfc3280_purpose', 'name', 'valid_from', 'valid_to'], null, $filter_funct
|
||||
);
|
||||
}
|
||||
|
||||
public function getAction($uuid = null)
|
||||
@ -179,6 +181,19 @@ class CertController extends ApiMutableModelControllerBase
|
||||
return [];
|
||||
}
|
||||
|
||||
public function rawDumpAction($uuid)
|
||||
{
|
||||
$payload = $this->getBase('cert', 'cert', $uuid);
|
||||
if (!empty($payload['cert'])) {
|
||||
if (!empty($payload['cert']['crt_payload'])) {
|
||||
return CertStore::dumpX509($payload['cert']['crt_payload']);
|
||||
} elseif (!empty($payload['cert']['csr_payload'])) {
|
||||
return CertStore::dumpCSR($payload['cert']['csr_payload']);
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public function caListAction()
|
||||
{
|
||||
$result = [];
|
||||
|
||||
@ -446,11 +446,97 @@ class Store
|
||||
$result[$target] = implode('\n', $values);
|
||||
}
|
||||
}
|
||||
|
||||
/* Extract certificate purpose */
|
||||
$purpose = [];
|
||||
foreach (['basicConstraints', 'extendedKeyUsage', 'keyUsage', 'authorityInfoAccess'] as $ext) {
|
||||
$purpose[$ext] = [];
|
||||
if (!empty($crt['extensions'][$ext])) {
|
||||
foreach (explode(",", $crt['extensions'][$ext]) as $item) {
|
||||
$purpose[$ext][] = trim($item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rfc3280 purpose definitions
|
||||
$result['rfc3280_purpose'] = '';
|
||||
if (
|
||||
in_array('TLS Web Server Authentication', $purpose['extendedKeyUsage']) &&
|
||||
in_array('Digital Signature', $purpose['keyUsage']) && (
|
||||
in_array('Key Encipherment', $purpose['keyUsage']) ||
|
||||
in_array('Key Agreement', $purpose['keyUsage'])
|
||||
)
|
||||
) {
|
||||
$result['rfc3280_purpose'] = 'id-kp-serverAuth';
|
||||
} elseif (
|
||||
in_array('TLS Web Client Authentication', $purpose['extendedKeyUsage']) &&
|
||||
in_array('Digital Signature', $purpose['keyUsage'])
|
||||
) {
|
||||
$result['rfc3280_purpose'] = 'id-kp-clientAuth';
|
||||
} elseif (
|
||||
in_array('OCSP Signing', $purpose['extendedKeyUsage']) &&
|
||||
in_array('Digital Signature', $purpose['keyUsage'])
|
||||
) {
|
||||
$result['rfc3280_purpose'] = 'id-kp-OCSPSigning';
|
||||
}
|
||||
//
|
||||
return $result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cert certificate
|
||||
* @return array [stdout|stderr]
|
||||
*/
|
||||
public static function dumpX509($cert)
|
||||
{
|
||||
$result = [];
|
||||
$process = proc_open(
|
||||
'/usr/local/bin/openssl x509 -fingerprint -sha256 -text',
|
||||
[["pipe", "r"], ["pipe", "w"], ["pipe", "w"]],
|
||||
$pipes
|
||||
);
|
||||
if (is_resource($process)) {
|
||||
fwrite($pipes[0], $cert);
|
||||
fclose($pipes[0]);
|
||||
$result['stdout'] = stream_get_contents($pipes[1]);
|
||||
fclose($pipes[1]);
|
||||
$result['stderr'] = stream_get_contents($pipes[2]);
|
||||
fclose($pipes[2]);
|
||||
proc_close($process);
|
||||
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $csr CSR
|
||||
* @return array [stdout|stderr]
|
||||
*/
|
||||
public static function dumpCSR($csr)
|
||||
{
|
||||
$result = [];
|
||||
$process = proc_open(
|
||||
'/usr/local/bin/openssl req -text -noout',
|
||||
[["pipe", "r"], ["pipe", "w"], ["pipe", "w"]],
|
||||
$pipes
|
||||
);
|
||||
if (is_resource($process)) {
|
||||
fwrite($pipes[0], $csr);
|
||||
fclose($pipes[0]);
|
||||
$result['stdout'] = stream_get_contents($pipes[1]);
|
||||
fclose($pipes[1]);
|
||||
$result['stderr'] = stream_get_contents($pipes[2]);
|
||||
fclose($pipes[2]);
|
||||
proc_close($process);
|
||||
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Extract certificate chain
|
||||
* @param string $caref reference number
|
||||
|
||||
@ -111,6 +111,7 @@
|
||||
<crt_payload type="TextField" volatile="true"/>
|
||||
<csr_payload type="TextField" volatile="true"/>
|
||||
<prv_payload type="TextField" volatile="true"/>
|
||||
<rfc3280_purpose type="TextField" volatile="true"/>
|
||||
|
||||
<name type="TextField" volatile="true"/>
|
||||
<valid_from type="TextField" volatile="true"/>
|
||||
|
||||
@ -41,6 +41,26 @@
|
||||
}
|
||||
return request;
|
||||
}
|
||||
},
|
||||
commands: {
|
||||
raw_dump: {
|
||||
method: function(event){
|
||||
let uuid = $(this).data("row-id") !== undefined ? $(this).data("row-id") : '';
|
||||
ajaxGet('/api/trust/cert/raw_dump/' + uuid, {}, function(data, status){
|
||||
if (data.stdout) {
|
||||
BootstrapDialog.show({
|
||||
title: "{{ lang._('Certificate info') }}",
|
||||
type:BootstrapDialog.TYPE_INFO,
|
||||
message: $("<div/>").text(data.stdout).html(),
|
||||
cssClass: 'monospace-dialog',
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
classname: 'fa fa-fw fa-info-circle',
|
||||
title: "{{ lang._('show certificate info') }}",
|
||||
sequence: 10
|
||||
}
|
||||
}
|
||||
});
|
||||
grid_cert.on("loaded.rs.jquery.bootgrid", function (e){
|
||||
@ -126,13 +146,26 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.monospace-dialog {
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.monospace-dialog > .modal-dialog {
|
||||
width:70% !important;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
max-height: calc(100vh - 210px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li class="active"><a data-toggle="tab" href="#cert">{{ lang._('Certificates') }}</a></li>
|
||||
</ul>
|
||||
@ -151,10 +184,11 @@
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="descr" data-width="15em" data-type="string">{{ lang._('Description') }}</th>
|
||||
<th data-column-id="caref" data-width="15em" data-type="string">{{ lang._('Issuer') }}</th>
|
||||
<th data-column-id="rfc3280_purpose" data-width="10em" data-type="string">{{ lang._('Purpose') }}</th>
|
||||
<th data-column-id="name" data-type="string">{{ lang._('Name') }}</th>
|
||||
<th data-column-id="valid_from" data-width="10em" data-type="datetime">{{ lang._('Valid from') }}</th>
|
||||
<th data-column-id="valid_to" data-width="10em" data-type="datetime">{{ lang._('Valid to') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
<th data-column-id="commands" data-width="9em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user