From 528949e82aa2c6d18aff0801df3705238c90120d Mon Sep 17 00:00:00 2001 From: r00t Date: Sun, 4 Dec 2016 14:27:23 -0500 Subject: [PATCH] preliminary work for SSL support in iPXE. untested and probably not currently functional. --- .gitignore | 1 + bdisk/bSSL.py | 99 +++++ bdisk/ipxe.py | 30 +- docs/BDisk_User_Manual.v1.fodt | 382 +++++++++++++++--- docs/TODO | 1 + extra/bin/hashgen.php | 7 - .../etc/systemd/system/pacmandb.service | 2 +- 7 files changed, 447 insertions(+), 75 deletions(-) create mode 100755 bdisk/bSSL.py delete mode 100644 extra/bin/hashgen.php diff --git a/.gitignore b/.gitignore index 4791437..61e7133 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ *.swp *.lck *~ +.~lock.* /extrasrc # You should really generate local copies of these, as they're pretty private. diff --git a/bdisk/bSSL.py b/bdisk/bSSL.py new file mode 100755 index 0000000..b1d8144 --- /dev/null +++ b/bdisk/bSSL.py @@ -0,0 +1,99 @@ +import OpenSSL +import os +import shutil +import datetime +import re + +def verifyCert(cert, key, CA = None): + # Verify a given certificate against a certificate. + # Optionally verify against a CA certificate as well (Hopefully. If/when PyOpenSSL ever supports it.) + chk = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_METHOD) + chk.use_privatekey(key) + chk.use_certificate(cert) + try: + chk.check_privatekey() + except OpenSSL.SSL.Error: + exit(("{0}: Key does not match certificate!".format(datetime.datetime.now()))) + else: + print("{0}: Key verified against certificate successfully.".format(datetime.datetime.now())) + # This is disabled because there doesn't seem to currently be any way + # to actually verify certificates against a given CA. + #if CA: + # try: + # magic stuff here + +def sslCAKey(): + key = OpenSSL.crypto.PKey() + print("{0}: Generating SSL CA key...".format(datetime.datetime.now())) + key.generate_key(OpenSSL.crypto.TYPE_RSA, 4096) + #print OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) + return(key) + +def sslCA(conf, key = None): + if not key: + try: + key = conf['ipxe']['ssl_cakey'] + except: + exit("{0}: Cannot find a valid CA Key to use.".format(datetime.datetime.now())) + domain = (re.sub('^(https?|ftp)://([a-z0-9.-]+)/?.*$', '\g<2>', + conf['ipxe']['uri'], + flags=re.IGNORECASE)).lower() + # http://www.pyopenssl.org/en/stable/api/crypto.html#pkey-objects + # http://docs.ganeti.org/ganeti/2.14/html/design-x509-ca.html + ca = OpenSSL.crypto.X509() + ca.set_version(3) + ca.set_serial_number(1) + ca.get_subject().CN = domain + ca.gmtime_adj_notBefore(0) + # valid for ROUGHLY 10 years. years(ish) * days * hours * mins * secs. + # the paramater is in seconds, which is why we need to multiply them all together. + ca.gmtime_adj_notAfter(10 * 365 * 24 * 60 * 60) + ca.set_issuer(ca.get_subject()) + ca.set_pubkey(key) + ca.add_extensions([ + OpenSSL.crypto.X509Extension("basicConstraints", + True, + "CA:TRUE, pathlen:0"), + OpenSSL.crypto.X509Extension("keyUsage", + True, + "keyCertSign, cRLSign"), + OpenSSL.crypto.X509Extension("subjectKeyIdentifier", + False, + "hash", + subject = ca),]) + ca.sign(key, "sha512") + #print OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, ca) + return(ca) + +def sslCKey(): + key = OpenSSL.crypto.PKey() + print("{0}: Generating SSL Client key...".format(datetime.datetime.now())) + key.generate_key(OpenSSL.crypto.TYPE_RSA, 4096) + #print OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) + return(key) + +def sslCSR(conf, key): + domain = (re.sub('^(https?|ftp)://([a-z0-9.-]+)/?.*$', '\g<2>', + conf['ipxe']['uri'], + flags=re.IGNORECASE)).lower() + csr = OpenSSL.crypto.X509Req() + csr.get_subject().CN = domain + csr.set_pubkey(key) + csr.sign(key, "sha512") + #print OpenSSL.crypto.dump_certificate_request(OpenSSL.crypto.FILETYPE_PEM, req) + return(csr) + +def sslSign(ca, key, csr): + ca_cert = OpenSSL.crypto.load_certificate(ca) + ca_key = OpenSSL.crypto.load_privatekey(key) + req = OpenSSL.crypto.load_certificate_request(csr) + cert = OpenSSL.crypto.X509() + cert.set_subject(req.get_subject()) + cert.set_serial_number(1) + cert.gmtime_adj_notBefore(0) + cert.gmtime_adj_notAfter(24 * 60 * 60) + cert.set_issuer(ca_cert.get_subject()) + cert.set_pubkey(req.get_pubkey()) + cert.sign(ca_key, "sha512") + #print OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert) + return(cert) diff --git a/bdisk/ipxe.py b/bdisk/ipxe.py index fea2fa6..b49bdbb 100755 --- a/bdisk/ipxe.py +++ b/bdisk/ipxe.py @@ -3,12 +3,32 @@ import shutil import jinja2 import git import patch -import OpenSSL import datetime +import bSSL def sslIPXE(conf): + try: + ca = conf['ipxe']['ssl_ca'] + except: + ca = None + try: + cakey = conf['ipxe']['ssl_cakey'] + except: + cakey = None + try: + crt = conf['ipxe']['ssl_crt'] + except: + crt = None + try: + key = conf['ipxe']['ssl_key'] + except: + key = None # http://www.pyopenssl.org/en/stable/api/crypto.html#pkey-objects + # http://docs.ganeti.org/ganeti/2.14/html/design-x509-ca.html + if not cakey: + cakey = bSSL.sslCAKey + pass def buildIPXE(conf): @@ -34,15 +54,17 @@ def buildIPXE(conf): eiso_commit = '189652b03032305a2db860e76fb58e81e3420c4d' nopie_commit = '58557055e51b2587ad3843af58075de916e5399b' # patch files - #cwd = os.getcwd() - #os.chdir(ipxe_src + '/src') for p in ('01.git-version.patch.j2', '02.banner.patch.j2'): try: patchfile = patch.fromfile(patches_dir + '/' + p) patchfile.apply(strip = 2, root = ipxe_src + '/src') except: pass - #os.chdir(cwd) # Patch using the files before applying the cherrypicks ipxe_repo.git.cherry_pick('-n', eiso_commit) ipxe_repo.git.cherry_pick('-n', nopie_commit) + # Now we make! + cwd = os.getcwd() + os.chdir(ipxe_src + '/src') + + os.chdir(cwd) diff --git a/docs/BDisk_User_Manual.v1.fodt b/docs/BDisk_User_Manual.v1.fodt index 5def90f..4e71e3d 100644 --- a/docs/BDisk_User_Manual.v1.fodt +++ b/docs/BDisk_User_Manual.v1.fodt @@ -1,24 +1,24 @@ - 2016-12-01T11:27:37.6655108212016-12-03T23:47:18.021215054PT11H14M18S19LibreOffice/5.2.3.3$Linux_X86_64 LibreOffice_project/20m0$Build-3 + 2016-12-01T11:27:37.6655108212016-12-04T05:22:38.498441678PT12H18M12S33LibreOffice/5.2.3.3$Linux_X86_64 LibreOffice_project/20m0$Build-3 - 59055 + 96203 0 40748 - 21751 + 20719 true false view2 - 14079 - 77479 + 14942 + 106932 0 - 59055 + 96203 40746 - 80804 + 116919 0 1 false @@ -69,7 +69,7 @@ false false true - 396750 + 947814 false false true @@ -122,6 +122,7 @@ + @@ -235,13 +236,24 @@ - + + + + + + + + + + + + @@ -297,7 +309,7 @@ - + @@ -322,96 +334,230 @@ - + + + + - + + + + - + - + - + - - - - + - + - - - + + + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -420,6 +566,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -451,12 +649,12 @@ - BDisk ManualPage 2 of 3 + BDisk ManualPage 5 of 5 - Saturday, December 3, 2016 + Sunday, December 4, 2016 @@ -470,18 +668,18 @@ - BDISK - Manual v1.0 + BDISK + Manual v1.0 Brent Saner bts@square-r00t.net - + Table of Contents - + @@ -563,32 +761,90 @@ - Table of Contents + Table of Contents - Chapter I: Introduction3 - Section I.1: What is BDisk?3 - Section I.2: Who wrote it?3 - Section I.3: What is this document?3 - Section I.4: Conventions used in this document3 - Section I.5: Further information/resources3 - I.5.i: For Developers3 + Chapter I: Introduction3 + Section I.1: What is BDisk?3 + Section I.2: Who wrote it?3 + Section I.3: What is this document?3 + I.3.i: Conventions used in this document3 + Section I.4: Further information/resources3 + I.4.i: For Users3 + I.4.ii: For Developers4 + Chapter II: Getting Started4 - - Introduction - What is BDisk? - BDisk refers to both a live distribution I use in my own uses (for rescue situations, recovery, etc.) but foremost and most importantly, it refers to the tool I use for building that distribution. This is what this project and documentation refer to when the word “BDisk” is used. + + Introduction + What is BDisk? + BDisk refers to both a live distribution I use in my own uses (for rescue situations, recovery, etc.) but foremost and most importantly, it refers to the tool I use for building that distribution. This is what this project and documentation refer to when the word “BDisk” is used. BDisk is GPLv3-licensed. This means that you can use it for business reasons, personal reasons, modify it, etc. There are a few restrictions I retain, however, on this (don’t worry; they’re all in line with the GPLv3). You can find the full license in docs/LICENSE. - Who wrote it? - I (Brent Saner) am a GNU/Linux Systems/Network Administrator/Engineer- I wear a lot of hats. I have a lot of side projects to keep me busy when I’m not working at ${dayjob}, mostly to assist in other side projects and become more efficient and proficient. - What is this document? - Conventions used in this document - Further information/resources - For Users - If you encounter any bugs (or have any suggestions on how to improve BDisk!), please file a bug report in my bug tracker. - For Developers - The source is available to browse online or can be checked out via git (via the git protocol or http protocol). It is also available via Arch Linux’s AUR. If you are interested in packaging BDisk for other distributions, please feel free to contact me. - + When I rewrote BDisk in Python 3.x (I should take the time to note that I am still quite new to python so expect there to be plenty of optimizations to be made and general WTF-ery from seasoned python developers), one of my main goals was to make it as easy to use as possible. This is surprisingly hard to do- it’s quite challenging to try to approach software you’ve written with the mindset of someone other than you. Please see the For Users section (I.4.i). + Who wrote it? + I (Brent Saner) am a GNU/Linux Systems/Network Administrator/Engineer- I wear a lot of hats. I have a lot of side projects to keep me busy when I’m not working at ${dayjob}, mostly to assist in other side projects and become more efficient and proficient at those tasks. “Shaving the yak,” indeed. + I did a lot of research into how low-level boot operations take place, both in BIOS and UEFI1 + Unified Extensible Firmware Interface. UEFI is not BIOS, and BIOS is not UEFI. (and corresponding concepts such as Secureboot, etc.) which is no easy task to understand and very commonly misunderstood. (For instance, a common misconception is that UEFI necessarily implies Secureboot. This is quite far from the truth and UEFI by itself is quite a useful replacement for BIOS). Many of these misconceptions are simply due to lack of knowledge about the intricacies and complexities behind these technologies. Some of it is simply FUD2 + Fear, Uncertainty, Doubt- propaganda, in other words. generated to prey on the fears of those who don’t understand the underlying specifications or technology. + It’s my hope that by releasing this utility and documenting it that you can use it and save some time for yourself as well (and hopefully get the chance to learn a bit more in the process!). + What is this document? + This document is intended to be an indexed and easier-to-use reference than the other plaintext files (in docs/). + Conventions used in this document + There are certain formats used in this document to specify what type of text they are representing. + + + Commands will be in italics. + + + e.g. cat /tmp/file.txt + + + + + Paths (files, directories) will be in bold (unless part of a command, output, etc.). + + + e.g. /tmp/file.txt + + + + + Variables will be underlined + + + e.g. print(foo) + + + + + URLs (hyperlinks, really; you should be able to click on them) are bold and underlined. + + + e.g. https://bdisk.square-r00t.net + + + + + Paramaters/arguments will be either in <angled brackets>, [square brackets], or [<both>] + + + <> are used for positional arguments/parameters, or “placeholders” + + + [] are used for optional arguments/parameters + + + Thus e.g. someprog –dostuff <stufftodo> [--domorestuff <morestufftodo>] + + + + + Further information/resources + For Users + If you encounter any bugs (or have any suggestions on how to improve BDisk!), please file a bug report in my bug tracker. + For Developers + The source is available to browse online or can be checked out via git (via the git protocol or http protocol). It is also available via Arch Linux’s AUR. If you are interested in packaging BDisk for other distributions, please feel free to contact me. + Getting Started + \ No newline at end of file diff --git a/docs/TODO b/docs/TODO index 8a17eb1..7847196 100644 --- a/docs/TODO +++ b/docs/TODO @@ -14,6 +14,7 @@ -- (http://blog.due.io/2014/linode-digitalocean-and-vultr-comparison/ etc.) -implement pyalpm to decreate dependency on chroot pacman-ing? --or even maybe https://wiki.archlinux.org/index.php/offline_installation_of_packages in pure python! +-set up automatic exporting to PDF of the user manual server-side. https://pypi.python.org/pypi/unoconv/0.6 ## NETWORKING ## diff --git a/extra/bin/hashgen.php b/extra/bin/hashgen.php deleted file mode 100644 index 1476ba9..0000000 --- a/extra/bin/hashgen.php +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/extra/pre-build.d/etc/systemd/system/pacmandb.service b/extra/pre-build.d/etc/systemd/system/pacmandb.service index cda181f..edefa06 100644 --- a/extra/pre-build.d/etc/systemd/system/pacmandb.service +++ b/extra/pre-build.d/etc/systemd/system/pacmandb.service @@ -4,7 +4,7 @@ Description=Restoring Installed Packages DB [Service] Type=oneshot #ExecStart=/usr/bin/tar -Jxf /usr/local/pacman.db.tar.xz -C /var/lib/pacman/ -ExecStart=/etc/systemd/system/scripts/pacmandb.sh +ExecStart=/usr/bin/bash /etc/systemd/system/scripts/pacmandb.sh RemainAfterExit=yes [Install]