func main() { // Start authentication engine zmq.AuthSetVerbose(true) zmq.AuthStart() zmq.AuthAllow("127.0.0.1") // Tell the authenticator to allow any CURVE requests for this domain zmq.AuthCurveAdd("global", zmq.CURVE_ALLOW_ANY) // We need two certificates, one for the client and one for // the server. The client must know the server's public key // to make a CURVE connection. client_public, client_secret, err := zmq.NewCurveKeypair() checkErr(err) server_public, server_secret, _ := zmq.NewCurveKeypair() checkErr(err) // Create and bind server socket server, _ := zmq.NewSocket(zmq.PUSH) server.ServerAuthCurve("global", server_secret) server.Bind("tcp://*:9000") // Create and connect client socket client, _ := zmq.NewSocket(zmq.PULL) client.ClientAuthCurve(server_public, client_public, client_secret) client.Connect("tcp://127.0.0.1:9000") // Send a single message from server to client _, err = server.Send("Hello", 0) checkErr(err) message, err := client.Recv(0) checkErr(err) if message != "Hello" { log.Fatalln(message, "!= Hello") } zmq.AuthStop() fmt.Println("Stonehouse test OK") }
func NewREQ(name string) (*Resource, error) { if name == "" { log.Fatal("Provide REQ resource name") } PublicKey, PrivateKey, err := zmq.NewCurveKeypair() if err != nil { return nil, err } r := Resource{PublicKey: PublicKey, PrivateKey: PrivateKey, Address: "tcp://127.0.0.1:8000", Name: name, Type: TYPE_REQ, UUID: uuid.New()} return &r, err }
func NewSocket(cb chan Response, socketType zmq.Type) *ZMQSocket { pub, secret, _ := zmq.NewCurveKeypair() l := new(sync.Mutex) socket := ZMQSocket{ socketType: socketType, publicKey: pub, secretKey: secret, callback: cb, lock: l, } return &socket }
/* * Loads a zmq curve key pair from disk. If the requested pair cannot be found, a new pair that * matches the name is generated. */ func InitKeys(private_key_path string) (private_key string, public_key string, err error) { if !strings.HasSuffix(private_key_path, ".private") { return "", "", errors.New(fmt.Sprintf("Invalid private key path '%v'.", private_key_path)) } if err = CheckPermissions(private_key_path); err != nil { return "", "", err } public_key_path := strings.TrimSuffix(private_key_path, ".private") + ".public" if err = CheckPermissions(public_key_path); err != nil { return "", "", err } CheckPermissions(public_key_path) private_key_buf, _ := ioutil.ReadFile(private_key_path) private_key = string(private_key_buf) public_key_buf, _ := ioutil.ReadFile(public_key_path) public_key = string(public_key_buf) if private_key != "" && public_key != "" { return private_key, public_key, nil } else if private_key == "" && public_key == "" { if public_key, private_key, err = zmq.NewCurveKeypair(); err != nil { return "", "", err } if err = ioutil.WriteFile(private_key_path, []byte(private_key), 0600); err != nil { return "", "", err } if err = ioutil.WriteFile(public_key_path, []byte(public_key), 0600); err != nil { return "", "", err } } else { return "", "", errors.New(fmt.Sprintf("Imbalanced key setup: '%v'", private_key_path)) } return private_key, public_key, nil }
func TestSecurityCurve(t *testing.T) { time.Sleep(100 * time.Millisecond) var handler, server, client *zmq.Socket defer func() { for _, s := range []*zmq.Socket{handler} { if s != nil { s.SetLinger(0) s.Close() } } }() if _, minor, _ := zmq.Version(); minor >= 1 && !zmq.HasCurve() { t.Skip("Curve not available") } // Generate new keypairs for this test client_public, client_secret, err := zmq.NewCurveKeypair() if err != nil { t.Fatal("NewCurveKeypair:", err) } server_public, server_secret, err := zmq.NewCurveKeypair() if err != nil { t.Fatal("NewCurveKeypair:", err) } handler, err = zmq.NewSocket(zmq.REP) if err != nil { t.Fatal("NewSocket:", err) } err = handler.Bind("inproc://zeromq.zap.01") if err != nil { t.Fatal("handler.Bind:", err) } doHandler := func(state zmq.State) error { msg, err := handler.RecvMessage(0) if err != nil { return err // Terminating } version := msg[0] sequence := msg[1] // domain := msg[2] // address := msg[3] identity := msg[4] mechanism := msg[5] client_key := msg[6] client_key_text := zmq.Z85encode(client_key) if version != "1.0" { return errors.New("version != 1.0") } if mechanism != "CURVE" { return errors.New("mechanism != CURVE") } if identity != "IDENT" { return errors.New("identity != IDENT") } if client_key_text == client_public { handler.SendMessage(version, sequence, "200", "OK", "anonymous", "") } else { handler.SendMessage(version, sequence, "400", "Invalid client public key", "", "") } return nil } doQuit := func(i interface{}) error { err := handler.Close() handler = nil if err != nil { t.Error("handler.Close:", err) } return errors.New("Quit") } quit := make(chan interface{}) reactor := zmq.NewReactor() reactor.AddSocket(handler, zmq.POLLIN, doHandler) reactor.AddChannel(quit, 0, doQuit) go func() { reactor.Run(100 * time.Millisecond) quit <- true }() defer func() { quit <- true <-quit close(quit) }() // Server socket will accept connections server, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = server.SetCurveServer(1) if err != nil { t.Fatal("server.SetCurveServer(1):", err) } err = server.SetCurveSecretkey(server_secret) if err != nil { t.Fatal("server.SetCurveSecretkey:", err) } err = server.SetIdentity("IDENT") if err != nil { t.Fatal("server.SetIdentity:", err) } server.Bind("tcp://127.0.0.1:9998") if err != nil { t.Fatal("server.Bind:", err) } err = server.SetRcvtimeo(time.Second) if err != nil { t.Fatal("server.SetRcvtimeo:", err) } // Check CURVE security with valid credentials client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(client_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(client_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } msg, err := bounce(server, client) if err != nil { t.Error(msg, err) } err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage server key // This will be caught by the curve_server class, not passed to ZAP garbage_key := "0000111122223333444455556666777788889999" client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(garbage_key) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(client_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(client_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage client secret key // This will be caught by the curve_server class, not passed to ZAP client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(garbage_key) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(client_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage client secret key // This will be caught by the curve_server class, not passed to ZAP client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(client_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(garbage_key) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } time.Sleep(100 * time.Millisecond) // Check CURVE security with bogus client credentials // This must be caught by the ZAP handler bogus_public, bogus_secret, _ := zmq.NewCurveKeypair() client, err = zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } err = client.SetCurveServerkey(server_public) if err != nil { t.Fatal("client.SetCurveServerkey:", err) } err = client.SetCurvePublickey(bogus_public) if err != nil { t.Fatal("client.SetCurvePublickey:", err) } err = client.SetCurveSecretkey(bogus_secret) if err != nil { t.Fatal("client.SetCurveSecretkey:", err) } err = client.Connect("tcp://127.0.0.1:9998") if err != nil { t.Fatal("client.Connect:", err) } err = client.SetRcvtimeo(time.Second) if err != nil { t.Fatal("client.SetRcvtimeo:", err) } _, err = bounce(server, client) if err == nil { t.Error("Expected failure, got success") } client.SetLinger(0) err = client.Close() client = nil if err != nil { t.Fatal("client.Close:", err) } // Shutdown err = server.Close() server = nil if err != nil { t.Error("server.Close:", err) } }
func Example_test_security_curve() { time.Sleep(100 * time.Millisecond) // Generate new keypairs for this test client_public, client_secret, err := zmq.NewCurveKeypair() if checkErr(err) { return } server_public, server_secret, err := zmq.NewCurveKeypair() if checkErr(err) { return } handler, err := zmq.NewSocket(zmq.REP) if checkErr(err) { return } err = handler.Bind("inproc://zeromq.zap.01") if checkErr(err) { return } doHandler := func(state zmq.State) error { msg, err := handler.RecvMessage(0) if err != nil { return err // Terminating } version := msg[0] sequence := msg[1] // domain := msg[2] // address := msg[3] identity := msg[4] mechanism := msg[5] client_key := msg[6] client_key_text := zmq.Z85encode(client_key) if version != "1.0" { return errors.New("version != 1.0") } if mechanism != "CURVE" { return errors.New("mechanism != CURVE") } if identity != "IDENT" { return errors.New("identity != IDENT") } if client_key_text == client_public { handler.SendMessage(version, sequence, "200", "OK", "anonymous", "") } else { handler.SendMessage(version, sequence, "400", "Invalid client public key", "", "") } return nil } doQuit := func(i interface{}) error { err := handler.Close() checkErr(err) fmt.Println("Handler closed") return errors.New("Quit") } quit := make(chan interface{}) reactor := zmq.NewReactor() reactor.AddSocket(handler, zmq.POLLIN, doHandler) reactor.AddChannel(quit, 0, doQuit) go func() { reactor.Run(100 * time.Millisecond) fmt.Println("Reactor finished") quit <- true }() defer func() { quit <- true <-quit close(quit) }() // Server socket will accept connections server, err := zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } err = server.SetCurveServer(1) if checkErr(err) { return } err = server.SetCurveSecretkey(server_secret) if checkErr(err) { return } err = server.SetIdentity("IDENT") if checkErr(err) { return } server.Bind("tcp://127.0.0.1:9998") if checkErr(err) { return } err = server.SetRcvtimeo(time.Second) if checkErr(err) { return } // Check CURVE security with valid credentials client, err := zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } err = client.SetCurveServerkey(server_public) if checkErr(err) { return } err = client.SetCurvePublickey(client_public) if checkErr(err) { return } err = client.SetCurveSecretkey(client_secret) if checkErr(err) { return } err = client.Connect("tcp://127.0.0.1:9998") if checkErr(err) { return } bounce(server, client, false) err = client.Close() if checkErr(err) { return } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage server key // This will be caught by the curve_server class, not passed to ZAP garbage_key := "0000111122223333444455556666777788889999" client, err = zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } err = client.SetCurveServerkey(garbage_key) if checkErr(err) { return } err = client.SetCurvePublickey(client_public) if checkErr(err) { return } err = client.SetCurveSecretkey(client_secret) if checkErr(err) { return } err = client.Connect("tcp://127.0.0.1:9998") if checkErr(err) { return } err = client.SetRcvtimeo(time.Second) if checkErr(err) { return } bounce(server, client, true) client.SetLinger(0) err = client.Close() if checkErr(err) { return } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage client secret key // This will be caught by the curve_server class, not passed to ZAP client, err = zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } err = client.SetCurveServerkey(server_public) if checkErr(err) { return } err = client.SetCurvePublickey(garbage_key) if checkErr(err) { return } err = client.SetCurveSecretkey(client_secret) if checkErr(err) { return } err = client.Connect("tcp://127.0.0.1:9998") if checkErr(err) { return } err = client.SetRcvtimeo(time.Second) if checkErr(err) { return } bounce(server, client, true) client.SetLinger(0) err = client.Close() if checkErr(err) { return } time.Sleep(100 * time.Millisecond) // Check CURVE security with a garbage client secret key // This will be caught by the curve_server class, not passed to ZAP client, err = zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } err = client.SetCurveServerkey(server_public) if checkErr(err) { return } err = client.SetCurvePublickey(client_public) if checkErr(err) { return } err = client.SetCurveSecretkey(garbage_key) if checkErr(err) { return } err = client.Connect("tcp://127.0.0.1:9998") if checkErr(err) { return } err = client.SetRcvtimeo(time.Second) if checkErr(err) { return } bounce(server, client, true) client.SetLinger(0) err = client.Close() if checkErr(err) { return } time.Sleep(100 * time.Millisecond) // Check CURVE security with bogus client credentials // This must be caught by the ZAP handler bogus_public, bogus_secret, _ := zmq.NewCurveKeypair() client, err = zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } err = client.SetCurveServerkey(server_public) if checkErr(err) { return } err = client.SetCurvePublickey(bogus_public) if checkErr(err) { return } err = client.SetCurveSecretkey(bogus_secret) if checkErr(err) { return } err = client.Connect("tcp://127.0.0.1:9998") if checkErr(err) { return } err = client.SetRcvtimeo(time.Second) if checkErr(err) { return } bounce(server, client, true) client.SetLinger(0) err = client.Close() if checkErr(err) { return } // Shutdown err = server.Close() checkErr(err) fmt.Println("Done") // Output: // 5 error // 5 error // 5 error // 5 error // Done // Handler closed // Reactor finished }
func TestAuthStart(t *testing.T) { if _, minor, _ := zmq.Version(); minor >= 1 && !zmq.HasCurve() { t.Skip("Curve not available") } type Meta struct { key string value string ok bool } zmq.AuthSetVerbose(false) // Start authentication engine err := zmq.AuthStart() if err != nil { t.Fatal("AuthStart:", err) } defer zmq.AuthStop() zmq.AuthSetMetadataHandler( func(version, request_id, domain, address, identity, mechanism string, credentials ...string) (metadata map[string]string) { return map[string]string{ "Identity": identity, "User-Id": "anonymous", "Hello": "World!", "Foo": "Bar", } }) zmq.AuthAllow("domain1", "127.0.0.1") // We need two certificates, one for the client and one for // the server. The client must know the server's public key // to make a CURVE connection. client_public, client_secret, err := zmq.NewCurveKeypair() if err != nil { t.Fatal("NewCurveKeypair:", err) } server_public, server_secret, err := zmq.NewCurveKeypair() if err != nil { t.Fatal("NewCurveKeypair:", err) } // Tell authenticator to use this public client key zmq.AuthCurveAdd("domain1", client_public) // Create and bind server socket server, err := zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } defer func() { server.SetLinger(0) server.Close() }() server.SetIdentity("Server1") server.ServerAuthCurve("domain1", server_secret) err = server.Bind("tcp://*:9000") if err != nil { t.Fatal("server.Bind:", err) } // Create and connect client socket client, err := zmq.NewSocket(zmq.DEALER) if err != nil { t.Fatal("NewSocket:", err) } defer func() { client.SetLinger(0) client.Close() }() server.SetIdentity("Client1") client.ClientAuthCurve(server_public, client_public, client_secret) err = client.Connect("tcp://127.0.0.1:9000") if err != nil { t.Fatal("client.Connect:", err) } // Send a message from client to server msg := []string{"Greetings", "Earthlings!"} _, err = client.SendMessage(msg[0], msg[1]) if err != nil { t.Fatal("client.SendMessage:", err) } // Receive message and metadata on the server tests := []Meta{ {"Identity", "Server1", true}, {"User-Id", "anonymous", true}, {"Socket-Type", "DEALER", true}, {"Hello", "World!", true}, {"Foo", "Bar", true}, {"Fuz", "", false}, } keys := make([]string, len(tests)) for i, test := range tests { keys[i] = test.key } message, metadata, err := server.RecvMessageWithMetadata(0, keys...) if err != nil { t.Fatal("server.RecvMessageWithMetadata:", err) } if !arrayEqual(message, msg) { t.Errorf("Received message was %q, expected %q", message, msg) } if _, minor, _ := zmq.Version(); minor < 1 { t.Log("Metadata not avalable in ZeroMQ versions prior to 4.1.0") } else { for _, test := range tests { value, ok := metadata[test.key] if value != test.value || ok != test.ok { t.Errorf("Metadata %s, expected %q %v, got %q %v", test.key, test.value, test.ok, value, ok) } } } }
func ExampleAuthStart() { checkErr := func(err error) bool { if err == nil { return false } log.Println(err) return true } zmq.AuthSetVerbose(false) // Start authentication engine err := zmq.AuthStart() if checkErr(err) { return } defer zmq.AuthStop() zmq.AuthSetMetadataHandler( func(version, request_id, domain, address, identity, mechanism string, credentials ...string) (metadata map[string]string) { return map[string]string{ "Identity": identity, "User-Id": "anonymous", "Hello": "World!", "Foo": "Bar", } }) zmq.AuthAllow("domain1", "127.0.0.1") // We need two certificates, one for the client and one for // the server. The client must know the server's public key // to make a CURVE connection. client_public, client_secret, err := zmq.NewCurveKeypair() if checkErr(err) { return } server_public, server_secret, err := zmq.NewCurveKeypair() if checkErr(err) { return } // Tell authenticator to use this public client key zmq.AuthCurveAdd("domain1", client_public) // Create and bind server socket server, err := zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } defer server.Close() server.SetIdentity("Server1") server.ServerAuthCurve("domain1", server_secret) err = server.Bind("tcp://*:9000") if checkErr(err) { return } // Create and connect client socket client, err := zmq.NewSocket(zmq.DEALER) if checkErr(err) { return } defer client.Close() server.SetIdentity("Client1") client.ClientAuthCurve(server_public, client_public, client_secret) err = client.Connect("tcp://127.0.0.1:9000") if checkErr(err) { return } // Send a message from client to server _, err = client.SendMessage("Greatings", "Earthlings!") if checkErr(err) { return } // Receive message and metadata on the server keys := []string{"Identity", "User-Id", "Socket-Type", "Hello", "Foo", "Fuz"} message, metadata, err := server.RecvMessageWithMetadata(0, keys...) if checkErr(err) { return } fmt.Println(message) if _, minor, _ := zmq.Version(); minor < 1 { // Metadata requires at least ZeroMQ version 4.1 fmt.Println(`Identity: "Server1" true`) fmt.Println(`User-Id: "anonymous" true`) fmt.Println(`Socket-Type: "DEALER" true`) fmt.Println(`Hello: "World!" true`) fmt.Println(`Foo: "Bar" true`) fmt.Println(`Fuz: "" false`) } else { for _, key := range keys { value, ok := metadata[key] fmt.Printf("%v: %q %v\n", key, value, ok) } } // Output: // [Greatings Earthlings!] // Identity: "Server1" true // User-Id: "anonymous" true // Socket-Type: "DEALER" true // Hello: "World!" true // Foo: "Bar" true // Fuz: "" false }