@ -2,19 +2,22 @@ package main
import (
import (
"bytes"
"bytes"
"crypto/rand"
"crypto/tls"
"crypto/tls"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"html/template"
"html/template"
"io/ioutil"
"io/ioutil"
"log"
"net/http"
"net/http"
"os"
"os/exec"
"os/exec"
"strings"
"strings"
"time"
"time"
"github.com/BurntSushi/toml"
"github.com/BurntSushi/toml"
"github.com/gorilla/csrf"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/nicksnyder/go-i18n/v2/i18n"
log "github.com/sirupsen/logrus"
"golang.org/x/text/language"
"golang.org/x/text/language"
)
)
@ -32,13 +35,28 @@ type responseData struct {
func ( h * signCertificate ) sign ( csrPem string , commonName string ) ( certPem string , err error ) {
func ( h * signCertificate ) sign ( csrPem string , commonName string ) ( certPem string , err error ) {
log . Printf ( "received CSR for %s:\n\n%s" , commonName , csrPem )
log . Printf ( "received CSR for %s:\n\n%s" , commonName , csrPem )
subjectDN := fmt . Sprintf ( "/CN=%s" , commonName )
subjectDN := fmt . Sprintf ( "/CN=%s" , commonName )
err = ioutil . WriteFile ( "in.pem" , [ ] byte ( csrPem ) , 0644 )
var csrFile * os . File
if err != nil {
if csrFile , err = ioutil . TempFile ( "" , "*.csr.pem" ) ; err != nil {
log . Print ( err )
log . Errorf ( "could not open temporary file: %s" , err )
return
}
if _ , err = csrFile . Write ( [ ] byte ( csrPem ) ) ; err != nil {
log . Errorf ( "could not write CSR to file: %s" , err )
return
return
}
}
if err = csrFile . Close ( ) ; err != nil {
log . Errorf ( "could not close CSR file: %s" , err )
return
}
defer func ( file * os . File ) {
err = os . Remove ( file . Name ( ) )
if err != nil {
log . Errorf ( "could not remove temporary file: %s" , err )
}
} ( csrFile )
opensslCommand := exec . Command (
opensslCommand := exec . Command (
"openssl" , "ca" , "-config" , "ca.cnf" , "-days" , "365" ,
"openssl" , "ca" , "-config" , "ca.cnf" ,
"-policy" , "policy_match" , "-extensions" , "client_ext" ,
"-policy" , "policy_match" , "-extensions" , "client_ext" ,
"-batch" , "-subj" , subjectDN , "-utf8" , "-rand_serial" , "-in" , "in.pem" )
"-batch" , "-subj" , subjectDN , "-utf8" , "-rand_serial" , "-in" , "in.pem" )
var out , cmdErr bytes . Buffer
var out , cmdErr bytes . Buffer
@ -159,6 +177,7 @@ func (i *indexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
"CSRButtonLabel" : csrButtonLabel ,
"CSRButtonLabel" : csrButtonLabel ,
"StatusLoading" : statusLoading ,
"StatusLoading" : statusLoading ,
"SendCSRButtonLabel" : sendCSRButtonLabel ,
"SendCSRButtonLabel" : sendCSRButtonLabel ,
csrf . TemplateTag : csrf . TemplateField ( r ) ,
} )
} )
if err != nil {
if err != nil {
log . Panic ( err )
log . Panic ( err )
@ -207,6 +226,18 @@ func (j *jsLocalesHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
}
}
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 main ( ) {
func main ( ) {
tlsConfig := & tls . Config {
tlsConfig := & tls . Config {
CipherSuites : [ ] uint16 {
CipherSuites : [ ] uint16 {
@ -227,6 +258,7 @@ func main() {
}
}
mux := http . NewServeMux ( )
mux := http . NewServeMux ( )
csrfKey := generateRandomBytes ( 32 )
mux . Handle ( "/sign/" , & signCertificate { } )
mux . Handle ( "/sign/" , & signCertificate { } )
mux . Handle ( "/" , & indexHandler { Bundle : bundle } )
mux . Handle ( "/" , & indexHandler { Bundle : bundle } )
fileServer := http . FileServer ( http . Dir ( "./public" ) )
fileServer := http . FileServer ( http . Dir ( "./public" ) )
@ -235,7 +267,7 @@ func main() {
mux . Handle ( "/locales/" , & jsLocalesHandler { Bundle : bundle } )
mux . Handle ( "/locales/" , & jsLocalesHandler { Bundle : bundle } )
server := http . Server {
server := http . Server {
Addr : ":8000" ,
Addr : ":8000" ,
Handler : mux,
Handler : csrf. Protect ( csrfKey , csrf . FieldName ( "csrfToken" ) , csrf . RequestHeader ( "X-CSRF-Token" ) ) ( mux) ,
TLSConfig : tlsConfig ,
TLSConfig : tlsConfig ,
ReadTimeout : 20 * time . Second ,
ReadTimeout : 20 * time . Second ,
ReadHeaderTimeout : 5 * time . Second ,
ReadHeaderTimeout : 5 * time . Second ,