Browse Source

Cleaned up implementation of certificates handler and added bunch of config files options.

pull/28/head
Simon Eisenmann 11 years ago
parent
commit
12c04a9198
  1. 9
      server.conf.in
  2. 30
      src/app/spreed-speakfreely-server/main.go
  3. 90
      src/app/spreed-speakfreely-server/users.go

9
server.conf.in

@ -130,10 +130,12 @@ enabled = false @@ -130,10 +130,12 @@ enabled = false
; set then the server will act as a CA and sign incoming user registrations and
; return certificates to users as registration.
;certificate_certificate = usersca.crt
; The HTTP header name where to find if the TLS lient authentication was
; The HTTP header name where to find if the TLS client authentication was
; successfull. The value of this header is matched to
; certificate_verifiedHeaderValue and only if there is a match, the proxy
; handled TLS client authentication is accepted as success.
; handled TLS client authentication is accepted as success. Make sure to secure
; these headers with your front end proxy (always set them). Do not use these
; settings when not using a front end proxy.
;certificate_verifiedHeader = x-verified
;certificate_verifiedHeaderValue = SUCCESS
; The HTTP header name where to find the userid extracted by a proxy after
@ -145,6 +147,9 @@ enabled = false @@ -145,6 +147,9 @@ enabled = false
; certificate_useridHeader value and the front end TLS proxy does inject the
; userid into that header.
;certificate_certificateHeader = x-certificate
; The valid duration of generated certificates created in certificate mode when
; allowRegistration is enabled.
;certificate_validForDays = 365
; If enabled the server can create new userids. Set allowRegistration to true to
; enable userid creation/registration. Users are created according the settings
; of the currently configured mode (see above).

30
src/app/spreed-speakfreely-server/main.go

