diff --git a/authd.pb.go b/authd.pb.go index 9d271beb7..e16f8b681 100644 --- a/authd.pb.go +++ b/authd.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.30.0 +// protoc-gen-go v1.31.0 // protoc v3.21.12 // source: authd.proto @@ -698,6 +698,61 @@ func (x *SDBFURequest) GetUsername() string { return "" } +type ASRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` +} + +func (x *ASRequest) Reset() { + *x = ASRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_authd_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ASRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ASRequest) ProtoMessage() {} + +func (x *ASRequest) ProtoReflect() protoreflect.Message { + mi := &file_authd_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ASRequest.ProtoReflect.Descriptor instead. +func (*ASRequest) Descriptor() ([]byte, []int) { + return file_authd_proto_rawDescGZIP(), []int{12} +} + +func (x *ASRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +func (x *ASRequest) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + type ABResponse_BrokerInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -711,7 +766,7 @@ type ABResponse_BrokerInfo struct { func (x *ABResponse_BrokerInfo) Reset() { *x = ABResponse_BrokerInfo{} if protoimpl.UnsafeEnabled { - mi := &file_authd_proto_msgTypes[12] + mi := &file_authd_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -724,7 +779,7 @@ func (x *ABResponse_BrokerInfo) String() string { func (*ABResponse_BrokerInfo) ProtoMessage() {} func (x *ABResponse_BrokerInfo) ProtoReflect() protoreflect.Message { - mi := &file_authd_proto_msgTypes[12] + mi := &file_authd_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -773,7 +828,7 @@ type SBResponse_AuthenticationMode struct { func (x *SBResponse_AuthenticationMode) Reset() { *x = SBResponse_AuthenticationMode{} if protoimpl.UnsafeEnabled { - mi := &file_authd_proto_msgTypes[13] + mi := &file_authd_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -786,7 +841,7 @@ func (x *SBResponse_AuthenticationMode) String() string { func (*SBResponse_AuthenticationMode) ProtoMessage() {} func (x *SBResponse_AuthenticationMode) ProtoReflect() protoreflect.Message { - mi := &file_authd_proto_msgTypes[13] + mi := &file_authd_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -904,27 +959,34 @@ var file_authd_proto_rawDesc = []byte{ 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x32, 0xed, 0x01, 0x0a, - 0x03, 0x50, 0x41, 0x4d, 0x12, 0x2b, 0x0a, 0x10, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x0a, 0x2e, 0x41, 0x42, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x41, 0x42, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x27, 0x0a, 0x0c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x42, 0x72, 0x6f, 0x6b, 0x65, - 0x72, 0x12, 0x0a, 0x2e, 0x53, 0x42, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, - 0x53, 0x42, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x18, 0x53, 0x65, - 0x6c, 0x65, 0x63, 0x74, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x2e, 0x53, 0x41, 0x4d, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x53, 0x41, 0x4d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x27, 0x0a, 0x0c, 0x49, 0x73, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, - 0x64, 0x12, 0x0a, 0x2e, 0x49, 0x41, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, - 0x49, 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x17, 0x53, 0x65, - 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x46, 0x6f, - 0x72, 0x55, 0x73, 0x65, 0x72, 0x12, 0x0d, 0x2e, 0x53, 0x44, 0x42, 0x46, 0x55, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x06, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x29, 0x0a, 0x03, - 0x4e, 0x53, 0x53, 0x12, 0x22, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x53, 0x53, 0x12, 0x06, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0f, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x19, 0x5a, 0x17, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x2f, 0x61, 0x75, 0x74, - 0x68, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x46, 0x0a, 0x09, + 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x32, 0x91, 0x02, 0x0a, 0x03, 0x50, 0x41, 0x4d, 0x12, 0x2b, 0x0a, 0x10, + 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x73, + 0x12, 0x0a, 0x2e, 0x41, 0x42, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x41, + 0x42, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0c, 0x53, 0x65, 0x6c, + 0x65, 0x63, 0x74, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x12, 0x0a, 0x2e, 0x53, 0x42, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x53, 0x42, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x35, 0x0a, 0x18, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x41, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, + 0x2e, 0x53, 0x41, 0x4d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x53, 0x41, + 0x4d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0c, 0x49, 0x73, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x0a, 0x2e, 0x49, 0x41, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x49, 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x0a, 0x2e, 0x41, 0x53, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x06, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x30, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x72, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, + 0x72, 0x12, 0x0d, 0x2e, 0x53, 0x44, 0x42, 0x46, 0x55, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x06, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x32, 0x29, 0x0a, 0x03, 0x4e, 0x53, 0x53, 0x12, + 0x22, 0x0a, 0x07, 0x54, 0x65, 0x73, 0x74, 0x4e, 0x53, 0x53, 0x12, 0x06, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x0f, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x42, 0x19, 0x5a, 0x17, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x75, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x64, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -939,7 +1001,7 @@ func file_authd_proto_rawDescGZIP() []byte { return file_authd_proto_rawDescData } -var file_authd_proto_msgTypes = make([]protoimpl.MessageInfo, 14) +var file_authd_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_authd_proto_goTypes = []interface{}{ (*ABRequest)(nil), // 0: ABRequest (*ABResponse)(nil), // 1: ABResponse @@ -953,28 +1015,31 @@ var file_authd_proto_goTypes = []interface{}{ (*IARequest)(nil), // 9: IARequest (*IAResponse)(nil), // 10: IAResponse (*SDBFURequest)(nil), // 11: SDBFURequest - (*ABResponse_BrokerInfo)(nil), // 12: ABResponse.BrokerInfo - (*SBResponse_AuthenticationMode)(nil), // 13: SBResponse.AuthenticationMode + (*ASRequest)(nil), // 12: ASRequest + (*ABResponse_BrokerInfo)(nil), // 13: ABResponse.BrokerInfo + (*SBResponse_AuthenticationMode)(nil), // 14: SBResponse.AuthenticationMode } var file_authd_proto_depIdxs = []int32{ - 12, // 0: ABResponse.brokers_infos:type_name -> ABResponse.BrokerInfo + 13, // 0: ABResponse.brokers_infos:type_name -> ABResponse.BrokerInfo 5, // 1: SBRequest.supported_ui_layouts:type_name -> UILayout - 13, // 2: SBResponse.authentication_modes:type_name -> SBResponse.AuthenticationMode + 14, // 2: SBResponse.authentication_modes:type_name -> SBResponse.AuthenticationMode 5, // 3: SAMResponse.ui_layout_info:type_name -> UILayout 0, // 4: PAM.AvailableBrokers:input_type -> ABRequest 4, // 5: PAM.SelectBroker:input_type -> SBRequest 7, // 6: PAM.SelectAuthenticationMode:input_type -> SAMRequest 9, // 7: PAM.IsAuthorized:input_type -> IARequest - 11, // 8: PAM.SetDefaultBrokerForUser:input_type -> SDBFURequest - 2, // 9: NSS.TestNSS:input_type -> Empty - 1, // 10: PAM.AvailableBrokers:output_type -> ABResponse - 6, // 11: PAM.SelectBroker:output_type -> SBResponse - 8, // 12: PAM.SelectAuthenticationMode:output_type -> SAMResponse - 10, // 13: PAM.IsAuthorized:output_type -> IAResponse - 2, // 14: PAM.SetDefaultBrokerForUser:output_type -> Empty - 3, // 15: NSS.TestNSS:output_type -> StringResponse - 10, // [10:16] is the sub-list for method output_type - 4, // [4:10] is the sub-list for method input_type + 12, // 8: PAM.AbortSession:input_type -> ASRequest + 11, // 9: PAM.SetDefaultBrokerForUser:input_type -> SDBFURequest + 2, // 10: NSS.TestNSS:input_type -> Empty + 1, // 11: PAM.AvailableBrokers:output_type -> ABResponse + 6, // 12: PAM.SelectBroker:output_type -> SBResponse + 8, // 13: PAM.SelectAuthenticationMode:output_type -> SAMResponse + 10, // 14: PAM.IsAuthorized:output_type -> IAResponse + 2, // 15: PAM.AbortSession:output_type -> Empty + 2, // 16: PAM.SetDefaultBrokerForUser:output_type -> Empty + 3, // 17: NSS.TestNSS:output_type -> StringResponse + 11, // [11:18] is the sub-list for method output_type + 4, // [4:11] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name @@ -1131,7 +1196,7 @@ func file_authd_proto_init() { } } file_authd_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ABResponse_BrokerInfo); i { + switch v := v.(*ASRequest); i { case 0: return &v.state case 1: @@ -1143,6 +1208,18 @@ func file_authd_proto_init() { } } file_authd_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ABResponse_BrokerInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_authd_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SBResponse_AuthenticationMode); i { case 0: return &v.state @@ -1158,14 +1235,14 @@ func file_authd_proto_init() { file_authd_proto_msgTypes[0].OneofWrappers = []interface{}{} file_authd_proto_msgTypes[1].OneofWrappers = []interface{}{} file_authd_proto_msgTypes[5].OneofWrappers = []interface{}{} - file_authd_proto_msgTypes[12].OneofWrappers = []interface{}{} + file_authd_proto_msgTypes[13].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_authd_proto_rawDesc, NumEnums: 0, - NumMessages: 14, + NumMessages: 15, NumExtensions: 0, NumServices: 2, }, diff --git a/authd.proto b/authd.proto index c92cbee24..08e75deb5 100644 --- a/authd.proto +++ b/authd.proto @@ -8,6 +8,7 @@ service PAM { rpc SelectBroker(SBRequest) returns (SBResponse); rpc SelectAuthenticationMode(SAMRequest) returns (SAMResponse); rpc IsAuthorized(IARequest) returns (IAResponse); + rpc AbortSession(ASRequest) returns (Empty); rpc SetDefaultBrokerForUser(SDBFURequest) returns (Empty); } @@ -94,4 +95,9 @@ message IAResponse { message SDBFURequest { string session_id = 1; string username = 2; -} \ No newline at end of file +} + +message ASRequest { + string session_id = 1; + string username = 2; +} diff --git a/authd_grpc.pb.go b/authd_grpc.pb.go index e34177914..cc7233a5e 100644 --- a/authd_grpc.pb.go +++ b/authd_grpc.pb.go @@ -23,6 +23,7 @@ const ( PAM_SelectBroker_FullMethodName = "/PAM/SelectBroker" PAM_SelectAuthenticationMode_FullMethodName = "/PAM/SelectAuthenticationMode" PAM_IsAuthorized_FullMethodName = "/PAM/IsAuthorized" + PAM_AbortSession_FullMethodName = "/PAM/AbortSession" PAM_SetDefaultBrokerForUser_FullMethodName = "/PAM/SetDefaultBrokerForUser" ) @@ -34,6 +35,7 @@ type PAMClient interface { SelectBroker(ctx context.Context, in *SBRequest, opts ...grpc.CallOption) (*SBResponse, error) SelectAuthenticationMode(ctx context.Context, in *SAMRequest, opts ...grpc.CallOption) (*SAMResponse, error) IsAuthorized(ctx context.Context, in *IARequest, opts ...grpc.CallOption) (*IAResponse, error) + AbortSession(ctx context.Context, in *ASRequest, opts ...grpc.CallOption) (*Empty, error) SetDefaultBrokerForUser(ctx context.Context, in *SDBFURequest, opts ...grpc.CallOption) (*Empty, error) } @@ -81,6 +83,15 @@ func (c *pAMClient) IsAuthorized(ctx context.Context, in *IARequest, opts ...grp return out, nil } +func (c *pAMClient) AbortSession(ctx context.Context, in *ASRequest, opts ...grpc.CallOption) (*Empty, error) { + out := new(Empty) + err := c.cc.Invoke(ctx, PAM_AbortSession_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *pAMClient) SetDefaultBrokerForUser(ctx context.Context, in *SDBFURequest, opts ...grpc.CallOption) (*Empty, error) { out := new(Empty) err := c.cc.Invoke(ctx, PAM_SetDefaultBrokerForUser_FullMethodName, in, out, opts...) @@ -98,6 +109,7 @@ type PAMServer interface { SelectBroker(context.Context, *SBRequest) (*SBResponse, error) SelectAuthenticationMode(context.Context, *SAMRequest) (*SAMResponse, error) IsAuthorized(context.Context, *IARequest) (*IAResponse, error) + AbortSession(context.Context, *ASRequest) (*Empty, error) SetDefaultBrokerForUser(context.Context, *SDBFURequest) (*Empty, error) mustEmbedUnimplementedPAMServer() } @@ -118,6 +130,9 @@ func (UnimplementedPAMServer) SelectAuthenticationMode(context.Context, *SAMRequ func (UnimplementedPAMServer) IsAuthorized(context.Context, *IARequest) (*IAResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method IsAuthorized not implemented") } +func (UnimplementedPAMServer) AbortSession(context.Context, *ASRequest) (*Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AbortSession not implemented") +} func (UnimplementedPAMServer) SetDefaultBrokerForUser(context.Context, *SDBFURequest) (*Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method SetDefaultBrokerForUser not implemented") } @@ -206,6 +221,24 @@ func _PAM_IsAuthorized_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } +func _PAM_AbortSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ASRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(PAMServer).AbortSession(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: PAM_AbortSession_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(PAMServer).AbortSession(ctx, req.(*ASRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _PAM_SetDefaultBrokerForUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(SDBFURequest) if err := dec(in); err != nil { @@ -247,6 +280,10 @@ var PAM_ServiceDesc = grpc.ServiceDesc{ MethodName: "IsAuthorized", Handler: _PAM_IsAuthorized_Handler, }, + { + MethodName: "AbortSession", + Handler: _PAM_AbortSession_Handler, + }, { MethodName: "SetDefaultBrokerForUser", Handler: _PAM_SetDefaultBrokerForUser_Handler, diff --git a/internal/brokers/broker.go b/internal/brokers/broker.go index be2a93ce3..1a2095b24 100644 --- a/internal/brokers/broker.go +++ b/internal/brokers/broker.go @@ -22,6 +22,8 @@ type brokerer interface { GetAuthenticationModes(ctx context.Context, username, lang string, supportedUiLayouts []map[string]string) (sessionID, encryptionKey string, authenticationModes []map[string]string, err error) SelectAuthenticationMode(ctx context.Context, sessionID, authenticationModeName string) (uiLayoutInfo map[string]string, err error) IsAuthorized(ctx context.Context, sessionID, authenticationData string) (access, infoUser string, err error) + AbortSession(ctx context.Context, sessionID string) (err error) + CancelIsAuthorized(ctx context.Context, sessionID string) } type Broker struct { @@ -91,7 +93,7 @@ func (b Broker) GetAuthenticationModes(ctx context.Context, username, lang strin // SelectAuthenticationMode calls the broker corresponding method, stripping broker ID prefix from sessionID. func (b Broker) SelectAuthenticationMode(ctx context.Context, sessionID, authenticationModeName string) (uiLayoutInfo map[string]string, err error) { - sessionID = strings.TrimPrefix(sessionID, fmt.Sprintf("%s-", b.ID)) + sessionID = b.parseSessionID(sessionID) uiLayoutInfo, err = b.brokerer.SelectAuthenticationMode(ctx, sessionID, authenticationModeName) if err != nil { return nil, err @@ -102,15 +104,26 @@ func (b Broker) SelectAuthenticationMode(ctx context.Context, sessionID, authent // IsAuthorized calls the broker corresponding method, stripping broker ID prefix from sessionID. func (b Broker) IsAuthorized(ctx context.Context, sessionID, authenticationData string) (access string, userInfo string, err error) { - sessionID = strings.TrimPrefix(sessionID, fmt.Sprintf("%s-", b.ID)) + sessionID = b.parseSessionID(sessionID) - access, userInfo, err = b.brokerer.IsAuthorized(ctx, sessionID, authenticationData) - if err != nil { - return "", "", err + // monitor ctx in goroutine to call cancel + done := make(chan struct{}) + go func() { + access, userInfo, err = b.brokerer.IsAuthorized(ctx, sessionID, authenticationData) + close(done) + }() + + select { + case <-done: + if err != nil { + return "", "", err + } + case <-ctx.Done(): + b.CancelIsAuthorized(ctx, sessionID) } // Validate access authorization. - if !slices.Contains([]string{"allowed", "denied"}, access) { + if !slices.Contains(authReplies, access) { return "", "", fmt.Errorf("invalid access authorization key: %v", access) } @@ -125,6 +138,20 @@ func (b Broker) IsAuthorized(ctx context.Context, sessionID, authenticationData return access, userInfo, nil } +// AbortSession calls the broker corresponding method, stripping broker ID prefix from sessionID. +func (b Broker) AbortSession(ctx context.Context, sessionID string) (err error) { + sessionID = b.parseSessionID(sessionID) + return b.brokerer.AbortSession(ctx, sessionID) +} + +// CancelIsAuthorized calls the broker corresponding method. +// If the session does not have a pending IsAuthorized call, this is a no-op. +// +// Even though this is a public method, it should only be interacted with through IsAuthorized and ctx cancellation. +func (b Broker) CancelIsAuthorized(ctx context.Context, sessionID string) { + b.brokerer.CancelIsAuthorized(ctx, sessionID) +} + // validateUILayout validates the required fields and values for a given type. // It returns only the required and optional fields for a given type. func validateUILayout(layout map[string]string) (r map[string]string, err error) { @@ -174,3 +201,8 @@ func validateUILayout(layout map[string]string) (r map[string]string, err error) return r, nil } + +// parseSessionID strips broker ID prefix from sessionID. +func (b Broker) parseSessionID(sessionID string) string { + return strings.TrimPrefix(sessionID, fmt.Sprintf("%s-", b.ID)) +} diff --git a/internal/brokers/dbusbroker.go b/internal/brokers/dbusbroker.go index 700f14794..af64b5742 100644 --- a/internal/brokers/dbusbroker.go +++ b/internal/brokers/dbusbroker.go @@ -67,3 +67,8 @@ func (b dbusBroker) SelectAuthenticationMode(ctx context.Context, sessionID, aut func (b dbusBroker) IsAuthorized(ctx context.Context, sessionID, authenticationData string) (access, infoUser string, err error) { return "", "", nil } +func (b dbusBroker) AbortSession(ctx context.Context, sessionID string) (err error) { + return nil +} +func (b dbusBroker) CancelIsAuthorized(ctx context.Context, sessionID string) { +} diff --git a/internal/brokers/examplebroker.go b/internal/brokers/examplebroker.go index e466ff0cf..e430df085 100644 --- a/internal/brokers/examplebroker.go +++ b/internal/brokers/examplebroker.go @@ -9,6 +9,7 @@ import ( "fmt" "sort" "strings" + "sync" "time" "github.com/google/uuid" @@ -22,9 +23,18 @@ type sessionInfo struct { allModes map[string]map[string]string } +type isAuthorizedCtx struct { + ctx context.Context + cancelFunc context.CancelFunc +} + type exampleBroker struct { - currentSessions map[string]sessionInfo - userLastSelectedMode map[string]string + currentSessions map[string]sessionInfo + currentSessionsMu sync.Mutex + userLastSelectedMode map[string]string + userLastSelectedModeMu sync.Mutex + isAuthorizedCalls map[string]isAuthorizedCtx + isAuthorizedCallsMu sync.Mutex } var ( @@ -66,12 +76,16 @@ const ( func newExampleBroker(name string) (b *exampleBroker, fullName, brandIcon string, err error) { return &exampleBroker{ - currentSessions: make(map[string]sessionInfo), - userLastSelectedMode: make(map[string]string), + currentSessions: make(map[string]sessionInfo), + currentSessionsMu: sync.Mutex{}, + userLastSelectedMode: make(map[string]string), + userLastSelectedModeMu: sync.Mutex{}, + isAuthorizedCalls: make(map[string]isAuthorizedCtx), + isAuthorizedCallsMu: sync.Mutex{}, }, strings.ReplaceAll(name, "_", " "), fmt.Sprintf("/usr/share/brokers/%s.png", name), nil } -func (b exampleBroker) GetAuthenticationModes(ctx context.Context, username, lang string, supportedUiLayouts []map[string]string) (sessionID, encryptionKey string, authenticationModes []map[string]string, err error) { +func (b *exampleBroker) GetAuthenticationModes(ctx context.Context, username, lang string, supportedUiLayouts []map[string]string) (sessionID, encryptionKey string, authenticationModes []map[string]string, err error) { sessionID = uuid.New().String() //var candidatesAuthenticationModes []map[string]string @@ -213,11 +227,13 @@ func (b exampleBroker) GetAuthenticationModes(ctx context.Context, username, lan }) } + b.currentSessionsMu.Lock() b.currentSessions[sessionID] = sessionInfo{ username: username, lang: lang, allModes: allModes, } + b.currentSessionsMu.Unlock() return sessionID, brokerEncryptionKey, authenticationModes, nil } @@ -254,11 +270,14 @@ func (b *exampleBroker) SelectAuthenticationMode(ctx context.Context, sessionID, // Store selected mode sessionInfo.selectedMode = authenticationModeName + b.currentSessionsMu.Lock() b.currentSessions[sessionID] = sessionInfo + b.currentSessionsMu.Unlock() return uiLayoutInfo, nil } +// IsAuthorized evaluates the provided authenticationData and returns the authorisation level of the user. func (b *exampleBroker) IsAuthorized(ctx context.Context, sessionID, authenticationData string) (access, infoUser string, err error) { sessionInfo, inprogress := b.currentSessions[sessionID] if !inprogress { @@ -273,71 +292,99 @@ func (b *exampleBroker) IsAuthorized(ctx context.Context, sessionID, authenticat } } - authDeniedResp := "denied" + // Handles the context that will be assigned for the IsAuthorized handler + if _, exists := b.isAuthorizedCalls[sessionID]; exists { + return "", "", fmt.Errorf("IsAuthorized already running for session %q", sessionID) + } + ctx, cancel := context.WithCancel(ctx) + b.isAuthorizedCallsMu.Lock() + b.isAuthorizedCalls[sessionID] = isAuthorizedCtx{ctx, cancel} + b.isAuthorizedCallsMu.Unlock() + + // Cleans up the IsAuthorized context when the call is done. + defer func() { + b.isAuthorizedCallsMu.Lock() + delete(b.isAuthorizedCalls, sessionID) + b.isAuthorizedCallsMu.Unlock() + }() + + access, infoUser, err = b.handleIsAuthorized(b.isAuthorizedCalls[sessionID].ctx, sessionInfo, authData) + + // Store last successful authentication mode for this user in the broker. + b.userLastSelectedModeMu.Lock() + b.userLastSelectedMode[sessionInfo.username] = sessionInfo.selectedMode + b.userLastSelectedModeMu.Unlock() + + return access, infoUser, nil +} +func (b *exampleBroker) handleIsAuthorized(ctx context.Context, sessionInfo sessionInfo, authData map[string]string) (access, infoUser string, err error) { // Note that the "wait" authentication can be cancelled and switch to another mode with a challenge. // Take into account the cancellation. switch sessionInfo.selectedMode { case "password": if authData["challenge"] != "goodpass" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } case "pincode": if authData["challenge"] != "4242" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } case "totp_with_button", "totp": if authData["challenge"] != "temporary pass" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } case "phoneack1": if authData["wait"] != "true" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } // Send notification to phone1 and wait on server signal to return if OK or not select { case <-time.After(5 * time.Second): + return AuthDenied, "", nil case <-ctx.Done(): - return authDeniedResp, "", nil + return AuthCancelled, "", nil } case "phoneack2": if authData["wait"] != "true" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } // This one is failing remotely as an example select { case <-time.After(2 * time.Second): + return AuthDenied, "", nil case <-ctx.Done(): - return authDeniedResp, "", nil + return AuthCancelled, "", nil } - return authDeniedResp, "", nil case "fidodevice1": if authData["wait"] != "true" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } // simulate direct exchange with the FIDO device select { case <-time.After(5 * time.Second): + return AuthDenied, "", nil case <-ctx.Done(): - return authDeniedResp, "", nil + return AuthCancelled, "", nil } case "qrcodewithtypo": if authData["wait"] != "true" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } // Simulate connexion with remote server to check that the correct code was entered select { case <-time.After(4 * time.Second): + return AuthDenied, "", nil case <-ctx.Done(): - return authDeniedResp, "", nil + return AuthCancelled, "", nil } } @@ -347,30 +394,52 @@ func (b *exampleBroker) IsAuthorized(ctx context.Context, sessionID, authenticat if authData["challenge"] != "" { // validate challenge given manually by the user if authData["challenge"] != "aaaaa" { - return authDeniedResp, "", nil + return AuthDenied, "", nil } } else if authData["wait"] == "true" { // we are simulating clicking on the url signal received by the broker // this can be cancelled to resend a challenge select { case <-time.After(10 * time.Second): + return AuthDenied, "", nil case <-ctx.Done(): - return authDeniedResp, "", nil + return AuthCancelled, "", nil } } else { - return authDeniedResp, "", nil + return AuthDenied, "", nil } } - userInfo, exists := users[sessionInfo.username] + infoUser, exists := users[sessionInfo.username] if !exists { - return authDeniedResp, "", nil + return AuthDenied, "", nil } - // Store last successful authentication mode for this user in the broker. - b.userLastSelectedMode[sessionInfo.username] = sessionInfo.selectedMode + return AuthAllowed, infoUser, nil +} + +// AbortSession cancels the authentication flow for the specified session. +func (b *exampleBroker) AbortSession(ctx context.Context, sessionID string) error { + if _, exists := b.currentSessions[sessionID]; !exists { + return fmt.Errorf("%q is not an active session", sessionID) + } + b.currentSessionsMu.Lock() + delete(b.currentSessions, sessionID) + b.currentSessionsMu.Unlock() + return nil +} + +// CancelIsAuthorized cancels the IsAuthorized request for the specified session. +// If there is no pending IsAuthorized call for the session, this is a no-op. +func (b *exampleBroker) CancelIsAuthorized(ctx context.Context, sessionID string) { + if _, exists := b.isAuthorizedCalls[sessionID]; !exists { + return + } + b.isAuthorizedCalls[sessionID].cancelFunc() - return "allowed", userInfo, nil + b.isAuthorizedCallsMu.Lock() + delete(b.isAuthorizedCalls, sessionID) + b.isAuthorizedCallsMu.Unlock() } func mapToJson(input map[string]string) string { diff --git a/internal/brokers/localbroker.go b/internal/brokers/localbroker.go index cbdcdc269..3907ff4d2 100644 --- a/internal/brokers/localbroker.go +++ b/internal/brokers/localbroker.go @@ -18,3 +18,8 @@ func (b localBroker) SelectAuthenticationMode(ctx context.Context, sessionID, au func (b localBroker) IsAuthorized(ctx context.Context, sessionID, authenticationData string) (access, infoUser string, err error) { return "", "", errors.New("IsAuthorized should never be called on local broker") } +func (b localBroker) AbortSession(ctx context.Context, sessionID string) (err error) { + return errors.New("AbortSession should never be called on local broker") +} +func (b localBroker) CancelIsAuthorized(ctx context.Context, sessionID string) { +} diff --git a/internal/brokers/manager.go b/internal/brokers/manager.go index 059518f9c..b4911b90c 100644 --- a/internal/brokers/manager.go +++ b/internal/brokers/manager.go @@ -183,3 +183,21 @@ func (m *Manager) BrokerForSessionID(sessionID string) (broker *Broker, err erro return broker, nil } + +// AbortSession sends a abortion request to the broker associated with the sessionID and then removes the +// session -> broker mapping. +func (m *Manager) AbortSession(ctx context.Context, sessionID string) error { + b, err := m.BrokerForSessionID(sessionID) + if err != nil { + return err + } + + if err = b.AbortSession(ctx, sessionID); err != nil { + return err + } + + m.transactionsToBrokerMu.Lock() + delete(m.transactionsToBroker, sessionID) + m.transactionsToBrokerMu.Unlock() + return nil +} diff --git a/internal/brokers/responses.go b/internal/brokers/responses.go new file mode 100644 index 000000000..83dedd5cf --- /dev/null +++ b/internal/brokers/responses.go @@ -0,0 +1,13 @@ +package brokers + +const ( + // AuthAllowed is the response when the authentication is allowed. + AuthAllowed = "allowed" + // AuthDenied is the response when the authentication is denied. + AuthDenied = "denied" + // AuthCancelled is the response when the authentication is cancelled. + AuthCancelled = "cancelled" +) + +// authReplies is the list of all possible authentication replies. +var authReplies = []string{AuthAllowed, AuthDenied, AuthCancelled} diff --git a/internal/services/pam/pam.go b/internal/services/pam/pam.go index 7e621f965..25a3b1a95 100644 --- a/internal/services/pam/pam.go +++ b/internal/services/pam/pam.go @@ -190,6 +190,18 @@ func (s Service) SetDefaultBrokerForUser(ctx context.Context, req *authd.SDBFURe return &authd.Empty{}, nil } +// AbortSession aborts the authentication flow for the specified session. +func (s Service) AbortSession(ctx context.Context, req *authd.ASRequest) (empty *authd.Empty, err error) { + decorate.OnError(&err, "could not abort session") + + sessionID := req.GetSessionId() + if sessionID == "" { + return nil, errors.New("no session id given") + } + + return &authd.Empty{}, s.brokerManager.AbortSession(ctx, sessionID) +} + func uiLayoutToMap(layout *authd.UILayout) (mapLayout map[string]string, err error) { if layout.GetType() == "" { return nil, fmt.Errorf("invalid layout option: type is required, got: %v", layout) diff --git a/pam/pam.go b/pam/pam.go index 7e61a9ca9..b539c5725 100644 --- a/pam/pam.go +++ b/pam/pam.go @@ -23,6 +23,7 @@ import ( "github.com/skip2/go-qrcode" "github.com/ubuntu/authd" + "github.com/ubuntu/authd/internal/brokers" "github.com/ubuntu/authd/internal/consts" "github.com/ubuntu/authd/internal/log" "golang.org/x/sys/unix" @@ -118,7 +119,6 @@ func pam_sm_authenticate(pamh *C.pam_handle_t, flags, argc C.int, argv **C.char) var challengeRetry int for { - switch stage { case StageBrokerSelection: // Broker selection and escape @@ -183,7 +183,6 @@ func pam_sm_authenticate(pamh *C.pam_handle_t, flags, argc C.int, argv **C.char) case StageChallenge: var iaResp *authd.IAResponse var err error - // TODO: handle context cancellation to return to previous authentication method selection. switch uiLayout.Type { case "form": @@ -211,7 +210,7 @@ func pam_sm_authenticate(pamh *C.pam_handle_t, flags, argc C.int, argv **C.char) // Check if authorized switch strings.ToLower(iaResp.Access) { - case "denied": + case brokers.AuthDenied: fmt.Println("Access Denied") challengeRetry++ if challengeRetry < maxChallengeRetries { @@ -219,9 +218,13 @@ func pam_sm_authenticate(pamh *C.pam_handle_t, flags, argc C.int, argv **C.char) continue } return C.PAM_AUTH_ERR - case "allowed": + case brokers.AuthAllowed: fmt.Printf("Welcome:\n%s\n", iaResp.UserInfo) return C.PAM_SUCCESS + case brokers.AuthCancelled: + currentAuthModeName = "" + stage = StageAuthenticationMode + continue default: // Invalid response log.Errorf(context.TODO(), "Invalid Reponse: %v", iaResp.Access) @@ -403,12 +406,8 @@ func formChallenge(client authd.PAMClient, sessionID, encryptionKey string, uiLa SessionId: sessionID, AuthenticationData: `{"wait": "true"}`, }) - - // No more processing if entry has been filed. - select { - case <-waitCtx.Done(): + if iaResp.Access == brokers.AuthCancelled { return - default: } cancelTerm()