2015-12-12 22:34:08 +00:00
|
|
|
|
2015-12-16 17:41:49 +00:00
|
|
|
import os
|
|
|
|
import click
|
2017-04-20 05:23:09 +00:00
|
|
|
import subprocess
|
2018-05-15 07:45:29 +00:00
|
|
|
from random import SystemRandom
|
|
|
|
|
|
|
|
random = SystemRandom()
|
|
|
|
|
|
|
|
try:
|
|
|
|
from time import time_ns
|
|
|
|
except ImportError:
|
|
|
|
from time import time
|
|
|
|
def time_ns():
|
|
|
|
return int(time() * 10**9) # 64 bits integer, 32 ns bits
|
2016-03-21 21:42:39 +00:00
|
|
|
|
2018-04-27 07:48:15 +00:00
|
|
|
MAPPING = dict(
|
|
|
|
common_name="CN",
|
|
|
|
organizational_unit_name="OU",
|
|
|
|
organization_name="O",
|
|
|
|
domain_component="DC"
|
|
|
|
)
|
|
|
|
|
|
|
|
def cert_to_dn(cert):
|
|
|
|
d = []
|
|
|
|
for key, value in cert["tbs_certificate"]["subject"].native.items():
|
|
|
|
if not isinstance(value, list):
|
|
|
|
value = [value]
|
|
|
|
for comp in value:
|
|
|
|
d.append("%s=%s" % (MAPPING[key], comp))
|
|
|
|
return ", ".join(d)
|
|
|
|
|
|
|
|
def cn_to_dn(common_name, namespace, o=None, ou=None):
|
|
|
|
from asn1crypto.x509 import Name, RelativeDistinguishedName, NameType, DirectoryString, RDNSequence, NameTypeAndValue, UTF8String, DNSName
|
|
|
|
|
|
|
|
rdns = []
|
|
|
|
|
2018-05-02 08:11:01 +00:00
|
|
|
for dc in reversed(namespace.split(".")):
|
2018-04-27 07:48:15 +00:00
|
|
|
rdns.append(RelativeDistinguishedName([
|
|
|
|
NameTypeAndValue({
|
2018-05-02 08:11:01 +00:00
|
|
|
'type': NameType.map("domain_component"),
|
|
|
|
'value': DNSName(value=dc)
|
2018-04-27 07:48:15 +00:00
|
|
|
})
|
|
|
|
]))
|
|
|
|
|
|
|
|
if o:
|
|
|
|
rdns.append(RelativeDistinguishedName([
|
|
|
|
NameTypeAndValue({
|
|
|
|
'type': NameType.map("organization_name"),
|
|
|
|
'value': DirectoryString(
|
|
|
|
name="utf8_string",
|
|
|
|
value=UTF8String(o))
|
|
|
|
})
|
|
|
|
]))
|
|
|
|
|
2018-05-02 08:11:01 +00:00
|
|
|
if ou:
|
2018-04-27 07:48:15 +00:00
|
|
|
rdns.append(RelativeDistinguishedName([
|
|
|
|
NameTypeAndValue({
|
2018-05-02 08:11:01 +00:00
|
|
|
'type': NameType.map("organizational_unit_name"),
|
|
|
|
'value': DirectoryString(
|
|
|
|
name="utf8_string",
|
|
|
|
value=UTF8String(ou))
|
2018-04-27 07:48:15 +00:00
|
|
|
})
|
|
|
|
]))
|
|
|
|
|
2018-05-02 08:11:01 +00:00
|
|
|
rdns.append(RelativeDistinguishedName([
|
|
|
|
NameTypeAndValue({
|
|
|
|
'type': NameType.map("common_name"),
|
|
|
|
'value': DirectoryString(
|
|
|
|
name="utf8_string",
|
|
|
|
value=UTF8String(common_name))
|
|
|
|
})
|
|
|
|
]))
|
|
|
|
|
2018-04-27 07:48:15 +00:00
|
|
|
return Name(name='', value=RDNSequence(rdns))
|
|
|
|
|
2017-05-27 18:17:21 +00:00
|
|
|
def selinux_fixup(path):
|
|
|
|
"""
|
|
|
|
Fix OpenVPN credential store security context on Fedora
|
|
|
|
"""
|
2017-07-06 09:29:02 +00:00
|
|
|
if os.path.exists("/usr/bin/chcon"):
|
|
|
|
cmd = "chcon", "--type=home_cert_t", path
|
|
|
|
subprocess.call(cmd)
|
2017-05-27 18:17:21 +00:00
|
|
|
|
2017-05-03 07:04:52 +00:00
|
|
|
def drop_privileges():
|
|
|
|
from certidude import config
|
|
|
|
import pwd
|
|
|
|
_, _, uid, gid, gecos, root, shell = pwd.getpwnam("certidude")
|
|
|
|
restricted_groups = []
|
|
|
|
restricted_groups.append(gid)
|
|
|
|
|
|
|
|
# PAM needs access to /etc/shadow
|
|
|
|
if config.AUTHENTICATION_BACKENDS == {"pam"}:
|
|
|
|
import grp
|
|
|
|
name, passwd, num, mem = grp.getgrnam("shadow")
|
|
|
|
click.echo("Adding current user to shadow group due to PAM authentication backend")
|
|
|
|
restricted_groups.append(num)
|
|
|
|
|
|
|
|
os.setgroups(restricted_groups)
|
|
|
|
os.setgid(gid)
|
|
|
|
os.setuid(uid)
|
|
|
|
click.echo("Switched to user %s (uid=%d, gid=%d); member of groups %s" %
|
|
|
|
("certidude", os.getuid(), os.getgid(), ", ".join([str(j) for j in os.getgroups()])))
|
|
|
|
os.umask(0o007)
|
|
|
|
|
2017-04-20 05:20:10 +00:00
|
|
|
def apt(packages):
|
|
|
|
"""
|
|
|
|
Install packages for Debian and Ubuntu
|
|
|
|
"""
|
|
|
|
if os.path.exists("/usr/bin/apt-get"):
|
2017-12-30 13:57:48 +00:00
|
|
|
cmd = ["/usr/bin/apt-get", "install", "-yqq", "-o", "Dpkg::Options::=--force-confold"] + packages.split(" ")
|
2017-04-20 05:20:10 +00:00
|
|
|
click.echo("Running: %s" % " ".join(cmd))
|
|
|
|
subprocess.call(cmd)
|
2017-05-06 21:07:41 +00:00
|
|
|
return True
|
|
|
|
return False
|
2017-04-20 05:20:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
def rpm(packages):
|
|
|
|
"""
|
|
|
|
Install packages for Fedora and CentOS
|
|
|
|
"""
|
|
|
|
if os.path.exists("/usr/bin/dnf"):
|
|
|
|
cmd = ["/usr/bin/dnf", "install", "-y"] + packages.split(" ")
|
|
|
|
click.echo("Running: %s" % " ".join(cmd))
|
|
|
|
subprocess.call(cmd)
|
2017-05-06 21:07:41 +00:00
|
|
|
return True
|
|
|
|
return False
|
2017-04-20 05:20:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
def pip(packages):
|
2017-12-30 13:57:48 +00:00
|
|
|
click.echo("Running: pip3 install %s" % packages)
|
2017-04-20 05:20:10 +00:00
|
|
|
import pip
|
|
|
|
pip.main(['install'] + packages.split(" "))
|
2017-05-06 21:07:41 +00:00
|
|
|
return True
|
2017-04-20 05:20:10 +00:00
|
|
|
|
2018-05-15 07:45:29 +00:00
|
|
|
def generate_serial():
|
|
|
|
return time_ns() << 56 | random.randint(0, 2**56-1)
|
|
|
|
|