-
Notifications
You must be signed in to change notification settings - Fork 26
Implement registration function #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5aafe11
30d7b12
1d7764a
7eeb6d0
9aacfb1
17589f6
fe26728
52616ce
3d3e0c1
228eba6
9dde8f5
a3148e5
72a20f0
a34c756
e10f76c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # CONIKS Server implementation in Golang | ||
|
|
||
| ## Usage | ||
| Generate new config file with proper format | ||
| ``` | ||
| go run keyserver/coniksserver/main.go -genconfig | ||
| ``` | ||
|
|
||
| Generate new key pair for VRF and signing | ||
| ``` | ||
| go run utils/keygen/mkkey.go -vrf -signing | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Think I'd prefer to use this as, |
||
| ``` | ||
|
|
||
| Generate a private key for secure connection (TLS) | ||
| ``` | ||
| openssl ecparam -genkey -name prime256v1 -out server.key | ||
| ``` | ||
|
|
||
| Generation of self-signed(x509) public key (PEM-encodings `.pem`) based on the private (`.key`) | ||
| ``` | ||
| openssl req -new -x509 -sha256 -key server.key -out server.pem -days 3650 | ||
| ``` | ||
|
|
||
| Run the server | ||
| ``` | ||
| go run keyserver/coniksserver/main.go | ||
| ``` | ||
|
|
||
| ## Disclaimer | ||
| Please keep in mind that this CONIKS server implementation is under active development. The repository may contain experimental features that aren't fully tested. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "flag" | ||
| "os" | ||
| "os/signal" | ||
|
|
||
| "github.com/BurntSushi/toml" | ||
| "github.com/coniks-sys/coniks-go/keyserver" | ||
| "github.com/coniks-sys/coniks-go/utils" | ||
| ) | ||
|
|
||
| const ConfigFile = "config.toml" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably want to put, in the .gitignore file. |
||
| const PoliciesFile = "policies.toml" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why a separate policy file?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I and @masomel have had a discussion over this (b5907c7#commitcomment-18595647). She pointed out for me that policy file was redundant. I probably should remove this |
||
|
|
||
| func main() { | ||
| genConfigPtr := flag.Bool("genconfig", false, "Generate server config") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there was only one config file, we could pass in a path for where to generate it, and get rid of the globals ( |
||
| configPathPtr := flag.String("config", "config.toml", "path to config file") | ||
| flag.Parse() | ||
|
|
||
| if *genConfigPtr { | ||
| mkConfig() | ||
| return | ||
| } | ||
|
|
||
| // set up a CONIKS server from config file | ||
| conf := keyserver.LoadServerConfig(*configPathPtr) | ||
| serv := keyserver.NewConiksServer(conf) | ||
|
|
||
| // run the server until receiving an interrupt signal | ||
| serv.RunWithConfig(conf) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Passing in the |
||
| ch := make(chan os.Signal, 1) | ||
| signal.Notify(ch, os.Interrupt) | ||
| <-ch | ||
| serv.Shutdown() | ||
| } | ||
|
|
||
| func mkConfig() { | ||
| var conf = keyserver.ServerConfig{ | ||
| SigningKeyPath: "ed25519.secret", | ||
| DatabasePath: "coniks.db", | ||
| RegistrationAddress: "127.0.0.1:3001", | ||
| Address: "0.0.0.0:3000", | ||
| PoliciesPath: "policies.toml", | ||
| LoadedHistoryLength: 1000000, | ||
| RegistrationCapacity: 100000, | ||
| } | ||
| conf.TLS.TLSCertPath = "server.pem" | ||
| conf.TLS.TLSKeyPath = "server.key" | ||
|
|
||
| var policies = keyserver.ServerPolicies{ | ||
| EpochDeadline: 60, | ||
| VRFKeyPath: "vrf.secret", | ||
| } | ||
|
|
||
| var confBuf bytes.Buffer | ||
| var policiesBuf bytes.Buffer | ||
|
|
||
| e := toml.NewEncoder(&confBuf) | ||
| err := e.Encode(conf) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| util.WriteFile(ConfigFile, confBuf) | ||
|
|
||
| e = toml.NewEncoder(&policiesBuf) | ||
| err = e.Encode(policies) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| util.WriteFile(PoliciesFile, policiesBuf) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| package keyserver | ||
|
|
||
| import ( | ||
| . "github.com/coniks-sys/coniks-go/protocol" | ||
| "github.com/coniks-sys/coniks-go/utils" | ||
| ) | ||
|
|
||
| func (server *ConiksServer) handleRegistrationMessage(reg *RegistrationRequest) (Response, error) { | ||
| if len(reg.Username) == 0 || len(reg.Key) == 0 { | ||
| return NewErrorResponse(ErrorMalformedClientMessage), | ||
| ErrorMalformedClientMessage.Error() | ||
| } | ||
|
|
||
| server.Lock() | ||
|
|
||
| ap, tb, errCode := server.directory.Register(reg.Username, []byte(reg.Key)) | ||
| if errCode != Success { | ||
| server.Unlock() | ||
| return NewErrorResponse(errCode), | ||
| errCode.Error() | ||
| } | ||
| server.Unlock() | ||
|
|
||
| // store the user policies into DB | ||
| err := server.StoreUserPoliciesToKV(&ConiksUserPolicies{ | ||
| AllowUnsignedKeychange: reg.AllowUnsignedKeychange, | ||
| AllowPublicLookup: reg.AllowPublicLookup, | ||
| }) | ||
| if err != nil { | ||
| return NewErrorResponse(ErrorInternalServer), | ||
| err | ||
| } | ||
|
|
||
| return &RegistrationResponse{ | ||
| Type: RegistrationType, | ||
| STR: server.directory.LatestSTR(), | ||
| AP: ap, | ||
| TB: tb, | ||
| }, nil | ||
| } | ||
|
|
||
| func (server *ConiksServer) StoreUserPoliciesToKV(up *ConiksUserPolicies) error { | ||
| buf := make([]byte, 0, 1) | ||
| buf = append(util.ToBytes([]bool{up.AllowUnsignedKeychange, up.AllowPublicLookup})) | ||
| if err := server.db.Put([]byte(up.Username), buf); err != nil { | ||
| return err | ||
| } | ||
| return nil | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| package keyserver | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "io" | ||
| "log" | ||
| "net" | ||
| "time" | ||
|
|
||
| . "github.com/coniks-sys/coniks-go/protocol" | ||
| ) | ||
|
|
||
| func (server *ConiksServer) listenForRequests(ln net.Listener, handler func(msg []byte) ([]byte, error)) { | ||
| defer server.waitStop.Done() | ||
| defer ln.Close() | ||
| go func() { | ||
| <-server.stop | ||
| ln.Close() | ||
| }() | ||
|
|
||
| for { | ||
| conn, err := ln.Accept() | ||
| if err != nil { | ||
| select { | ||
| case <-server.stop: | ||
| return | ||
| default: | ||
| log.Printf("accept client: %s", err) | ||
| continue | ||
| } | ||
| } | ||
| server.waitStop.Add(1) | ||
| go server.acceptClient(conn, handler) | ||
| } | ||
| } | ||
|
|
||
| func (server *ConiksServer) acceptClient(conn net.Conn, handler func(msg []byte) ([]byte, error)) { | ||
| defer conn.Close() | ||
| defer server.waitStop.Done() | ||
| closed := make(chan struct{}) | ||
| defer close(closed) | ||
| go func() { | ||
| select { | ||
| case <-server.stop: | ||
| conn.Close() | ||
| case <-closed: | ||
| } | ||
| }() | ||
|
|
||
| conn.SetDeadline(time.Now().Add(5 * time.Second)) | ||
|
|
||
| // handle request | ||
| buf := make([]byte, 4096) | ||
| for { | ||
| n, err := conn.Read(buf) | ||
| if err != nil { | ||
| select { | ||
| case <-server.stop: | ||
| return | ||
| default: | ||
| if err != io.EOF { | ||
| log.Printf("client read %v: %v", conn.RemoteAddr(), err) | ||
| } | ||
| return | ||
| } | ||
| } | ||
|
|
||
| res, err := handler(buf[:n]) | ||
| if err != nil { | ||
| log.Printf("client handle %v: %v", conn.RemoteAddr(), err) | ||
| } | ||
|
|
||
| n, err = conn.Write([]byte(res)) | ||
| if err != nil { | ||
| select { | ||
| case <-server.stop: | ||
| return | ||
| default: | ||
| log.Printf("client write %v: %v", conn.RemoteAddr(), err) | ||
| return | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func malformedClientMsg() []byte { | ||
| res, err := MarshalErrorResponse(ErrorMalformedClientMessage) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| return res | ||
| } | ||
|
|
||
| // handleClientMessage returns a byte slice of marshaled response | ||
| // and an error for server logging | ||
| func (server *ConiksServer) handleClientMessage(msg []byte) ([]byte, error) { | ||
| // get request message | ||
| req, _, err := UnmarshalRequest(msg) | ||
| if err != nil { | ||
| return malformedClientMsg(), err | ||
| } | ||
|
|
||
| // handle request | ||
| switch req.Type { | ||
| default: | ||
| log.Printf("unknown message type: %q", req.Type) | ||
| return malformedClientMsg(), ErrorMalformedClientMessage.Error() | ||
| } | ||
| } | ||
|
|
||
| func (server *ConiksServer) handleBotMessage(msg []byte) ([]byte, error) { | ||
| var response Response | ||
| var err error | ||
|
|
||
| // get request message | ||
| req, content, err := UnmarshalRequest(msg) | ||
| if err != nil { | ||
| return malformedClientMsg(), err | ||
| } | ||
|
|
||
| // handle request | ||
| switch req.Type { | ||
| case RegistrationType: | ||
| var reg RegistrationRequest | ||
| if err = json.Unmarshal(content, ®); err != nil { | ||
| return malformedClientMsg(), err | ||
| } | ||
| response, err = server.handleRegistrationMessage(®) | ||
| if err == nil { | ||
| res, e := MarshalRegistrationResponse(response.(*RegistrationResponse)) | ||
| if e != nil { | ||
| panic(e) | ||
| } | ||
| return res, nil | ||
| } | ||
| res, e := MarshalErrorResponse(response.(*ErrorResponse).Error) | ||
| if e != nil { | ||
| panic(e) | ||
| } | ||
| return res, nil | ||
|
|
||
| default: | ||
| log.Printf("unknown message type: %q", req.Type) | ||
| return malformedClientMsg(), ErrorMalformedClientMessage.Error() | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package keyserver | ||
|
|
||
| import ( | ||
| "io/ioutil" | ||
| "log" | ||
|
|
||
| "github.com/BurntSushi/toml" | ||
| "github.com/coniks-sys/coniks-go/crypto/vrf" | ||
| "github.com/coniks-sys/coniks-go/merkletree" | ||
| ) | ||
|
|
||
| type ServerPolicies struct { | ||
| EpochDeadline merkletree.TimeStamp `toml:"epoch_deadline"` | ||
| VRFKeyPath string `toml:"vrf_key_path"` | ||
| } | ||
|
|
||
| func readPolicies(path string) (*ServerPolicies, *vrf.PrivateKey, error) { | ||
| var p ServerPolicies | ||
| if _, err := toml.DecodeFile(path, &p); err != nil { | ||
| log.Fatalf("Failed to load config: %v", err) | ||
| return nil, nil, err | ||
| } | ||
|
|
||
| // load vrf key | ||
| skBytes, err := ioutil.ReadFile(p.VRFKeyPath) | ||
| if err != nil { | ||
| log.Fatalf("Cannot read VRF key: %v", err) | ||
| return nil, nil, nil | ||
| } | ||
| if len(skBytes) != vrf.PrivateKeySize { | ||
| log.Fatalf("Signing key must be 64 bytes (got %d)", len(skBytes)) | ||
| return nil, nil, nil | ||
| } | ||
|
|
||
| vrfKey := new(vrf.PrivateKey) | ||
| copy(vrfKey[:], skBytes) | ||
| return &p, vrfKey, nil | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose at some point we'll encourage people to,