diff --git a/Dokumentation/sourcecode/bbwmodul/bbwca.crt b/Dokumentation/sourcecode/bbwmodul/bbwca.crt new file mode 120000 index 0000000..0929ee8 --- /dev/null +++ b/Dokumentation/sourcecode/bbwmodul/bbwca.crt @@ -0,0 +1 @@ +../ca/ca.pem \ No newline at end of file diff --git a/Dokumentation/sourcecode/bbwmodul/dovecot-ldap.conf b/Dokumentation/sourcecode/bbwmodul/dovecot-ldap.conf new file mode 100644 index 0000000..f4a65f2 --- /dev/null +++ b/Dokumentation/sourcecode/bbwmodul/dovecot-ldap.conf @@ -0,0 +1,151 @@ +# This file is commonly accessed via passdb {} or userdb {} section in +# conf.d/auth-ldap.conf.ext + +# This file is opened as root, so it should be owned by root and mode 0600. +# +# http://wiki2.dovecot.org/AuthDatabase/LDAP +# +# NOTE: If you're not using authentication binds, you'll need to give +# dovecot-auth read access to userPassword field in the LDAP server. +# With OpenLDAP this is done by modifying /etc/ldap/slapd.conf. There should +# already be something like this: + +# access to attribute=userPassword +# by dn="" read # add this +# by anonymous auth +# by self write +# by * none + +# Space separated list of LDAP hosts to use. host:port is allowed too. +#hosts = + +# LDAP URIs to use. You can use this instead of hosts list. Note that this +# setting isn't supported by all LDAP libraries. +#uris = + +# Distinguished Name - the username used to login to the LDAP server. +# Leave it commented out to bind anonymously (useful with auth_bind=yes). +#dn = + +# Password for LDAP server, if dn is specified. +#dnpass = + +# Use SASL binding instead of the simple binding. Note that this changes +# ldap_version automatically to be 3 if it's lower. +#sasl_bind = no +# SASL mechanism name to use. +#sasl_mech = +# SASL realm to use. +#sasl_realm = +# SASL authorization ID, ie. the dnpass is for this "master user", but the +# dn is still the logged in user. Normally you want to keep this empty. +#sasl_authz_id = + +# Use TLS to connect to the LDAP server. +#tls = no +# TLS options, currently supported only with OpenLDAP: +#tls_ca_cert_file = +#tls_ca_cert_dir = +#tls_cipher_suite = +# TLS cert/key is used only if LDAP server requires a client certificate. +#tls_cert_file = +#tls_key_file = +# Valid values: never, hard, demand, allow, try +#tls_require_cert = + +# Use the given ldaprc path. +#ldaprc_path = + +# LDAP library debug level as specified by LDAP_DEBUG_* in ldap_log.h. +# -1 = everything. You may need to recompile OpenLDAP with debugging enabled +# to get enough output. +#debug_level = 0 + +# Use authentication binding for verifying password's validity. This works by +# logging into LDAP server using the username and password given by client. +# The pass_filter is used to find the DN for the user. Note that the pass_attrs +# is still used, only the password field is ignored in it. Before doing any +# search, the binding is switched back to the default DN. +#auth_bind = no + +# If authentication binding is used, you can save one LDAP request per login +# if users' DN can be specified with a common template. The template can use +# the standard %variables (see user_filter). Note that you can't +# use any pass_attrs if you use this setting. +# +# If you use this setting, it's a good idea to use a different +# dovecot-ldap.conf.ext for userdb (it can even be a symlink, just as long as +# the filename is different in userdb's args). That way one connection is used +# only for LDAP binds and another connection is used for user lookups. +# Otherwise the binding is changed to the default DN before each user lookup. +# +# For example: +# auth_bind_userdn = cn=%u,ou=people,o=org +# +#auth_bind_userdn = + +# LDAP protocol version to use. Likely 2 or 3. +#ldap_version = 3 + +# LDAP base. %variables can be used here. +# For example: dc=mail, dc=example, dc=org +base = + +# Dereference: never, searching, finding, always +#deref = never + +# Search scope: base, onelevel, subtree +#scope = subtree + +# User attributes are given in LDAP-name=dovecot-internal-name list. The +# internal names are: +# uid - System UID +# gid - System GID +# home - Home directory +# mail - Mail location +# +# There are also other special fields which can be returned, see +# http://wiki2.dovecot.org/UserDatabase/ExtraFields +#user_attrs = homeDirectory=home,uidNumber=uid,gidNumber=gid + +# Filter for user lookup. Some variables can be used (see +# http://wiki2.dovecot.org/Variables for full list): +# %u - username +# %n - user part in user@domain, same as %u if there's no domain +# %d - domain part in user@domain, empty if user there's no domain +#user_filter = (&(objectClass=posixAccount)(uid=%u)) + +# Password checking attributes: +# user: Virtual user name (user@domain), if you wish to change the +# user-given username to something else +# password: Password, may optionally start with {type}, eg. {crypt} +# There are also other special fields which can be returned, see +# http://wiki2.dovecot.org/PasswordDatabase/ExtraFields +#pass_attrs = uid=user,userPassword=password + +# If you wish to avoid two LDAP lookups (passdb + userdb), you can use +# userdb prefetch instead of userdb ldap in dovecot.conf. In that case you'll +# also have to include user_attrs in pass_attrs field prefixed with "userdb_" +# string. For example: +#pass_attrs = uid=user,userPassword=password,\ +# homeDirectory=userdb_home,uidNumber=userdb_uid,gidNumber=userdb_gid + +# Filter for password lookups +#pass_filter = (&(objectClass=posixAccount)(uid=%u)) + +# Attributes and filter to get a list of all users +#iterate_attrs = uid=user +#iterate_filter = (objectClass=posixAccount) + +# Default password scheme. "{scheme}" before password overrides this. +# List of supported schemes is in: http://wiki2.dovecot.org/Authentication +#default_pass_scheme = CRYPT + +# By default all LDAP lookups are performed by the auth master process. +# If blocking=yes, auth worker processes are used to perform the lookups. +# Each auth worker process creates its own LDAP connection so this can +# increase parallelism. With blocking=no the auth master process can +# keep 8 requests pipelined for the LDAP connection, while with blocking=yes +# each connection has a maximum of 1 request running. For small systems the +# blocking=no is sufficient and uses less resources. +#blocking = no diff --git a/Dokumentation/sourcecode/ca/ca.txt b/Dokumentation/sourcecode/ca/ca.txt new file mode 100644 index 0000000..36f5c96 --- /dev/null +++ b/Dokumentation/sourcecode/ca/ca.txt @@ -0,0 +1,20 @@ +organization = "Berufsbildungswerk Südhessen gGmbH" +unit = "Kaufmännischer Bereich" +unit = "IT" +locality = "Karben" +state = "Hessen" +country = DE +cn = "BBW Root Zertifikat" +dc = "bbw" +dn_oid = "2.5.4.9 Am Heroldsrain 1" # Straße +dn_oid = "2.5.4.17 61184" # Postleitzahl +activation_date = "2018-03-01 00:00:00 UTC" +expiration_date = "2028-03-01 00:00:00 UTC" +ca +signing_key +crl_signing_key +ocsp_signing_key +policy1_txt = "Internes Zertifikat" +nc_permit_dns = bbw +honor_crq_extensions + diff --git a/Dokumentation/sourcecode/ca/certs/.gitignore b/Dokumentation/sourcecode/ca/certs/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/Dokumentation/sourcecode/ca/config b/Dokumentation/sourcecode/ca/config new file mode 100644 index 0000000..76512d6 --- /dev/null +++ b/Dokumentation/sourcecode/ca/config @@ -0,0 +1,3 @@ +export typ=rsa +export laenge=4096 +export crtdir=certs diff --git a/Dokumentation/sourcecode/ca/genca b/Dokumentation/sourcecode/ca/genca new file mode 100755 index 0000000..628eca0 --- /dev/null +++ b/Dokumentation/sourcecode/ca/genca @@ -0,0 +1,4 @@ +#!/bin/bash +source ./config +certtool -p --null-password --bits=$laenge --$typ --outfile=ca.key -8 +certtool -s --null-password --load-privkey=ca.key --outfile=ca.pem --template=ca.txt diff --git a/Dokumentation/sourcecode/ca/gencrt b/Dokumentation/sourcecode/ca/gencrt new file mode 100755 index 0000000..f7f4cf0 --- /dev/null +++ b/Dokumentation/sourcecode/ca/gencrt @@ -0,0 +1,9 @@ +#!/bin/bash +source ./config +if [ -z "$1" ]; then + echo -e "nicht genügend Argumente\nnutzung: $0 domain" + exit 1 +fi +sed "s/DOMAIN/$1/g" normcert.txt >$crtdir/$1.txt +certtool -p --null-password --bits=$laenge --$typ --outfile=$crtdir/$1.key -8 +certtool -c --null-password --load-ca-privkey=ca.key --load-ca-certificate=ca.pem --load-privkey=$crtdir/$1.key --outfile=$crtdir/$1.pem --template=$crtdir/$1.txt diff --git a/Dokumentation/sourcecode/ca/genpuppet b/Dokumentation/sourcecode/ca/genpuppet new file mode 100755 index 0000000..b778aa8 --- /dev/null +++ b/Dokumentation/sourcecode/ca/genpuppet @@ -0,0 +1,4 @@ +#!/bin/bash +source ./config +certtool -p --null-password --bits=$laenge --$typ --outfile=puppet.key -8 +certtool -c --null-password --load-ca-privkey=ca.key --load-ca-certificate=ca.pem --load-privkey=puppet.key --outfile=puppet.pem --template=puppet.txt diff --git a/Dokumentation/sourcecode/ca/normcert.txt b/Dokumentation/sourcecode/ca/normcert.txt new file mode 100644 index 0000000..b61c818 --- /dev/null +++ b/Dokumentation/sourcecode/ca/normcert.txt @@ -0,0 +1,16 @@ +organization = "Berufsbildungswerk Südhessen gGmbH" +unit = "Kaufmännischer Bereich" +unit = "IT" +locality = "Karben" +state = "Hessen" +country = DE +dc = "bbw" +dn_oid = "2.5.4.9 Am Heroldsrain 1" # Straße +dn_oid = "2.5.4.17 61184" # Postleitzahl +activation_date = "2018-03-01 00:00:00 UTC" +expiration_date = "2028-03-01 00:00:00 UTC" +tls_www_server +encryption_key +cn = "DOMAIN" +dns_name = "DOMAIN" +dns_name = "www.DOMAIN" diff --git a/Dokumentation/sourcecode/ca/puppet.txt b/Dokumentation/sourcecode/ca/puppet.txt new file mode 100644 index 0000000..fcbd9a2 --- /dev/null +++ b/Dokumentation/sourcecode/ca/puppet.txt @@ -0,0 +1,14 @@ +organization = "Berufsbildungswerk Südhessen gGmbH" +unit = "Kaufmännischer Bereich" +unit = "IT" +locality = "Karben" +state = "Hessen" +country = DE +cn = "Puppet Zertifikat" +dc = "bbw" +dn_oid = "2.5.4.9 Am Heroldsrain 1" # Straße +dn_oid = "2.5.4.17 61184" # Postleitzahl +activation_date = "2018-03-01 00:00:00 UTC" +expiration_date = "2028-03-01 00:00:00 UTC" +ca +honor_crq_extensions diff --git a/Dokumentation/sourcecode/site.pp b/Dokumentation/sourcecode/site.pp new file mode 100644 index 0000000..129e4fe --- /dev/null +++ b/Dokumentation/sourcecode/site.pp @@ -0,0 +1,134 @@ + +mod "oxc-dovecot", "1.0.1" +mod "pcfens-ca_cert", "1.7.1" + +class { "ca_cert": } + +ca_cert::ca { "GlobalSign-OrgSSL-Intermediate": + ensure => "trusted", + source => "puppet:///module/bbwmodul/bbwca.crt", +} + +class {"apt": + update => { + frequency => "daily", + }, +} +class { "apt::backports":} + + +node "zeus", "hades" { + apt::source { "fusiondirectory": + location => "http://repos.fusiondirectory.org/fusiondirectory-current/debian-jessie/", + release => "stable", + repos => "main", + key => { + "id" => "D744D55EACDA69FF", + "server" => "pgp.mit.edu", + }, + include => { + "deb" => true, + }, + } +} + +node "zeus" { + class { "postgresql::globals": + encoding => "UTF-8", + locale => "de_DE.UTF-8", + } + class { "postgresql::server": + } + postgresql::server::db { "icinga": + user => "icinga", + password => postgresql_password("icinga", ""), + } + postgresql::server::db { "sogo": + user => "sogo", + password => postgresql_password("sogo", ""), + } + postgresql::server::role { "tobieseb": + password_hash => postgresql_password("tobieseb", "mypasswd"), + superuser => true, + } + postgresql::server::pg_hba_rule { "sogo access rule": + description => "Gibt sogo zugriff auf die datenbank", + type => "host", + database => "sogo", + user => "sogo", + address => "10.x.x.3", + auth_method => "md5", + } + postgresql::server::pg_hba_rule { "icinga access rule": + description => "Gibt Icinga zugriff auf die datenbank", + type => "host", + database => "icinga", + user => "icinga", + address => "10.x.x.3", + auth_method => "md5", + } + postgresql::server::pg_hba_rule { "tobieseb access rule": + description => "Gibt dem Superuser Zugriff auf die datenbank", + type => "host", + user => "tobieseb", + address => "172.16.34.0/23", + auth_method => "md5", + } + file { "/etc/dovecot/private/dovecot-ldap.conf": + mode => 000, + owner => "", + group => "", + source => "puppet:///modules/bbwmodul/dovecot-ldap.conf", + } + class { "dovecot": + "plugins" => [ "imap" ], + "config" => { + "protocols" => "imap", + "listen" => "*, ::", + }, + "configs" => { + "auth-ldap" => { + "passdb" => { + "driver" => "ldap", + "args" => "/etc/dovecot/private/dovecot-ldap.conf", + }, + "userdb" => { + "driver" => "ldap", + "args" => "/etc/dovecot/private/dovecot-ldap.conf", + }, + }, + }, + } +} +node "poseidon" { +} +node "hades" { + class { "apache": } + class { "apache::mod::ssl": } + apache2::vhost { "sogo.bbw http": + "port" => "80", + redirect_status => "permanent", + redirect_dest => "https://sogo.bbw/", + "servername" => "sogo.bbw", + "ssl" => false, + } + apache2::vhost { "sogo.bbw https": + "port" => "443", + "docroot" => "", + "servername" => "sogo.bbw", + "ssl" => true, + } + apache2::vhost { "management.bbw http": + "port" => "80", + redirect_status => "permanent", + redirect_dest => "https://management.bbw/", + "servername" => "management.bbw", + "ssl" => false, + } + apache2::vhost { "management.bbw https": + "port" => "80", + "docroot" => "", + "servername" => "management.bbw", + "ssl" => true, + } +} diff --git a/Serverkonfiguration.odt b/Serverkonfiguration.odt index dd90b2a..ed85b0e 100644 Binary files a/Serverkonfiguration.odt and b/Serverkonfiguration.odt differ diff --git a/ca/myca.py b/ca/myca.py deleted file mode 100755 index ea62bc7..0000000 --- a/ca/myca.py +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/bin/python3 -import argparse -import sqlite3 -from cryptography import x509 -from cryptography.hazmat.primitives.asymmetric import rsa -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.serialization import PrivateFormat, NoEncryption, BestAvailableEncryption, load_pem_private_key -from cryptography.x509.oid import NameOID -from cryptography.hazmat.primitives.serialization import Encoding -from concurrent.futures import ThreadPoolExecutor -import datetime - - -def parser_factory(): - parser = argparse.ArgumentParser(description="Programm zur Administration von Zertifikaten") - parser.add_argument("--db", type=str, help="Datenbank die benutzt wird.", default="certificates.sqlite3") - subparser = parser.add_subparsers(dest="aktion", title="Kommandos", ) - newca = subparser.add_parser("newca", help="erstellt ein neues CA-Zertifikat") - request = subparser.add_parser("request", help="erstellt eine Zertifikatsanfrage") - sign = subparser.add_parser("sign", help="TBI Signiert eine Zertifikatsanfrage") - config = subparser.add_parser("config", help="TBI") - for kommando in [ newca, request]: - kommando.add_argument("--length", type=int, help="Schlüssellänge des Zertifikats, sollte ein Exponent von 2 und größer als 1024 sein", default=4096, dest="länge") - kommando.add_argument("--commonname", type=str, help="Name des Besitzers", required=True, dest="cn") - kommando.add_argument("--location", help="Stadt", dest="l") - kommando.add_argument("--state", help="Bundesland/Kanton", dest="st") - kommando.add_argument("--organization", help="Firma", dest="o") - kommando.add_argument("--ou", help="Abteilung", dest="ou") - kommando.add_argument("--country", help="Land", dest="c") - kommando.add_argument("--street", help="Straße", dest="street") - request.add_argument( - "--san", - help="Alternativer Name für die Resource, kann eine Emailadresse, URI oder eine Domain sein. sonderzeichen in Domains sollten bereits mittels IDNA umkodiert worden sein.", - action="append", - dest="san", - nargs="?", - ) - request.add_argument("-s", dest="server", action="store_true", help="Serverzertifikat") - request.add_argument("-cl", dest="client", action="store_true", help="Clientzertifikat") - request.add_argument("-co", dest="code", action="store_true", help="Codesignaturzertifikat") - request.add_argument("-e", dest="email", action="store_true", help="Emailzertifikat") - request.add_argument("--ca", dest="ca", help="Certificate Authority, Zertifizierungstelle mit optionaler Pfadlänge", nargs="?", type=int) - newca.add_argument("tage", type=int, help="Tage die das Zertifikat gültig ist") - return parser - -def initdb(cursor): - cursor.execute("CREATE TABLE IF NOT EXISTS \"certificates\" ( `commonname` TEXT NOT NULL, `serial` TEXT NOT NULL UNIQUE, `publickey` TEXT NOT NULL, `privatkey` TEXT NOT NULL UNIQUE, `parent` integer, `ca` INTEGER NOT NULL, PRIMARY KEY(`commonname`), FOREIGN KEY(`parent`) REFERENCES `certificates`(`serial`) ) WITHOUT ROWID") - cursor.execute("CREATE TABLE IF NOT EXISTS \"requests\" ( `commonname` TEXT NOT NULL, `csr` TEXT NOT NULL UNIQUE, `privatkey` TEXT NOT NULL, PRIMARY KEY(`commonname`) )") - -def print_wrp(text): - def wrapper(*t): - print(text) - return wrapper - -def str_exttype(exttype): - if isinstance(exttype, x509.BasicConstraints): - if not exttype.ca: - return "Keine CA" - if exttype.path_length in [None, 0]: - return "CA, unendliche Pfadlänge" - return "CA, Pfadlänge {}".format(exttype.path_length) - elif isinstance(exttype, x509.ExtendedKeyUsage): - text = "" - for usage in exttype: - text += usage._name + ", " - return text[:-2] - elif isinstance(exttype, x509.SubjectAlternativeName): - text = "" - for an in exttype._general_names: - text += an._value + ", " - return text[:-2] - else: - return repr(exttype) - -def print_info(cert): - for name in cert.subject.rdns: - for oid in name: - print("{}: {}".format(oid._oid._name, oid.value)) - for extension in cert.extensions: - kritisch = "kritisch" - if not extension.critical: - kritisch = "nicht" + kritisch - print("{}({}): {}".format(extension.oid._name, kritisch, str_exttype(extension.value))) - -class Certwrapper: - def __init__(self, backend): - self.threads = ThreadPoolExecutor(3, "cryptoops") - self.anfragetemplate = x509.CertificateSigningRequestBuilder() - self.backend = backend - - def gencert(self, länge): - return self.threads.submit(rsa.generate_private_key, 65537, länge, self.backend) - - def sign(self, subject, issuer, time_valid, public_key, privat_ca_key, extensions=None, ca_key=None): - if not extensions: - extensions = [] - builder = x509.CertificateBuilder() - jetzt = datetime.datetime.now() - builder = builder.serial_number(x509.random_serial_number()) - builder = builder.not_valid_before(jetzt) - builder = builder.not_valid_after(jetzt + time_valid) - builder = builder.subject_name(subject) - builder = builder.issuer_name(issuer) - builder = builder.public_key(public_key) - for extension in extensions: - builder = builder.add_extension(extension, True) - if ca_key: - builder = builder.add_extension(x509.AuthorityKeyIdentifier(ca_key.fingerprint(hashes.SHA512()), None, None), True) - return builder.sign(privat_ca_key, hashes.SHA512(), self.backend) - - def request(self, subject, erweiterungen=[], certlänge=4096): - cert = self.gencert(certlänge) - anfrage = self.anfragetemplate.subject_name(subject) - for erweiterung in erweiterungen: - anfrage = anfrage.add_extension(erweiterung, True) - anfrage = anfrage.sign(cert.result(), hashes.SHA512(), self.backend) - return { - "privat": cert.result(), - "csr": anfrage - } - - -class DBbackend: - def __init__(self, connection): - self.connection = connection - - def insert_certificate(self, commonname: str, serial, publickey, privatkey, ca: bool): - self.connection.execute( - "INSERT INTO `certificates`(commonname, serial, publickey, privatkey, ca) VALUES (?, ?, ?, ?, ?)", - ( - commonname, - serial, - publickey, - privatkey, - ca - ) - ) - self.connection.commit() - - def insert_request(self, commonname, cst, privatkey): - self.connection.execute( - "INSERT INTO `requests`(commonname, csr, privatkey) VALUES (?, ?, ?)", - ( - commonname, - csr, - privatkey, - ) - ) - self.connection.commit() - - -class Commands: - def __init__(self, backend, connection, args): - self.backend = backend - self.threads = ThreadPoolExecutor(3, "cryptoops") - self.connection = connection - self.connection.row_factory = sqlite3.Row - self.cursor = connection.cursor() - self.arguments = args - self.wrapper = Certwrapper(backend) - self.db = DBbackend(connection) - - def get(self, name): - try: - return self.__getattribute__(name) - except (AttributeError, TypeError): - return None - - def fragen(self, fragen, typ=tuple): - antworten = [] - for id in fragen: - antworten.append(typ(id, self.frage(fragen[id], False))) - return antworten - - def frage(self, text, typ=str): - while True: - antwort = input("{}: ".format(text)) - try: - return typ(antwort) - except TypeError: - print("Falsche Eingabe") - continue - - def parsedn(self, dn): - namen = [] - if dn.cn: - namen.append(x509.NameAttribute(x509.NameOID.COMMON_NAME, dn.cn)) - if dn.st: - namen.append(x509.NameAttribute(x509.NameOID.STATE_OR_PROVINCE_NAME, dn.st)) - if dn.l: - namen.append(x509.NameAttribute(x509.NameOID.LOCALITY_NAME, dn.l)) - if dn.o: - namen.append(x509.NameAttribute(x509.NameOID.ORGANIZATION_NAME, dn.o)) - if dn.ou: - namen.append(x509.NameAttribute(x509.NameOID.ORGANIZATIONAL_UNIT_NAME, dn.ou)) - if dn.c: - namen.append(x509.NameAttribute(x509.NameOID.COUNTRY_NAME, dn.c)) - if dn.street: - namen.append(x509.NameAttribute(x509.NameOID.STREET_ADDRESS, dn.street)) - return namen - - def newca(self): - privater = self.wrapper.gencert(self.arguments.länge) - jetzt = datetime.datetime.now() - privater.add_done_callback(print_wrp("Privater Schlüssel generiert")) - subject = x509.Name(self.parsedn(self.arguments)) - zertifikat = self.wrapper.sign( - subject=subject, - issuer=subject, - time_valid=datetime.timedelta(days=self.arguments.tage), - public_key=privater.result().public_key(), - privat_ca_key=privater.result() - ) - passwort = self.frage("Passwort") - if passwort: - encryption = BestAvailableEncryption(passwort.encode()) - else: - encryption = NoEncryption() - self.db.insert_certificate( - self.arguments.cn, - hex(zertifikat.serial_number), - zertifikat.public_bytes(Encoding.PEM), - privater.result().private_bytes(encoding=Encoding.PEM, format=PrivateFormat.PKCS8, encryption_algorithm=encryption), - True - ) - - def request(self): - erweiterungen = [] - if self.arguments.ca: - erweiterungen.append(x509.BasicConstraints(True, self.arguments.ca)) - else: - erweiterungen.append(x509.BasicConstraints(False, None)) - if self.arguments.san: - alt = [] - for san in self.arguments.san: - if ":" in san: - alt.append(x509.UniformResourceIdentifier(san)) - elif "@" in san: - alt.append(x509.RFC822Name(san)) - else: - alt.append(x509.DNSName(san)) - erweiterungen.append(x509.SubjectAlternativeName(alt)) - ziele = [] - if self.arguments.server: - ziele.append(x509.oid.ExtendedKeyUsageOID.SERVER_AUTH) - if self.arguments.client: - ziele.append(x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH) - if self.arguments.code: - ziele.append(x509.oid.ExtendedKeyUsageOID.CODE_SIGNING) - if self.arguments.email: - ziele.append(x509.oid.ExtendedKeyUsageOID.EMAIL_PROTECTION) - erweiterungen.append(x509.ExtendedKeyUsage(ziele)) - anfrage = self.wrapper.request( - subject=x509.Name(self.parsedn(self.arguments)), - erweiterungen=erweiterungen, - certlänge=self.arguments.länge - ) - passwort = self.frage("Passwort") - if passwort: - encryption = BestAvailableEncryption(passwort.encode()) - else: - encryption = NoEncryption() - self.db.insert_request( - self.arguments.cn, - anfrage.public_bytes(Encoding.PEM), - privater.result().private_bytes(encoding=Encoding.PEM, format=PrivateFormat.PKCS8, encryption_algorithm=encryption), - ) - self.connection.commit() - - def sign(self): - def delete_request(subject): - self.cursor.execute("DELETE FROM requests WHERE commonname=?", (subject, )) - self.cursor.execute("SELECT commonname, csr, privatkey FROM requests") - for reihe in self.cursor.fetchall(): - try: - anfrage = x509.load_pem_x509_csr(reihe["csr"], self.backend) - if not anfrage.is_signature_valid: - raise TypeError() - except TypeError: - delete_request(reihe["commonname"]) - continue - print_info(anfrage) - if not self.frage("Möchten Sie das Zertifikat signieren[01]" ,int): - delete_request(reihe["commonname"]) - continue - cas = [] - for row in self.cursor.execute("SELECT commonname, publickey, privatkey FROM certificates WHERE ca=1"): - cas.append((row["commonname"], x509.load_pem_x509_certificate(row["publickey"], self.backend), row["privatkey"])) - print("Wähle die CA:\n") - for counter in range(1, len(cas)+1): - print("{}: {}".format(counter, cas[counter-1][0])) - while True: - antwort = self.frage("CA", int) - antwort -= 1 - if 0 <= antwort < len(cas): - break - try: - privat = load_pem_private_key(cas[antwort][2], None, self.backend) - except TypeError: - while True: - try: - pw = self.frage("Passwort") - privat = load_pem_private_key(cas[antwort][2], pw.encode("utf-8"), self.backend) - except TypeError: - print("Falsches Passwort") - ca = cas[antwort][1] - dn = cas[antwort][0] - zertifikat = self.sign_cert( - anfrage.subject, - ca.subject, - datetime.timedelta(days=self.frage("Laufzeit", int)), - anfrage.public_key(), - privat, - [ext.value for ext in anfrage.extensions], - ca - ) - self.db.insert_certificate( - reihe["commonname"], - hex(zertifikat.serial_number), - zertifikat.public_bytes(Encoding.PEM), - reihe["privatkey"], - dn, - 0 - ) - delete_request(reihe["commonname"]) - self.connection.commit() - -if __name__ == "__main__": - parser = parser_factory() - argumente = parser.parse_args() - print(argumente.aktion) - datenbank = sqlite3.connect(argumente.db) - initdb(datenbank.cursor()) - commandos = Commands(default_backend(), datenbank, argumente) - if commandos.get(argumente.aktion): - commandos.get(argumente.aktion)() - else: - parser.print_help() \ No newline at end of file