summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorkali kaneko (leap communications) <kali@leap.se>2020-01-24 21:19:19 -0600
committerkali kaneko (leap communications) <kali@leap.se>2020-01-24 21:20:50 -0600
commitd437b73a8c2dda9884c92d2be44727e66c2289e2 (patch)
treeb9936d4e12a14b76d88ba1464a765e5b05ca6159 /pkg
parent12f0aca04bb613cae64d3c438042b85474abb411 (diff)
refactor into cmd/pkg
Diffstat (limited to 'pkg')
-rw-r--r--pkg/auth/middleware.go12
-rw-r--r--pkg/config/main.go97
-rw-r--r--pkg/web/certs.go84
-rw-r--r--pkg/web/handlers.go19
4 files changed, 212 insertions, 0 deletions
diff --git a/pkg/auth/middleware.go b/pkg/auth/middleware.go
new file mode 100644
index 0000000..a3a955c
--- /dev/null
+++ b/pkg/auth/middleware.go
@@ -0,0 +1,12 @@
+package auth
+
+import ()
+
+import (
+ "github.com/auth0/go-jwt-middleware"
+ jwt "github.com/dgrijalva/jwt-go"
+)
+
+func getProtectedHandler() {
+ jwtMiddleware.Handler(CertHandler)
+}
diff --git a/pkg/config/main.go b/pkg/config/main.go
new file mode 100644
index 0000000..142738d
--- /dev/null
+++ b/pkg/config/main.go
@@ -0,0 +1,97 @@
+package config
+
+import (
+ "flag"
+ "log"
+ "os"
+ "reflect"
+)
+
+const DefaultAuthenticationModule = "anonymous"
+
+type Opts struct {
+ Notls bool
+ CaCrt string
+ CaKey string
+ TlsCrt string
+ TlsKey string
+ Port string
+ Auth string
+}
+
+func (o *Opts) fallbackToEnv(field string, envVar string, defaultVal string) {
+ r := reflect.ValueOf(o)
+ f := reflect.Indirect(r).FieldByName(field)
+
+ if f.String() == "" {
+ val, exists := os.LookupEnv(envVar)
+ if exists && val != "" {
+ f.SetString(val)
+ } else {
+ f.SetString(defaultVal)
+ }
+ }
+}
+
+func doCaFilesSanityCheck(caCrt string, caKey string) {
+ if _, err := os.Stat(caCrt); os.IsNotExist(err) {
+ log.Fatal("cannot find caCrt file")
+ }
+ if _, err := os.Stat(caKey); os.IsNotExist(err) {
+ log.Fatal("cannot find caKey file")
+ }
+}
+
+func doTlsFilesSanityCheck(tlsCrt string, tlsKey string) {
+ if _, err := os.Stat(tlsCrt); os.IsNotExist(err) {
+ log.Fatal("cannot find tlsCrt file")
+ }
+ if _, err := os.Stat(tlsKey); os.IsNotExist(err) {
+ log.Fatal("cannot find tlsKey file")
+ }
+}
+
+func InitializeFlags(opts *Opts) {
+ flag.BoolVar(&opts.Notls, "notls", false, "disable TLS on the service")
+ flag.StringVar(&opts.CaCrt, "caCrt", "", "path to the CA public key")
+ flag.StringVar(&opts.CaKey, "caKey", "", "path to the CA private key")
+ flag.StringVar(&opts.TlsCrt, "tls_crt", "", "path to the cert file for TLS")
+ flag.StringVar(&opts.TlsKey, "tls_key", "", "path to the key file for TLS")
+ flag.StringVar(&opts.Port, "port", "", "port where the server will listen (default: 8000)")
+ flag.StringVar(&opts.Auth, "auth", "", "authentication module (anonymous, sip)")
+ flag.Parse()
+
+ opts.fallbackToEnv("CaCrt", "VPNWEB_CACRT", "")
+ opts.fallbackToEnv("CaKey", "VPNWEB_CAKEY", "")
+ opts.fallbackToEnv("TlsCrt", "VPNWEB_TLSCRT", "")
+ opts.fallbackToEnv("TlsKey", "VPNWEB_TLSKEY", "")
+ opts.fallbackToEnv("Port", "VPNWEB_PORT", "8000")
+ opts.fallbackToEnv("Auth", "VPNWEB_AUTH", DefaultAuthenticationModule)
+}
+
+func CheckConfigurationOptions(opts *Opts) {
+ if opts.CaCrt == "" {
+ log.Fatal("missing caCrt parameter")
+ }
+ if opts.CaKey == "" {
+ log.Fatal("missing caKey parameter")
+ }
+
+ if opts.Notls == false {
+ if opts.TlsCrt == "" {
+ log.Fatal("missing tls_crt parameter. maybe use -notls?")
+ }
+ if opts.TlsKey == "" {
+ log.Fatal("missing tls_key parameter. maybe use -notls?")
+ }
+ }
+
+ doCaFilesSanityCheck(opts.CaCrt, opts.CaKey)
+ if opts.Notls == false {
+ doTlsFilesSanityCheck(opts.TlsCrt, opts.TlsKey)
+ }
+
+ log.Println("Authentication module:", opts.Auth)
+
+ // TODO -- check authentication module is valud, bail out otherwise
+}
diff --git a/pkg/web/certs.go b/pkg/web/certs.go
new file mode 100644
index 0000000..8c5d423
--- /dev/null
+++ b/pkg/web/certs.go
@@ -0,0 +1,84 @@
+package web
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/tls"
+ "crypto/x509"
+ "crypto/x509/pkix"
+ "encoding/pem"
+ "io"
+ "math/big"
+ mrand "math/rand"
+ "time"
+)
+
+const keySize = 2048
+const expiryDays = 28
+const certPrefix = "UNLIMITED"
+
+var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz")
+
+func randStringRunes(n int) string {
+ b := make([]rune, n)
+ for i := range b {
+ b[i] = letterRunes[mrand.Intn(len(letterRunes))]
+ }
+ return string(b)
+}
+
+type caInfo struct {
+ cacrt, cakey string
+}
+
+func NewCaInfo(cacrt string, cakey string) caInfo {
+ return caInfo{cacrt, cakey}
+}
+
+// CertWriter main handler
+
+func (ci *caInfo) CertWriter(out io.Writer) {
+ catls, err := tls.LoadX509KeyPair(ci.cacrt, ci.cakey)
+
+ if err != nil {
+ panic(err)
+ }
+ ca, err := x509.ParseCertificate(catls.Certificate[0])
+ if err != nil {
+ panic(err)
+ }
+ serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+ serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+
+ subjectKeyID := make([]byte, 20)
+ rand.Read(subjectKeyID)
+
+ _ = randStringRunes(25)
+ // Prepare certificate
+ cert := &x509.Certificate{
+ SerialNumber: serialNumber,
+
+ Subject: pkix.Name{
+ //CommonName: certPrefix + randStringRunes(25),
+ CommonName: certPrefix,
+ },
+ NotBefore: time.Now().AddDate(0, 0, -7),
+ NotAfter: time.Now().AddDate(0, 0, expiryDays),
+
+ SubjectKeyId: subjectKeyID,
+
+ ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
+ KeyUsage: x509.KeyUsageDigitalSignature,
+ }
+ priv, _ := rsa.GenerateKey(rand.Reader, keySize)
+ pub := &priv.PublicKey
+
+ // Sign the certificate
+ certB, err := x509.CreateCertificate(rand.Reader, cert, ca, pub, catls.PrivateKey)
+
+ // Write the private Key
+ pem.Encode(out, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
+
+ // Write the public key
+ pem.Encode(out, &pem.Block{Type: "CERTIFICATE", Bytes: certB})
+}
diff --git a/pkg/web/handlers.go b/pkg/web/handlers.go
new file mode 100644
index 0000000..c4f2e9a
--- /dev/null
+++ b/pkg/web/handlers.go
@@ -0,0 +1,19 @@
+package web
+
+import (
+ "net/http"
+)
+
+type CertHandler struct {
+ Cainfo caInfo
+}
+
+func (ch *CertHandler) CertResponder(w http.ResponseWriter, r *http.Request) {
+ ch.Cainfo.CertWriter(w)
+}
+
+func HttpFileHandler(route string, path string) {
+ http.HandleFunc(route, func(w http.ResponseWriter, r *http.Request) {
+ http.ServeFile(w, r, path)
+ })
+}