From d8ee0857d5a4b89904c27ac0c9e3c069e52867bb Mon Sep 17 00:00:00 2001 From: Lesterpig Date: Wed, 24 Feb 2016 15:11:04 +0100 Subject: [PATCH] [p] Add JoinSignature API --- dfssp/api/gRPCServices.pb.go | 106 +++++++++++++++++--------------- dfssp/api/gRPCServices.proto | 13 ++-- dfssp/contract/contract_test.go | 22 ++++++- dfssp/contract/create_test.go | 3 +- dfssp/contract/starter.go | 94 ++++++++++++++++++++++++++++ dfssp/contract/starter_test.go | 58 +++++++++++++++++ dfssp/entities/contract.go | 14 +++++ dfssp/server/server.go | 15 ++++- net/server.go | 8 +-- 9 files changed, 271 insertions(+), 62 deletions(-) create mode 100644 dfssp/contract/starter.go create mode 100644 dfssp/contract/starter_test.go diff --git a/dfssp/api/gRPCServices.pb.go b/dfssp/api/gRPCServices.pb.go index 373c5db..b68c3ee 100644 --- a/dfssp/api/gRPCServices.pb.go +++ b/dfssp/api/gRPCServices.pb.go @@ -17,6 +17,7 @@ It has these top-level messages: PostContractRequest JoinSignatureRequest UserConnected + User ReadySignRequest LaunchSignature */ @@ -161,6 +162,7 @@ func (*JoinSignatureRequest) Descriptor() ([]byte, []int) { return fileDescripto type UserConnected struct { ErrorCode *ErrorCode `protobuf:"bytes,1,opt,name=errorCode" json:"errorCode,omitempty"` ContractUuid string `protobuf:"bytes,2,opt,name=contractUuid" json:"contractUuid,omitempty"` + User *User `protobuf:"bytes,3,opt,name=user" json:"user,omitempty"` } func (m *UserConnected) Reset() { *m = UserConnected{} } @@ -175,17 +177,24 @@ func (m *UserConnected) GetErrorCode() *ErrorCode { return nil } -type UserConnected_User struct { - KeyHash []byte `protobuf:"bytes,1,opt,name=KeyHash,proto3" json:"KeyHash,omitempty"` +func (m *UserConnected) GetUser() *User { + if m != nil { + return m.User + } + return nil +} + +type User struct { + KeyHash []byte `protobuf:"bytes,1,opt,name=keyHash,proto3" json:"keyHash,omitempty"` Email string `protobuf:"bytes,2,opt,name=email" json:"email,omitempty"` Ip string `protobuf:"bytes,3,opt,name=ip" json:"ip,omitempty"` Port uint32 `protobuf:"varint,4,opt,name=port" json:"port,omitempty"` } -func (m *UserConnected_User) Reset() { *m = UserConnected_User{} } -func (m *UserConnected_User) String() string { return proto.CompactTextString(m) } -func (*UserConnected_User) ProtoMessage() {} -func (*UserConnected_User) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7, 0} } +func (m *User) Reset() { *m = User{} } +func (m *User) String() string { return proto.CompactTextString(m) } +func (*User) ProtoMessage() {} +func (*User) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } // ReadySignRequest contains the contract unique identitier that is ready to be signed type ReadySignRequest struct { @@ -195,7 +204,7 @@ type ReadySignRequest struct { func (m *ReadySignRequest) Reset() { *m = ReadySignRequest{} } func (m *ReadySignRequest) String() string { return proto.CompactTextString(m) } func (*ReadySignRequest) ProtoMessage() {} -func (*ReadySignRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (*ReadySignRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } // LaunchSignature is emitted by the platform when every signers are ready type LaunchSignature struct { @@ -207,7 +216,7 @@ type LaunchSignature struct { func (m *LaunchSignature) Reset() { *m = LaunchSignature{} } func (m *LaunchSignature) String() string { return proto.CompactTextString(m) } func (*LaunchSignature) ProtoMessage() {} -func (*LaunchSignature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (*LaunchSignature) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } func (m *LaunchSignature) GetErrorCode() *ErrorCode { if m != nil { @@ -225,7 +234,7 @@ func init() { proto.RegisterType((*PostContractRequest)(nil), "api.PostContractRequest") proto.RegisterType((*JoinSignatureRequest)(nil), "api.JoinSignatureRequest") proto.RegisterType((*UserConnected)(nil), "api.UserConnected") - proto.RegisterType((*UserConnected_User)(nil), "api.UserConnected.User") + proto.RegisterType((*User)(nil), "api.User") proto.RegisterType((*ReadySignRequest)(nil), "api.ReadySignRequest") proto.RegisterType((*LaunchSignature)(nil), "api.LaunchSignature") proto.RegisterEnum("api.ErrorCode_Code", ErrorCode_Code_name, ErrorCode_Code_value) @@ -462,43 +471,44 @@ var _Platform_serviceDesc = grpc.ServiceDesc{ } var fileDescriptor0 = []byte{ - // 605 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0x6f, 0x6f, 0xd2, 0x40, - 0x18, 0xa7, 0xa5, 0x1b, 0xe3, 0xd9, 0x60, 0xcd, 0x31, 0x4d, 0xed, 0x0b, 0xb3, 0x5c, 0x4c, 0x34, - 0xc6, 0xe0, 0x82, 0x89, 0x89, 0xbe, 0xeb, 0x2a, 0xd9, 0xa6, 0x86, 0x90, 0x63, 0x68, 0xe2, 0xbb, - 0x5a, 0x6e, 0xd0, 0x8c, 0xb6, 0x78, 0x3d, 0x34, 0xbc, 0xf2, 0x9b, 0xf8, 0x4d, 0xfc, 0x1c, 0x7e, - 0x1c, 0xbd, 0xbb, 0xf6, 0xa0, 0x65, 0xc4, 0x64, 0xbc, 0x80, 0xfe, 0x9e, 0xff, 0xcf, 0xef, 0xf9, - 0x15, 0x40, 0x53, 0x32, 0xf4, 0x47, 0x94, 0x7d, 0x8f, 0x42, 0x9a, 0x75, 0x17, 0x2c, 0xe5, 0x29, - 0xaa, 0x07, 0x8b, 0x08, 0x7b, 0x70, 0x4c, 0xe8, 0x34, 0xca, 0x38, 0x65, 0x84, 0x7e, 0x5b, 0xd2, - 0x8c, 0xa3, 0x13, 0xd8, 0xa3, 0x71, 0x10, 0xcd, 0x1d, 0xe3, 0xd4, 0x78, 0xd6, 0x24, 0x39, 0x40, - 0x0e, 0x34, 0x58, 0x1e, 0xe0, 0x98, 0xca, 0xae, 0x21, 0xfe, 0x65, 0x40, 0xb3, 0xcf, 0x58, 0xca, - 0xfc, 0x74, 0x42, 0xd1, 0x53, 0xb0, 0x42, 0xf1, 0xab, 0x92, 0xdb, 0xbd, 0x4e, 0x57, 0x34, 0xe9, - 0xae, 0xbd, 0x5d, 0xf9, 0x45, 0x54, 0x80, 0x2c, 0x18, 0xd3, 0x2c, 0x0b, 0xa6, 0x54, 0x17, 0x2c, - 0x20, 0x1e, 0x80, 0xa5, 0x4a, 0x1d, 0x42, 0x63, 0x34, 0xf6, 0xfd, 0xfe, 0x68, 0x64, 0xd7, 0x10, - 0xc0, 0xfe, 0xd5, 0xe0, 0x93, 0x47, 0x2e, 0x6c, 0x43, 0x3a, 0xce, 0xbd, 0x77, 0xde, 0xf8, 0xfa, - 0xd2, 0x36, 0x25, 0xf8, 0xec, 0x91, 0xc1, 0xd5, 0xe0, 0xc2, 0xae, 0xa3, 0x8e, 0x8c, 0xba, 0xee, - 0x13, 0x62, 0xff, 0xd5, 0x1f, 0x03, 0xbf, 0x81, 0x43, 0x6f, 0xc9, 0x67, 0xff, 0xdf, 0x4f, 0x58, - 0x79, 0x7a, 0x4b, 0x93, 0x62, 0x98, 0x1c, 0xe0, 0x33, 0x68, 0x6b, 0x7a, 0xe8, 0x64, 0x9c, 0x51, - 0x86, 0x1e, 0x03, 0x84, 0xf3, 0x88, 0x26, 0xdc, 0xa7, 0x8c, 0x17, 0x25, 0x4a, 0x16, 0xdc, 0x80, - 0xbd, 0x7e, 0xbc, 0xe0, 0x2b, 0xfc, 0x03, 0x3a, 0xc3, 0x34, 0xe3, 0x7e, 0x9a, 0x70, 0x16, 0x84, - 0x5c, 0x77, 0x47, 0x60, 0xcd, 0x82, 0x6c, 0xa6, 0x32, 0x8f, 0x88, 0x7a, 0x46, 0x2e, 0x1c, 0xdc, - 0x44, 0x73, 0x9a, 0x04, 0xb1, 0xe6, 0x62, 0x8d, 0xd1, 0x43, 0xd8, 0xcf, 0xa2, 0x69, 0x42, 0x99, - 0x53, 0x3f, 0xad, 0x0b, 0x4f, 0x81, 0x24, 0x7d, 0x61, 0x1a, 0xc7, 0xa2, 0xad, 0x63, 0xe5, 0xf4, - 0x15, 0x50, 0xd0, 0x77, 0xf2, 0x3e, 0x8d, 0x92, 0x91, 0x88, 0x0b, 0xf8, 0x92, 0x51, 0xdd, 0x19, - 0xc3, 0x51, 0x58, 0x0c, 0x33, 0x5e, 0x46, 0x93, 0x62, 0xf6, 0x8a, 0x4d, 0x4e, 0xb7, 0x48, 0x59, - 0x7e, 0xe2, 0x16, 0x51, 0xcf, 0xf8, 0xb7, 0x01, 0x2d, 0xb9, 0xba, 0xd8, 0x24, 0xa1, 0x21, 0xa7, - 0x13, 0xf4, 0x02, 0x9a, 0x54, 0x9f, 0x54, 0x95, 0x39, 0xec, 0xb5, 0xab, 0x87, 0x26, 0x9b, 0x80, - 0x3b, 0x7d, 0xcd, 0xbb, 0x7d, 0xdd, 0x2f, 0x60, 0x29, 0x76, 0xc5, 0x56, 0x1f, 0xe8, 0xea, 0x72, - 0x43, 0x50, 0xe3, 0x36, 0x87, 0x9b, 0xab, 0x99, 0xe5, 0xab, 0xb5, 0xc1, 0x8c, 0x16, 0x82, 0x19, - 0x69, 0x12, 0x4f, 0xeb, 0xf9, 0xad, 0xd2, 0xfc, 0xaf, 0xc1, 0x26, 0x34, 0x98, 0xac, 0x24, 0x21, - 0xf7, 0xe0, 0x02, 0xff, 0x84, 0xe3, 0x8f, 0xc1, 0x32, 0x09, 0x67, 0x6b, 0x26, 0xef, 0xb9, 0xf8, - 0x13, 0x68, 0x65, 0x3a, 0xb5, 0xb4, 0x79, 0xd5, 0x28, 0x57, 0x2e, 0x76, 0x2c, 0x2e, 0xac, 0x61, - 0xef, 0x8f, 0x09, 0x07, 0xc3, 0x79, 0xc0, 0x6f, 0x52, 0x16, 0xa3, 0x1e, 0x1c, 0x68, 0x25, 0xa2, - 0x13, 0xd5, 0x73, 0xeb, 0xbd, 0x75, 0xb7, 0x26, 0xc1, 0x35, 0xf4, 0x12, 0x2c, 0x29, 0x7c, 0x64, - 0x2b, 0x4f, 0xe9, 0x1d, 0x70, 0x3b, 0x95, 0x0a, 0xb9, 0xb4, 0x45, 0xc2, 0x73, 0x80, 0x71, 0xc2, - 0x74, 0x1b, 0xc8, 0x0b, 0x4a, 0x35, 0xef, 0x28, 0xfe, 0x16, 0x8e, 0xca, 0xfa, 0x46, 0x8e, 0x8a, - 0xd8, 0x21, 0xf9, 0x1d, 0xb9, 0xe7, 0xd0, 0xaa, 0x48, 0x14, 0x3d, 0x52, 0x21, 0xbb, 0x64, 0xeb, - 0x22, 0xe5, 0xaa, 0x08, 0x10, 0xd7, 0xce, 0x0c, 0xd1, 0xbf, 0xb9, 0x3e, 0x2b, 0x7a, 0x50, 0xec, - 0x53, 0x3d, 0xb3, 0x9b, 0x13, 0xb5, 0x75, 0x45, 0x5c, 0xfb, 0xba, 0xaf, 0xfe, 0x01, 0x5f, 0xfd, - 0x0b, 0x00, 0x00, 0xff, 0xff, 0x91, 0x07, 0xf4, 0xa6, 0x17, 0x05, 0x00, 0x00, + // 618 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x54, 0x5f, 0x6f, 0xd3, 0x3e, + 0x14, 0x6d, 0xd2, 0xec, 0x4f, 0xee, 0xd6, 0x2e, 0x72, 0xf7, 0xfb, 0x29, 0x54, 0x02, 0x4d, 0x16, + 0x12, 0x08, 0xa1, 0x32, 0x15, 0x09, 0x09, 0xde, 0xb2, 0x50, 0x6d, 0x43, 0xa8, 0x9a, 0xdc, 0x15, + 0x24, 0xde, 0x42, 0xea, 0xb5, 0xd1, 0x9a, 0xa4, 0x38, 0x0e, 0x68, 0x4f, 0xf0, 0x49, 0xf8, 0x5a, + 0x7c, 0x1c, 0xb0, 0x9d, 0x38, 0x4d, 0x4a, 0x85, 0xb4, 0x3e, 0xb4, 0x3e, 0xd7, 0xd7, 0xe7, 0xf8, + 0x9e, 0x7b, 0x5d, 0x40, 0x73, 0x72, 0xe5, 0x4f, 0x28, 0xfb, 0x1a, 0x85, 0x34, 0x1b, 0xac, 0x58, + 0xca, 0x53, 0xd4, 0x0e, 0x56, 0x11, 0xf6, 0xe0, 0x88, 0xd0, 0x79, 0x94, 0x71, 0xca, 0x08, 0xfd, + 0x92, 0xd3, 0x8c, 0xa3, 0x63, 0xd8, 0xa1, 0x71, 0x10, 0x2d, 0x5d, 0xe3, 0xc4, 0x78, 0x6a, 0x93, + 0x02, 0x20, 0x17, 0xf6, 0x58, 0x91, 0xe0, 0x9a, 0x2a, 0xae, 0x21, 0xfe, 0x69, 0x80, 0x3d, 0x62, + 0x2c, 0x65, 0x7e, 0x3a, 0xa3, 0xe8, 0x09, 0x58, 0xa1, 0xf8, 0x55, 0x87, 0xbb, 0xc3, 0xde, 0x40, + 0x88, 0x0c, 0xaa, 0xdd, 0x81, 0xfc, 0x22, 0x2a, 0x41, 0x12, 0xc6, 0x34, 0xcb, 0x82, 0x39, 0xd5, + 0x84, 0x25, 0xc4, 0x63, 0xb0, 0x14, 0xd5, 0x01, 0xec, 0x4d, 0xa6, 0xbe, 0x3f, 0x9a, 0x4c, 0x9c, + 0x16, 0x02, 0xd8, 0xbd, 0x1c, 0x7f, 0xf0, 0xc8, 0xb9, 0x63, 0xc8, 0x8d, 0x33, 0xef, 0xad, 0x37, + 0xbd, 0xbe, 0x70, 0x4c, 0x09, 0x3e, 0x7a, 0x64, 0x7c, 0x39, 0x3e, 0x77, 0xda, 0xa8, 0x27, 0xb3, + 0xae, 0x47, 0x84, 0x38, 0xbf, 0xf5, 0xc7, 0xc0, 0xaf, 0xe1, 0xc0, 0xcb, 0xf9, 0xe2, 0xdf, 0xf5, + 0x89, 0x28, 0x4f, 0x6f, 0x69, 0x52, 0x5e, 0xa6, 0x00, 0xf8, 0x14, 0xba, 0xda, 0x1e, 0x3a, 0x9b, + 0x66, 0x94, 0xa1, 0x47, 0x00, 0xe1, 0x32, 0xa2, 0x09, 0xf7, 0x29, 0xe3, 0x25, 0x45, 0x2d, 0x82, + 0xf7, 0x60, 0x67, 0x14, 0xaf, 0xf8, 0x1d, 0xfe, 0x06, 0xbd, 0xab, 0x34, 0xe3, 0x7e, 0x9a, 0x70, + 0x16, 0x84, 0x5c, 0xab, 0x23, 0xb0, 0x16, 0x41, 0xb6, 0x50, 0x27, 0x0f, 0x89, 0x5a, 0xa3, 0x3e, + 0xec, 0xdf, 0x44, 0x4b, 0x9a, 0x04, 0xb1, 0xf6, 0xa2, 0xc2, 0xe8, 0x7f, 0xd8, 0xcd, 0xa2, 0x79, + 0x42, 0x99, 0xdb, 0x3e, 0x69, 0x8b, 0x9d, 0x12, 0x49, 0xfb, 0xc2, 0x34, 0x8e, 0x85, 0xac, 0x6b, + 0x15, 0xf6, 0x95, 0x50, 0xd8, 0x77, 0xfc, 0x2e, 0x8d, 0x92, 0x89, 0xc8, 0x0b, 0x78, 0xce, 0xa8, + 0x56, 0xc6, 0x70, 0x18, 0x96, 0x97, 0x99, 0xe6, 0xd1, 0xac, 0xbc, 0x7b, 0x23, 0x26, 0x6f, 0xb7, + 0x4a, 0x59, 0xd1, 0xe2, 0x0e, 0x51, 0x6b, 0xfc, 0xc3, 0x80, 0x8e, 0x2c, 0x5d, 0x54, 0x92, 0xd0, + 0x90, 0xd3, 0x19, 0x7a, 0x0e, 0x36, 0xd5, 0x2d, 0x55, 0x34, 0x07, 0xc3, 0x6e, 0xb3, 0xd1, 0x64, + 0x9d, 0xf0, 0x97, 0xae, 0xb9, 0x45, 0xf7, 0x21, 0x58, 0x79, 0xa6, 0x6a, 0x94, 0x64, 0xb6, 0x22, + 0x93, 0x9a, 0x44, 0x85, 0xf1, 0x27, 0xb0, 0x94, 0xf9, 0xa2, 0xe8, 0x5b, 0x7a, 0x77, 0xb1, 0xf6, + 0x4f, 0xc3, 0x75, 0x53, 0xcd, 0x7a, 0x53, 0xbb, 0x60, 0x46, 0x2b, 0x45, 0x6a, 0x13, 0xb1, 0xaa, + 0xca, 0xb3, 0x6a, 0xe5, 0xbd, 0x02, 0x87, 0xd0, 0x60, 0x76, 0x27, 0xfd, 0xba, 0x87, 0x55, 0xf8, + 0x3b, 0x1c, 0xbd, 0x0f, 0xf2, 0x24, 0x5c, 0x54, 0x46, 0xdf, 0xd3, 0x97, 0xc7, 0xd0, 0xc9, 0xf4, + 0xd1, 0x9a, 0x31, 0xcd, 0x60, 0xbd, 0xe4, 0x62, 0x00, 0x34, 0x1c, 0xfe, 0x32, 0x61, 0xff, 0x6a, + 0x19, 0xf0, 0x9b, 0x94, 0xc5, 0x68, 0x08, 0xfb, 0x7a, 0x50, 0xd1, 0xb1, 0xd2, 0xdc, 0x78, 0xd6, + 0xfd, 0x8d, 0x9b, 0xe0, 0x16, 0x7a, 0x01, 0x96, 0x7c, 0x17, 0xc8, 0x51, 0x3b, 0xb5, 0x27, 0xd2, + 0xef, 0x35, 0x18, 0x8a, 0xc9, 0x17, 0x07, 0x9e, 0x01, 0x4c, 0x13, 0xa6, 0x65, 0xa0, 0x20, 0x94, + 0xc3, 0xbe, 0x85, 0xfc, 0x0d, 0x1c, 0xd6, 0xc7, 0x1f, 0xb9, 0x2a, 0x63, 0xcb, 0x8b, 0xd8, 0x72, + 0xf6, 0x0c, 0x3a, 0x8d, 0x09, 0x46, 0x0f, 0x54, 0xca, 0xb6, 0xa9, 0xee, 0xa3, 0x6a, 0x56, 0xaa, + 0xf9, 0xc4, 0xad, 0x53, 0x43, 0xe8, 0xdb, 0x55, 0x5b, 0xd1, 0x7f, 0x65, 0x3d, 0xcd, 0x36, 0xf7, + 0x0b, 0xa3, 0x36, 0xba, 0x88, 0x5b, 0x9f, 0x77, 0xd5, 0x1f, 0xe4, 0xcb, 0x3f, 0x01, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xc7, 0x56, 0xf4, 0x36, 0x05, 0x00, 0x00, } diff --git a/dfssp/api/gRPCServices.proto b/dfssp/api/gRPCServices.proto index 83283b3..e959850 100644 --- a/dfssp/api/gRPCServices.proto +++ b/dfssp/api/gRPCServices.proto @@ -74,14 +74,15 @@ message JoinSignatureRequest { message UserConnected { ErrorCode errorCode = 1; string contractUuid = 2; - message User { - bytes KeyHash = 1; - string email = 2; - string ip = 3; - uint32 port = 4; - } + User user = 3; } +message User { + bytes keyHash = 1; + string email = 2; + string ip = 3; + uint32 port = 4; +} // ReadySignRequest contains the contract unique identitier that is ready to be signed message ReadySignRequest { string contractUuid = 1; diff --git a/dfssp/contract/contract_test.go b/dfssp/contract/contract_test.go index 61b5797..3b62080 100644 --- a/dfssp/contract/contract_test.go +++ b/dfssp/contract/contract_test.go @@ -113,10 +113,9 @@ func TestInsertContract(t *testing.T) { // Insert some contracts with missing user and test waiting contracts for this user func TestGetWaitingForUser(t *testing.T) { - knownID := bson.NewObjectId() - dropDataset() + c1 := entities.NewContract() c1.AddSigner(nil, "mail1", []byte{}) c1.Ready = false @@ -139,3 +138,22 @@ func TestGetWaitingForUser(t *testing.T) { assert.Equal(t, nil, err) assert.Equal(t, 2, len(contracts)) } + +func TestCheckAuthorization(t *testing.T) { + dropDataset() + createDataset() + id := addTestContract() + + assert.T(t, repository.CheckAuthorization(user1.CertHash, id)) + assert.T(t, !repository.CheckAuthorization(user1.CertHash, bson.NewObjectId())) + assert.T(t, !repository.CheckAuthorization(user2.CertHash, id)) + assert.T(t, !repository.CheckAuthorization(user2.CertHash, bson.NewObjectId())) + + contract := entities.Contract{} + _ = repository.Collection.FindByID(entities.Contract{ID: id}, &contract) + contract.Ready = false + _, _ = repository.Collection.UpdateByID(contract) + + // Not valid if contract is not ready + assert.T(t, !repository.CheckAuthorization(user1.CertHash, id)) +} diff --git a/dfssp/contract/create_test.go b/dfssp/contract/create_test.go index ca3e70b..082016d 100644 --- a/dfssp/contract/create_test.go +++ b/dfssp/contract/create_test.go @@ -2,6 +2,7 @@ package contract_test import ( "crypto/sha512" + "fmt" "io/ioutil" "path/filepath" "testing" @@ -27,7 +28,7 @@ func createDataset() { user1.Email = "user1@example.com" user1.Expiration = time.Now().AddDate(1, 0, 0) user1.Certificate = "Certificate1" - user1.CertHash = []byte{0x01} + _, _ = fmt.Sscanf("23a012afa19d5892f66ae9681afb3bb010e61c8bb4afdedd6a407fa40dbb7d4d1ad94953ca25866b6b07e25f8bf604cc94b13fb9dc1e7fa53980040db2a7f787", "%x", &user1.CertHash) user2.Email = "user2@example.com" user2.Expiration = time.Now().AddDate(1, 0, 0) diff --git a/dfssp/contract/starter.go b/dfssp/contract/starter.go new file mode 100644 index 0000000..b10f63c --- /dev/null +++ b/dfssp/contract/starter.go @@ -0,0 +1,94 @@ +package contract + +import ( + n "net" + + "dfss/auth" + "dfss/dfssp/api" + "dfss/dfssp/common" + "dfss/dfssp/entities" + "dfss/mgdb" + "dfss/net" + "gopkg.in/mgo.v2/bson" +) + +// JoinSignature allows a client to wait for other clients connections on a specific contract. +// Firstly, every client present BEFORE the call of this function is sent to the stream. +// Then, client information is sent to the stream as it's available. +// +// Please note that the current user will also receive it's own information. +// There is no timeout, this function will shut down on stream disconnection or on error. +func JoinSignature(db *mgdb.MongoManager, rooms *common.WaitingGroupMap, in *api.JoinSignatureRequest, stream api.Platform_JoinSignatureServer) { + repository := entities.NewContractRepository(db.Get("contracts")) + ctx := stream.Context() + state, addr, _ := net.GetTLSState(&ctx) + hash := auth.GetCertificateHash(state.VerifiedChains[0][0]) + + if !bson.IsObjectIdHex(in.ContractUuid) { + _ = stream.Send(&api.UserConnected{ + ErrorCode: &api.ErrorCode{ + Code: api.ErrorCode_INVARG, + Message: "invalid contract uuid", + }, + }) + return + } + + if !repository.CheckAuthorization(hash, bson.ObjectIdHex(in.ContractUuid)) { + _ = stream.Send(&api.UserConnected{ + ErrorCode: &api.ErrorCode{ + Code: api.ErrorCode_INVARG, + Message: "unauthorized signature", + }, + }) + return + } + + // Join room + roomID := "contract_" + in.ContractUuid + channel, pendingSigners := rooms.Join(roomID) + + // Send pendingSigners + for _, p := range pendingSigners { + err := sendUserToStream(&stream, in.ContractUuid, p.(*api.User)) + if err != nil { + rooms.Unjoin(roomID, channel) + return + } + } + + // Broadcast self identity + host, _, _ := n.SplitHostPort(addr.String()) + rooms.Broadcast(roomID, &api.User{ + KeyHash: hash, + Email: net.GetCN(&ctx), + Ip: host, + Port: in.Port, + }) + + // Listen for others + for { + select { + case user, ok := <-channel: + if !ok { // channel is closed, means that the room is closed + return + } + err := sendUserToStream(&stream, in.ContractUuid, user.(*api.User)) + if err != nil { + rooms.Unjoin(roomID, channel) + return + } + case <-ctx.Done(): + rooms.Unjoin(roomID, channel) + return + } + } +} + +func sendUserToStream(stream *api.Platform_JoinSignatureServer, contractUUID string, user *api.User) error { + return (*stream).Send(&api.UserConnected{ + ErrorCode: &api.ErrorCode{Code: api.ErrorCode_SUCCESS}, + ContractUuid: contractUUID, + User: user, + }) +} diff --git a/dfssp/contract/starter_test.go b/dfssp/contract/starter_test.go new file mode 100644 index 0000000..16d2fad --- /dev/null +++ b/dfssp/contract/starter_test.go @@ -0,0 +1,58 @@ +package contract_test + +import ( + "testing" + + "dfss/dfssp/api" + "dfss/dfssp/entities" + "github.com/bmizerany/assert" + "golang.org/x/net/context" + "gopkg.in/mgo.v2/bson" +) + +func addTestContract() bson.ObjectId { + contract := entities.NewContract() + contract.AddSigner(&user1.ID, user1.Email, user1.CertHash) + contract.Ready = true + _, _ = manager.Get("contracts").Insert(contract) + return contract.ID +} + +func TestJoinSignature(t *testing.T) { + dropDataset() + createDataset() + contractID := addTestContract() + + client := clientTest(t) + stream, err := client.JoinSignature(context.Background(), &api.JoinSignatureRequest{ + ContractUuid: contractID.Hex(), + Port: 5050, + }) + assert.Equal(t, nil, err) + + user, err := stream.Recv() + assert.Equal(t, nil, err) + assert.Equal(t, "", user.ErrorCode.Message) + assert.Equal(t, api.ErrorCode_SUCCESS, user.ErrorCode.Code) + assert.Equal(t, contractID.Hex(), user.ContractUuid) + assert.Equal(t, "test@test.com", user.User.Email) + assert.Equal(t, "127.0.0.1", user.User.Ip) + assert.Equal(t, uint32(5050), user.User.Port) +} + +func TestJoinSignatureBadContract(t *testing.T) { + dropDataset() + createDataset() + + client := clientTest(t) + stream, err := client.JoinSignature(context.Background(), &api.JoinSignatureRequest{ + ContractUuid: bson.NewObjectId().Hex(), + Port: 5050, + }) + assert.Equal(t, nil, err) + + user, err := stream.Recv() + assert.Equal(t, nil, err) + assert.Equal(t, "unauthorized signature", user.ErrorCode.Message) + assert.Equal(t, api.ErrorCode_INVARG, user.ErrorCode.Code) +} diff --git a/dfssp/entities/contract.go b/dfssp/entities/contract.go index 30dffab..fa262ed 100644 --- a/dfssp/entities/contract.go +++ b/dfssp/entities/contract.go @@ -83,3 +83,17 @@ func (r *ContractRepository) GetWaitingForUser(email string) ([]Contract, error) }, &res) return res, err } + +// CheckAuthorization checks that a client is allowed to sign a specific contract +func (r *ContractRepository) CheckAuthorization(signerHash []byte, contractID bson.ObjectId) bool { + + count, _ := r.Collection.Collection.Find(bson.M{ + "_id": contractID, + "ready": true, + "signers": bson.M{ + "$elemMatch": bson.M{"hash": signerHash}, + }, + }).Count() + + return count == 1 +} diff --git a/dfssp/server/server.go b/dfssp/server/server.go index f774f31..e195926 100644 --- a/dfssp/server/server.go +++ b/dfssp/server/server.go @@ -6,6 +6,7 @@ import ( "dfss/dfssp/api" "dfss/dfssp/authority" + "dfss/dfssp/common" "dfss/dfssp/contract" "dfss/dfssp/user" "dfss/mgdb" @@ -17,6 +18,7 @@ import ( type platformServer struct { Pid *authority.PlatformID DB *mgdb.MongoManager + Rooms *common.WaitingGroupMap CertDuration int Verbose bool } @@ -61,7 +63,17 @@ func (s *platformServer) PostContract(ctx context.Context, in *api.PostContractR // // Handle incoming JoinSignatureRequest messages func (s *platformServer) JoinSignature(in *api.JoinSignatureRequest, stream api.Platform_JoinSignatureServer) error { - // TODO + + ctx := stream.Context() + cn := net.GetCN(&ctx) + if len(cn) == 0 { + _ = stream.Send(&api.UserConnected{ + ErrorCode: &api.ErrorCode{Code: api.ErrorCode_BADAUTH}, + }) + return nil + } + + contract.JoinSignature(s.DB, s.Rooms, in, stream) return nil } @@ -91,6 +103,7 @@ func GetServer(keyPath, db string, certValidity int, verbose bool) *grpc.Server api.RegisterPlatformServer(server, &platformServer{ Pid: pid, DB: dbManager, + Rooms: common.NewWaitingGroupMap(), CertDuration: certValidity, Verbose: verbose, }) diff --git a/net/server.go b/net/server.go index 8741132..e1978d9 100644 --- a/net/server.go +++ b/net/server.go @@ -56,18 +56,18 @@ func Listen(addrPort string, grpcServer *grpc.Server) error { // GetTLSState returns the current tls connection state from a grpc context. // If you just need to check that the connected peer provides its certificate, use `GetCN`. -func GetTLSState(ctx *context.Context) (tls.ConnectionState, bool) { +func GetTLSState(ctx *context.Context) (tls.ConnectionState, net.Addr, bool) { p, ok := peer.FromContext(*ctx) if !ok { - return tls.ConnectionState{}, false + return tls.ConnectionState{}, nil, false } - return p.AuthInfo.(credentials.TLSInfo).State, true + return p.AuthInfo.(credentials.TLSInfo).State, p.Addr, true } // GetCN returns the current common name of connected peer from grpc context. // The returned string is empty if encountering a non-auth peer. func GetCN(ctx *context.Context) string { - state, ok := GetTLSState(ctx) + state, _, ok := GetTLSState(ctx) if !ok || len(state.VerifiedChains) == 0 { return "" } -- GitLab