Remove unneeded Go code, update dependencies
This commit is contained in:
parent
30c7ddba80
commit
4ecdedadf7
32 changed files with 175 additions and 7257 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,7 +1,5 @@
|
||||||
*.pem
|
*.pem
|
||||||
.*.swp
|
.*.swp
|
||||||
/translate.*.toml
|
|
||||||
/.idea/
|
/.idea/
|
||||||
/example_ca/
|
|
||||||
/node_modules/
|
/node_modules/
|
||||||
/public/
|
/public/
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
[CSRButtonLabel]
|
|
||||||
hash = "sha1-7f7bcb57602a96a49c8df4868fad7b81992e0734"
|
|
||||||
other = "Zertifikats-Signier-Anfrage erzeugen"
|
|
||||||
|
|
||||||
[CSRGenTitle]
|
|
||||||
hash = "sha1-f1a8f21b12fe51250da4a11f1c6ab28eab69b69d"
|
|
||||||
other = "CSR-Erzeugung im Browser"
|
|
||||||
|
|
||||||
[DownloadDescription]
|
|
||||||
hash = "sha1-f4a7826398e5c57c7feb4709ee939ea655f05469"
|
|
||||||
other = "Dein Schlüsselmaterial ist bereit zum Herunterladen. Die herunterladbare Datei enthält deinen privaten Schlüssel und dein Zertifikat verschlüsselt mit deinem Passwort. Du kannst die Datei jetzt verwenden, um dein Zertifikat in deinem Browser oder anderen Anwendungen zu installieren."
|
|
||||||
|
|
||||||
[DownloadLabel]
|
|
||||||
hash = "sha1-a479c9c34e878d07b4d67a73a48f432ad7dc53c8"
|
|
||||||
other = "Herunterladen"
|
|
||||||
|
|
||||||
["JavaScript.Certificate.Received"]
|
|
||||||
hash = "sha1-217622c21b50fcfb864802155080be482c285456"
|
|
||||||
other = "Zertifikat von der CA erhalten"
|
|
||||||
|
|
||||||
["JavaScript.Certificate.Waiting"]
|
|
||||||
hash = "sha1-0a528daa78d850d2c9360cdec82f6f849ffb6bcf"
|
|
||||||
other = "Warte auf Zertifikat ..."
|
|
||||||
|
|
||||||
["JavaScript.KeyGen.Generated"]
|
|
||||||
hash = "sha1-34cdfcdc837e3fc052733a3588cc3923b793103e"
|
|
||||||
other = "Schlüssel in __seconds__ Sekunden erzeugt"
|
|
||||||
|
|
||||||
["JavaScript.KeyGen.Running"]
|
|
||||||
hash = "sha1-fd272f37118fe10395f6238a3eae94685b5f8cf1"
|
|
||||||
other = "Schlüsselerzeugung läuft seit __seconds__ Sekunden"
|
|
||||||
|
|
||||||
["JavaScript.KeyGen.Started"]
|
|
||||||
hash = "sha1-e68739d705d5eb16317984a95a486fb9ff9bae6d"
|
|
||||||
other = "Schlüsselerzeugung gestartet"
|
|
||||||
|
|
||||||
[NameHelpText]
|
|
||||||
hash = "sha1-52b81217549e37d161090a04b7f84223a270928e"
|
|
||||||
other = "Gib deinen Namen so ein, wie er im Zertifikat erscheinen soll"
|
|
||||||
|
|
||||||
[NameLabel]
|
|
||||||
hash = "sha1-ab42293e29e1ffb306c1403dd95144d664853a60"
|
|
||||||
other = "Dein Name"
|
|
||||||
|
|
||||||
[PasswordLabel]
|
|
||||||
hash = "sha1-2b5e8edbf45819afdfa973c224b6b02d699e60de"
|
|
||||||
other = "Passwort für dein Client-Zertifikat"
|
|
||||||
|
|
||||||
[RSA2048Label]
|
|
||||||
hash = "sha1-2b1e7b638c31426d30d7e4bdebadbaa07d7521b0"
|
|
||||||
other = "2048 Bit (nicht empfohlen)"
|
|
||||||
|
|
||||||
[RSA3072Label]
|
|
||||||
hash = "sha1-97d1a8f9e8c5cf1f473b4a6fa0b5c39905f0f747"
|
|
||||||
other = "3072 Bit"
|
|
||||||
|
|
||||||
[RSA4096Label]
|
|
||||||
hash = "sha1-b14d7490195ac7f2d649f3b75dd2fe0daea53967"
|
|
||||||
other = "4096 Bit"
|
|
||||||
|
|
||||||
[RSAHelpText]
|
|
||||||
hash = "sha1-82511ecf2909ba189d7b16a828fce97c9359fad1"
|
|
||||||
other = "In Deinem Browser wird ein RSA-Schlüsselpaar erzeugt. Größere Schlüssellängen bieten eine erhöhte Sicherheit, benötigen aber bei der Erzeugung mehr Zeit."
|
|
||||||
|
|
||||||
[RSAKeySizeLabel]
|
|
||||||
hash = "sha1-bd446df78ad62000d6516a95594a24b98688e1fa"
|
|
||||||
other = "RSA-Schlüssellänge"
|
|
||||||
|
|
||||||
[StatusLoading]
|
|
||||||
hash = "sha1-530afa5bce434b05e3a10e83ff2567f7f8622af9"
|
|
||||||
other = "Lade ..."
|
|
|
@ -1,71 +0,0 @@
|
||||||
[CSRButtonLabel]
|
|
||||||
hash = "sha1-7f7bcb57602a96a49c8df4868fad7b81992e0734"
|
|
||||||
other = "Generate signing request"
|
|
||||||
|
|
||||||
[CSRGenTitle]
|
|
||||||
hash = "sha1-f1a8f21b12fe51250da4a11f1c6ab28eab69b69d"
|
|
||||||
other = "CSR generation in browser"
|
|
||||||
|
|
||||||
[DownloadDescription]
|
|
||||||
hash = "sha1-f4a7826398e5c57c7feb4709ee939ea655f05469"
|
|
||||||
other = "Your key material is ready for download. The downloadable file contains your private key and your certificate encrypted with your password. You can now use the file to install your certificate in your browser or other applications."
|
|
||||||
|
|
||||||
[DownloadLabel]
|
|
||||||
hash = "sha1-a479c9c34e878d07b4d67a73a48f432ad7dc53c8"
|
|
||||||
other = "Download"
|
|
||||||
|
|
||||||
["JavaScript.Certificate.Received"]
|
|
||||||
hash = "sha1-217622c21b50fcfb864802155080be482c285456"
|
|
||||||
other = "received certificate from CA"
|
|
||||||
|
|
||||||
["JavaScript.Certificate.Waiting"]
|
|
||||||
hash = "sha1-0a528daa78d850d2c9360cdec82f6f849ffb6bcf"
|
|
||||||
other = "waiting for certificate ..."
|
|
||||||
|
|
||||||
["JavaScript.KeyGen.Generated"]
|
|
||||||
hash = "sha1-34cdfcdc837e3fc052733a3588cc3923b793103e"
|
|
||||||
other = "key generated in __seconds__ seconds"
|
|
||||||
|
|
||||||
["JavaScript.KeyGen.Running"]
|
|
||||||
hash = "sha1-fd272f37118fe10395f6238a3eae94685b5f8cf1"
|
|
||||||
other = "key generation running for __seconds__ seconds"
|
|
||||||
|
|
||||||
["JavaScript.KeyGen.Started"]
|
|
||||||
hash = "sha1-e68739d705d5eb16317984a95a486fb9ff9bae6d"
|
|
||||||
other = "started key generation"
|
|
||||||
|
|
||||||
[NameHelpText]
|
|
||||||
hash = "sha1-52b81217549e37d161090a04b7f84223a270928e"
|
|
||||||
other = "Please input your name as it should be added to your certificate"
|
|
||||||
|
|
||||||
[NameLabel]
|
|
||||||
hash = "sha1-ab42293e29e1ffb306c1403dd95144d664853a60"
|
|
||||||
other = "Your name"
|
|
||||||
|
|
||||||
[PasswordLabel]
|
|
||||||
hash = "sha1-2b5e8edbf45819afdfa973c224b6b02d699e60de"
|
|
||||||
other = "Password for your client certificate"
|
|
||||||
|
|
||||||
[RSA2048Label]
|
|
||||||
hash = "sha1-2b1e7b638c31426d30d7e4bdebadbaa07d7521b0"
|
|
||||||
other = "2048 Bit (not recommended)"
|
|
||||||
|
|
||||||
[RSA3072Label]
|
|
||||||
hash = "sha1-97d1a8f9e8c5cf1f473b4a6fa0b5c39905f0f747"
|
|
||||||
other = "3072 Bit"
|
|
||||||
|
|
||||||
[RSA4096Label]
|
|
||||||
hash = "sha1-b14d7490195ac7f2d649f3b75dd2fe0daea53967"
|
|
||||||
other = "4096 Bit"
|
|
||||||
|
|
||||||
[RSAHelpText]
|
|
||||||
hash = "sha1-82511ecf2909ba189d7b16a828fce97c9359fad1"
|
|
||||||
other = "An RSA key pair will be generated in your browser. Longer key sizes provide better security but take longer to generate."
|
|
||||||
|
|
||||||
[RSAKeySizeLabel]
|
|
||||||
hash = "sha1-bd446df78ad62000d6516a95594a24b98688e1fa"
|
|
||||||
other = "RSA Key Size"
|
|
||||||
|
|
||||||
[StatusLoading]
|
|
||||||
hash = "sha1-530afa5bce434b05e3a10e83ff2567f7f8622af9"
|
|
||||||
other = "Loading ..."
|
|
|
@ -1,18 +0,0 @@
|
||||||
CSRButtonLabel = "Generate signing request"
|
|
||||||
CSRGenTitle = "CSR generation in browser"
|
|
||||||
DownloadDescription = "Your key material is ready for download. The downloadable file contains your private key and your certificate encrypted with your password. You can now use the file to install your certificate in your browser or other applications."
|
|
||||||
DownloadLabel = "Download"
|
|
||||||
"JavaScript.Certificate.Received" = "received certificate from CA"
|
|
||||||
"JavaScript.Certificate.Waiting" = "waiting for certificate ..."
|
|
||||||
"JavaScript.KeyGen.Generated" = "key generated in __seconds__ seconds"
|
|
||||||
"JavaScript.KeyGen.Running" = "key generation running for __seconds__ seconds"
|
|
||||||
"JavaScript.KeyGen.Started" = "started key generation"
|
|
||||||
NameHelpText = "Please input your name as it should be added to your certificate"
|
|
||||||
NameLabel = "Your name"
|
|
||||||
PasswordLabel = "Password for your client certificate"
|
|
||||||
RSA2048Label = "2048 Bit (not recommended)"
|
|
||||||
RSA3072Label = "3072 Bit"
|
|
||||||
RSA4096Label = "4096 Bit"
|
|
||||||
RSAHelpText = "An RSA key pair will be generated in your browser. Longer key sizes provide better security but take longer to generate."
|
|
||||||
RSAKeySizeLabel = "RSA Key Size"
|
|
||||||
StatusLoading = "Loading ..."
|
|
140
ca.cnf
140
ca.cnf
|
@ -1,140 +0,0 @@
|
||||||
extensions = v3_ext
|
|
||||||
|
|
||||||
[ca]
|
|
||||||
default_ca = sub_ca
|
|
||||||
|
|
||||||
[rootca]
|
|
||||||
dir = ./example_ca/root
|
|
||||||
certs = $dir/certs
|
|
||||||
crl_dir = $dir/crl
|
|
||||||
database = $dir/index.txt
|
|
||||||
serial = $dir/serial
|
|
||||||
new_certs_dir = $dir/newcerts
|
|
||||||
|
|
||||||
crl = $dir/crl.pem
|
|
||||||
certificate = $dir/ca.crt.pem
|
|
||||||
private_key = $dir/private/ca.key.pem
|
|
||||||
RANDFILE = $dir/private/.rand
|
|
||||||
|
|
||||||
policy = policy_any
|
|
||||||
unique_subject = no
|
|
||||||
email_in_dn = no
|
|
||||||
copy_extensions = none
|
|
||||||
|
|
||||||
default_md = sha256
|
|
||||||
default_days = 1825
|
|
||||||
default_crl_days = 30
|
|
||||||
|
|
||||||
[sub_ca]
|
|
||||||
dir = ./example_ca/sub
|
|
||||||
certs = $dir/certs
|
|
||||||
crl_dir = $dir/crl
|
|
||||||
database = $dir/index.txt
|
|
||||||
serial = $dir/serial
|
|
||||||
new_certs_dir = $dir/newcerts
|
|
||||||
|
|
||||||
crl = $dir/crl.pem
|
|
||||||
certificate = $dir/ca.crt.pem
|
|
||||||
private_key = $dir/private/ca.key.pem
|
|
||||||
RANDFILE = $dir/private/.rand
|
|
||||||
unique_subject = no
|
|
||||||
email_in_dn = no
|
|
||||||
|
|
||||||
default_md = sha256
|
|
||||||
default_days = 365
|
|
||||||
default_crl_days = 30
|
|
||||||
|
|
||||||
[email_ca]
|
|
||||||
dir = ./example_ca/email
|
|
||||||
certs = $dir/certs
|
|
||||||
crl_dir = $dir/crl
|
|
||||||
database = $dir/index.txt
|
|
||||||
serial = $dir/serial
|
|
||||||
new_certs_dir = $dir/newcerts
|
|
||||||
|
|
||||||
crl = $dir/crl.pem
|
|
||||||
certificate = $dir/ca.crt.pem
|
|
||||||
private_key = $dir/private/ca.key.pem
|
|
||||||
RANDFILE = $dir/private/.rand
|
|
||||||
unique_subject = no
|
|
||||||
email_in_dn = no
|
|
||||||
|
|
||||||
default_md = sha256
|
|
||||||
default_days = 365
|
|
||||||
default_crl_days = 30
|
|
||||||
|
|
||||||
[policy_any]
|
|
||||||
countryName = match
|
|
||||||
stateOrProvinceName = optional
|
|
||||||
organizationName = match
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
[policy_match]
|
|
||||||
commonName = supplied
|
|
||||||
|
|
||||||
[email_ext]
|
|
||||||
basicConstraints = critical,CA:false
|
|
||||||
keyUsage = keyEncipherment,digitalSignature,nonRepudiation
|
|
||||||
extendedKeyUsage = clientAuth,emailProtection
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always
|
|
||||||
authorityInfoAccess = 1.3.6.1.5.5.7.48.2;URI:http://example.org/ca/root/ca.crt,OCSP;URI:http://ocsp.example.org/
|
|
||||||
crlDistributionPoints = URI:http://crl.example.org/email.crl
|
|
||||||
|
|
||||||
[req]
|
|
||||||
default_bits = 3072
|
|
||||||
default_keyfile = privkey.pem
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
attributes = req_attributes
|
|
||||||
x509_extensions = root_ca
|
|
||||||
|
|
||||||
[req_distinguished_name]
|
|
||||||
countryName = Country Name (2 letter code)
|
|
||||||
countryName_default = CH
|
|
||||||
countryName_min = 2
|
|
||||||
countryName_max = 2
|
|
||||||
|
|
||||||
localityName = Locality Name (eg, city)
|
|
||||||
|
|
||||||
organizationName = Organization Name (eg, company)
|
|
||||||
organizationalUnitName = Organizational Unit Name (eg, section)
|
|
||||||
|
|
||||||
commonName = Common Name (e.g. server FQDN or YOUR name)
|
|
||||||
commonName_max = 64
|
|
||||||
|
|
||||||
[req_attributes]
|
|
||||||
|
|
||||||
[root_ca]
|
|
||||||
basicConstraints = critical,CA:true
|
|
||||||
keyUsage = critical,keyCertSign,cRLSign
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
|
|
||||||
[ext_sub_ca]
|
|
||||||
basicConstraints = critical,CA:true,pathlen:0
|
|
||||||
keyUsage = critical,keyCertSign,cRLSign
|
|
||||||
extendedKeyUsage = serverAuth,clientAuth
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always
|
|
||||||
authorityInfoAccess = 1.3.6.1.5.5.7.48.2;URI:http://example.org/ca/root/ca.crt,OCSP;URI:http://ocsp.example.org/
|
|
||||||
crlDistributionPoints = URI:http://crl.example.org/sub.crl
|
|
||||||
certificatePolicies = @policy_sub_ca
|
|
||||||
|
|
||||||
[ext_email_ca]
|
|
||||||
basicConstraints = critical,CA:true,pathlen:0
|
|
||||||
keyUsage = critical,keyCertSign,cRLSign
|
|
||||||
extendedKeyUsage = clientAuth,emailProtection
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always
|
|
||||||
authorityInfoAccess = 1.3.6.1.5.5.7.48.2;URI:http://example.org/ca/root/ca.crt,OCSP;URI:http://ocsp.example.org/
|
|
||||||
crlDistributionPoints = URI:http://crl.example.org/email.crl
|
|
||||||
certificatePolicies = @policy_email_ca
|
|
||||||
|
|
||||||
[policy_sub_ca]
|
|
||||||
policyIdentifier = 1.3.6.1.5.5.7.2.1
|
|
||||||
CPS = http://example.org/ca/sub/cps.html
|
|
||||||
|
|
||||||
[policy_email_ca]
|
|
||||||
policyIdentifier = 1.3.6.1.5.5.7.2.1
|
|
||||||
CPS = http://example.org/ca/email/cps.html
|
|
|
@ -1,8 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "code.cacert.org/jandd/poc-browser-csr-generation/migrations"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
}
|
|
17
go.mod
17
go.mod
|
@ -1,17 +0,0 @@
|
||||||
module code.cacert.org/jandd/poc-browser-csr-generation
|
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/BurntSushi/toml v0.3.1
|
|
||||||
github.com/go-sql-driver/mysql v1.5.0
|
|
||||||
github.com/gobwas/httphead v0.1.0 // indirect
|
|
||||||
github.com/gobwas/pool v0.2.1 // indirect
|
|
||||||
github.com/gobwas/ws v1.0.4
|
|
||||||
github.com/gorilla/csrf v1.7.0
|
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.1.1
|
|
||||||
github.com/pressly/goose v2.6.0+incompatible
|
|
||||||
github.com/sirupsen/logrus v1.7.0
|
|
||||||
golang.org/x/text v0.3.4
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
)
|
|
40
go.sum
40
go.sum
|
@ -1,40 +0,0 @@
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
|
||||||
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
|
||||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
|
||||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
|
||||||
github.com/gobwas/ws v1.0.4 h1:5eXU1CZhpQdq5kXbKb+sECH5Ia5KiO6CYzIzdlVx6Bs=
|
|
||||||
github.com/gobwas/ws v1.0.4/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
|
||||||
github.com/gorilla/csrf v1.7.0 h1:mMPjV5/3Zd460xCavIkppUdvnl5fPXMpv2uz2Zyg7/Y=
|
|
||||||
github.com/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA=
|
|
||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
|
||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.1.1 h1:ATCOanRDlrfKVB4WHAdJnLEqZtDmKYsweqsOUYflnBU=
|
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.1.1/go.mod h1:d++QJC9ZVf7pa48qrsRWhMJ5pSHIPmS3OLqK1niyLxs=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/pressly/goose v2.6.0+incompatible h1:3f8zIQ8rfgP9tyI0Hmcs2YNAqUCL1c+diLe3iU8Qd/k=
|
|
||||||
github.com/pressly/goose v2.6.0+incompatible/go.mod h1:m+QHWCqxR3k8D9l7qfzuC/djtlfzxr34mozWDYEu1z8=
|
|
||||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|
|
@ -36,12 +36,8 @@ function jsMinify() {
|
||||||
|
|
||||||
function publishAssets() {
|
function publishAssets() {
|
||||||
return src([
|
return src([
|
||||||
'node_modules/popper.js/dist/*.js',
|
'node_modules/bootstrap/dist/js/bootstrap.bundle.*',
|
||||||
'node_modules/popper.js/dist/*.map',
|
'node_modules/node-forge/dist/forge.min.js',
|
||||||
'node_modules/jquery/dist/*.*',
|
|
||||||
'node_modules/bootstrap/dist/js/*.*',
|
|
||||||
'node_modules/node-forge/dist/*.*',
|
|
||||||
'node_modules/i18next-client/i18next.min.js',
|
|
||||||
]).pipe(dest('public/js'));
|
]).pipe(dest('public/js'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html/template"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gorilla/csrf"
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IndexHandler struct {
|
|
||||||
bundle *i18n.Bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIndexHandler(bundle *i18n.Bundle) *IndexHandler {
|
|
||||||
return &IndexHandler{bundle: bundle}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *IndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "GET" {
|
|
||||||
http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.URL.Path != "/" {
|
|
||||||
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
localizer := i18n.NewLocalizer(i.bundle, r.Header.Get("Accept-Language"))
|
|
||||||
csrGenTitle := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "CSRGenTitle",
|
|
||||||
Other: "CSR generation in browser",
|
|
||||||
}})
|
|
||||||
nameLabel := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "NameLabel",
|
|
||||||
Other: "Your name",
|
|
||||||
}})
|
|
||||||
nameHelpText := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "NameHelpText",
|
|
||||||
Other: "Please input your name as it should be added to your certificate",
|
|
||||||
}})
|
|
||||||
passwordLabel := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "PasswordLabel",
|
|
||||||
Other: "Password for your client certificate",
|
|
||||||
}})
|
|
||||||
rsaKeySizeLegend := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "RSAKeySizeLabel",
|
|
||||||
Other: "RSA Key Size",
|
|
||||||
}})
|
|
||||||
rsa3072Label := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "RSA3072Label",
|
|
||||||
Other: "3072 Bit",
|
|
||||||
}})
|
|
||||||
rsa2048Label := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "RSA2048Label",
|
|
||||||
Other: "2048 Bit (not recommended)",
|
|
||||||
}})
|
|
||||||
rsa4096Label := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "RSA4096Label",
|
|
||||||
Other: "4096 Bit",
|
|
||||||
}})
|
|
||||||
rsaHelpText := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "RSAHelpText",
|
|
||||||
Other: "An RSA key pair will be generated in your browser. Longer key" +
|
|
||||||
" sizes provide better security but take longer to generate.",
|
|
||||||
}})
|
|
||||||
csrButtonLabel := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "CSRButtonLabel",
|
|
||||||
Other: "Generate signing request",
|
|
||||||
}})
|
|
||||||
statusLoading := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "StatusLoading",
|
|
||||||
Other: "Loading ...",
|
|
||||||
}})
|
|
||||||
downloadLabel := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "DownloadLabel",
|
|
||||||
Other: "Download",
|
|
||||||
}})
|
|
||||||
downloadDescription := localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "DownloadDescription",
|
|
||||||
Other: "Your key material is ready for download. The downloadable file contains your private key and your" +
|
|
||||||
" certificate encrypted with your password. You can now use the file to install your certificate in your" +
|
|
||||||
" browser or other applications.",
|
|
||||||
}})
|
|
||||||
|
|
||||||
t := template.Must(template.ParseFiles("templates/index.html"))
|
|
||||||
err := t.Execute(w, map[string]interface{}{
|
|
||||||
"Title": csrGenTitle,
|
|
||||||
"NameLabel": nameLabel,
|
|
||||||
"NameHelpText": nameHelpText,
|
|
||||||
"PasswordLabel": passwordLabel,
|
|
||||||
"RSAKeySizeLegend": rsaKeySizeLegend,
|
|
||||||
"RSA3072Label": rsa3072Label,
|
|
||||||
"RSA2048Label": rsa2048Label,
|
|
||||||
"RSA4096Label": rsa4096Label,
|
|
||||||
"RSAHelpText": rsaHelpText,
|
|
||||||
"CSRButtonLabel": csrButtonLabel,
|
|
||||||
"StatusLoading": statusLoading,
|
|
||||||
"DownloadDescription": downloadDescription,
|
|
||||||
"DownloadLabel": downloadLabel,
|
|
||||||
csrf.TemplateTag: csrf.TemplateField(r),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
||||||
)
|
|
||||||
|
|
||||||
type JSLocalesHandler struct {
|
|
||||||
bundle *i18n.Bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewJSLocalesHandler(bundle *i18n.Bundle) *JSLocalesHandler {
|
|
||||||
return &JSLocalesHandler{bundle: bundle}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *JSLocalesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
parts := strings.Split(r.URL.Path, "/")
|
|
||||||
if len(parts) != 4 {
|
|
||||||
http.Error(w, "Not found", http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
lang := parts[2]
|
|
||||||
|
|
||||||
localizer := i18n.NewLocalizer(j.bundle, lang)
|
|
||||||
|
|
||||||
type translationData struct {
|
|
||||||
Keygen struct {
|
|
||||||
Started string `json:"started"`
|
|
||||||
Running string `json:"running"`
|
|
||||||
Generated string `json:"generated"`
|
|
||||||
} `json:"keygen"`
|
|
||||||
Certificate struct {
|
|
||||||
Waiting string `json:"waiting"`
|
|
||||||
Received string `json:"received"`
|
|
||||||
} `json:"certificate"`
|
|
||||||
}
|
|
||||||
|
|
||||||
translations := &translationData{}
|
|
||||||
translations.Keygen.Started = localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "JavaScript.KeyGen.Started",
|
|
||||||
Other: "started key generation",
|
|
||||||
}})
|
|
||||||
translations.Keygen.Running = localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "JavaScript.KeyGen.Running",
|
|
||||||
Other: "key generation running for __seconds__ seconds",
|
|
||||||
}})
|
|
||||||
translations.Keygen.Generated = localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "JavaScript.KeyGen.Generated",
|
|
||||||
Other: "key generated in __seconds__ seconds",
|
|
||||||
}})
|
|
||||||
translations.Certificate.Waiting = localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "JavaScript.Certificate.Waiting",
|
|
||||||
Other: "waiting for certificate ...",
|
|
||||||
}})
|
|
||||||
translations.Certificate.Received = localizer.MustLocalize(&i18n.LocalizeConfig{DefaultMessage: &i18n.Message{
|
|
||||||
ID: "JavaScript.Certificate.Received",
|
|
||||||
Other: "received certificate from CA",
|
|
||||||
}})
|
|
||||||
|
|
||||||
encoder := json.NewEncoder(w)
|
|
||||||
if err := encoder.Encode(translations); err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,215 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/pem"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SigningRequestRegistry struct {
|
|
||||||
caCertificates []*x509.Certificate
|
|
||||||
caChainMap map[string][]string
|
|
||||||
requests map[string]chan *responseData
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSigningRequestRegistry(caCertificates []*x509.Certificate) *SigningRequestRegistry {
|
|
||||||
return &SigningRequestRegistry{
|
|
||||||
caCertificates: caCertificates,
|
|
||||||
caChainMap: make(map[string][]string),
|
|
||||||
requests: make(map[string]chan *responseData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type SigningRequestAttributes struct {
|
|
||||||
CommonName string
|
|
||||||
CSRBytes []byte
|
|
||||||
RequestToken string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (registry *SigningRequestRegistry) AddSigningRequest(request *requestData) (string, error) {
|
|
||||||
requestToken, csrBytes, err := validateCsr(request.Csr)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
requestAttributes := &SigningRequestAttributes{
|
|
||||||
CommonName: request.CommonName,
|
|
||||||
CSRBytes: csrBytes,
|
|
||||||
RequestToken: requestToken,
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
responseChannel := make(chan *responseData, 1)
|
|
||||||
registry.requests[requestToken] = responseChannel
|
|
||||||
registry.signCertificate(responseChannel, requestAttributes)
|
|
||||||
}()
|
|
||||||
return requestToken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateCsr(csr string) (string, []byte, error) {
|
|
||||||
csrBlock, _ := pem.Decode([]byte(csr))
|
|
||||||
if csrBlock == nil {
|
|
||||||
return "", nil, errors.New("request data did not contain valid PEM data")
|
|
||||||
}
|
|
||||||
if csrBlock.Type != "CERTIFICATE REQUEST" {
|
|
||||||
return "", nil, fmt.Errorf("request is not valid, type in PEM data is %s", csrBlock.Type)
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
var csrContent *x509.CertificateRequest
|
|
||||||
csrContent, err = x509.ParseCertificateRequest(csrBlock.Bytes)
|
|
||||||
if err != nil {
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
if err = csrContent.CheckSignature(); err != nil {
|
|
||||||
log.Errorf("invalid CSR signature %v", err)
|
|
||||||
return "", nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// generate request token as defined in CAB Baseline Requirements 1.7.3 Request Token definition
|
|
||||||
requestToken := fmt.Sprintf(
|
|
||||||
"%s%x", time.Now().UTC().Format("200601021504"), sha256.Sum256(csrContent.Raw),
|
|
||||||
)
|
|
||||||
log.Debugf("generated request token %s", requestToken)
|
|
||||||
return requestToken, csrContent.Raw, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (registry *SigningRequestRegistry) signCertificate(channel chan *responseData, request *SigningRequestAttributes) {
|
|
||||||
responseData, err := registry.sign(request)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
close(channel)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
channel <- responseData
|
|
||||||
}
|
|
||||||
|
|
||||||
func (registry *SigningRequestRegistry) sign(request *SigningRequestAttributes) (*responseData, error) {
|
|
||||||
log.Infof("handling signing request %s", request.RequestToken)
|
|
||||||
subjectDN := fmt.Sprintf("/CN=%s", request.CommonName)
|
|
||||||
|
|
||||||
var err error
|
|
||||||
var csrFile *os.File
|
|
||||||
if csrFile, err = ioutil.TempFile("", "*.csr.pem"); err != nil {
|
|
||||||
log.Errorf("could not open temporary file: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err = pem.Encode(csrFile, &pem.Block{
|
|
||||||
Type: "CERTIFICATE REQUEST",
|
|
||||||
Bytes: request.CSRBytes,
|
|
||||||
}); err != nil {
|
|
||||||
log.Errorf("could not write CSR to file: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err = csrFile.Close(); err != nil {
|
|
||||||
log.Errorf("could not close CSR file: %s", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func(file *os.File) {
|
|
||||||
err = os.Remove(file.Name())
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("could not remove temporary file: %s", err)
|
|
||||||
}
|
|
||||||
}(csrFile)
|
|
||||||
|
|
||||||
// simulate a delay during certificate creation
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
|
|
||||||
opensslCommand := exec.Command(
|
|
||||||
"openssl", "ca", "-config", "ca.cnf", "-name", "email_ca",
|
|
||||||
"-policy", "policy_match", "-extensions", "email_ext",
|
|
||||||
"-batch", "-subj", subjectDN, "-utf8", "-rand_serial", "-in", csrFile.Name())
|
|
||||||
var out, cmdErr bytes.Buffer
|
|
||||||
opensslCommand.Stdout = &out
|
|
||||||
opensslCommand.Stderr = &cmdErr
|
|
||||||
err = opensslCommand.Run()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
log.Error(cmdErr.String())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var block *pem.Block
|
|
||||||
if block, _ = pem.Decode(out.Bytes()); block == nil {
|
|
||||||
err = fmt.Errorf("could not decode pem")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var certificate *x509.Certificate
|
|
||||||
if certificate, err = x509.ParseCertificate(block.Bytes); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var caChain []string
|
|
||||||
if caChain, err = registry.getCAChain(certificate); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
response := &responseData{
|
|
||||||
Certificate: string(pem.EncodeToMemory(&pem.Block{
|
|
||||||
Type: "CERTIFICATE",
|
|
||||||
Bytes: certificate.Raw,
|
|
||||||
})),
|
|
||||||
CAChain: caChain,
|
|
||||||
}
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (registry *SigningRequestRegistry) GetResponseChannel(requestUuid string) (chan *responseData, error) {
|
|
||||||
if responseChannel, exists := registry.requests[requestUuid]; exists {
|
|
||||||
delete(registry.requests, requestUuid)
|
|
||||||
return responseChannel, nil
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("no request found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (registry *SigningRequestRegistry) getCAChain(certificate *x509.Certificate) ([]string, error) {
|
|
||||||
issuerString := string(certificate.RawIssuer)
|
|
||||||
|
|
||||||
if value, exists := registry.caChainMap[issuerString]; exists {
|
|
||||||
return value, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
result := make([]string, 0)
|
|
||||||
|
|
||||||
appendCert := func(cert *x509.Certificate) {
|
|
||||||
result = append(
|
|
||||||
result,
|
|
||||||
string(pem.EncodeToMemory(&pem.Block{Bytes: cert.Raw, Type: "CERTIFICATE"})))
|
|
||||||
log.Debugf("added %s to cachain", result[len(result)-1])
|
|
||||||
}
|
|
||||||
|
|
||||||
var previous *x509.Certificate
|
|
||||||
var count = 0
|
|
||||||
for {
|
|
||||||
if len(registry.caCertificates) == 0 {
|
|
||||||
return nil, errors.New("no CA certificates loaded")
|
|
||||||
}
|
|
||||||
if count > len(registry.caCertificates) {
|
|
||||||
return nil, errors.New("could not construct certificate chain")
|
|
||||||
}
|
|
||||||
for _, caCert := range registry.caCertificates {
|
|
||||||
if previous == nil {
|
|
||||||
if bytes.Equal(caCert.RawSubject, certificate.RawIssuer) {
|
|
||||||
previous = caCert
|
|
||||||
appendCert(caCert)
|
|
||||||
}
|
|
||||||
} else if bytes.Equal(previous.RawSubject, previous.RawIssuer) {
|
|
||||||
registry.caChainMap[issuerString] = result
|
|
||||||
return result, nil
|
|
||||||
} else if bytes.Equal(caCert.RawSubject, previous.RawIssuer) {
|
|
||||||
previous = caCert
|
|
||||||
appendCert(caCert)
|
|
||||||
} else {
|
|
||||||
log.Debugf("skipped certificate %s", caCert.Subject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CertificateSigningHandler struct {
|
|
||||||
requestRegistry *SigningRequestRegistry
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCertificateSigningHandler(requestRegistry *SigningRequestRegistry) *CertificateSigningHandler {
|
|
||||||
return &CertificateSigningHandler{requestRegistry: requestRegistry}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *CertificateSigningHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != "POST" {
|
|
||||||
http.Error(w, "Only POST requests support", http.StatusMethodNotAllowed)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if r.Header.Get("content-type") != "application/json" {
|
|
||||||
http.Error(w, "Only JSON content is accepted", http.StatusNotAcceptable)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var err error
|
|
||||||
var requestBody requestData
|
|
||||||
|
|
||||||
if err = json.NewDecoder(r.Body).Decode(&requestBody); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type acceptedResponse struct {
|
|
||||||
RequestId string `json:"request_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
taskUuid, err := h.requestRegistry.AddSigningRequest(&requestBody)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusAccepted)
|
|
||||||
response := &acceptedResponse{RequestId: taskUuid}
|
|
||||||
if err = json.NewEncoder(w).Encode(response); err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type requestData struct {
|
|
||||||
Csr string `json:"csr"`
|
|
||||||
CommonName string `json:"common_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type responseData struct {
|
|
||||||
Certificate string `json:"certificate"`
|
|
||||||
CAChain []string `json:"ca_chain"`
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
package handlers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gobwas/ws"
|
|
||||||
"github.com/gobwas/ws/wsutil"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type WebSocketHandler struct {
|
|
||||||
requestRegistry *SigningRequestRegistry
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWebSocketHandler(registry *SigningRequestRegistry) *WebSocketHandler {
|
|
||||||
return &WebSocketHandler{requestRegistry: registry}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WebSocketHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
|
||||||
conn, _, _, err := ws.UpgradeHTTP(request, writer)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(writer, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer func() { _ = conn.Close() }()
|
|
||||||
|
|
||||||
var (
|
|
||||||
reader = wsutil.NewReader(conn, ws.StateServerSide)
|
|
||||||
writer = wsutil.NewWriter(conn, ws.StateServerSide, ws.OpText)
|
|
||||||
jsonDecoder = json.NewDecoder(reader)
|
|
||||||
jsonEncoder = json.NewEncoder(writer)
|
|
||||||
)
|
|
||||||
|
|
||||||
for {
|
|
||||||
header, err := reader.NextFrame()
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if header.OpCode == ws.OpClose {
|
|
||||||
log.Debug("channel closed")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
type requestType struct {
|
|
||||||
RequestId string `json:"request_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
request := &requestType{}
|
|
||||||
err = jsonDecoder.Decode(request)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
channel, err := w.requestRegistry.GetResponseChannel(request.RequestId)
|
|
||||||
if err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
var response *responseData
|
|
||||||
response = <-channel
|
|
||||||
if err = jsonEncoder.Encode(response); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
close(channel)
|
|
||||||
|
|
||||||
if err = writer.Flush(); err != nil {
|
|
||||||
log.Error(err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
148
main.go
148
main.go
|
@ -1,148 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/pem"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"github.com/gorilla/csrf"
|
|
||||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/text/language"
|
|
||||||
|
|
||||||
"code.cacert.org/jandd/poc-browser-csr-generation/handlers"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
log.SetFormatter(&log.TextFormatter{
|
|
||||||
FullTimestamp: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
bundle := loadI18nBundle()
|
|
||||||
mux := http.NewServeMux()
|
|
||||||
|
|
||||||
csrfKey := initCSRFKey()
|
|
||||||
|
|
||||||
signingRequestRegistry := handlers.NewSigningRequestRegistry(loadCACertificates())
|
|
||||||
mux.Handle("/sign/", handlers.NewCertificateSigningHandler(signingRequestRegistry))
|
|
||||||
mux.Handle("/", handlers.NewIndexHandler(bundle))
|
|
||||||
fileServer := http.FileServer(http.Dir("./public"))
|
|
||||||
mux.Handle("/css/", fileServer)
|
|
||||||
mux.Handle("/js/", fileServer)
|
|
||||||
mux.Handle("/locales/", handlers.NewJSLocalesHandler(bundle))
|
|
||||||
mux.Handle("/ws/", handlers.NewWebSocketHandler(signingRequestRegistry))
|
|
||||||
|
|
||||||
tlsConfig := &tls.Config{
|
|
||||||
CipherSuites: []uint16{
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
||||||
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
||||||
},
|
|
||||||
NextProtos: []string{"h2"},
|
|
||||||
PreferServerCipherSuites: true,
|
|
||||||
MinVersion: tls.VersionTLS12,
|
|
||||||
}
|
|
||||||
server := http.Server{
|
|
||||||
Addr: ":8000",
|
|
||||||
Handler: csrf.Protect(csrfKey, csrf.FieldName("csrfToken"), csrf.RequestHeader("X-CSRF-Token"))(mux),
|
|
||||||
TLSConfig: tlsConfig,
|
|
||||||
ReadTimeout: 20 * time.Second,
|
|
||||||
ReadHeaderTimeout: 5 * time.Second,
|
|
||||||
WriteTimeout: 30 * time.Second,
|
|
||||||
IdleTimeout: 30 * time.Second,
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
err := server.ListenAndServeTLS("server.crt.pem", "server.key.pem")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
var hostPort string
|
|
||||||
if strings.HasPrefix(server.Addr, ":") {
|
|
||||||
hostPort = fmt.Sprintf("localhost%s", server.Addr)
|
|
||||||
} else {
|
|
||||||
hostPort = server.Addr
|
|
||||||
}
|
|
||||||
log.Infof("started web server on https://%s/", hostPort)
|
|
||||||
c := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
|
||||||
s := <-c
|
|
||||||
log.Infof("received %s, shutting down", s)
|
|
||||||
_ = server.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadI18nBundle() *i18n.Bundle {
|
|
||||||
bundle := i18n.NewBundle(language.English)
|
|
||||||
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
|
|
||||||
for _, lang := range []string{"en-US", "de-DE"} {
|
|
||||||
if _, err := bundle.LoadMessageFile(fmt.Sprintf("active.%s.toml", lang)); err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bundle
|
|
||||||
}
|
|
||||||
|
|
||||||
func initCSRFKey() []byte {
|
|
||||||
var csrfKey []byte = nil
|
|
||||||
|
|
||||||
if csrfB64, exists := os.LookupEnv("CSRF_KEY"); exists {
|
|
||||||
csrfKey, _ = base64.RawStdEncoding.DecodeString(csrfB64)
|
|
||||||
log.Info("read CSRF key from environment variable")
|
|
||||||
}
|
|
||||||
if csrfKey == nil {
|
|
||||||
csrfKey = generateRandomBytes(32)
|
|
||||||
log.Infof(
|
|
||||||
"generated new random CSRF key, set environment variable CSRF_KEY to %s to "+
|
|
||||||
"keep the same key for new sessions",
|
|
||||||
base64.RawStdEncoding.EncodeToString(csrfKey))
|
|
||||||
}
|
|
||||||
return csrfKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateRandomBytes(count int) []byte {
|
|
||||||
randomBytes := make([]byte, count)
|
|
||||||
|
|
||||||
_, err := rand.Read(randomBytes)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("could not read random bytes: %v", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return randomBytes
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadCACertificates() (caCertificates []*x509.Certificate) {
|
|
||||||
var err error
|
|
||||||
caFiles, err := filepath.Glob("example_ca/*/ca.crt.pem")
|
|
||||||
if err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
caCertificates = make([]*x509.Certificate, len(caFiles))
|
|
||||||
for index, certFile := range caFiles {
|
|
||||||
var certBytes []byte
|
|
||||||
if certBytes, err = ioutil.ReadFile(certFile); err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
var block *pem.Block
|
|
||||||
if block, _ = pem.Decode(certBytes); block == nil {
|
|
||||||
log.Panicf("no PEM data found in %s", certFile)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if caCertificates[index], err = x509.ParseCertificate(block.Bytes); err != nil {
|
|
||||||
log.Panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.Infof("read %d CA certificates", len(caCertificates))
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,615 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2020 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- Initial database schema
|
|
||||||
CREATE TABLE `abusereports` (
|
|
||||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`when` datetime NOT NULL,
|
|
||||||
`IP` int(11) DEFAULT NULL,
|
|
||||||
`url` varchar(255) NOT NULL,
|
|
||||||
`name` varchar(255) NOT NULL,
|
|
||||||
`email` varchar(255) NOT NULL,
|
|
||||||
`comment` varchar(255) NOT NULL,
|
|
||||||
`reason` varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `addlang` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`userid` int(11) NOT NULL,
|
|
||||||
`lang` varchar(5) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `userid` (`userid`, `lang`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `adminlog` (
|
|
||||||
`when` datetime NOT NULL,
|
|
||||||
`uid` int(11) NOT NULL,
|
|
||||||
`adminid` int(11) NOT NULL,
|
|
||||||
`actiontypeid` int(11) DEFAULT NULL,
|
|
||||||
`old-lname` varchar(255),
|
|
||||||
`old-dob` varchar(255),
|
|
||||||
`new-lname` varchar(255),
|
|
||||||
`new-dob` varchar(255)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `advertising` (
|
|
||||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`replaceid` int(10) UNSIGNED NOT NULL,
|
|
||||||
`replaced` tinyint(3) UNSIGNED NOT NULL,
|
|
||||||
`orderid` tinyint(3) UNSIGNED NOT NULL,
|
|
||||||
`link` varchar(255) NOT NULL,
|
|
||||||
`title` varchar(255) NOT NULL,
|
|
||||||
`months` tinyint(3) UNSIGNED NOT NULL,
|
|
||||||
`who` int(10) UNSIGNED NOT NULL,
|
|
||||||
`when` datetime NOT NULL,
|
|
||||||
`active` tinyint(3) UNSIGNED NOT NULL,
|
|
||||||
`approvedby` int(10) UNSIGNED NOT NULL,
|
|
||||||
`expires` datetime NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `alerts` (
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`general` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`country` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`regional` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`radius` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`memid`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `baddomains` (
|
|
||||||
`domain` varchar(255) NOT NULL DEFAULT ''
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `cats_passed` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`user_id` int(11) NOT NULL,
|
|
||||||
`variant_id` int(11) NOT NULL,
|
|
||||||
`pass_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP(),
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `test_passed` (`user_id`, `variant_id`, `pass_date`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `cats_type` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`type_text` varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `type_text` (`type_text`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `cats_variant` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`type_id` int(11) NOT NULL,
|
|
||||||
`test_text` varchar(255) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `test_text` (`test_text`, `type_id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `countries` (
|
|
||||||
`id` int(3) NOT NULL AUTO_INCREMENT,
|
|
||||||
`name` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`acount` int(11) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `disputedomain` (
|
|
||||||
`id` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`oldmemid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`domain` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`hash` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`attempts` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`action` enum ('accept','reject','failed') NOT NULL DEFAULT 'accept'
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `disputeemail` (
|
|
||||||
`id` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`oldmemid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`email` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`hash` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`attempts` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`action` enum ('accept','reject','failed') NOT NULL DEFAULT 'accept',
|
|
||||||
`IP` varchar(20) NOT NULL DEFAULT ''
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `domaincerts` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`domid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`serial` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`CN` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`subject` text NOT NULL,
|
|
||||||
`csr_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`crt_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`revoked` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`expire` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`warning` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`renewed` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`rootcert` int(2) NOT NULL DEFAULT 1,
|
|
||||||
`md` enum ('md5','sha1','sha256','sha512') NOT NULL DEFAULT 'sha512',
|
|
||||||
`type` tinyint(4) DEFAULT NULL,
|
|
||||||
`pkhash` char(40) DEFAULT NULL,
|
|
||||||
`certhash` char(40) DEFAULT NULL,
|
|
||||||
`coll_found` tinyint(1) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `domaincerts_pkhash` (`pkhash`),
|
|
||||||
KEY `revoked` (`revoked`),
|
|
||||||
KEY `created` (`created`),
|
|
||||||
KEY `domid` (`domid`),
|
|
||||||
KEY `serial` (`serial`),
|
|
||||||
KEY `stats_domaincerts_expire` (`expire`),
|
|
||||||
KEY `domaincrt` (`crt_name`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `domains` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`domain` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`deleted` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`hash` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`attempts` int(1) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `memid` (`memid`),
|
|
||||||
KEY `domain` (`domain`),
|
|
||||||
KEY `memid_2` (`memid`),
|
|
||||||
KEY `stats_domains_hash` (`hash`),
|
|
||||||
KEY `stats_domains_deleted` (`deleted`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `domlink` (
|
|
||||||
`certid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`domid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
UNIQUE KEY `index` (`certid`, `domid`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `email` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`email` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`deleted` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`hash` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`attempts` int(1) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `memid` (`memid`),
|
|
||||||
KEY `stats_email_hash` (`hash`),
|
|
||||||
KEY `stats_email_deleted` (`deleted`),
|
|
||||||
KEY `email` (`email`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `emailcerts` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`serial` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`CN` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`subject` text NOT NULL,
|
|
||||||
`keytype` char(2) NOT NULL DEFAULT 'NS',
|
|
||||||
`codesign` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`csr_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`crt_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`revoked` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`expire` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`warning` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`renewed` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`rootcert` int(2) NOT NULL DEFAULT 1,
|
|
||||||
`md` enum ('md5','sha1','sha256','sha512') NOT NULL DEFAULT 'sha512',
|
|
||||||
`type` tinyint(4) DEFAULT NULL,
|
|
||||||
`disablelogin` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`pkhash` char(40) DEFAULT NULL,
|
|
||||||
`certhash` char(40) DEFAULT NULL,
|
|
||||||
`coll_found` tinyint(1) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `emailcerts_pkhash` (`pkhash`),
|
|
||||||
KEY `revoked` (`revoked`),
|
|
||||||
KEY `created` (`created`),
|
|
||||||
KEY `memid` (`memid`),
|
|
||||||
KEY `serial` (`serial`),
|
|
||||||
KEY `stats_emailcerts_expire` (`expire`),
|
|
||||||
KEY `emailcrt` (`crt_name`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `emaillink` (
|
|
||||||
`emailcertsid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`emailid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
KEY `index` (`emailcertsid`, `emailid`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `gpg` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`email` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`level` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`multiple` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`expires` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`csr` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`crt` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`issued` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`expire` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`keyid` char(18) DEFAULT NULL,
|
|
||||||
`warning` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `stats_gpg_expire` (`expire`),
|
|
||||||
KEY `stats_gpg_issued` (`issued`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `languages` (
|
|
||||||
`locale` varchar(5) NOT NULL,
|
|
||||||
`en_co` varchar(255) NOT NULL,
|
|
||||||
`en_lang` varchar(255) NOT NULL,
|
|
||||||
`country` varchar(255) NOT NULL,
|
|
||||||
`lang` varchar(255) NOT NULL
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `localias` (
|
|
||||||
`locid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
KEY `locid` (`locid`),
|
|
||||||
KEY `name` (`name`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `locations` (
|
|
||||||
`id` int(7) NOT NULL AUTO_INCREMENT,
|
|
||||||
`regid` int(4) NOT NULL DEFAULT 0,
|
|
||||||
`ccid` int(3) NOT NULL DEFAULT 0,
|
|
||||||
`name` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`lat` double(6, 3) NOT NULL DEFAULT 0.000,
|
|
||||||
`long` double(6, 3) NOT NULL DEFAULT 0.000,
|
|
||||||
`acount` int(11) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `ccid` (`ccid`),
|
|
||||||
KEY `regid` (`regid`),
|
|
||||||
KEY `name` (`name`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `news` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`when` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`who` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`short` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`story` text NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `notary` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`from` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`to` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`awarded` int(3) NOT NULL DEFAULT 0,
|
|
||||||
`points` int(3) NOT NULL DEFAULT 0,
|
|
||||||
`method` enum ('Face to Face Meeting','Trusted Third Parties','Thawte Points Transfer','Administrative Increase','CT Magazine - Germany','Temporary Increase','Unknown') NOT NULL DEFAULT 'Face to Face Meeting',
|
|
||||||
`location` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`date` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`when` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`expire` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`sponsor` int(11) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `from` (`from`),
|
|
||||||
KEY `to` (`to`),
|
|
||||||
KEY `from_2` (`from`),
|
|
||||||
KEY `to_2` (`to`),
|
|
||||||
KEY `stats_notary_when` (`when`),
|
|
||||||
KEY `stats_notary_method` (`method`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `org` (
|
|
||||||
`orgid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`OU` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`masteracc` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`comments` text NOT NULL,
|
|
||||||
UNIQUE KEY `orgid` (`orgid`, `memid`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `orgdomaincerts` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`orgid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`subject` text NOT NULL,
|
|
||||||
`serial` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`CN` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`csr_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`crt_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`revoked` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`expire` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`renewed` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`rootcert` int(2) NOT NULL DEFAULT 1,
|
|
||||||
`md` enum ('md5','sha1','sha256','sha512') NOT NULL DEFAULT 'sha512',
|
|
||||||
`type` tinyint(4) DEFAULT NULL,
|
|
||||||
`warning` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`pkhash` char(40) DEFAULT NULL,
|
|
||||||
`certhash` char(40) DEFAULT NULL,
|
|
||||||
`coll_found` tinyint(1) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `orgdomaincerts_pkhash` (`pkhash`),
|
|
||||||
KEY `stats_orgdomaincerts_created` (`created`),
|
|
||||||
KEY `stats_orgdomaincerts_revoked` (`revoked`),
|
|
||||||
KEY `stats_orgdomaincerts_expire` (`expire`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `orgdomains` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`orgid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`domain` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `orgdomlink` (
|
|
||||||
`orgcertid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`orgdomid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
UNIQUE KEY `index` (`orgcertid`, `orgdomid`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `orgemailcerts` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`orgid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`serial` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`CN` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`subject` text NOT NULL,
|
|
||||||
`keytype` char(2) NOT NULL DEFAULT 'NS',
|
|
||||||
`csr_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`crt_name` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`revoked` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`expire` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`renewed` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`rootcert` int(2) NOT NULL DEFAULT 1,
|
|
||||||
`md` enum ('md5','sha1','sha256','sha512') NOT NULL DEFAULT 'sha512',
|
|
||||||
`type` tinyint(4) DEFAULT NULL,
|
|
||||||
`codesign` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`warning` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`pkhash` char(40) DEFAULT NULL,
|
|
||||||
`certhash` char(40) DEFAULT NULL,
|
|
||||||
`coll_found` tinyint(1) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `orgemailcerts_pkhash` (`pkhash`),
|
|
||||||
KEY `stats_orgemailcerts_created` (`created`),
|
|
||||||
KEY `stats_orgemailcerts_revoked` (`revoked`),
|
|
||||||
KEY `stats_orgemailcerts_expire` (`expire`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `orgemaillink` (
|
|
||||||
`emailcertsid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`domid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
KEY `index` (`emailcertsid`, `domid`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `orginfo` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`contact` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`O` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`L` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`ST` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`C` char(2) NOT NULL DEFAULT '',
|
|
||||||
`comments` text NOT NULL,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `otphashes` (
|
|
||||||
`when` datetime NOT NULL,
|
|
||||||
`username` varchar(255) NOT NULL,
|
|
||||||
`otp` varchar(255) NOT NULL
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `pinglog` (
|
|
||||||
`when` datetime NOT NULL,
|
|
||||||
`uid` int(11) NOT NULL,
|
|
||||||
`email` varchar(255) NOT NULL,
|
|
||||||
`result` varchar(255) NOT NULL
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `regions` (
|
|
||||||
`id` int(5) NOT NULL AUTO_INCREMENT,
|
|
||||||
`ccid` int(3) NOT NULL DEFAULT 0,
|
|
||||||
`name` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`acount` int(11) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `ccid` (`ccid`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
-- stores names of root certificates (CN from SubjectDN?)
|
|
||||||
CREATE TABLE `root_certs` (
|
|
||||||
`id` int(2) NOT NULL,
|
|
||||||
`cert_text` varchar(255) DEFAULT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `cert_text` (`cert_text`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
-- TODO: replace with goose_db_version table
|
|
||||||
CREATE TABLE `schema_version` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`version` int(11) NOT NULL,
|
|
||||||
`when` datetime NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `version` (`version`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `stampcache` (
|
|
||||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
||||||
`certid` int(10) UNSIGNED DEFAULT NULL,
|
|
||||||
`cacheexpire` bigint(20) UNSIGNED DEFAULT NULL,
|
|
||||||
`issued` datetime NOT NULL,
|
|
||||||
`expire` datetime NOT NULL,
|
|
||||||
`subject` varchar(255) NOT NULL,
|
|
||||||
`hostname` varchar(255) NOT NULL,
|
|
||||||
`org` tinyint(1) NOT NULL,
|
|
||||||
`points` tinyint(3) UNSIGNED NOT NULL,
|
|
||||||
`O` varchar(255) NOT NULL,
|
|
||||||
`L` varchar(255) NOT NULL,
|
|
||||||
`ST` varchar(255) NOT NULL,
|
|
||||||
`C` varchar(255) NOT NULL,
|
|
||||||
`valid` tinyint(1) NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
UNIQUE KEY `hostname` (`hostname`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `statscache` (
|
|
||||||
`timestamp` bigint(20) NOT NULL,
|
|
||||||
`cache` text NOT NULL,
|
|
||||||
PRIMARY KEY (`timestamp`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
-- not mentioned in version5.sh
|
|
||||||
CREATE TABLE `temp` (
|
|
||||||
`id` int(11) DEFAULT NULL,
|
|
||||||
`data` int(11) DEFAULT NULL
|
|
||||||
) ENGINE = InnoDB
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `tickets` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP(),
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `timestamp` (`timestamp`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1 COMMENT ='Is used to generate ticket numbers for tracing back problems';
|
|
||||||
|
|
||||||
CREATE TABLE `tverify` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`photoid` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`URL` text NOT NULL,
|
|
||||||
`CN` text NOT NULL,
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `tverify-vote` (
|
|
||||||
`tverify` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`when` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`vote` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`comment` varchar(255) NOT NULL DEFAULT ''
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `userlocations` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`memid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`ccid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`regid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
`locid` int(11) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
CREATE TABLE `users` (
|
|
||||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`email` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`password` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`fname` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`mname` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`lname` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`suffix` varchar(50) NOT NULL DEFAULT '',
|
|
||||||
`dob` date NOT NULL DEFAULT '0000-00-00',
|
|
||||||
`verified` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`ccid` int(3) NOT NULL DEFAULT 0,
|
|
||||||
`regid` int(5) NOT NULL DEFAULT 0,
|
|
||||||
`locid` int(7) NOT NULL DEFAULT 0,
|
|
||||||
`listme` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`codesign` int(1) NOT NULL DEFAULT 0,
|
|
||||||
`1024bit` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`contactinfo` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`admin` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`orgadmin` tinyint(1) NOT NULL,
|
|
||||||
`ttpadmin` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`adadmin` tinyint(1) UNSIGNED NOT NULL,
|
|
||||||
`board` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`tverify` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`locadmin` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
`language` varchar(5) NOT NULL DEFAULT '',
|
|
||||||
`Q1` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`Q2` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`Q3` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`Q4` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`Q5` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`A1` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`A2` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`A3` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`A4` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`A5` varchar(255) NOT NULL DEFAULT '',
|
|
||||||
`created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`deleted` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
`locked` tinyint(1) NOT NULL,
|
|
||||||
`uniqueID` varchar(255) NOT NULL,
|
|
||||||
`otphash` varchar(16) NOT NULL,
|
|
||||||
`otppin` smallint(4) UNSIGNED ZEROFILL NOT NULL,
|
|
||||||
`assurer` int(2) NOT NULL DEFAULT 0,
|
|
||||||
`assurer_blocked` tinyint(1) NOT NULL DEFAULT 0,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `ccid` (`ccid`),
|
|
||||||
KEY `regid` (`regid`),
|
|
||||||
KEY `locid` (`locid`),
|
|
||||||
KEY `email` (`email`),
|
|
||||||
KEY `stats_users_created` (`created`),
|
|
||||||
KEY `stats_users_verified` (`verified`),
|
|
||||||
KEY `userverified` (`verified`)
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
|
@ -1,113 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2020 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- changes from version1.sh of the original code base
|
|
||||||
|
|
||||||
-- CCA agreements and such
|
|
||||||
CREATE TABLE `user_agreements` (
|
|
||||||
`id` int(11) PRIMARY KEY AUTO_INCREMENT,
|
|
||||||
|
|
||||||
-- the user that agrees
|
|
||||||
`memid` int(11) NOT NULL,
|
|
||||||
|
|
||||||
-- user that is involved in the agreement (e.g. Assurer)
|
|
||||||
`secmemid` int(11) DEFAULT NULL,
|
|
||||||
|
|
||||||
-- what is being agreed to? e.g. CCA
|
|
||||||
`document` varchar(50) DEFAULT NULL,
|
|
||||||
|
|
||||||
-- when did the agreement take place?
|
|
||||||
`date` datetime DEFAULT NULL,
|
|
||||||
|
|
||||||
-- whether the user actively agreed or if the agreement took place via
|
|
||||||
-- an indirect process (e.g. Assurance)
|
|
||||||
`active` int(1) NOT NULL,
|
|
||||||
|
|
||||||
-- in which process did the agreement take place (e.g. certificate
|
|
||||||
-- issuance, account creation, assurance)
|
|
||||||
`method` varchar(100) NOT NULL,
|
|
||||||
|
|
||||||
-- user comment
|
|
||||||
`comment` varchar(100) DEFAULT NULL
|
|
||||||
) DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- description for all certs to make identifying a cert easier
|
|
||||||
ALTER TABLE `domaincerts`
|
|
||||||
ADD `description` varchar(100) NOT NULL
|
|
||||||
DEFAULT '';
|
|
||||||
ALTER TABLE `emailcerts`
|
|
||||||
ADD `description` varchar(100) NOT NULL
|
|
||||||
DEFAULT '';
|
|
||||||
ALTER TABLE `gpg`
|
|
||||||
ADD `description` varchar(100) NOT NULL
|
|
||||||
DEFAULT '';
|
|
||||||
ALTER TABLE `orgdomaincerts`
|
|
||||||
ADD `description` varchar(100) NOT NULL
|
|
||||||
DEFAULT '';
|
|
||||||
ALTER TABLE `orgemailcerts`
|
|
||||||
ADD `description` varchar(100) NOT NULL
|
|
||||||
DEFAULT '';
|
|
||||||
|
|
||||||
|
|
||||||
-- Bugs #855, #863, #864, #888
|
|
||||||
ALTER TABLE `notary`
|
|
||||||
-- allow for marking as deleted instead of really deleting
|
|
||||||
ADD `deleted` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
|
|
||||||
-- add "TOPUP" as method for point transfers (for TTP)
|
|
||||||
MODIFY `method`
|
|
||||||
enum (
|
|
||||||
'Face to Face Meeting',
|
|
||||||
'Trusted Third Parties',
|
|
||||||
'Thawte Points Transfer',
|
|
||||||
'Administrative Increase',
|
|
||||||
'CT Magazine - Germany',
|
|
||||||
'Temporary Increase',
|
|
||||||
'Unknown',
|
|
||||||
'TOPUP'
|
|
||||||
) NOT NULL DEFAULT 'Face to Face Meeting';
|
|
||||||
|
|
||||||
|
|
||||||
-- Organisation Assurance
|
|
||||||
ALTER TABLE `orginfo`
|
|
||||||
-- which Organisation Assurer entered the organisation?
|
|
||||||
ADD `creator_id` int(11) NOT NULL DEFAULT '0',
|
|
||||||
|
|
||||||
-- when was the organisation entered?
|
|
||||||
ADD `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
|
|
||||||
-- allow for marking as deleted instead of really deleting
|
|
||||||
ADD `deleted` datetime NOT NULL DEFAULT '0000-00-00 00:00:00';
|
|
||||||
|
|
||||||
|
|
||||||
ALTER TABLE `org`
|
|
||||||
-- which Organisation Assurer assigned the Organisation Admin?
|
|
||||||
ADD `creator_id` int(11) NOT NULL DEFAULT '0',
|
|
||||||
|
|
||||||
-- when was the Organisation Admin assigned?
|
|
||||||
ADD `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
|
||||||
|
|
||||||
-- allow for marking as deleted instead of really deleting
|
|
||||||
ADD `deleted` datetime NOT NULL DEFAULT '0000-00-00 00:00:00';
|
|
||||||
|
|
||||||
|
|
||||||
-- Update schema version number
|
|
||||||
INSERT INTO `schema_version`
|
|
||||||
(`version`, `when`)
|
|
||||||
VALUES ('1', NOW());
|
|
|
@ -1,46 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2020 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- changes from version2.sh of the original code base
|
|
||||||
|
|
||||||
-- Organisation Assurance bug #1118
|
|
||||||
ALTER TABLE `orgemailcerts`
|
|
||||||
ADD `ou` varchar(50) NOT NULL
|
|
||||||
DEFAULT '';
|
|
||||||
|
|
||||||
|
|
||||||
-- Bugs #855, #863, #864, #888, #1118
|
|
||||||
ALTER TABLE `notary`
|
|
||||||
-- add "TTP-Assisted" as method for point transfers (for TTP)
|
|
||||||
MODIFY `method`
|
|
||||||
enum (
|
|
||||||
'Face to Face Meeting',
|
|
||||||
'Trusted Third Parties',
|
|
||||||
'Thawte Points Transfer',
|
|
||||||
'Administrative Increase',
|
|
||||||
'CT Magazine - Germany',
|
|
||||||
'Temporary Increase',
|
|
||||||
'Unknown',
|
|
||||||
'TOPUP',
|
|
||||||
'TTP-Assisted'
|
|
||||||
) NOT NULL DEFAULT 'Face to Face Meeting';
|
|
||||||
|
|
||||||
-- Update schema version number
|
|
||||||
INSERT INTO `schema_version`
|
|
||||||
(`version`, `when`)
|
|
||||||
VALUES ('2', NOW());
|
|
|
@ -1,52 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2020 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- changes from version3.sh of the original code base
|
|
||||||
|
|
||||||
-- alter table Admin log
|
|
||||||
ALTER TABLE `adminlog`
|
|
||||||
ADD `type` varchar(50) NOT NULL,
|
|
||||||
ADD `information` varchar(50) NOT NULL;
|
|
||||||
|
|
||||||
|
|
||||||
-- create new table OrgAdminLog
|
|
||||||
CREATE TABLE IF NOT EXISTS `orgadminlog` (
|
|
||||||
`when` datetime NOT NULL,
|
|
||||||
`oid` int(11) NOT NULL,
|
|
||||||
`adminid` int(11) NOT NULL,
|
|
||||||
`type` varchar(50) NOT NULL,
|
|
||||||
`information` varchar(50) NOT NULL
|
|
||||||
) ENGINE = MyISAM
|
|
||||||
DEFAULT CHARSET = latin1;
|
|
||||||
|
|
||||||
|
|
||||||
-- alter table OrgDomainCerts
|
|
||||||
ALTER TABLE `orgdomaincerts`
|
|
||||||
ADD orgadminid int(11) NULL,
|
|
||||||
ADD revokeorgadminid int(11) NULL;
|
|
||||||
|
|
||||||
|
|
||||||
-- alter table OrgEmailCerts
|
|
||||||
ALTER TABLE `orgemailcerts`
|
|
||||||
ADD orgadminid int(11) NULL,
|
|
||||||
ADD revokeorgadminid int(11) NULL;
|
|
||||||
|
|
||||||
-- Update schema version number
|
|
||||||
INSERT INTO `schema_version`
|
|
||||||
(`version`, `when`)
|
|
||||||
VALUES ('3', NOW());
|
|
|
@ -1,38 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2020 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- changes from version4.sh of the original code base
|
|
||||||
|
|
||||||
-- update table admin log
|
|
||||||
|
|
||||||
UPDATE `adminlog`
|
|
||||||
SET `type` = 'old name or dob change',
|
|
||||||
`information` = 'see adminlog_table_backup_1135';
|
|
||||||
|
|
||||||
-- alter table admin log
|
|
||||||
|
|
||||||
ALTER TABLE `adminlog`
|
|
||||||
DROP `old-lname`,
|
|
||||||
DROP `old-dob`,
|
|
||||||
DROP `new-lname`,
|
|
||||||
DROP `new-dob`;
|
|
||||||
|
|
||||||
-- Update schema version number
|
|
||||||
INSERT INTO `schema_version`
|
|
||||||
(`version`, `when`)
|
|
||||||
VALUES ('4', NOW());
|
|
|
@ -1,158 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2020 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- changes from version5.sh of the original code base
|
|
||||||
|
|
||||||
-- Move myISAM to InnoDB bug #1172
|
|
||||||
|
|
||||||
ALTER TABLE `abusereports`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `addlang`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `adminlog`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `advertising`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `alerts`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `baddomains`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `cats_passed`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `cats_type`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `cats_variant`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `countries`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `disputedomain`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `disputeemail`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `domaincerts`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `domains`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `domlink`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `email`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `emailcerts`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `emaillink`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `gpg`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `languages`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `localias`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `locations`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `news`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `notary`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `org`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `orgadminlog`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `orgdomaincerts`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `orgdomains`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `orgdomlink`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `orgemailcerts`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `orgemaillink`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `orginfo`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `otphashes`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `pinglog`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `regions`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `root_certs`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `schema_version`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `stampcache`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `statscache`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `tickets`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `tverify`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `tverify-vote`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `user_agreements`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
ALTER TABLE `userlocations`
|
|
||||||
ENGINE =INNODB;
|
|
||||||
|
|
||||||
-- Update schema version number
|
|
||||||
INSERT INTO `schema_version`
|
|
||||||
(`version`, `when`)
|
|
||||||
VALUES ('5', NOW());
|
|
|
@ -1,26 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2011 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- changes from version6.sh of the original code base
|
|
||||||
ALTER TABLE `users`
|
|
||||||
ADD `lastLoginAttempt` datetime NULL;
|
|
||||||
|
|
||||||
-- Update schema version number
|
|
||||||
INSERT INTO `schema_version`
|
|
||||||
(`version`, `when`)
|
|
||||||
VALUES ('6', NOW());
|
|
|
@ -1,60 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
|
|
||||||
-- LibreSSL - CAcert web application
|
|
||||||
-- Copyright (C) 2004-2020 CAcert Inc.
|
|
||||||
--
|
|
||||||
-- This program is free software; you can redistribute it and/or modify
|
|
||||||
-- it under the terms of the GNU General Public License as published by
|
|
||||||
-- the Free Software Foundation; version 2 of the License.
|
|
||||||
--
|
|
||||||
-- This program is distributed in the hope that it will be useful,
|
|
||||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
-- GNU General Public License for more details.
|
|
||||||
--
|
|
||||||
-- You should have received a copy of the GNU General Public License
|
|
||||||
-- along with this program; if not, write to the Free Software
|
|
||||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
-- initial data set from test database
|
|
||||||
|
|
||||||
-- tables for cats (https://cats.cacert.org/)
|
|
||||||
INSERT INTO cats_type (id, type_text)
|
|
||||||
VALUES (1, 'Assurer Challenge'),
|
|
||||||
(2, 'Org Assurer Test'),
|
|
||||||
(3, 'Triage Challenge'),
|
|
||||||
(5, 'Data Privacy Quiz');
|
|
||||||
|
|
||||||
INSERT INTO cats_variant (id, type_id, test_text)
|
|
||||||
VALUES (5, 1, 'Assurer\'s challenge (EN)'),
|
|
||||||
(6, 1, 'CAcert Assurer Prüfung (DE)'),
|
|
||||||
(4, 1, 'CATS V0.1'),
|
|
||||||
(12, 5, 'Data Privacy Quiz (Generic)'),
|
|
||||||
(15, 5, 'Data Privacy Quiz (Infrastructure Admins)'),
|
|
||||||
(13, 5, 'Data Privacy Quiz (Software)'),
|
|
||||||
(14, 5, 'Data Privacy Quiz (Triage and Support)'),
|
|
||||||
(11, 1, 'Výzva zaručovatele (CZ)');
|
|
||||||
|
|
||||||
|
|
||||||
-- country list
|
|
||||||
-- TODO: fetch from external source like https://github.com/datasets/country-codes
|
|
||||||
-- TODO: check for completeness / add mapping to ISO country codes?
|
|
||||||
|
|
||||||
|
|
||||||
-- language selection
|
|
||||||
-- TODO: fetch from external source like https://github.com/datasets/language-codes
|
|
||||||
-- in combination with http://www.unicode.org/Public/cldr/latest/core.zip
|
|
||||||
-- TODO: transform to UTF-8, check against current ISO standards
|
|
||||||
|
|
||||||
|
|
||||||
-- region names
|
|
||||||
-- TODO: take from https://github.com/datasets/fips-10-4
|
|
||||||
|
|
||||||
-- locations list is just too big to include here (>110 MiB dump)
|
|
||||||
-- TODO: take from an external source like https://github.com/datasets/un-locode
|
|
||||||
|
|
||||||
;
|
|
||||||
|
|
||||||
-- +goose Down
|
|
||||||
TRUNCATE TABLE cats_variant;
|
|
||||||
TRUNCATE TABLE cats_type;
|
|
|
@ -1,4 +0,0 @@
|
||||||
-- +goose Up
|
|
||||||
INSERT INTO root_certs (id, cert_text)
|
|
||||||
VALUES (1, 'CAcert Testserver Root'),
|
|
||||||
(2, 'CAcert Testserver Class 3');
|
|
|
@ -1,310 +0,0 @@
|
||||||
package migrations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/md5"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/sha1"
|
|
||||||
"database/sql"
|
|
||||||
"encoding/csv"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pressly/goose"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/text/encoding"
|
|
||||||
"golang.org/x/text/encoding/charmap"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
goose.AddMigration(Up20201214193523, Down20201214193523)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Up20201214193523(tx *sql.Tx) error {
|
|
||||||
// This code is executed when the migration is applied.
|
|
||||||
var (
|
|
||||||
data int
|
|
||||||
countryId, regionId, locationId int64
|
|
||||||
row *sql.Row
|
|
||||||
result sql.Result
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
|
|
||||||
row = tx.QueryRow("SELECT COUNT(*) FROM users WHERE admin=1")
|
|
||||||
if err = row.Scan(&data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Infof("%d admins found\n", data)
|
|
||||||
|
|
||||||
var countryFipsCodeMap map[string]int64
|
|
||||||
if countryFipsCodeMap, err = updateCountries(tx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = updateRegions(tx, &countryFipsCodeMap); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if data == 0 {
|
|
||||||
location, err := time.LoadLocation("Europe/Berlin")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
dob, err := time.ParseInLocation(
|
|
||||||
"2006-01-02",
|
|
||||||
"1977-08-08",
|
|
||||||
location,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if countryId, err = getCountryId(tx, "Germany"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if regionId, err = getRegionId(tx, "Sachsen", countryId); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if locationId, err = getLocationId(tx, "Dresden", countryId, regionId); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
random64Bytes := make([]byte, 64)
|
|
||||||
_, err = rand.Read(random64Bytes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err = tx.Exec(`INSERT INTO users (email, password, fname, mname,
|
|
||||||
lname, suffix, dob, verified, ccid,
|
|
||||||
regid, locid, listme, codesign, 1024bit, contactinfo, admin, orgadmin,
|
|
||||||
ttpadmin, adadmin, board, tverify, locadmin, language,
|
|
||||||
Q1, Q2, Q3, Q4, Q5,
|
|
||||||
A1, A2, A3, A4, A5,
|
|
||||||
created, modified, locked, uniqueID,
|
|
||||||
otphash, otppin, assurer, assurer_blocked, lastLoginAttempt)
|
|
||||||
VALUES (?, ?, ?, '', ?, '', ?, 0,
|
|
||||||
?, ?, ?, 0, 1, 0, ?,
|
|
||||||
1, 0, 0, 0, 0, 0, 0, ?,
|
|
||||||
'', '', '', '', '', '', '', '', '', '',
|
|
||||||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0,
|
|
||||||
SHA1(CONCAT(NOW(), ?)),
|
|
||||||
'', 0, 0, 0, NULL)`,
|
|
||||||
"jandd@cacert.org",
|
|
||||||
fmt.Sprintf("%x", sha1.Sum([]byte("abcdefghijklmn"))),
|
|
||||||
"Jan",
|
|
||||||
"Dittberner",
|
|
||||||
dob,
|
|
||||||
countryId,
|
|
||||||
regionId,
|
|
||||||
locationId,
|
|
||||||
"Somewhere over the rainbow",
|
|
||||||
"de_DE",
|
|
||||||
fmt.Sprintf("%x", md5.Sum(random64Bytes)))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
lastId, err := result.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
log.Infof("new user id is %d", lastId)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateRegions(tx *sql.Tx, codeMap *map[string]int64) error {
|
|
||||||
client := &http.Client{}
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
request *http.Request
|
|
||||||
response *http.Response
|
|
||||||
csvReader *csv.Reader
|
|
||||||
)
|
|
||||||
request, err = http.NewRequest("GET", "https://raw.githubusercontent.com/datasets/fips-10-4/master/data/data.csv", nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
response, err = client.Do(request)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if response.StatusCode != 200 {
|
|
||||||
return fmt.Errorf("got unexpected HTTP status %d %s", response.StatusCode, response.Status)
|
|
||||||
}
|
|
||||||
csvReader = csv.NewReader(response.Body)
|
|
||||||
headings, err := csvReader.Read()
|
|
||||||
log.Infof("CSV headings %s", strings.Join(headings, ","))
|
|
||||||
for {
|
|
||||||
record, err := csvReader.Read()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
regionCode := record[0]
|
|
||||||
regionDivision := record[1]
|
|
||||||
regionName := record[2]
|
|
||||||
fipsCode := regionCode[:2]
|
|
||||||
log.Infof("read %s %s %s", regionCode, regionName, fipsCode)
|
|
||||||
var countryId int64
|
|
||||||
var exists bool
|
|
||||||
if countryId, exists = (*codeMap)[fipsCode]; exists {
|
|
||||||
log.Infof("country id %d", countryId)
|
|
||||||
} else if regionDivision == "country" {
|
|
||||||
countryId, err = getCountryId(tx, regionName)
|
|
||||||
(*codeMap)[fipsCode] = countryId
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("could not find country for %s %s", fipsCode, regionName)
|
|
||||||
}
|
|
||||||
_, err = getRegionId(tx, regionName, countryId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateCountries(tx *sql.Tx) (map[string]int64, error) {
|
|
||||||
client := &http.Client{}
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
request *http.Request
|
|
||||||
response *http.Response
|
|
||||||
csvReader *csv.Reader
|
|
||||||
)
|
|
||||||
request, err = http.NewRequest("GET", "https://raw.githubusercontent.com/datasets/country-codes/master/data/country-codes.csv", nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
response, err = client.Do(request)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if response.StatusCode != 200 {
|
|
||||||
return nil, fmt.Errorf("got unexpected HTTP status %d %s", response.StatusCode, response.Status)
|
|
||||||
}
|
|
||||||
csvReader = csv.NewReader(response.Body)
|
|
||||||
|
|
||||||
headings, err := csvReader.Read()
|
|
||||||
log.Infof("CSV headings %s", strings.Join(headings, ","))
|
|
||||||
|
|
||||||
countryFipsMapping := make(map[string]int64, 0)
|
|
||||||
var count int64 = 0
|
|
||||||
for {
|
|
||||||
record, err := csvReader.Read()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
name := strings.TrimSpace(record[54])
|
|
||||||
if len(name) > 0 {
|
|
||||||
countryId, err := getCountryId(tx, name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
countryFipsMapping[record[7]] = countryId
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.Infof("read %d countries", count)
|
|
||||||
|
|
||||||
return countryFipsMapping, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getLocationId(tx *sql.Tx, name string, countryId, regionId int64) (int64, error) {
|
|
||||||
var (
|
|
||||||
row *sql.Row
|
|
||||||
result sql.Result
|
|
||||||
locationId int64
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
row = tx.QueryRow("SELECT id FROM locations WHERE name=? AND ccid=? AND regid=?", name, countryId, regionId)
|
|
||||||
if err := row.Scan(&locationId); err != nil {
|
|
||||||
if err != sql.ErrNoRows {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return locationId, nil
|
|
||||||
}
|
|
||||||
result, err = tx.Exec("INSERT INTO locations (regid, ccid, name, acount) VALUES (?, ?, ?, ?)", regionId, countryId, name, 0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
locationId, err = result.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return locationId, nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRegionId(tx *sql.Tx, name string, countryId int64) (int64, error) {
|
|
||||||
var (
|
|
||||||
row *sql.Row
|
|
||||||
result sql.Result
|
|
||||||
regionId int64
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
encoder := charmap.ISO8859_1.NewEncoder()
|
|
||||||
cutDownName, err := encoding.HTMLEscapeUnsupported(encoder).String(name)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
if len(cutDownName) > 50 {
|
|
||||||
cutDownName = cutDownName[:50]
|
|
||||||
}
|
|
||||||
row = tx.QueryRow("SELECT id FROM regions WHERE name=? AND ccid=?", cutDownName, countryId)
|
|
||||||
if err := row.Scan(®ionId); err != nil {
|
|
||||||
if err != sql.ErrNoRows {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return regionId, nil
|
|
||||||
}
|
|
||||||
result, err = tx.Exec("INSERT INTO regions (ccid, name, acount) VALUES (?, ?, ?)", countryId, cutDownName, 0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
regionId, err = result.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return regionId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCountryId(tx *sql.Tx, name string) (int64, error) {
|
|
||||||
var (
|
|
||||||
row *sql.Row
|
|
||||||
result sql.Result
|
|
||||||
countryId int64
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
row = tx.QueryRow("SELECT id FROM countries WHERE name=?", name)
|
|
||||||
if err := row.Scan(&countryId); err != nil {
|
|
||||||
if err != sql.ErrNoRows {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return countryId, nil
|
|
||||||
}
|
|
||||||
result, err = tx.Exec("INSERT INTO countries (countries.name, countries.acount) VALUES (?, ?)", name, 0)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
countryId, err = result.LastInsertId()
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
return countryId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Down20201214193523(tx *sql.Tx) error {
|
|
||||||
// This code is executed when the migration is rolled back.
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
INSERT INTO cacert_test.languages (locale, en_co, en_lang, country, lang)
|
|
||||||
VALUES ('sq_AL', 'Albania', 'Albanian', 'Shqipëria', 'shqipe'),
|
|
||||||
('ar_DZ', 'Algeria', 'Arabic', 'ﺮﺌﺎﺰﺠﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('ar_AA', 'Arabic Speaking', 'Arabic', 'ﺔﻴﺐﺮﻌﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('es_AR', 'Argentina', 'Spanish', 'Argentina', 'Español'),
|
|
||||||
('en_AU', 'Australia', 'English', 'Australia', 'English'),
|
|
||||||
('de_AT', 'Austria', 'German', 'Österreich', 'Deutsch'),
|
|
||||||
('ar_BH', 'Bahrain', 'Arabic', 'ﻦﻴﺮﺤﺐﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('be_BY', 'Belarus', 'Belarusian', 'Беларусь', 'беларуски'),
|
|
||||||
('nl_BE', 'Belgium', 'Dutch', 'België', 'Nederlands'),
|
|
||||||
('fr_BE', 'Belgium', 'French', 'Belgique', 'français'),
|
|
||||||
('es_BO', 'Bolivia', 'Spanish', 'Bolivia', 'Español'),
|
|
||||||
('sh_BA', 'Bosnia Herzogovina', 'Serbo-Croatian', 'Bosnia Herzogovina', 'Serbo-Croatian'),
|
|
||||||
('pt_BR', 'Brazil', 'Portuguese', 'Brasil', 'Português'),
|
|
||||||
('bg_BG', 'Bulgaria', 'Bulgarian', 'България', 'български'),
|
|
||||||
('en_CA', 'Canada', 'English', 'Canada', 'English'),
|
|
||||||
('fr_CA', 'Canada', 'French', 'Canada', 'français'),
|
|
||||||
('es_CL', 'Chile', 'Spanish', 'Chile', 'Español'),
|
|
||||||
('es_CO', 'Colombia', 'Spanish', 'Colombia', 'Español'),
|
|
||||||
('es_CR', 'Costa Rica', 'Spanish', 'Costa Rica', 'Español'),
|
|
||||||
('hr_HR', 'Croatia', 'Croatian', 'Hrvatska', 'hrvatski'),
|
|
||||||
('cs_CZ', 'Czech Republic', 'Czech', 'Česká republika', 'čeština'),
|
|
||||||
('da_DK', 'Denmark', 'Danish', 'Danmark', 'dansk'),
|
|
||||||
('es_DO', 'Dominican Republic', 'Spanish', 'República Dominicana', 'Español'),
|
|
||||||
('es_EC', 'Ecuador', 'Spanish', 'Ecuador', 'Español'),
|
|
||||||
('ar_EG', 'Egypt', 'Arabic', 'ﺮﺼﻣ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('es_SV', 'El Salvador', 'Spanish', 'El Salvador', 'Español'),
|
|
||||||
('et_EE', 'Estonia', 'Estonian', 'Eesti', 'eesti'),
|
|
||||||
('mk_MK', 'FYR Macedonia', 'Macedonian', 'FYR Macedonia', 'Macedonian'),
|
|
||||||
('fi_FI', 'Finland', 'Finnish', 'Suomi', 'suomi'),
|
|
||||||
('sv_FI', 'Finland', 'Swedish', 'Finland', 'svenska'),
|
|
||||||
('fr_FR', 'France', 'French', 'France', 'français'),
|
|
||||||
('de_DE', 'Germany', 'German', 'Deutschland', 'Deutsch'),
|
|
||||||
('el_GR', 'Greece', 'Greek', 'Ελλάδα', 'ελληνικά'),
|
|
||||||
('es_GT', 'Guatemala', 'Spanish', 'Guatemala', 'Español'),
|
|
||||||
('es_HN', 'Honduras', 'Spanish', 'Honduras', 'Español'),
|
|
||||||
('zh_HK', 'Hong Kong', 'Chinese', '香港', '中文'),
|
|
||||||
('hu_HU', 'Hungary', 'Hungarian', 'Magyarország', 'magyar'),
|
|
||||||
('is_IS', 'Iceland', 'Icelandic', 'Ísland', 'íslenska'),
|
|
||||||
('in_ID', 'Indonesia', 'Indonesian', 'Indonesia', 'Bahasa Indonesia'),
|
|
||||||
('fa_IR', 'Iran', 'Farsi', 'Iran', 'ﻰﺴﺮﺎﻓ'),
|
|
||||||
('en_IE', 'Ireland', 'English', 'Ireland', 'English'),
|
|
||||||
('he_IL', 'Israel', 'Hebrew', 'לארשי', 'תירבע'),
|
|
||||||
('iw_IL', 'Israel', 'Hebrew', 'לארשי', 'תירבע'),
|
|
||||||
('it_IT', 'Italy', 'Italian', 'Italia', 'italiano'),
|
|
||||||
('ja_JP', 'Japan', 'Japanese', '日本', '日本語'),
|
|
||||||
('ar_JO', 'Jordan', 'Arabic', 'ﻦﺪﺮﺄﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('ko_KR', 'Korea', 'Korean', '대한민국', '한국어'),
|
|
||||||
('ar_KW', 'Kuwait', 'Arabic', 'ﺖﻴﻮﻜﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('es_LA', 'Latin America', 'Spanish', 'América latina', 'Español'),
|
|
||||||
('lv_LV', 'Latvia', 'Latvian', 'Latvija', 'latviešu'),
|
|
||||||
('ar_LB', 'Lebanon', 'Arabic', 'ﻦﺎﻨﺐﻟ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('de_LI', 'Liechtenstein', 'German', 'Liechtenstein', 'Deutsch'),
|
|
||||||
('lt_LT', 'Lithuania', 'Lithuanian', 'Lietuva', 'lietuvių'),
|
|
||||||
('fr_LU', 'Luxembourg', 'French', 'Luxembourg', 'français'),
|
|
||||||
('de_LU', 'Luxembourg', 'German', 'Luxemburg', 'Deutsch'),
|
|
||||||
('es_MX', 'Mexico', 'Spanish', 'México', 'Español'),
|
|
||||||
('ar_MA', 'Morocco', 'Arabic', 'ﺔﻴﺐﺮﻐﻤﻠﺍ ﺔﻜﻠﻤﻤﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('nl_NL', 'Netherlands', 'Dutch', 'Nederland', 'Nederlands'),
|
|
||||||
('en_NZ', 'New Zealand', 'English', 'New Zealand', 'English'),
|
|
||||||
('es_NI', 'Nicaragua', 'Spanish', 'Nicarágua', 'Español'),
|
|
||||||
('no_NO', 'Norway', 'Norwegian', 'Norge', 'bokmål'),
|
|
||||||
('ar_OM', 'Oman', 'Arabic', 'ﻦﺎﻤﻋ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('es_PA', 'Panama', 'Spanish', 'Panamá', 'Español'),
|
|
||||||
('es_PY', 'Paraguay', 'Spanish', 'Paraguay', 'Español'),
|
|
||||||
('zh_CN', 'People''s Republic of China', 'Chinese', '中华人民共和国', '中文'),
|
|
||||||
('es_PE', 'Peru', 'Spanish', 'Perú', 'Español'),
|
|
||||||
('pl_PL', 'Poland', 'Polish', 'Polska', 'polski'),
|
|
||||||
('pt_PT', 'Portugal', 'Portuguese', 'Portugal', 'português'),
|
|
||||||
('ar_QA', 'Qatar', 'Arabic', 'ﺮﻄﻗ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('ro_RO', 'Romania', 'Romanian', 'România', 'română'),
|
|
||||||
('ru_RU', 'Russia', 'Russian', 'Россия', 'русский'),
|
|
||||||
('ar_SA', 'Saudi Arabia', 'Arabic', 'ﺔﻴﺪﻮﻌﺴﻠﺍ ﺔﻴﺐﺮﻌﻠﺍ ﺔﻜﻠﻤﻤﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('hr_SP', 'Serbia', 'Romanian', 'Srbija', 'română'),
|
|
||||||
('sr_SP', 'Serbia', 'Serbian (Cyrillic)', 'Југославија', 'српски'),
|
|
||||||
('zh_SG', 'Singapore', 'Chinese', '新加坡', '中文'),
|
|
||||||
('sk_SK', 'Slovakia', 'Slovak', 'Slovenská republika', 'slovenčina'),
|
|
||||||
('sl_SI', 'Slovenia', 'Slovene', 'Slovenija', 'slovenski'),
|
|
||||||
('en_ZA', 'South Africa', 'English', 'South Africa', 'English'),
|
|
||||||
('eu_ES', 'Spain', 'Basque', 'Espainia', 'Euskara'),
|
|
||||||
('ca_ES', 'Spain', 'Catalan', 'Espanya', 'català'),
|
|
||||||
('es_ES', 'Spain', 'Spanish', 'España', 'Español'),
|
|
||||||
('sv_SE', 'Sweden', 'Swedish', 'Sverige', 'svenska'),
|
|
||||||
('fr_CH', 'Switzerland', 'French', 'Suisse', 'français'),
|
|
||||||
('de_CH', 'Switzerland', 'German', 'Schweiz', 'Deutsch'),
|
|
||||||
('it_CH', 'Switzerland', 'Italian', 'Svizzera', 'italiano'),
|
|
||||||
('ar_SY', 'Syria', 'Arabic', 'ﺎﻴﺮﻮﺳ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('zh_TW', 'Taiwan', 'Chinese', '中華民國', '中文'),
|
|
||||||
('th_TH', 'Thailand', 'Thai', 'ไทย', 'ไทย'),
|
|
||||||
('ar_TN', 'Tunisia', 'Arabic', 'ﺲﻨﻮﺗ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('tr_TR', 'Turkey', 'Turkish', 'Türkiye', 'Türkçe'),
|
|
||||||
('ar_UA', 'U.A.E.', 'Arabic', 'ﺔﺪﺤﺘﻤﻠﺍ ﺔﻴﺐﺮﻌﻠﺍ ﺖﺎﺮﺎﻤﺈﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ'),
|
|
||||||
('uk_UA', 'Ukraine', 'Ukrainian', 'Україна', 'україньска'),
|
|
||||||
('en_GB', 'United Kingdom', 'English', 'United Kingdom', 'English'),
|
|
||||||
('en_US', 'United States', 'English', 'United States', 'English'),
|
|
||||||
('es_US', 'United States', 'Spanish', 'Estados Unidos', 'Español'),
|
|
||||||
('es_UY', 'Uruguay', 'Spanish', 'Uruguay', 'Español'),
|
|
||||||
('es_VE', 'Venezuela', 'Spanish', 'Venezuela', 'Español'),
|
|
||||||
('vi_VN', 'Vietnam', 'Vietnamese', 'Việt Nam', 'Tiểng Việt'),
|
|
||||||
('ar_YE', 'Yemen', 'Arabic', 'ﻦﻤﻴﻠﺍ', 'ﺔﻴﺐﺮﻌﻠﺍ');
|
|
|
@ -1,57 +0,0 @@
|
||||||
package migrations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"flag"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/pressly/goose"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
|
|
||||||
_ "github.com/go-sql-driver/mysql"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
flags = flag.NewFlagSet("goose", flag.ExitOnError)
|
|
||||||
dir = flags.String("dir", ".", "directory with migration files")
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
_ = flags.Parse(os.Args[1:])
|
|
||||||
args := flags.Args()
|
|
||||||
|
|
||||||
if len(args) < 1 {
|
|
||||||
flags.Usage()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
command := args[0]
|
|
||||||
|
|
||||||
var dbUrl string
|
|
||||||
var exists bool
|
|
||||||
if dbUrl, exists = os.LookupEnv("DB_URL"); !exists {
|
|
||||||
log.Fatalf("define database URL in environment variable DB_URL")
|
|
||||||
}
|
|
||||||
db, err := sql.Open("mysql", dbUrl)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("goose: failt to open DB: %v\n", err)
|
|
||||||
}
|
|
||||||
if err = goose.SetDialect("mysql"); err != nil {
|
|
||||||
log.Fatalf("failed to set dialect: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := db.Close(); err != nil {
|
|
||||||
log.Fatalf("goose: failed to close DB: %v\n", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
arguments := make([]string, 0)
|
|
||||||
if len(args) > 3 {
|
|
||||||
arguments = append(arguments, args[3:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := goose.Run(command, db, *dir, arguments...); err != nil {
|
|
||||||
log.Fatalf("goose %v: %v", command, err)
|
|
||||||
}
|
|
||||||
}
|
|
4426
package-lock.json
generated
4426
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -13,8 +13,11 @@
|
||||||
],
|
],
|
||||||
"author": "Jan Dittberner",
|
"author": "Jan Dittberner",
|
||||||
"license": "GPL-2.0+",
|
"license": "GPL-2.0+",
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^5.2.3",
|
||||||
|
"node-forge": "^1.3.0"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bootstrap": "^4.5.3",
|
|
||||||
"delete": "^1.1.0",
|
"delete": "^1.1.0",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"gulp-csso": "^4.0.0",
|
"gulp-csso": "^4.0.0",
|
||||||
|
@ -24,10 +27,6 @@
|
||||||
"gulp-sourcemaps": "^3.0.0",
|
"gulp-sourcemaps": "^3.0.0",
|
||||||
"gulp-sri-hash": "^2.2.0",
|
"gulp-sri-hash": "^2.2.0",
|
||||||
"gulp-uglify": "^3.0.0",
|
"gulp-uglify": "^3.0.0",
|
||||||
"i18next-client": "^1.11.0",
|
|
||||||
"jquery": "^3.5.0",
|
|
||||||
"node-forge": "^1.3.0",
|
|
||||||
"popper.js": "^1.16.0",
|
|
||||||
"sass": "^1.56.0"
|
"sass": "^1.56.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
COUNTRY_CODE=CH
|
|
||||||
ORGANIZATION="Acme Ltd."
|
|
||||||
|
|
||||||
if [ ! -d "example_ca" ]; then
|
|
||||||
mkdir -p example_ca/root/newcerts example_ca/sub/newcerts example_ca/email/newcerts
|
|
||||||
touch example_ca/root/index.txt example_ca/sub/index.txt example_ca/email/index.txt
|
|
||||||
umask 077
|
|
||||||
mkdir example_ca/root/private example_ca/sub/private example_ca/email/private
|
|
||||||
openssl req -new -x509 \
|
|
||||||
-config ca.cnf \
|
|
||||||
-keyout example_ca/root/private/ca.key.pem \
|
|
||||||
-newkey rsa:3072 \
|
|
||||||
-nodes \
|
|
||||||
-subj "/CN=Example Root CA/C=${COUNTRY_CODE}/O=${ORGANIZATION}" \
|
|
||||||
-utf8 \
|
|
||||||
-days 3650 \
|
|
||||||
-out example_ca/root/ca.crt.pem
|
|
||||||
chmod +r example_ca/root/ca.crt.pem
|
|
||||||
openssl req -new \
|
|
||||||
-config ca.cnf \
|
|
||||||
-keyout example_ca/sub/private/ca.key.pem \
|
|
||||||
-newkey rsa:3072 \
|
|
||||||
-nodes \
|
|
||||||
-subj "/CN=Example Sub CA/C=${COUNTRY_CODE}/O=${ORGANIZATION}" \
|
|
||||||
-utf8 \
|
|
||||||
-out example_ca/sub/ca.csr.pem
|
|
||||||
openssl ca \
|
|
||||||
-config ca.cnf \
|
|
||||||
-name rootca \
|
|
||||||
-in example_ca/sub/ca.csr.pem \
|
|
||||||
-extensions ext_sub_ca \
|
|
||||||
-out example_ca/sub/ca.crt.pem \
|
|
||||||
-rand_serial \
|
|
||||||
-batch
|
|
||||||
openssl req -new \
|
|
||||||
-config ca.cnf \
|
|
||||||
-keyout example_ca/email/private/ca.key.pem \
|
|
||||||
-newkey rsa:3072 \
|
|
||||||
-nodes \
|
|
||||||
-subj "/CN=Example Email CA/C=${COUNTRY_CODE}/O=${ORGANIZATION}" \
|
|
||||||
-utf8 \
|
|
||||||
-out example_ca/email/ca.csr.pem
|
|
||||||
openssl ca \
|
|
||||||
-config ca.cnf \
|
|
||||||
-name rootca \
|
|
||||||
-in example_ca/email/ca.csr.pem \
|
|
||||||
-extensions ext_email_ca \
|
|
||||||
-out example_ca/email/ca.crt.pem \
|
|
||||||
-rand_serial \
|
|
||||||
-batch
|
|
||||||
fi
|
|
|
@ -8,11 +8,11 @@
|
||||||
<link rel="stylesheet" href="../public/css/styles.min.css">
|
<link rel="stylesheet" href="../public/css/styles.min.css">
|
||||||
<meta name="theme-color" content="#ffffff">
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
<title>CSR generation in browser</title>
|
<title>CSR generation in your browser</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>CSR generation in browser</h1>
|
<h1>CSR generation in your browser</h1>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<form id="csr-form">
|
<form id="csr-form">
|
||||||
|
@ -31,13 +31,12 @@
|
||||||
<fieldset class="form-group">
|
<fieldset class="form-group">
|
||||||
<legend>RSA Key Size</legend>
|
<legend>RSA Key Size</legend>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="radio" name="keySize" id="size3072" value="3072"
|
<input class="form-check-input" type="radio" name="keySize" id="size3072" value="3072" checked>
|
||||||
checked>
|
|
||||||
<label class="form-check-label" for="size3072">3072 Bit</label>
|
<label class="form-check-label" for="size3072">3072 Bit</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="radio" name="keySize" id="size2048" value="2048">
|
<input class="form-check-input" type="radio" name="keySize" id="size2048" value="2048">
|
||||||
<label class="form-check-label" for="size2048">2048 Bit (not recommended)</label>
|
<label class="form-check-label" for="size2048">2048 Bit (most compatible, least secure)</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="radio" name="keySize" id="size4096" value="4096">
|
<input class="form-check-input" type="radio" name="keySize" id="size4096" value="4096">
|
||||||
|
@ -51,29 +50,34 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="status-block" class="d-none row">
|
<div id="status-block" class="d-none row">
|
||||||
<div class="col-12">
|
<div class="col-12 py-3">
|
||||||
<div class="d-flex align-items-center">
|
<div class="progress" style="height: 2rem">
|
||||||
<strong id="status-text">Loading ...</strong>
|
<div id="progress-bar" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0"
|
||||||
<div class="spinner-border ml-auto" id="status-spinner" role="status" aria-hidden="true"></div>
|
aria-valuemax="4">Loading ...
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-12 d-none" id="download-wrapper">
|
||||||
<div class="row">
|
<p class="text-info">Your key material is ready for download. The downloadable file contains your private
|
||||||
<div class="col-12">
|
key and your certificate encrypted with your password. You can now use the file to install your
|
||||||
<div id="result">
|
certificate in your browser or other applications.</p>
|
||||||
<button type="button" disabled id="send-button" class="btn btn-default disabled">Send signing request
|
<a href="#" class="btn btn-success" id="download-link">
|
||||||
</button>
|
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-download" fill="currentColor"
|
||||||
</div>
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
|
||||||
|
</svg>
|
||||||
|
Download</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<pre id="key"></pre>
|
<pre id="key"></pre>
|
||||||
<pre id="csr"></pre>
|
<pre id="csr"></pre>
|
||||||
<pre id="crt"></pre>
|
<pre id="crt"></pre>
|
||||||
</div>
|
</div>
|
||||||
<script src="../public/js/jquery.min.js"></script>
|
<script src="../public/js/forge.min.js"></script>
|
||||||
<script src="../public/js/forge.all.min.js"></script>
|
|
||||||
<script src="../public/js/bootstrap.bundle.min.js"></script>
|
<script src="../public/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="../public/js/i18next.min.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
async function postData(url = '', data = {}) {
|
async function postData(url = '', data = {}) {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
|
@ -92,10 +96,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
i18n.init({fallbackLng: 'en', debug: true}, (err) => {
|
|
||||||
if (err) return console.log('something went wrong loading', err);
|
|
||||||
});
|
|
||||||
|
|
||||||
const keyElement = document.getElementById('key');
|
const keyElement = document.getElementById('key');
|
||||||
document.getElementById('csr-form').onsubmit = function (event) {
|
document.getElementById('csr-form').onsubmit = function (event) {
|
||||||
const subject = event.target["nameInput"].value;
|
const subject = event.target["nameInput"].value;
|
||||||
|
@ -104,24 +104,27 @@
|
||||||
if (isNaN(keySize)) {
|
if (isNaN(keySize)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const spinner = document.getElementById('status-spinner');
|
|
||||||
const statusText = document.getElementById('status-text');
|
|
||||||
const statusBlock = document.getElementById('status-block');
|
const statusBlock = document.getElementById('status-block');
|
||||||
|
const progressBar = document.getElementById('progress-bar');
|
||||||
statusBlock.classList.remove('d-none');
|
statusBlock.classList.remove('d-none');
|
||||||
spinner.classList.remove('d-none');
|
|
||||||
|
|
||||||
|
progressBar.classList.add('progress-bar-striped', 'progress-bar-animated');
|
||||||
|
progressBar.style.width = "25%";
|
||||||
|
progressBar.setAttribute("aria-valuenow", "1");
|
||||||
const state = forge.pki.rsa.createKeyPairGenerationState(keySize, 0x10001);
|
const state = forge.pki.rsa.createKeyPairGenerationState(keySize, 0x10001);
|
||||||
statusText.innerHTML = 'started key generation';
|
progressBar.innerHTML = 'started key generation';
|
||||||
const startDate = new Date();
|
const startDate = new Date();
|
||||||
const step = function () {
|
const step = function () {
|
||||||
let duration = (new Date()).getTime() - startDate.getTime();
|
let duration = (new Date()).getTime() - startDate.getTime();
|
||||||
let seconds = Math.floor(duration / 100) / 10;
|
let seconds = Math.floor(duration / 100) / 10;
|
||||||
if (!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) {
|
if (!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) {
|
||||||
setTimeout(step, 1);
|
setTimeout(step, 1);
|
||||||
statusText.innerHTML = `key generation running for ${seconds} seconds`;
|
progressBar.innerHTML = "key generation running";
|
||||||
} else {
|
} else {
|
||||||
statusText.innerHTML = `key generated in ${seconds} seconds`
|
progressBar.classList.remove("progress-bar-animated", 'progress-bar-striped');
|
||||||
spinner.classList.add('d-none');
|
progressBar.style.width = "50%";
|
||||||
|
progressBar.setAttribute("aria-valuenow", "2");
|
||||||
|
progressBar.innerHTML = "key generated";
|
||||||
const keys = state.keys;
|
const keys = state.keys;
|
||||||
keyElement.innerHTML = forge.pki.privateKeyToPem(keys.privateKey);
|
keyElement.innerHTML = forge.pki.privateKeyToPem(keys.privateKey);
|
||||||
const csr = forge.pki.createCertificationRequest();
|
const csr = forge.pki.createCertificationRequest();
|
||||||
|
@ -138,6 +141,11 @@
|
||||||
if (verified) {
|
if (verified) {
|
||||||
let csrPem = forge.pki.certificationRequestToPem(csr);
|
let csrPem = forge.pki.certificationRequestToPem(csr);
|
||||||
document.getElementById("csr").innerHTML = csrPem;
|
document.getElementById("csr").innerHTML = csrPem;
|
||||||
|
progressBar.style.width = "75%";
|
||||||
|
progressBar.setAttribute("aria-valuenow", "3");
|
||||||
|
progressBar.classList.add('progress-bar-striped', 'progress-bar-animated');
|
||||||
|
progressBar.innerHTML = "key generated, certificate waiting";
|
||||||
|
|
||||||
const sendButton =
|
const sendButton =
|
||||||
document.getElementById("send-button");
|
document.getElementById("send-button");
|
||||||
sendButton.addEventListener("click", function () {
|
sendButton.addEventListener("click", function () {
|
||||||
|
@ -163,6 +171,34 @@
|
||||||
});
|
});
|
||||||
sendButton.removeAttribute("disabled");
|
sendButton.removeAttribute("disabled");
|
||||||
sendButton.classList.remove("disabled");
|
sendButton.classList.remove("disabled");
|
||||||
|
|
||||||
|
function handleCertificateResponse(data) {
|
||||||
|
document.getElementById("crt").innerHTML = data["certificate"];
|
||||||
|
let certificates = []
|
||||||
|
certificates.push(forge.pki.certificateFromPem(data["certificate"]));
|
||||||
|
|
||||||
|
for (let certificatePemData of data["ca_chain"]) {
|
||||||
|
certificates.push(forge.pki.certificateFromPem(certificatePemData));
|
||||||
|
}
|
||||||
|
|
||||||
|
// browsers have trouble importing anything but 3des encrypted PKCS#12
|
||||||
|
const p12asn1 = forge.pkcs12.toPkcs12Asn1(
|
||||||
|
keys.privateKey, certificates, password,
|
||||||
|
{algorithm: '3des'}
|
||||||
|
);
|
||||||
|
const p12Der = forge.asn1.toDer(p12asn1).getBytes();
|
||||||
|
const p12B64 = forge.util.encode64(p12Der);
|
||||||
|
|
||||||
|
const downloadLink = document.getElementById('download-link');
|
||||||
|
downloadLink.download = 'client_certificate.p12';
|
||||||
|
downloadLink.setAttribute('href', 'data:application/x-pkcs12;base64,' + p12B64);
|
||||||
|
|
||||||
|
document.getElementById('download-wrapper').classList.remove("d-none");
|
||||||
|
progressBar.classList.remove("progress-bar-animated", 'progress-bar-striped');
|
||||||
|
progressBar.style.width = "100%";
|
||||||
|
progressBar.innerHTML = i18n.t('keygen.generated', {seconds: seconds}) + ', ' + i18n.t('certificate.received');
|
||||||
|
progressBar.setAttribute("aria-valuenow", "4");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,214 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
|
||||||
<link rel="stylesheet" href="css/styles.min.css">
|
|
||||||
<meta name="theme-color" content="#ffffff">
|
|
||||||
|
|
||||||
<title>{{ .Title }}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<h1>{{ .Title }}</h1>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-12">
|
|
||||||
<form id="csr-form">
|
|
||||||
{{ .csrfField }}
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="nameInput">{{ .NameLabel }}</label>
|
|
||||||
<input type="text" class="form-control" id="nameInput" aria-describedby="nameHelp" required
|
|
||||||
minlength="3">
|
|
||||||
<small id="nameHelp" class="form-text text-muted">{{ .NameHelpText }}</small>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="passwordInput">{{ .PasswordLabel }}</label>
|
|
||||||
<input type="password" class="form-control" id="passwordInput" aria-describedby="nameHelp" required
|
|
||||||
minlength="8">
|
|
||||||
</div>
|
|
||||||
<fieldset class="form-group">
|
|
||||||
<legend>{{ .RSAKeySizeLegend }}</legend>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="radio" name="keySize" id="size3072" value="3072" checked>
|
|
||||||
<label class="form-check-label" for="size3072">{{ .RSA3072Label }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="radio" name="keySize" id="size2048" value="2048">
|
|
||||||
<label class="form-check-label" for="size2048">{{ .RSA2048Label }}</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input" type="radio" name="keySize" id="size4096" value="4096">
|
|
||||||
<label class="form-check-label" for="size4096">{{ .RSA4096Label }}</label>
|
|
||||||
</div>
|
|
||||||
<small id="keySizeHelp" class="form-text text-muted">{{ .RSAHelpText }}</small>
|
|
||||||
</fieldset>
|
|
||||||
<button type="submit" id="action-button" class="btn btn-primary">{{ .CSRButtonLabel }}</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row d-none" id="status-block">
|
|
||||||
<div class="col-12 py-3">
|
|
||||||
<div class="progress" style="height: 2rem">
|
|
||||||
<div id="progress-bar" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0"
|
|
||||||
aria-valuemax="4">{{ .StatusLoading }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-12 d-none" id="download-wrapper">
|
|
||||||
<p class="text-info">{{ .DownloadDescription }}</p>
|
|
||||||
<a href="#" class="btn btn-success" id="download-link">
|
|
||||||
<svg width="1em" height="1em" viewBox="0 0 16 16" class="bi bi-download" fill="currentColor"
|
|
||||||
xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path fill-rule="evenodd"
|
|
||||||
d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5z"/>
|
|
||||||
<path fill-rule="evenodd"
|
|
||||||
d="M7.646 11.854a.5.5 0 0 0 .708 0l3-3a.5.5 0 0 0-.708-.708L8.5 10.293V1.5a.5.5 0 0 0-1 0v8.793L5.354 8.146a.5.5 0 1 0-.708.708l3 3z"/>
|
|
||||||
</svg>
|
|
||||||
{{ .DownloadLabel }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre id="key" class="d-none"></pre>
|
|
||||||
<pre id="csr" class="d-none"></pre>
|
|
||||||
<pre id="crt" class="d-none"></pre>
|
|
||||||
</div>
|
|
||||||
<script src="js/jquery.min.js"></script>
|
|
||||||
<script src="js/forge.all.min.js"></script>
|
|
||||||
<script src="js/bootstrap.bundle.min.js"></script>
|
|
||||||
<script src="js/i18next.min.js"></script>
|
|
||||||
<script>
|
|
||||||
async function postData(url = '', data = {}, csrfToken) {
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: 'POST',
|
|
||||||
mode: 'cors',
|
|
||||||
cache: 'no-cache',
|
|
||||||
credentials: 'same-origin',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-CSRF-Token': csrfToken,
|
|
||||||
},
|
|
||||||
redirect: "error",
|
|
||||||
referrerPolicy: "no-referrer",
|
|
||||||
body: JSON.stringify(data),
|
|
||||||
});
|
|
||||||
return response.json()
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
|
||||||
i18n.init({fallbackLng: 'en', debug: true, useCookie: false}, (err) => {
|
|
||||||
if (err) return console.log('something went wrong loading', err);
|
|
||||||
});
|
|
||||||
|
|
||||||
const keyElement = document.getElementById('key');
|
|
||||||
document.getElementById('csr-form').onsubmit = function (event) {
|
|
||||||
const subject = event.target["nameInput"].value;
|
|
||||||
const password = event.target["passwordInput"].value;
|
|
||||||
const csrfToken = event.target["csrfToken"].value;
|
|
||||||
const keySize = parseInt(event.target["keySize"].value);
|
|
||||||
if (isNaN(keySize)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const statusBlock = document.getElementById('status-block');
|
|
||||||
const progressBar = document.getElementById('progress-bar');
|
|
||||||
statusBlock.classList.remove('d-none');
|
|
||||||
|
|
||||||
progressBar.classList.add('progress-bar-striped', 'progress-bar-animated');
|
|
||||||
progressBar.style.width = "25%";
|
|
||||||
progressBar.setAttribute("aria-valuenow", "1");
|
|
||||||
const state = forge.pki.rsa.createKeyPairGenerationState(keySize, 0x10001);
|
|
||||||
progressBar.innerHTML = i18n.t('keygen.started');
|
|
||||||
const startDate = new Date();
|
|
||||||
const step = function () {
|
|
||||||
let duration = (new Date()).getTime() - startDate.getTime();
|
|
||||||
let seconds = Math.floor(duration / 100) / 10;
|
|
||||||
if (!forge.pki.rsa.stepKeyPairGenerationState(state, 100)) {
|
|
||||||
setTimeout(step, 1);
|
|
||||||
progressBar.innerHTML = i18n.t('keygen.running', {seconds: seconds});
|
|
||||||
} else {
|
|
||||||
progressBar.classList.remove("progress-bar-animated", 'progress-bar-striped');
|
|
||||||
progressBar.style.width = "50%";
|
|
||||||
progressBar.setAttribute("aria-valuenow", "2");
|
|
||||||
progressBar.innerHTML = i18n.t('keygen.generated', {seconds: seconds});
|
|
||||||
const keys = state.keys;
|
|
||||||
keyElement.innerHTML = forge.pki.privateKeyToPem(keys.privateKey);
|
|
||||||
const csr = forge.pki.createCertificationRequest();
|
|
||||||
|
|
||||||
csr.publicKey = keys.publicKey;
|
|
||||||
csr.setSubject([{
|
|
||||||
name: 'commonName',
|
|
||||||
value: subject,
|
|
||||||
valueTagClass: forge.asn1.Type.UTF8,
|
|
||||||
}]);
|
|
||||||
csr.sign(keys.privateKey, forge.md.sha256.create());
|
|
||||||
|
|
||||||
const verified = csr.verify();
|
|
||||||
if (verified) {
|
|
||||||
let csrPem = forge.pki.certificationRequestToPem(csr);
|
|
||||||
document.getElementById("csr").innerHTML = csrPem;
|
|
||||||
progressBar.style.width = "75%";
|
|
||||||
progressBar.setAttribute("aria-valuenow", "3");
|
|
||||||
progressBar.classList.add('progress-bar-striped', 'progress-bar-animated');
|
|
||||||
progressBar.innerHTML = i18n.t('keygen.generated', {seconds: seconds}) + ', ' + i18n.t('certificate.waiting');
|
|
||||||
postData("/sign/", {"csr": csrPem, "common_name": subject}, csrfToken)
|
|
||||||
.then(data => {
|
|
||||||
const request_id = data["request_id"]
|
|
||||||
const webSocket = new WebSocket(
|
|
||||||
"wss://" + window.location.toString().substring(
|
|
||||||
"https://".length
|
|
||||||
).split("/")[0] + "/ws/")
|
|
||||||
webSocket.onopen = function () {
|
|
||||||
webSocket.send(JSON.stringify({"request_id": request_id}))
|
|
||||||
}
|
|
||||||
webSocket.onmessage = function (event) {
|
|
||||||
handleCertificateResponse(JSON.parse(event.data));
|
|
||||||
}
|
|
||||||
webSocket.onclose = function (event) {
|
|
||||||
if (event.wasClean) {
|
|
||||||
console.debug("websocket closed cleanly");
|
|
||||||
} else {
|
|
||||||
console.error("websocket connection died");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
webSocket.onerror = function (error) {
|
|
||||||
console.error(error.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function handleCertificateResponse(data) {
|
|
||||||
document.getElementById("crt").innerHTML = data["certificate"];
|
|
||||||
let certificates = []
|
|
||||||
certificates.push(forge.pki.certificateFromPem(data["certificate"]));
|
|
||||||
|
|
||||||
for (let certificatePemData of data["ca_chain"]) {
|
|
||||||
certificates.push(forge.pki.certificateFromPem(certificatePemData));
|
|
||||||
}
|
|
||||||
|
|
||||||
// browsers have trouble importing anything but 3des encrypted PKCS#12
|
|
||||||
const p12asn1 = forge.pkcs12.toPkcs12Asn1(
|
|
||||||
keys.privateKey, certificates, password,
|
|
||||||
{algorithm: '3des'}
|
|
||||||
);
|
|
||||||
const p12Der = forge.asn1.toDer(p12asn1).getBytes();
|
|
||||||
const p12B64 = forge.util.encode64(p12Der);
|
|
||||||
|
|
||||||
const downloadLink = document.getElementById('download-link');
|
|
||||||
downloadLink.download = 'client_certificate.p12';
|
|
||||||
downloadLink.setAttribute('href', 'data:application/x-pkcs12;base64,' + p12B64);
|
|
||||||
|
|
||||||
document.getElementById('download-wrapper').classList.remove("d-none");
|
|
||||||
progressBar.classList.remove("progress-bar-animated", 'progress-bar-striped');
|
|
||||||
progressBar.style.width = "100%";
|
|
||||||
progressBar.innerHTML = i18n.t('keygen.generated', {seconds: seconds}) + ', ' + i18n.t('certificate.received');
|
|
||||||
progressBar.setAttribute("aria-valuenow", "4");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setTimeout(step);
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Loading…
Reference in a new issue