Add ability to autogen self-signed x509 certs for use with Grumble.

This commit is contained in:
Mikkel Krautz 2011-04-28 20:27:38 +02:00
parent f36ae37afd
commit 1cc9745727
4 changed files with 105 additions and 3 deletions

View file

@ -38,7 +38,8 @@ GOFILES = \
group.go \ group.go \
user.go \ user.go \
murmurdb.go \ murmurdb.go \
freeze.go freeze.go \
gencert.go
.PHONY: grumble .PHONY: grumble
grumble: pkg grumble: pkg

79
gencert.go Normal file
View file

@ -0,0 +1,79 @@
// Copyright (c) 2011 The Grumble Authors
// The use of this source code is goverened by a BSD-style
// license that can be found in the LICENSE-file.
package main
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"log"
"os"
"path/filepath"
"time"
)
// Generate a 2048-bit RSA keypair and a Grumble auto-generated X509
// certificate. Output PEM-encoded DER representations of the resulting
// certificate and private key to certpath and keypath.
func GenerateSelfSignedCert(certpath, keypath string) (err os.Error) {
now := time.Seconds()
tmpl := &x509.Certificate{
SerialNumber: []byte{0},
Subject: x509.Name{
CommonName: "Grumble Autogenerated Certificate",
},
NotBefore: time.SecondsToUTC(now - 300),
NotAfter: time.SecondsToUTC(now + 60*60*24*365), // valid for 1 year.
SubjectKeyId: []byte{1, 2, 3, 4},
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
}
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return err
}
certbuf, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &priv.PublicKey, priv)
if err != nil {
log.Printf("Error: %v", err)
return err
}
certblk := pem.Block{
Type: "CERTIFICATE",
Bytes: certbuf,
}
keybuf := x509.MarshalPKCS1PrivateKey(priv)
keyblk := pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: keybuf,
}
certfn := filepath.Join(*datadir, "cert")
file, err := os.OpenFile(certfn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0700)
if err != nil {
return err
}
defer file.Close()
err = pem.Encode(file, &certblk)
if err != nil {
return err
}
keyfn := filepath.Join(*datadir, "key")
file, err = os.OpenFile(keyfn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0700)
if err != nil {
return err
}
defer file.Close()
err = pem.Encode(file, &keyblk)
if err != nil {
return err
}
return nil
}

View file

@ -24,6 +24,7 @@ var datadir *string = flag.String("datadir", "", "Directory to use for server st
var blobdir *string = flag.String("blobdir", "", "Directory to use for blob storage") var blobdir *string = flag.String("blobdir", "", "Directory to use for blob storage")
var sqlitedb *string = flag.String("murmurdb", "", "Path to murmur.sqlite to import server structure from") var sqlitedb *string = flag.String("murmurdb", "", "Path to murmur.sqlite to import server structure from")
var cleanup *bool = flag.Bool("clean", false, "Clean up existing data dir content before importing Murmur data") var cleanup *bool = flag.Bool("clean", false, "Clean up existing data dir content before importing Murmur data")
var gencert *bool = flag.Bool("gencert", false, "Generate a self-signed certificate for use with Grumble")
var globalBlobstore *blobstore.BlobStore var globalBlobstore *blobstore.BlobStore
@ -94,6 +95,26 @@ func main() {
log.Fatalf("Unable to initialize blobstore: %v", err.String()) log.Fatalf("Unable to initialize blobstore: %v", err.String())
} }
// Generate a cert?
if *gencert {
certfn := filepath.Join(*datadir, "cert")
keyfn := filepath.Join(*datadir, "key")
log.Printf("Generating 2048-bit RSA keypair for self-signed certificate...")
err := GenerateSelfSignedCert(certfn, keyfn)
if err != nil {
log.Printf("Error: %v", err)
return
}
log.Printf("Certificate output to %v", certfn)
log.Printf("Private key output to %v", keyfn)
log.Printf("Done generating certificate and private key.")
log.Printf("Please restart Grumble to make use of the generated certificate and private key.")
return
}
// Should we import data from a Murmur SQLite file? // Should we import data from a Murmur SQLite file?
if len(*sqlitedb) > 0 { if len(*sqlitedb) > 0 {
f, err := os.Open(*datadir) f, err := os.Open(*datadir)

View file

@ -9,13 +9,14 @@ import (
"encoding/pem" "encoding/pem"
"crypto/x509" "crypto/x509"
"io/ioutil" "io/ioutil"
"path/filepath"
) )
func NewTLSListener(port int) (rl *tls.Listener) { func NewTLSListener(port int) (rl *tls.Listener) {
rl = nil rl = nil
// Load the certificate // Load the certificate
pemBytes, err := ioutil.ReadFile("grumble.crt") pemBytes, err := ioutil.ReadFile(filepath.Join(*datadir, "cert"))
if err != nil { if err != nil {
log.Printf("Failed to read server.crt: %s", err) log.Printf("Failed to read server.crt: %s", err)
return return
@ -29,7 +30,7 @@ func NewTLSListener(port int) (rl *tls.Listener) {
} }
// Load the private key // Load the private key
keyBytes, err := ioutil.ReadFile("grumble.key") keyBytes, err := ioutil.ReadFile(filepath.Join(*datadir, "key"))
if err != nil { if err != nil {
log.Printf("Failed to read server.key.insecure: %s", err) log.Printf("Failed to read server.key.insecure: %s", err)
return return