mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-15 00:54:41 +00:00
System: Trust: Authorities - finish crl fetch script for installed certificates and hook into form and cron updates.
According to rfc5280 an CRL update should be issued before "next update", but does not seem to define a validity. Various sources seem to indicate updates should be fetched at least every couple of hours, in which case an hourly update sounds reasonable. To avoid excessive writes, we compare each CRL offered with the last one received before flushing it to disk and keep track of actual changes. When nothing changes, no rehash is neede, which the configd action takes care of. Distribution points could either be HTTP or LDAP, LDAPS and HTTPS may not be used according to the RFC (CAs SHOULD NOT include URIs that specify https, ldaps, or similar schemes in extensions.)
This commit is contained in:
parent
6f79579537
commit
b709232e44
@ -344,6 +344,10 @@ function core_cron()
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty((string)(new OPNsense\Trust\General())->fetch_crls)) {
|
||||
$jobs[]['autocron'] = array('/usr/local/sbin/configctl -d system trust download_crls', '1');
|
||||
}
|
||||
|
||||
return $jobs;
|
||||
}
|
||||
|
||||
|
||||
@ -44,6 +44,8 @@ class SettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
(new Backend())->configdRun('system trust configure', true);
|
||||
/* CRL fetches are scheduled */
|
||||
(new Backend())->configdRun('cron restart', true);
|
||||
return ['status' => 'ok'];
|
||||
}
|
||||
return ['status' => 'failed'];
|
||||
|
||||
@ -17,11 +17,16 @@
|
||||
<type>checkbox</type>
|
||||
<help>Store all configured CRL's in the default trust store.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>trust.fetch_crls</id>
|
||||
<label>Auto fetch CRL's</label>
|
||||
<type>checkbox</type>
|
||||
<help>Schedule an hourly job to download CRLs using the defined Distributionpoints in the CAs deployed in our trust store.</help>
|
||||
</field>
|
||||
<field>
|
||||
<type>header</type>
|
||||
<label>Configuration constraints</label>
|
||||
</field>
|
||||
|
||||
<field>
|
||||
<id>trust.enable_legacy_sect</id>
|
||||
<label>Enable legacy</label>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<model>
|
||||
<mount>//OPNsense/trust/general</mount>
|
||||
<description>Trust general settings</description>
|
||||
<version>1.0.0</version>
|
||||
<version>1.0.1</version>
|
||||
<items>
|
||||
<store_intermediate_certs type="BooleanField">
|
||||
<Default>0</Default>
|
||||
@ -11,6 +11,10 @@
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</install_crls>
|
||||
<fetch_crls type="BooleanField">
|
||||
<Default>0</Default>
|
||||
<Required>Y</Required>
|
||||
</fetch_crls>
|
||||
<enable_legacy_sect type="BooleanField">
|
||||
<Default>1</Default>
|
||||
<Required>Y</Required>
|
||||
|
||||
@ -23,9 +23,14 @@
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
Simple CRL Distributionpoint downloader using the CA's configured in the central trust store
|
||||
Script returns exit status 0 when nothing has changed, 1 when changes have been made so a rehash can be scheduled
|
||||
"""
|
||||
import glob
|
||||
import hashlib
|
||||
import urllib
|
||||
import os
|
||||
import subprocess
|
||||
import ldap3
|
||||
import requests
|
||||
@ -39,7 +44,7 @@ TRUSTPATH = ['/usr/share/certs/trusted', '/usr/local/share/certs', '/usr/local/e
|
||||
def fetch_crl(uri):
|
||||
p = urllib.parse.urlparse(uri)
|
||||
payload = None
|
||||
if p.scheme and p.scheme.lower() == 'ldap':
|
||||
if p.scheme.lower() == 'ldap':
|
||||
server = ldap3.Server(p.netloc)
|
||||
conn = ldap3.Connection(server, auto_bind=True)
|
||||
conn.search(
|
||||
@ -53,7 +58,7 @@ def fetch_crl(uri):
|
||||
if value and key.split(';')[0].lower() == 'certificaterevocationlist':
|
||||
payload = value[0]
|
||||
break
|
||||
elif p.scheme and p.scheme.lower() == 'http':
|
||||
elif p.scheme.lower() == 'http':
|
||||
r = requests.get(uri)
|
||||
if r.status_code >= 200 and r.status_code < 300:
|
||||
payload = r.content
|
||||
@ -76,7 +81,12 @@ def fetch_crl(uri):
|
||||
'pem': crl.public_bytes(serialization.Encoding.PEM).decode()
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
changes = 0
|
||||
output_pattern = '/usr/local/share/certs/ca-crl-upd-opn-%s.crl'
|
||||
crl_files = []
|
||||
dp_uri = ''
|
||||
for path in TRUSTPATH:
|
||||
for filename in glob.glob('%s/*[.pem|.crt]' % path):
|
||||
try:
|
||||
@ -84,7 +94,10 @@ def main():
|
||||
for ext in cert.extensions:
|
||||
if type(ext.value) is CRLDistributionPoints:
|
||||
for Distributionpoint in ext.value:
|
||||
this_crl = fetch_crl(Distributionpoint.full_name[0].value)
|
||||
dp_uri = Distributionpoint.full_name[0].value
|
||||
target_filename = output_pattern % hashlib.sha256(dp_uri.encode()).hexdigest()
|
||||
this_crl = fetch_crl(dp_uri)
|
||||
crl_files.append(target_filename)
|
||||
# use local trust store to validate if the received CRL is valid
|
||||
sp = subprocess.run(
|
||||
['/usr/local/bin/openssl', 'crl', '-verify'],
|
||||
@ -93,16 +106,28 @@ def main():
|
||||
text=True
|
||||
)
|
||||
if sp.stderr.strip() == 'verify OK':
|
||||
print('ok')
|
||||
print(filename)
|
||||
|
||||
print(this_crl)
|
||||
sys.exit(0)
|
||||
#print(Distributionpoint.full_name[0].value)
|
||||
if os.path.isfile(target_filename):
|
||||
if open(target_filename).read() == this_crl['pem']:
|
||||
print('[-] skip unchanged crl from %s' % dp_uri)
|
||||
continue
|
||||
with open(target_filename, 'w') as f_out:
|
||||
print('[+] store crl from %s' % dp_uri)
|
||||
f_out.write(this_crl['pem'])
|
||||
changes += 1
|
||||
else:
|
||||
print('[-] skip crl from %s (%s)' % (dp_uri, sp.stderr.strip()))
|
||||
except Exception as e:
|
||||
# error handling
|
||||
print(e)
|
||||
print('[-] error processing %s [%s]' % (dp_uri, e))
|
||||
|
||||
# cleanup unused CRLs within our responsible scope
|
||||
for filename in glob.glob(output_pattern % '*'):
|
||||
if filename not in crl_files:
|
||||
os.unlink(filename)
|
||||
changes += 1
|
||||
|
||||
return changes
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
sys.exit(0 if main() == 0 else 1)
|
||||
|
||||
@ -146,6 +146,12 @@ parameters:
|
||||
type:script
|
||||
message:configure trust
|
||||
|
||||
[trust.download_crls]
|
||||
command:/usr/local/opnsense/scripts/system/crl_fetch.py || /usr/local/opnsense/scripts/system/certctl.py rehash
|
||||
parameters:
|
||||
type:script
|
||||
message:download CRLs from Distributionpoints
|
||||
|
||||
[trust.crl]
|
||||
command:/usr/local/sbin/pluginctl -c crl
|
||||
type:script
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user