@ -24,8 +24,6 @@ package main @@ -24,8 +24,6 @@ package main
import (
"app/spreed-speakfreely-server/sleepy"
"bytes"
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"github.com/gorilla/mux"
@ -358,6 +356,12 @@ func runner(runtime phoenix.Runtime) error { @@ -358,6 +356,12 @@ func runner(runtime phoenix.Runtime) error {
// Create router.
router := mux.NewRouter()
r := router.PathPrefix(basePath).Subrouter().StrictSlash(true)
// Prepare listeners.
runtime.DefaultHTTPHandler(r)
runtime.DefaultHTTPSHandler(r)
// Add handlers.
r.HandleFunc("/", httputils.MakeGzipHandler(mainHandler))
r.Handle("/static/img/buddy/{flags}/{imageid}/{idx:.*}", http.StripPrefix(basePath, makeImageHandler(hub, time.Duration(24)*time.Hour)))
r.Handle("/static/{path:.*}", http.StripPrefix(basePath, httputils.FileStaticServer(http.Dir(rootFolder))))
@ -393,28 +397,6 @@ func runner(runtime phoenix.Runtime) error { @@ -393,28 +397,6 @@ func runner(runtime phoenix.Runtime) error {
}
}
runtime.DefaultHTTPHandler(r)
runtime.DefaultHTTPSHandler(r)
if tlsConfig, err := runtime.TLSConfig(); err == nil {
tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven
// Create cert pool.
pool := x509.NewCertPool()
if certificateFn, err := runtime.GetString("users", "certificate_certificate"); err == nil {
if certificate, err := loadX509Certificate(certificateFn); err == nil {
for _, derCert := range certificate.Certificate {
cert, err := x509.ParseCertificate(derCert)
if err != nil {
continue
}
pool.AddCert(cert)
}
}
log.Printf("Initialized TLS auth pool with %d certtificates.", len(pool.Subjects()))
}
tlsConfig.ClientCAs = pool
}
return runtime.Start()
}

90
src/app/spreed-speakfreely-server/users.go

@ -26,6 +26,7 @@ import ( @@ -26,6 +26,7 @@ import (
"crypto/hmac"
"crypto/rand"
"crypto/sha256"
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/base64"
@ -253,17 +254,41 @@ type Users struct { @@ -253,17 +254,41 @@ type Users struct {
func NewUsers(hub *Hub, realm string, runtime phoenix.Runtime) *Users {
var users = &Users{
hub: hub,
realm: realm,
}
var handler UsersHandler
var err error
// Create handler based on mode.
mode, _ := runtime.GetString("users", "mode")
if handler, err = users.createHandler(mode, runtime); err == nil {
users.handler = handler
// Register handler Get at the hub.
users.hub.useridRetriever = func(request *http.Request) (userid string, err error) {
userid, err = handler.Get(request)
if userid != "" {
log.Printf("Users handler get success: %s\n", userid)
}
return
}
log.Printf("Enabled users handler '%s'\n", mode)
}
return users
}
func (users *Users) createHandler(mode string, runtime phoenix.Runtime) (handler UsersHandler, err error) {
switch mode {
case "sharedsecret":
secret, _ := runtime.GetString("users", "sharedsecret_secret")
if secret != "" {
handler = &UsersSharedsecretHandler{secret: []byte(secret)}
} else {
log.Println("Cannot enable sharedsecret users handler: No secret.")
err = errors.New("Cannot enable sharedsecret users handler: No secret.")
}
case "httpheader":
headerName, _ := runtime.GetString("users", "httpheader_header")
@ -272,57 +297,58 @@ func NewUsers(hub *Hub, realm string, runtime phoenix.Runtime) *Users { @@ -272,57 +297,58 @@ func NewUsers(hub *Hub, realm string, runtime phoenix.Runtime) *Users {
}
handler = &UsersHTTPHeaderHandler{headerName: headerName}
case "certificate":
var err2 error
uh := &UsersCertificateHandler{}
// TODO(longsleep): Add validFor to configuration.
uh.validFor = 24 * time.Hour * 365
validForDays, _ := runtime.GetInt("users", "certificate_validForDays")
if validForDays == 0 {
validForDays = 365
}
uh.validFor = time.Duration(validForDays) * 24 * time.Hour
keyFn, _ := runtime.GetString("users", "certificate_key")
certificateFn, _ := runtime.GetString("users", "certificate_certificate")
if keyFn != "" && certificateFn != "" {
if uh.privateKey, err = loadX509PrivateKey(keyFn); err == nil {
// Load private key from file and use it for signing,
if uh.privateKey, err2 = loadX509PrivateKey(keyFn); err2 == nil {
log.Printf("Users certificate private key loaded from %s\n", keyFn)
} else {
log.Printf("Failed to load certificat private key: %s\n", err)
log.Printf("Failed to load certificat private key: %s\n", err2)
}
}
if certificateFn != "" {
// Load Certificate from file.
if certificate, err := loadX509Certificate(certificateFn); err == nil {
// Parse first certificate in file.
if certificates, err := x509.ParseCertificates(certificate.Certificate[0]); err == nil {
// Use first parsed certificate as CA.
uh.certificate = certificates[0]
log.Printf("Users certificate loaded from %s\n", certificateFn)
handler = uh
} else {
log.Printf("Failed to parse users certificate: %s\n", err)
// Get TLS config if the server has one.
if tlsConfig, err2 := runtime.TLSConfig(); err2 == nil {
// Enable TLS client certificate authentication.
tlsConfig.ClientAuth = tls.VerifyClientCertIfGiven
// Create cert pool.
pool := x509.NewCertPool()
// Add CA certificate to pool for TLS client authentication.
for _, derCert := range certificate.Certificate {
cert, err2 := x509.ParseCertificate(derCert)
if err2 != nil {
continue
}
pool.AddCert(cert)
}
// Add pool to config.
tlsConfig.ClientCAs = pool
log.Printf("Initialized TLS auth pool with %d certificates.", len(pool.Subjects()))
}
}
} else {
log.Printf("Failed to load users certificate: %s\n", err)
}
} else {
log.Println("Cannot enable certificate users handler: No certificate.")
err = errors.New("Cannot enable certificate users handler: No certificate.")
}
default:
mode = ""
}
if handler != nil {
// Register handler Get at the hub.
hub.useridRetriever = func(request *http.Request) (userid string, err error) {
userid, err = handler.Get(request)
if userid != "" {
log.Printf("Users handler get success: %s\n", userid)
}
return
}
log.Printf("Enabled users handler '%s'\n", mode)
}
return &Users{
hub: hub,
realm: realm,
handler: handler,
}
return
}

Loading…
Cancel
Save