Initial commit...
This commit is contained in:
parent
58c94cc4e1
commit
5e38b5557d
|
@ -1,3 +1,10 @@
|
|||
# EzyCA
|
||||
Easily create Certificate Authorities and sign a server PEM and key for use.
|
||||
|
||||
Easily create Certificate Authorities and sign a server PEM and key for use.
|
||||
# Requirements
|
||||
* Need Python 3+
|
||||
* Need OpenSSL
|
||||
* Need PyGObject
|
||||
# Images
|
||||
![1 Interface CA.... ](images/pic1.png)
|
||||
![2 Interface Server Cert.... ](images/pic2.png)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 141 KiB |
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
|
@ -0,0 +1,33 @@
|
|||
# Python imports
|
||||
import inspect
|
||||
|
||||
|
||||
# Gtk imports
|
||||
|
||||
|
||||
# Application imports
|
||||
from utils import Settings
|
||||
from signal_classes import Signals
|
||||
|
||||
|
||||
class Main:
|
||||
def __init__(self, args):
|
||||
settings = Settings()
|
||||
builder = settings.returnBuilder()
|
||||
|
||||
# Gets the methods from the classes and sets to handler.
|
||||
# Then, builder connects to any signals it needs.
|
||||
classes = [Signals(settings)]
|
||||
|
||||
handlers = {}
|
||||
for c in classes:
|
||||
methods = None
|
||||
try:
|
||||
methods = inspect.getmembers(c, predicate=inspect.ismethod)
|
||||
handlers.update(methods)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
builder.connect_signals(handlers)
|
||||
window = settings.createWindow()
|
||||
window.show()
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
|
||||
# Python imports
|
||||
import argparse
|
||||
from setproctitle import setproctitle
|
||||
|
||||
# Gtk imports
|
||||
import gi, faulthandler, signal
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk as gtk
|
||||
from gi.repository import GLib
|
||||
|
||||
# Application imports
|
||||
from __init__ import Main
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
setproctitle('EzyCA')
|
||||
GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signal.SIGINT, gtk.main_quit)
|
||||
faulthandler.enable() # For better debug info
|
||||
parser = argparse.ArgumentParser()
|
||||
# Add long and short arguments
|
||||
parser.add_argument("--file", "-f", default="default", help="JUST SOME FILE ARG.")
|
||||
|
||||
# Read arguments (If any...)
|
||||
args = parser.parse_args()
|
||||
main = Main(args)
|
||||
gtk.main()
|
||||
except Exception as e:
|
||||
print( repr(e) )
|
|
@ -0,0 +1,399 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.20"/>
|
||||
<object class="GtkImage" id="generate_img">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="stock">gtk-file</property>
|
||||
<property name="icon_size">3</property>
|
||||
</object>
|
||||
<object class="GtkTextBuffer" id="textview_buffer"/>
|
||||
<object class="GtkApplicationWindow" id="Main_Window">
|
||||
<property name="width-request">800</property>
|
||||
<property name="height-request">600</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="title" translatable="yes">EzyCA</property>
|
||||
<property name="icon">x509_cert_64x64.png</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-left">10</property>
|
||||
<property name="label" translatable="yes">Target Directory: </property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkFileChooserButton">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<property name="margin-top">15</property>
|
||||
<property name="margin-bottom">15</property>
|
||||
<property name="action">select-folder</property>
|
||||
<property name="do-overwrite-confirmation">True</property>
|
||||
<property name="preview-widget-active">False</property>
|
||||
<property name="use-preview-label">False</property>
|
||||
<property name="title" translatable="yes">Target Directory...</property>
|
||||
<signal name="file-set" handler="set_work_directory" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="xpad">25</property>
|
||||
<property name="ypad">10</property>
|
||||
<property name="pixbuf">x509_cert.png</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkNotebook">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="ca_entry_vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">15</property>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="max-length">2</property>
|
||||
<property name="placeholder-text" translatable="yes">Country Name (2 letter code eg, US)</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
<signal name="key-release-event" handler="set_server_country" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="max-length">32</property>
|
||||
<property name="placeholder-text" translatable="yes">State or Province Name (full name eg, 'North Carolina')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
<signal name="key-release-event" handler="set_server_state" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Locality/City Name (full name eg, 'Durham')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
<signal name="key-release-event" handler="set_server_city" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Organization Name (eg, company 'Microsoft')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
<signal name="key-release-event" handler="set_server_org" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Organizational Unit (eg, division 'Microsoft Developent')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Common Name (e.g. server FQDN or YOUR name 'Microsoft CA')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Email Address (eg, 'no-reply@microsoft.com')</property>
|
||||
<property name="input-purpose">email</property>
|
||||
<signal name="key-release-event" handler="set_server_email" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab-expand">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">CA Conf</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="tab-fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="server_entry_vbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">15</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="svrCountry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="max-length">2</property>
|
||||
<property name="placeholder-text" translatable="yes">Country Name (2 letter code eg, US)</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="svrState">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="max-length">32</property>
|
||||
<property name="placeholder-text" translatable="yes">State or Province Name (full name eg, 'North Carolina')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="svrCity">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Locality/City Name (full name eg, 'Durham')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="svrOrg">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Organization Name (eg, company 'Microsoft')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Common Name (e.g. server FQDN or YOUR name 'Microsoft Test Server')</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkEntry" id="svrEmail">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="placeholder-text" translatable="yes">Email Address (eg, 'no-reply@microsoft.com')</property>
|
||||
<property name="input-purpose">email</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">5</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="ypad">10</property>
|
||||
<property name="label" translatable="yes">Below, add domain names each on a new line...</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="track-visited-links">False</property>
|
||||
<attributes>
|
||||
<attribute name="underline" value="True"/>
|
||||
<attribute name="foreground" value="#ffffa3a34848"/>
|
||||
</attributes>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">6</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="shadow-type">in</property>
|
||||
<property name="overlay-scrolling">False</property>
|
||||
<child>
|
||||
<object class="GtkTextView">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="buffer">textview_buffer</property>
|
||||
<property name="accepts-tab">False</property>
|
||||
<property name="input-purpose">alpha</property>
|
||||
<property name="monospace">True</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">7</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab-expand">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<object class="GtkLabel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="label" translatable="yes">Server Conf</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
<property name="tab-fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
<child type="tab">
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton">
|
||||
<property name="label" translatable="yes">Generate</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="margin-left">10</property>
|
||||
<property name="margin-right">10</property>
|
||||
<property name="margin-top">15</property>
|
||||
<property name="margin-bottom">15</property>
|
||||
<property name="image">generate_img</property>
|
||||
<property name="use-underline">True</property>
|
||||
<property name="always-show-image">True</property>
|
||||
<signal name="clicked" handler="generate_ca_and_server_certs" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
|
@ -0,0 +1,19 @@
|
|||
/* * {
|
||||
background: rgba(0, 0, 0, 0.14);
|
||||
background: rgba(0, 0, 0, 1);
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
notebook > header {
|
||||
border-color: rgba(0, 232, 255, 0.64);
|
||||
}
|
||||
|
||||
* selection {
|
||||
background-color: rgba(75, 0, 116, 0.65);
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
textarea.view {
|
||||
border-style: solid;
|
||||
border-color: rgba(255, 255, 255, 1);
|
||||
} */
|
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,130 @@
|
|||
# Python imports
|
||||
import threading, subprocess, os
|
||||
|
||||
# Gtk imports
|
||||
|
||||
# Application imports
|
||||
from .mixins import *
|
||||
|
||||
|
||||
def threaded(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
threading.Thread(target=fn, args=args, kwargs=kwargs).start()
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class Signals(Utils, CAGenerator, ServerCertGenerator):
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
self.builder = self.settings.returnBuilder()
|
||||
|
||||
self.ca_entry_vbox = self.builder.get_object("ca_entry_vbox")
|
||||
self.server_entry_vbox = self.builder.get_object("server_entry_vbox")
|
||||
self.textview_buffer = self.builder.get_object("textview_buffer")
|
||||
|
||||
self.target_path = None
|
||||
|
||||
|
||||
def set_work_directory(self, widget, data=None):
|
||||
self.target_path = widget.get_filename()
|
||||
|
||||
|
||||
def generate_ca_and_server_certs(self, widget):
|
||||
print("Generating CA and signed Server Certs...")
|
||||
ca_data = []
|
||||
server_cert_data = []
|
||||
ca_entries = self.ca_entry_vbox.get_children()
|
||||
server_entries = self.server_entry_vbox.get_children()
|
||||
|
||||
self.fill_data_block(ca_data, ca_entries)
|
||||
self.fill_data_block(server_cert_data, server_entries)
|
||||
|
||||
buffer = self.textview_buffer
|
||||
domains = buffer.get_text(
|
||||
buffer.get_start_iter(),
|
||||
buffer.get_end_iter(),
|
||||
True
|
||||
).strip().split("\n")
|
||||
|
||||
assert(self.target_path != None and self.target_path != ''), "A target work directory must be set!"
|
||||
assert(len(ca_data) == len(ca_entries)), "All CA entries must be filled!"
|
||||
assert(len(server_cert_data) == (len(server_entries) - 2) ), "All Server Cert entries must be filled!"
|
||||
|
||||
|
||||
self.step_1_create_ca_settings(self.target_path, ca_data)
|
||||
self.step_2_create_signing_ca_settings(self.target_path, ca_data)
|
||||
self.step_3_create_openssl_server_cert_settings(self.target_path, server_cert_data, domains)
|
||||
self.step_4_generate_all(self.target_path)
|
||||
|
||||
|
||||
def step_4_generate_all(self, target_path):
|
||||
print("Step 4: Running generation process...")
|
||||
opensslcacnf = target_path + "/openssl-ca-settings.cnf"
|
||||
opensslsigningcasettingscnf = target_path + "/openssl-signing-ca-settings.cnf"
|
||||
opensslservercnf = target_path + "/openssl-server-cert.cnf"
|
||||
|
||||
signedcertsdir = target_path + "/signed_certs"
|
||||
cacertpem = target_path + "/cacert.pem"
|
||||
servercertpem = target_path + "/servercert.pem"
|
||||
servercertcsr = target_path + "/servercert.csr"
|
||||
indexfile = target_path + "/index.txt"
|
||||
serialfile = target_path + "/serial.txt"
|
||||
|
||||
|
||||
os.chdir(target_path)
|
||||
os.mkdir(signedcertsdir)
|
||||
with open(indexfile, 'a') as f:
|
||||
f.close()
|
||||
with open(serialfile, 'w') as f:
|
||||
f.write("01")
|
||||
|
||||
print("\t\tCreating CA cert key...")
|
||||
# openssl req -batch -x509 -days 10000 -config ./openssl-ca.cnf -newkey
|
||||
# rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM
|
||||
command = ["openssl", "req", "-batch", "-x509", "-days", "10000", "-config", opensslcacnf, "-newkey", "rsa:4096",
|
||||
"-sha256", "-nodes", "-out", cacertpem, "-outform", "PEM"]
|
||||
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||
proc.wait()
|
||||
# You can dump the certificate with the following.
|
||||
# openssl x509 -in cacert.pem -text -noout
|
||||
|
||||
|
||||
print("\t\tCreating Server cert key pare...")
|
||||
# openssl req -batch -config ./openssl-server.cnf -newkey rsa:2048
|
||||
# -sha256 -nodes -out servercert.csr -outform PEM
|
||||
command = ["openssl", "req", "-batch", "-config", opensslservercnf, "-newkey", "rsa:4096", "-sha256", "-nodes",
|
||||
"-out", servercertcsr, "-outform", "PEM"]
|
||||
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||
proc.wait()
|
||||
# You can inspect.
|
||||
# openssl req -text -noout -verify -in servercert.csr
|
||||
|
||||
|
||||
print("\t\tCertifying Server cert with our CA...")
|
||||
# openssl ca -batch -config ./openssl-ca.cnf -policy signing_policy
|
||||
# -extensions signing_req -out servercert.pem -infiles servercert.csr
|
||||
command = ["openssl", "ca", "-batch", "-config", opensslsigningcasettingscnf,
|
||||
"-policy", "signing_policy", "-extensions", "signing_req", "-out",
|
||||
servercertpem, "-infiles", "servercert.csr"]
|
||||
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
|
||||
proc.wait()
|
||||
# Finally, you can inspect your freshly minted certificate with the following:
|
||||
# openssl x509 -in servercert.pem -text -noout
|
||||
|
||||
|
||||
|
||||
def set_server_country(self, widget, data=None):
|
||||
self.builder.get_object("svrCountry").set_text(widget.get_text().strip())
|
||||
|
||||
def set_server_state(self, widget, data=None):
|
||||
self.builder.get_object("svrState").set_text(widget.get_text().strip())
|
||||
|
||||
def set_server_city(self, widget, data=None):
|
||||
self.builder.get_object("svrCity").set_text(widget.get_text().strip())
|
||||
|
||||
def set_server_org(self, widget, data=None):
|
||||
self.builder.get_object("svrOrg").set_text(widget.get_text().strip())
|
||||
|
||||
def set_server_email(self, widget, data=None):
|
||||
self.builder.get_object("svrEmail").set_text(widget.get_text().strip())
|
|
@ -0,0 +1,5 @@
|
|||
"""
|
||||
Gtk Bound Signal Module
|
||||
"""
|
||||
from .mixins import *
|
||||
from .Signals import Signals
|
|
@ -0,0 +1,210 @@
|
|||
# Python imports
|
||||
import threading, subprocess, os
|
||||
|
||||
# Gtk imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class CAGenerator:
|
||||
"""Empty docstring for CAGenerator"""
|
||||
ca_settings = """# ----------------------------- NOTE
|
||||
# Remember to disable very bottom when generating first ca key and pem.
|
||||
# Check notes at [ CA_default ] section as well!
|
||||
# ----------------------------- NOTE
|
||||
|
||||
HOME = {}
|
||||
RANDFILE = $ENV::HOME/.rnd
|
||||
|
||||
####################################################################
|
||||
[ ca ]
|
||||
default_ca = CA_default # The default ca section
|
||||
|
||||
[ CA_default ]
|
||||
default_days = 3000 # How long to certify for
|
||||
default_crl_days = 3000 # How long before next CRL
|
||||
default_md = sha256 # Use public key default MD
|
||||
preserve = no # Keep passed DN ordering
|
||||
x509_extensions = ca_extensions # The extensions to add to the cert
|
||||
email_in_dn = no # Don't concat the email in the DN
|
||||
copy_extensions = copy # Required to copy SANs from CSR to cert
|
||||
|
||||
# ca_default_additional_block_marker
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 4096
|
||||
default_keyfile = cakey.pem
|
||||
distinguished_name = ca_distinguished_name
|
||||
x509_extensions = ca_extensions
|
||||
string_mask = utf8only
|
||||
|
||||
|
||||
####################################################################
|
||||
[ ca_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = {}
|
||||
stateOrProvinceName = State or Province Name (full name eg, 'North Carolina')
|
||||
stateOrProvinceName_default = {}
|
||||
localityName = Locality/City Name (full name eg, 'Durham')
|
||||
localityName_default = {}
|
||||
organizationName = Organization Name (eg, company 'Microsoft')
|
||||
organizationName_default = {}
|
||||
organizationalUnitName = Organizational Unit (eg, division)
|
||||
organizationalUnitName_default = {}
|
||||
commonName = Common Name (e.g. server FQDN or YOUR name)
|
||||
commonName_default = {}
|
||||
emailAddress = Email Address (eg, 'no-reply@microsoft.com')
|
||||
emailAddress_default = {}
|
||||
|
||||
|
||||
####################################################################
|
||||
[ ca_extensions ]
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always, issuer
|
||||
basicConstraints = critical, CA:true
|
||||
keyUsage = keyCertSign, cRLSign
|
||||
|
||||
# Extensions for a typical CA
|
||||
# PKIX recommendation.
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer
|
||||
basicConstraints = critical,CA:true
|
||||
|
||||
# Key usage: This is typical for a CA certificate. However since it will prevent
|
||||
# it being used as an test self-signed certificate it is best left out by default.
|
||||
# keyUsage = cRLSign, keyCertSign
|
||||
|
||||
# Some might want this also...
|
||||
# nsCertType = sslCA, emailCA
|
||||
|
||||
# subjectAltName=email:copy # Include email address in subject alt name: another PKIX recommendation
|
||||
# issuerAltName=issuer:copy # Copy issuer details
|
||||
|
||||
# DER hex encoding of an extension: Beware experts only!
|
||||
# obj=DER:02:03 # Where 'obj' is a standard or added object
|
||||
# basicConstraints= critical, DER:30:03:01:01:FF # You can even override a supported extension.
|
||||
|
||||
|
||||
####################################################################
|
||||
[ crl_ext ]
|
||||
# CRL extensions. Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||
# issuerAltName = issuer:copy
|
||||
authorityKeyIdentifier = keyid:always
|
||||
|
||||
|
||||
####################################################################
|
||||
[ proxy_cert_ext ]
|
||||
# These extensions should be added when creating a proxy certificate
|
||||
# This goes against PKIX guidelines but some CAs do it and some software
|
||||
# requires this to avoid interpreting an end user certificate as a CA.
|
||||
basicConstraints=CA:FALSE
|
||||
|
||||
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||
# the certificate can be used for anything *except* object signing.
|
||||
# nsCertType = server # This is OK for an SSL server.
|
||||
# nsCertType = objsign # For an object signing certificate this would be used.
|
||||
# nsCertType = client, email # For normal client using this is typical.
|
||||
# nsCertType = client, email, objsign # For everything including object signing.
|
||||
|
||||
# This is typical in keyUsage for a client certificate.
|
||||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
# This will be displayed in Netscape's comment listbox.
|
||||
nsComment = 'OpenSSL Generated Certificate'
|
||||
|
||||
# PKIX recommendations harmless if included in all certificates.
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid,issuer
|
||||
|
||||
# This stuff is for subjectAltName and issuerAltname.
|
||||
# subjectAltName = email:copy # Import the email address.
|
||||
# subjectAltName = email:move # An alternative to produce certificates that aren't deprecated according to PKIX.
|
||||
# issuerAltName = issuer:copy # Copy subject details
|
||||
|
||||
#nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem
|
||||
#nsBaseUrl
|
||||
#nsRevocationUrl
|
||||
#nsRenewalUrl
|
||||
#nsCaPolicyUrl
|
||||
#nsSslServerName
|
||||
|
||||
# This really needs to be in place for it to be a proxy certificate.
|
||||
proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo
|
||||
|
||||
|
||||
####################################################################
|
||||
[ tsa ]
|
||||
default_tsa = tsa_config1 # The default TSA section (Which is set below...)
|
||||
|
||||
[ tsa_config1 ]
|
||||
# These are used by the TSA reply generation only.
|
||||
dir = /etc/ssl # TSA root directory
|
||||
serial = $dir/tsaserial # The current serial number
|
||||
crypto_device = builtin # OpenSSL engine to use for signing
|
||||
signer_cert = $dir/tsacert.pem # The TSA signing certificate (optional)
|
||||
certs = $dir/cacert.pem # Certificate chain to include in reply (optional)
|
||||
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
|
||||
signer_digest = sha256 # Signing digest to use. (optional)
|
||||
default_policy = tsa_policy1 # Policy if request did not specify it (optional)
|
||||
other_policies = tsa_policy2, tsa_policy3 # Acceptable policies (optional)
|
||||
digests = sha1, sha256, sha384, sha512 # Acceptable message digests
|
||||
accuracy = secs:1, millisecs:500, microsecs:100 # (optional)
|
||||
clock_precision_digits = 0 # Number of digits after dot. (optional)
|
||||
ordering = yes # Is ordering defined for timestamps? (optional, default: no)
|
||||
tsa_name = yes # Must the TSA name be included in the reply? (optional, default: no)
|
||||
ess_cert_id_chain = no # Must the ESS cert id chain be included? (optional, default: no)
|
||||
ess_cert_id_alg = sha1 # Algorithm to compute certificate identifier (optional, default: sha1)
|
||||
|
||||
# ca_signing_block_marker
|
||||
"""
|
||||
|
||||
ca_default_additional_block = """base_dir = {}
|
||||
certificate = $base_dir/cacert.pem # The CA certifcate
|
||||
private_key = $base_dir/cakey.pem # The CA private key
|
||||
new_certs_dir = $base_dir/signed_certs/ # Location for new certs after signing
|
||||
database = $base_dir/index.txt # Database index file
|
||||
serial = $base_dir/serial.txt # The current serial number
|
||||
unique_subject = no # Set to 'no' to allow creation of several certificates with same subject.
|
||||
"""
|
||||
|
||||
ca_signing_block = """####################################################################
|
||||
[ signing_policy ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ signing_req ]
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = digitalSignature, keyEncipherment
|
||||
"""
|
||||
|
||||
|
||||
def step_1_create_ca_settings(self, path, data):
|
||||
print("Step 1: Creating CA Settings...")
|
||||
all_data = [path] + data
|
||||
fpath = path + "/openssl-ca-settings.cnf"
|
||||
output_str = self.ca_settings.format(*all_data)
|
||||
|
||||
with open(fpath, "w") as f:
|
||||
f.write(output_str)
|
||||
|
||||
|
||||
def step_2_create_signing_ca_settings(self, path, data):
|
||||
print("Step 2: Creating Signing CA Settings...")
|
||||
all_data = [path] + data
|
||||
fpath = path + "/openssl-signing-ca-settings.cnf"
|
||||
output_str = self.ca_settings.format(*all_data)
|
||||
ca_block = self.ca_default_additional_block.format(path)
|
||||
|
||||
output_str = output_str.replace("# ca_default_additional_block_marker", ca_block)
|
||||
output_str = output_str.replace("# ca_signing_block_marker", self.ca_signing_block)
|
||||
|
||||
with open(fpath, "w") as f:
|
||||
f.write(output_str)
|
|
@ -0,0 +1,83 @@
|
|||
# Python imports
|
||||
import threading, subprocess, os
|
||||
|
||||
# Gtk imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class ServerCertGenerator:
|
||||
"""Empty docstring for ServerCertGenerator"""
|
||||
|
||||
server_cert_settings = """# ----------------------------- NOTE
|
||||
HOME = {}
|
||||
RANDFILE = $ENV::HOME/.rnd
|
||||
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_keyfile = privkey.pem
|
||||
distinguished_name = server_distinguished_name
|
||||
req_extensions = server_req_extensions
|
||||
string_mask = utf8only
|
||||
|
||||
|
||||
####################################################################
|
||||
[ server_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = {}
|
||||
stateOrProvinceName = State or Province Name (full name eg, 'North Carolina')
|
||||
stateOrProvinceName_default = {}
|
||||
localityName = Locality/City Name (full name eg, 'Durham')
|
||||
localityName_default = {}
|
||||
organizationName = Organization Name (eg, company 'Microsoft')
|
||||
organizationName_default = {}
|
||||
commonName = Common Name (e.g. server FQDN or YOUR name)
|
||||
commonName_default = {}
|
||||
emailAddress = Email Address (eg, 'no-reply@microsoft.com')
|
||||
emailAddress_default = {}
|
||||
|
||||
|
||||
####################################################################
|
||||
[ server_req_extensions ]
|
||||
subjectKeyIdentifier = hash
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = digitalSignature, keyEncipherment
|
||||
subjectAltName = @alternate_names
|
||||
nsComment = "OpenSSL Generated Certificate"
|
||||
|
||||
####################################################################
|
||||
[ alternate_names ]
|
||||
# alternate_names_marker
|
||||
|
||||
|
||||
# If you are developing and need to use your workstation as a server, then you may
|
||||
# need to do the following for Chrome. Otherwise Chrome may complain a Common Name
|
||||
# is invalid (ERR_CERT_COMMON_NAME_INVALID). I'm not sure what the relationship is
|
||||
# between an IP address in the SAN and a CN in this instance.
|
||||
|
||||
# IPv4 localhost
|
||||
IP.1 = 0.0.0.0
|
||||
IP.2 = 127.0.0.1
|
||||
|
||||
# IPv6 localhost
|
||||
IP.2 = ::1
|
||||
"""
|
||||
|
||||
|
||||
def step_3_create_openssl_server_cert_settings(self, path, data, domains):
|
||||
print("Step 3: Creating OpenSSL Server Cert Settings...")
|
||||
all_data = [path] + data
|
||||
fpath = path + "/openssl-server-cert.cnf"
|
||||
output_str = self.server_cert_settings.format(*all_data)
|
||||
domain_block = ""
|
||||
i = 1
|
||||
|
||||
for domain in domains:
|
||||
domain_block += "DNS.{} = {}".format(*(i, domain + "\n"))
|
||||
i += 1
|
||||
|
||||
output_str = output_str.replace("# alternate_names_marker", domain_block)
|
||||
with open(fpath, "w") as f:
|
||||
f.write(output_str)
|
|
@ -0,0 +1,35 @@
|
|||
# Python imports
|
||||
import threading, subprocess, os
|
||||
|
||||
# Gtk imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Utils:
|
||||
"""Empty docstring for Utils"""
|
||||
|
||||
def fill_data_block(self, target, data):
|
||||
for entry in data:
|
||||
text = ''
|
||||
|
||||
if hasattr(entry, "get_children"):
|
||||
entry = entry.get_children()[0]
|
||||
|
||||
if hasattr(entry, "get_text"):
|
||||
text = entry.get_text().strip()
|
||||
|
||||
if text != '' and text != 'Below, add domain names each on a new line...':
|
||||
target.append(text)
|
||||
|
||||
def getClipboardData(self):
|
||||
proc = subprocess.Popen(['xclip','-selection', 'clipboard', '-o'], stdout=subprocess.PIPE)
|
||||
retcode = proc.wait()
|
||||
data = proc.stdout.read()
|
||||
return data.decode("utf-8").strip()
|
||||
|
||||
def setClipboardData(self, data):
|
||||
proc = subprocess.Popen(['xclip','-selection','clipboard'], stdin=subprocess.PIPE)
|
||||
proc.stdin.write(data)
|
||||
proc.stdin.close()
|
||||
retcode = proc.wait()
|
|
@ -0,0 +1,3 @@
|
|||
from .Utils import Utils
|
||||
from .CAGenerator import CAGenerator
|
||||
from .ServerCertGenerator import ServerCertGenerator
|
|
@ -0,0 +1,56 @@
|
|||
# Python imports
|
||||
import os, logging
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Logger:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def get_logger(self, loggerName = "NO_LOGGER_NAME_PASSED", createFile = True):
|
||||
"""
|
||||
Create a new logging object and return it.
|
||||
:note:
|
||||
NOSET # Don't know the actual log level of this... (defaulting or literally none?)
|
||||
Log Levels (From least to most)
|
||||
Type Value
|
||||
CRITICAL 50
|
||||
ERROR 40
|
||||
WARNING 30
|
||||
INFO 20
|
||||
DEBUG 10
|
||||
:param loggerName: Sets the name of the logger object. (Used in log lines)
|
||||
:param createFile: Whether we create a log file or just pump to terminal
|
||||
|
||||
:return: the logging object we created
|
||||
"""
|
||||
|
||||
globalLogLvl = logging.DEBUG # Keep this at highest so that handlers can filter to their desired levels
|
||||
chLogLevel = logging.CRITICAL # Prety musch the only one we change ever
|
||||
fhLogLevel = logging.DEBUG
|
||||
log = logging.getLogger(loggerName)
|
||||
log.setLevel(globalLogLvl)
|
||||
|
||||
# Set our log output styles
|
||||
fFormatter = logging.Formatter('[%(asctime)s] %(pathname)s:%(lineno)d %(levelname)s - %(message)s', '%m-%d %H:%M:%S')
|
||||
cFormatter = logging.Formatter('%(pathname)s:%(lineno)d] %(levelname)s - %(message)s')
|
||||
|
||||
ch = logging.StreamHandler()
|
||||
ch.setLevel(level=chLogLevel)
|
||||
ch.setFormatter(cFormatter)
|
||||
log.addHandler(ch)
|
||||
|
||||
if createFile:
|
||||
folder = "logs"
|
||||
file = folder + "/application.log"
|
||||
|
||||
if not os.path.exists(folder):
|
||||
os.mkdir(folder)
|
||||
|
||||
fh = logging.FileHandler(file)
|
||||
fh.setLevel(level=fhLogLevel)
|
||||
fh.setFormatter(fFormatter)
|
||||
log.addHandler(fh)
|
||||
|
||||
return log
|
|
@ -0,0 +1,84 @@
|
|||
# Python imports
|
||||
import os
|
||||
|
||||
# Gtk imports
|
||||
import gi, cairo
|
||||
gi.require_version('Gtk', '3.0')
|
||||
gi.require_version('Gdk', '3.0')
|
||||
|
||||
from gi.repository import Gtk as gtk
|
||||
from gi.repository import Gdk as gdk
|
||||
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
class Settings:
|
||||
def __init__(self):
|
||||
self.SCRIPT_PTH = os.path.dirname(os.path.realpath(__file__)) + "/"
|
||||
self.builder = gtk.Builder()
|
||||
self.builder.add_from_file(self.SCRIPT_PTH + "../resources/Main_Window.glade")
|
||||
|
||||
# 'Filters'
|
||||
self.office = ('.doc', '.docx', '.xls', '.xlsx', '.xlt', '.xltx', '.xlm',
|
||||
'.ppt', 'pptx', '.pps', '.ppsx', '.odt', '.rtf')
|
||||
self.vids = ('.mkv', '.avi', '.flv', '.mov', '.m4v', '.mpg', '.wmv',
|
||||
'.mpeg', '.mp4', '.webm')
|
||||
self.txt = ('.txt', '.text', '.sh', '.cfg', '.conf')
|
||||
self.music = ('.psf', '.mp3', '.ogg' , '.flac')
|
||||
self.images = ('.png', '.jpg', '.jpeg', '.gif')
|
||||
self.pdf = ('.pdf')
|
||||
|
||||
|
||||
def createWindow(self):
|
||||
# Get window and connect signals
|
||||
window = self.builder.get_object("Main_Window")
|
||||
window.connect("delete-event", gtk.main_quit)
|
||||
self.setWindowData(window, False)
|
||||
return window
|
||||
|
||||
def setWindowData(self, window, paintable):
|
||||
screen = window.get_screen()
|
||||
visual = screen.get_rgba_visual()
|
||||
|
||||
if visual != None and screen.is_composited():
|
||||
window.set_visual(visual)
|
||||
|
||||
# bind css file
|
||||
cssProvider = gtk.CssProvider()
|
||||
cssProvider.load_from_path(self.SCRIPT_PTH + '../resources/stylesheet.css')
|
||||
screen = gdk.Screen.get_default()
|
||||
styleContext = gtk.StyleContext()
|
||||
styleContext.add_provider_for_screen(screen, cssProvider, gtk.STYLE_PROVIDER_PRIORITY_USER)
|
||||
|
||||
window.set_app_paintable(paintable)
|
||||
if paintable:
|
||||
window.connect("draw", self.area_draw)
|
||||
|
||||
def getMonitorData(self):
|
||||
screen = self.builder.get_object("Main_Window").get_screen()
|
||||
monitors = []
|
||||
for m in range(screen.get_n_monitors()):
|
||||
monitors.append(screen.get_monitor_geometry(m))
|
||||
|
||||
for monitor in monitors:
|
||||
print("{}x{}+{}+{}".format(monitor.width, monitor.height, monitor.x, monitor.y))
|
||||
|
||||
return monitors
|
||||
|
||||
def area_draw(self, widget, cr):
|
||||
cr.set_source_rgba(0, 0, 0, 0.54)
|
||||
cr.set_operator(cairo.OPERATOR_SOURCE)
|
||||
cr.paint()
|
||||
cr.set_operator(cairo.OPERATOR_OVER)
|
||||
|
||||
|
||||
def returnBuilder(self): return self.builder
|
||||
|
||||
# Filter returns
|
||||
def returnOfficeFilter(self): return self.office
|
||||
def returnVidsFilter(self): return self.vids
|
||||
def returnTextFilter(self): return self.txt
|
||||
def returnMusicFilter(self): return self.music
|
||||
def returnImagesFilter(self): return self.images
|
||||
def returnPdfFilter(self): return self.pdf
|
|
@ -0,0 +1,6 @@
|
|||
"""
|
||||
Utils module
|
||||
"""
|
||||
|
||||
from .Logger import Logger
|
||||
from .Settings import Settings
|
Loading…
Reference in New Issue