ovpn-certman/handlers/cert.go
2018-01-29 09:18:19 +01:00

151 lines
3.7 KiB
Go

package handlers
import (
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"log"
"math/big"
"net/http"
"time"
"git.klink.asia/paul/certman/models"
"git.klink.asia/paul/certman/services"
"git.klink.asia/paul/certman/views"
)
func ListCertHandler(w http.ResponseWriter, req *http.Request) {
v := views.New(req)
v.Render(w, "cert_list")
}
func CreateCertHandler(w http.ResponseWriter, req *http.Request) {
email := services.SessionStore.GetUserEmail(req)
certname := req.FormValue("certname")
user := models.User{}
err := services.Database.Where(&models.User{Email: email}).Find(&user).Error
if err != nil {
fmt.Printf("Could not fetch user for mail %s\n", email)
}
// Load CA master certificate
caCert, caKey, err := loadX509KeyPair("ca.crt", "ca.key")
if err != nil {
log.Fatalf("error loading ca keyfiles: %s", err)
panic(err.Error())
}
// Generate Keypair
key, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
log.Fatalf("Could not generate keypair: %s", err)
}
// Generate Certificate
derBytes, err := CreateCertificate(key, caCert, caKey)
// Initialize new client config
client := models.Client{
Name: certname,
PrivateKey: x509.MarshalPKCS1PrivateKey(key),
Cert: derBytes,
UserID: user.ID,
}
// Insert client into database
if err := services.Database.Create(&client).Error; err != nil {
panic(err.Error())
}
services.SessionStore.Flash(w, req,
services.Flash{
Type: "success",
Message: "The certificate was created successfully.",
},
)
http.Redirect(w, req, "/certs", http.StatusFound)
}
func DownloadCertHandler(w http.ResponseWriter, req *http.Request) {
//v := views.New(req)
//
//derBytes, err := CreateCertificate(key, caCert, caKey)
//pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
//
//pkBytes := x509.MarshalPKCS1PrivateKey(key)
//pem.Encode(w, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: pkBytes})
return
}
func loadX509KeyPair(certFile, keyFile string) (*x509.Certificate, *rsa.PrivateKey, error) {
cf, err := ioutil.ReadFile(certFile)
if err != nil {
return nil, nil, err
}
kf, err := ioutil.ReadFile(keyFile)
if err != nil {
return nil, nil, err
}
cpb, cr := pem.Decode(cf)
fmt.Println(string(cr))
kpb, kr := pem.Decode(kf)
fmt.Println(string(kr))
crt, err := x509.ParseCertificate(cpb.Bytes)
if err != nil {
return nil, nil, err
}
key, err := x509.ParsePKCS1PrivateKey(kpb.Bytes)
if err != nil {
return nil, nil, err
}
return crt, key, nil
}
// CreateCertificate creates a CA-signed certificate
func CreateCertificate(key interface{}, caCert *x509.Certificate, caKey interface{}) ([]byte, error) {
subj := caCert.Subject
// .. except for the common name
subj.CommonName = "clientName"
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
log.Fatalf("Obscure error in cert serial number generation: %s", err)
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: subj,
NotBefore: time.Now(),
NotAfter: time.Now().Add(24 * time.Hour * 356 * 5),
SignatureAlgorithm: x509.SHA256WithRSA,
//KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageDataEncipherment,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
BasicConstraintsValid: true,
}
return x509.CreateCertificate(rand.Reader, &template, caCert, publicKey(key), caKey)
}
func publicKey(priv interface{}) interface{} {
switch k := priv.(type) {
case *rsa.PrivateKey:
return &k.PublicKey
case *ecdsa.PrivateKey:
return &k.PublicKey
default:
return nil
}
}