From d172058d5dca72498cc83960374594154ae399d9 Mon Sep 17 00:00:00 2001 From: John Graham-Cumming Date: Tue, 19 Nov 2013 04:11:38 -0800 Subject: [PATCH] Clean up comments and run 'go gmt' across code --- .gitignore | 4 + src/redoctober/core/core.go | 82 +++++++++--------- src/redoctober/core/core_test.go | 15 ++-- src/redoctober/cryptor/cryptor.go | 40 ++++----- src/redoctober/keycache/keycache.go | 18 ++-- src/redoctober/keycache/keycache_test.go | 19 +++-- src/redoctober/padding/padding.go | 11 +-- src/redoctober/passvault/passvault.go | 71 ++++++++-------- src/redoctober/passvault/passvault_test.go | 19 +++-- src/redoctober/redoctober.go | 97 +++++++++++----------- 10 files changed, 199 insertions(+), 177 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8abc69b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +bin/ +pkg/ +src/code.google.com/ +*~ diff --git a/src/redoctober/core/core.go b/src/redoctober/core/core.go index 4c05d8d..0d6a7c6 100644 --- a/src/redoctober/core/core.go +++ b/src/redoctober/core/core.go @@ -1,58 +1,59 @@ -// Pacakge core handles the main operations of the Red October server. +// Package core handles the main operations of the Red October server. +// +// Copyright (c) 2013 CloudFlare, Inc. + package core import ( - "log" - "errors" "encoding/json" - "redoctober/passvault" + "errors" + "log" "redoctober/cryptor" "redoctober/keycache" + "redoctober/passvault" ) +type credential struct { + Name string + Password string +} + // format of incoming sign-in request type create struct { - Name string - Password string + credential } type summary struct { - Name string - Password string + credential } type delegate struct { - Name string - Password string - Uses int - Time string + credential + Uses int + Time string } type password struct { - Name string - Password string + credential NewPassword string } type encrypt struct { - Name string - Password string - Minimum int - Owners []string - Data []byte + credential + Minimum int + Owners []string + Data []byte } type decrypt struct { - Name string - Password string - Data []byte + credential + Data []byte } type modify struct { - Name string - Password string + credential ToModify string - Command string + Command string } // response JSON format @@ -61,39 +62,39 @@ type status struct { } type responseData struct { - Status string + Status string Response []byte } type summaryData struct { Status string - Live map[string]keycache.ActiveUser - All map[string]passvault.Summary + Live map[string]keycache.ActiveUser + All map[string]passvault.Summary } func errToJson(err error) (ret []byte) { if err == nil { - ret, _ = json.Marshal(status{Status:"ok"}) + ret, _ = json.Marshal(status{Status: "ok"}) } else { - ret, _ = json.Marshal(status{Status:err.Error()}) + ret, _ = json.Marshal(status{Status: err.Error()}) } return } func summaryToJson(err error) (ret []byte) { if err == nil { - ret, _ = json.Marshal(summaryData{Status:"ok", Live:keycache.GetSummary(), All:passvault.GetSummary()}) + ret, _ = json.Marshal(summaryData{Status: "ok", Live: keycache.GetSummary(), All: passvault.GetSummary()}) } else { - ret, _ = json.Marshal(status{Status:err.Error()}) + ret, _ = json.Marshal(status{Status: err.Error()}) } return } func responseToJson(resp []byte, err error) (ret []byte) { if err == nil { - ret, _ = json.Marshal(responseData{Status:"ok", Response:resp}) + ret, _ = json.Marshal(responseData{Status: "ok", Response: resp}) } else { - ret, _ = json.Marshal(status{Status:err.Error()}) + ret, _ = json.Marshal(status{Status: err.Error()}) } return } @@ -299,19 +300,22 @@ func Modify(jsonIn []byte) []byte { return errToJson(errors.New("Cannot modify own record")) } switch s.Command { - case "delete": { + case "delete": + { err = passvault.DeleteRecord(s.ToModify) } - case "revoke": { + case "revoke": + { err = passvault.RevokeRecord(s.ToModify) } - case "admin": { + case "admin": + { err = passvault.MakeAdmin(s.ToModify) } - default: { + default: + { return errToJson(errors.New("Unknown command")) } } return errToJson(err) } - diff --git a/src/redoctober/core/core_test.go b/src/redoctober/core/core_test.go index aa251d1..cfb2221 100644 --- a/src/redoctober/core/core_test.go +++ b/src/redoctober/core/core_test.go @@ -1,16 +1,19 @@ +// core_test.go: tests for core.go +// +// Copyright (c) 2013 CloudFlare, Inc. package core import ( - "os" "encoding/json" - "redoctober/passvault" + "os" "redoctober/keycache" + "redoctober/passvault" "redoctober/testing" ) func TestCreate(t *testing.T) { createJson := []byte("{\"Name\":\"Alice\",\"Password\":\"Hello\"}") - + os.Remove("/tmp/db1.json") Init("/tmp/db1.json") @@ -138,7 +141,7 @@ func TestSummary(t *testing.T) { t.Fatalf("Error in summary of account, record missing ") } - // + // keycache.FlushCache() os.Remove("/tmp/db1.json") @@ -310,9 +313,8 @@ func TestEncryptDecrypt(t *testing.T) { t.Fatalf("Error in encrypt, ", s.Status) } - // decrypt file - decryptJson, err := json.Marshal(decrypt{Name:"Alice", Password:"Hello", In:s.Response}) + decryptJson, err := json.Marshal(decrypt{Name: "Alice", Password: "Hello", In: s.Response}) if err != nil { t.Fatalf("Error in marshalling decryption,", err) } @@ -527,4 +529,3 @@ func TestModify(t *testing.T) { os.Remove("/tmp/db1.json") } - diff --git a/src/redoctober/cryptor/cryptor.go b/src/redoctober/cryptor/cryptor.go index 342fc48..1d914fe 100644 --- a/src/redoctober/cryptor/cryptor.go +++ b/src/redoctober/cryptor/cryptor.go @@ -1,17 +1,21 @@ -// Package cryptor encrypts and decrypts files using the Red October vault and key cache. +// Package cryptor encrypts and decrypts files using the Red October +// vault and key cache. +// +// Copyright (c) 2013 CloudFlare, Inc. + package cryptor import ( "crypto/aes" - "crypto/hmac" - "crypto/sha1" - "crypto/rand" "crypto/cipher" + "crypto/hmac" + "crypto/rand" + "crypto/sha1" "encoding/json" "errors" - "redoctober/passvault" "redoctober/keycache" "redoctober/padding" + "redoctober/passvault" ) const ( @@ -23,25 +27,25 @@ const ( // the names of the users in Name in order. type MultiWrappedKey struct { Name []string - Key []byte + Key []byte } // SingleWrappedKey is a structure containing // a 16-byte key encrypted by an RSA key. type SingleWrappedKey struct { - Key []byte + Key []byte aesKey []byte } // EncryptedFile is the format for encrypted data containing all the keys necessary to // decrypt it when delegated. type EncryptedFile struct { - Version int - VaultId int - KeySet []MultiWrappedKey + Version int + VaultId int + KeySet []MultiWrappedKey KeySetRSA map[string]SingleWrappedKey - IV []byte - Data []byte + IV []byte + Data []byte Signature []byte } @@ -90,7 +94,7 @@ func encryptKey(nameInner, nameOuter string, clearKey []byte, rsaKeys map[string err = errors.New("Missing user in file") return } - + overrideOuter, ok = rsaKeys[nameOuter] if !ok { err = errors.New("Missing user in file") @@ -122,7 +126,7 @@ func encryptKey(nameInner, nameOuter string, clearKey []byte, rsaKeys map[string // decrypt first key in keys whose encryption keys are in keycache func unwrapKey(keys []MultiWrappedKey, rsaKeys map[string]SingleWrappedKey) (unwrappedKey []byte, err error) { var ( - keyFound error + keyFound error fullMatch bool = false ) for _, mwKey := range keys { @@ -153,7 +157,6 @@ func unwrapKey(keys []MultiWrappedKey, rsaKeys map[string]SingleWrappedKey) (unw return } - // Encrypt encrypts data with the keys associated with names // This requires a minimum of min keys to decrypt. // NOTE: as currently implemented, the maximum value for min is 2. @@ -182,14 +185,14 @@ func Encrypt(in []byte, names []string, min int) (resp []byte, err error) { if err != nil { return } - + // allocate set of keys to be able to cover all ordered subsets // of length 2 of names encrypted.KeySet = make([]MultiWrappedKey, len(names)*(len(names)-1)) // create map to hold RSA encrypted keys encrypted.KeySetRSA = make(map[string]SingleWrappedKey) - + var singleWrappedKey SingleWrappedKey for _, name := range names { rec, ok := passvault.GetRecord(name) @@ -300,7 +303,7 @@ func Decrypt(in []byte) (resp []byte, err error) { if err != nil { return } - + // set up the decryption context aesCrypt, err := aes.NewCipher(unwrappedKey) if err != nil { @@ -314,4 +317,3 @@ func Decrypt(in []byte) (resp []byte, err error) { return padding.RemovePadding(clearData) } - diff --git a/src/redoctober/keycache/keycache.go b/src/redoctober/keycache/keycache.go index 6835c80..ec322f3 100644 --- a/src/redoctober/keycache/keycache.go +++ b/src/redoctober/keycache/keycache.go @@ -1,16 +1,19 @@ // Package keycache provides the ability to hold active keys in memory // for the Red October server. +// +// Copyright (c) 2013 CloudFlare, Inc. + package keycache import ( - "log" - "time" - "errors" "crypto/aes" + "crypto/rand" "crypto/rsa" "crypto/sha1" - "crypto/rand" + "errors" + "log" "redoctober/passvault" + "time" ) // UserKeys is the set of decrypted keys in memory, indexed by name. @@ -18,10 +21,10 @@ var UserKeys map[string]ActiveUser = make(map[string]ActiveUser) // ActiveUser holds the information about an actively delegated key type ActiveUser struct { - Admin bool - Type string + Admin bool + Type string Expiry time.Time - Uses int + Uses int // non-public members aesKey []byte rsaKey rsa.PrivateKey @@ -184,4 +187,3 @@ func DecryptKey(in []byte, name string, rsaEncryptedKey []byte) (out []byte, err return } - diff --git a/src/redoctober/keycache/keycache_test.go b/src/redoctober/keycache/keycache_test.go index b960f89..60cef7a 100644 --- a/src/redoctober/keycache/keycache_test.go +++ b/src/redoctober/keycache/keycache_test.go @@ -1,9 +1,12 @@ +// keycache_test.go: tests for keycache.go +// +// Copyright (c) 2013 CloudFlare, Inc. package keycache import ( "passvault" - "time" "testing" + "time" ) var now = time.Now() @@ -13,10 +16,10 @@ var dummy = make([]byte, 16) func TestUsesFlush(t *testing.T) { singleUse := ActiveUser{ - Admin: true, - Type: passvault.AESRecord, + Admin: true, + Type: passvault.AESRecord, Expiry: nextYear, - Uses: 2, + Uses: 2, aesKey: emptyKey, } @@ -47,10 +50,10 @@ func TestTimeFlush(t *testing.T) { one := now.Add(oneSec) singleUse := ActiveUser{ - Admin: true, - Type: passvault.AESRecord, + Admin: true, + Type: passvault.AESRecord, Expiry: one, - Uses: 10, + Uses: 10, aesKey: emptyKey, } @@ -76,5 +79,3 @@ func TestTimeFlush(t *testing.T) { t.Fatalf("Error in pruning expired key") } } - - diff --git a/src/redoctober/padding/padding.go b/src/redoctober/padding/padding.go index da9de2a..9a54212 100644 --- a/src/redoctober/padding/padding.go +++ b/src/redoctober/padding/padding.go @@ -1,4 +1,7 @@ // Package padding adds and removes padding for AES-CBC mode. +// +// Copyright (c) 2013 CloudFlare, Inc. + package padding import "errors" @@ -6,7 +9,7 @@ import "errors" // RemovePadding removes padding from clear data. func RemovePadding(bytesPadded []byte) ([]byte, error) { // last byte is padding byte - paddingLen := int(bytesPadded[len(bytesPadded) - 1]) + paddingLen := int(bytesPadded[len(bytesPadded)-1]) if paddingLen > 16 { return nil, errors.New("Padding incorrect") } @@ -18,12 +21,10 @@ func RemovePadding(bytesPadded []byte) ([]byte, error) { // PadClearFile adds padding to clear file. func PadClearFile(fileBytes []byte) (paddedFile []byte) { // pad with zeros, last byte is the size of padding - paddingLen := 16 - len(fileBytes) % 16 + paddingLen := 16 - len(fileBytes)%16 padding := make([]byte, paddingLen) - padding[paddingLen - 1] = byte(paddingLen) + padding[paddingLen-1] = byte(paddingLen) paddedFile = append(fileBytes, padding...) return } - - diff --git a/src/redoctober/passvault/passvault.go b/src/redoctober/passvault/passvault.go index be8664c..e3abffb 100644 --- a/src/redoctober/passvault/passvault.go +++ b/src/redoctober/passvault/passvault.go @@ -1,20 +1,24 @@ -// Package passvault manages the vault containing user records on disk. +// Package passvault manages the vault containing user records on +// disk. +// +// Copyright (c) 2013 CloudFlare, Inc. + package passvault import ( - "code.google.com/p/go.crypto/scrypt" - "crypto/sha1" - "crypto/aes" - "crypto/rsa" - "crypto/rand" - "crypto/cipher" - mrand "math/rand" - "math/big" - "io/ioutil" - "encoding/json" "bytes" + "code.google.com/p/go.crypto/scrypt" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/rsa" + "crypto/sha1" "encoding/binary" + "encoding/json" "errors" + "io/ioutil" + "math/big" + mrand "math/rand" "redoctober/padding" ) @@ -35,41 +39,41 @@ const ( DEFAULT_VERSION = 1 ) - // Set of encrypted records from disk var records diskRecords + // Path of current vault var localPath string // DiskPasswordRecord is the set of password records on disk. type DiskPasswordRecord struct { - Type string - Salt []byte + Type string + Salt []byte HashedPassword []byte - KeySalt []byte - AESKey []byte - RSAKey struct { - RSAExp []byte - RSAExpIV []byte - RSAPrimeP []byte + KeySalt []byte + AESKey []byte + RSAKey struct { + RSAExp []byte + RSAExpIV []byte + RSAPrimeP []byte RSAPrimePIV []byte - RSAPrimeQ []byte + RSAPrimeQ []byte RSAPrimeQIV []byte - RSAPublic rsa.PublicKey + RSAPublic rsa.PublicKey } Admin bool } type diskRecords struct { - Version int - VaultId int - HmacKey []byte + Version int + VaultId int + HmacKey []byte Passwords map[string]DiskPasswordRecord } // Summary is a minmal account summary. type Summary struct { Admin bool - Type string + Type string } // Intialization. @@ -272,22 +276,22 @@ func InitFromDisk(path string) { } } if rec.Type == RSARecord { - if len(rec.RSAKey.RSAExp) == 0 || len(rec.RSAKey.RSAExp) % 16 != 0 { + if len(rec.RSAKey.RSAExp) == 0 || len(rec.RSAKey.RSAExp)%16 != 0 { formatErr = true } - if len(rec.RSAKey.RSAPrimeP) == 0 || len(rec.RSAKey.RSAPrimeP) % 16 != 0 { + if len(rec.RSAKey.RSAPrimeP) == 0 || len(rec.RSAKey.RSAPrimeP)%16 != 0 { formatErr = true } - if len(rec.RSAKey.RSAPrimeQ) == 0 || len(rec.RSAKey.RSAPrimeQ) % 16 != 0 { + if len(rec.RSAKey.RSAPrimeQ) == 0 || len(rec.RSAKey.RSAPrimeQ)%16 != 0 { formatErr = true } - if len(rec.RSAKey.RSAExpIV) != 16 { + if len(rec.RSAKey.RSAExpIV) != 16 { formatErr = true } - if len(rec.RSAKey.RSAPrimePIV) != 16 { + if len(rec.RSAKey.RSAPrimePIV) != 16 { formatErr = true } - if len(rec.RSAKey.RSAPrimeQIV) != 16 { + if len(rec.RSAKey.RSAPrimeQIV) != 16 { formatErr = true } } @@ -404,7 +408,7 @@ func ChangePassword(name string, password string, newPassword string) (err error return } } else if passwordRec.Type == RSARecord { - // encrypt RSA key with password key + // encrypt RSA key with password key err = encryptRSARecord(&passwordRec, &rsaKey, newPassKey) if err != nil { return @@ -619,4 +623,3 @@ func (passwordRec DiskPasswordRecord) ValidatePassword(password string) (err err } return } - diff --git a/src/redoctober/passvault/passvault_test.go b/src/redoctober/passvault/passvault_test.go index 1c44303..23116df 100644 --- a/src/redoctober/passvault/passvault_test.go +++ b/src/redoctober/passvault/passvault_test.go @@ -1,3 +1,7 @@ +// passvault_test: tests for passvault.go +// +// Copyright (c) 2013 CloudFlare, Inc. + package passvault import ( @@ -9,10 +13,10 @@ var dummy = make([]byte, 16) func TestUsesFlush(t *testing.T) { singleUse := ActiveUser{ - Admin: true, + Admin: true, Expiry: nextYear, - Uses: 1, - key: emptyKey, + Uses: 1, + key: emptyKey, } LiveKeys["first"] = singleUse @@ -22,7 +26,6 @@ func TestUsesFlush(t *testing.T) { t.Fatalf("Error in number of live keys") } - EncryptKey(dummy, "first") FlushCache() @@ -36,10 +39,10 @@ func TestTimeFlush(t *testing.T) { one := now.Add(oneSec) singleUse := ActiveUser{ - Admin: true, + Admin: true, Expiry: one, - Uses: 10, - key: emptyKey, + Uses: 10, + key: emptyKey, } LiveKeys["first"] = singleUse @@ -64,5 +67,3 @@ func TestTimeFlush(t *testing.T) { t.Fatalf("Error in pruning expired key") } } - - diff --git a/src/redoctober/redoctober.go b/src/redoctober/redoctober.go index 6843511..dd727d6 100644 --- a/src/redoctober/redoctober.go +++ b/src/redoctober/redoctober.go @@ -1,65 +1,70 @@ // Package redoctober contains the server code for Red October. +// +// Copyright (c) 2013 CloudFlare, Inc. + package main import ( - "fmt" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "encoding/pem" "flag" - "os" + "fmt" "io/ioutil" "net" "net/http" - "crypto/tls" - "crypto/rand" - "crypto/x509" - "encoding/pem" + "os" "redoctober/core" ) -// list of URLs to register +// List of URLs to register + const ( - Create string = "/create" - Summary = "/summary" - Delegate = "/delegate" - Password = "/password" - Encrypt = "/encrypt" - Decrypt = "/decrypt" - Modify = "/modify" + Create string = "/create" + Summary = "/summary" + Delegate = "/delegate" + Password = "/password" + Encrypt = "/encrypt" + Decrypt = "/decrypt" + Modify = "/modify" ) -// the channel handling user request +// The channel handling user requests + var process = make(chan userRequest) type userRequest struct { - rt string - in []byte + rt string + in []byte resp chan []byte } func init() { - go func () { + go func() { for { - foo := <-process + req := <-process switch { - case foo.rt == Create: - foo.resp <- core.Create(foo.in) - case foo.rt == Summary: - foo.resp <- core.Summary(foo.in) - case foo.rt == Delegate: - foo.resp <- core.Delegate(foo.in) - case foo.rt == Password: - foo.resp <- core.Password(foo.in) - case foo.rt == Encrypt: - foo.resp <- core.Encrypt(foo.in) - case foo.rt == Decrypt: - foo.resp <- core.Decrypt(foo.in) - case foo.rt == Modify: - foo.resp <- core.Modify(foo.in) - default: - fmt.Printf("Unknown! %s\n", foo.rt) - foo.resp <- []byte("Unknown command") + case req.rt == Create: + req.resp <- core.Create(req.in) + case req.rt == Summary: + req.resp <- core.Summary(req.in) + case req.rt == Delegate: + req.resp <- core.Delegate(req.in) + case req.rt == Password: + req.resp <- core.Password(req.in) + case req.rt == Encrypt: + req.resp <- core.Encrypt(req.in) + case req.rt == Decrypt: + req.resp <- core.Decrypt(req.in) + case req.rt == Modify: + req.resp <- core.Modify(req.in) + default: + fmt.Printf("Unknown! %s\n", req.rt) + req.resp <- []byte("Unknown command") } } - } () + }() } func queueRequest(requestType string, w http.ResponseWriter, r *http.Request, c *tls.ConnectionState) { @@ -70,15 +75,14 @@ func queueRequest(requestType string, w http.ResponseWriter, r *http.Request, c response := make(chan []byte, 1) req := userRequest{rt: requestType, in: body, resp: response} - process <-req + process <- req code := <-response - + w.Write(code) } func NewServer(addr string, certPath string, keyPath string, caPath string) (*http.Server, *net.Listener, error) { - // set up server mux := http.NewServeMux() srv := http.Server{ Addr: addr, @@ -91,11 +95,11 @@ func NewServer(addr string, certPath string, keyPath string, caPath string) (*ht } config := tls.Config{ - Certificates: []tls.Certificate{cert}, - Rand: rand.Reader, - ClientAuth: tls.RequestClientCert, + Certificates: []tls.Certificate{cert}, + Rand: rand.Reader, + ClientAuth: tls.RequestClientCert, PreferServerCipherSuites: true, - SessionTicketsDisabled: true, + SessionTicketsDisabled: true, } config.Rand = rand.Reader @@ -129,7 +133,7 @@ func NewServer(addr string, certPath string, keyPath string, caPath string) (*ht lstnr := tls.NewListener(conn, &config) - for _, action := range []string {Create, Summary, Delegate, Password, Encrypt, Decrypt, Modify} { + for _, action := range []string{Create, Summary, Delegate, Password, Encrypt, Decrypt, Modify} { var requestType = action mux.HandleFunc(requestType, func(w http.ResponseWriter, r *http.Request) { queueRequest(requestType, w, r, r.TLS) @@ -148,7 +152,7 @@ redoctober /tmp/diskrecord.json localhost:8080 cert.pem cert.key ` -func main () { +func main() { flag.Usage = func() { fmt.Fprint(os.Stderr, usage) flag.PrintDefaults() @@ -172,4 +176,3 @@ func main () { s, l, _ := NewServer(*addr, *certPath, *keyPath, *caPath) s.Serve(*l) } -