mirror of
https://gitlab.com/ric_harvey/MailHog.git
synced 2024-11-27 08:14:04 +00:00
Add AUTH LOGIN tests
This commit is contained in:
parent
8d1a721bac
commit
e2226baeca
2 changed files with 111 additions and 1 deletions
|
@ -36,6 +36,8 @@ type Protocol struct {
|
|||
state State
|
||||
message *data.SMTPMessage
|
||||
|
||||
lastCommand *Command
|
||||
|
||||
Hostname string
|
||||
Ident string
|
||||
|
||||
|
@ -159,6 +161,9 @@ func (proto *Protocol) ProcessCommand(line string) (reply *Reply) {
|
|||
|
||||
// Command applies an SMTP verb and arguments to the state machine
|
||||
func (proto *Protocol) Command(command *Command) (reply *Reply) {
|
||||
defer func() {
|
||||
proto.lastCommand = command
|
||||
}()
|
||||
switch {
|
||||
case "RSET" == command.verb:
|
||||
proto.logf("Got RSET command, switching to MAIL state")
|
||||
|
@ -199,7 +204,7 @@ func (proto *Protocol) Command(command *Command) (reply *Reply) {
|
|||
proto.logf("Got LOGIN authentication response: '%s', switching to MAIL state", command.args)
|
||||
proto.state = MAIL
|
||||
if proto.ValidateAuthenticationHandler != nil {
|
||||
if reply, ok := proto.ValidateAuthenticationHandler("LOGIN", command.orig); !ok {
|
||||
if reply, ok := proto.ValidateAuthenticationHandler("LOGIN", proto.lastCommand.orig, command.orig); !ok {
|
||||
return reply
|
||||
}
|
||||
}
|
||||
|
|
|
@ -802,3 +802,108 @@ func TestAuthPlain(t *testing.T) {
|
|||
So(handlerCalled, ShouldBeTrue)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthCramMD5(t *testing.T) {
|
||||
Convey("Two part AUTH CRAM-MD5 should call ValidateAuthenticationHandler", t, func() {
|
||||
proto := NewProtocol()
|
||||
handlerCalled := false
|
||||
proto.ValidateAuthenticationHandler = func(mechanism string, args ...string) (*Reply, bool) {
|
||||
handlerCalled = true
|
||||
So(mechanism, ShouldEqual, "CRAM-MD5")
|
||||
So(len(args), ShouldEqual, 1)
|
||||
So(args[0], ShouldEqual, "oink!")
|
||||
return nil, true
|
||||
}
|
||||
proto.Start()
|
||||
proto.Command(ParseCommand("EHLO localhost"))
|
||||
reply := proto.Command(ParseCommand("AUTH CRAM-MD5"))
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 334)
|
||||
So(reply.Lines(), ShouldResemble, []string{"334 PDQxOTI5NDIzNDEuMTI4Mjg0NzJAc291cmNlZm91ci5hbmRyZXcuY211LmVkdT4=\n"})
|
||||
|
||||
_, reply = proto.Parse("oink!\n")
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 235)
|
||||
So(reply.Lines(), ShouldResemble, []string{"235 Authentication successful\n"})
|
||||
So(handlerCalled, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Two part AUTH CRAM-MD5 ValidateAuthenticationHandler errors should be returned", t, func() {
|
||||
proto := NewProtocol()
|
||||
handlerCalled := false
|
||||
proto.ValidateAuthenticationHandler = func(mechanism string, args ...string) (*Reply, bool) {
|
||||
handlerCalled = true
|
||||
return ReplyError(errors.New("OINK :(")), false
|
||||
}
|
||||
proto.Start()
|
||||
proto.Command(ParseCommand("EHLO localhost"))
|
||||
reply := proto.Command(ParseCommand("AUTH CRAM-MD5"))
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 334)
|
||||
So(reply.Lines(), ShouldResemble, []string{"334 PDQxOTI5NDIzNDEuMTI4Mjg0NzJAc291cmNlZm91ci5hbmRyZXcuY211LmVkdT4=\n"})
|
||||
|
||||
_, reply = proto.Parse("oink!\n")
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 550)
|
||||
So(reply.Lines(), ShouldResemble, []string{"550 OINK :(\n"})
|
||||
So(handlerCalled, ShouldBeTrue)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthLogin(t *testing.T) {
|
||||
Convey("AUTH LOGIN should call ValidateAuthenticationHandler", t, func() {
|
||||
proto := NewProtocol()
|
||||
handlerCalled := false
|
||||
proto.ValidateAuthenticationHandler = func(mechanism string, args ...string) (*Reply, bool) {
|
||||
handlerCalled = true
|
||||
So(mechanism, ShouldEqual, "LOGIN")
|
||||
So(len(args), ShouldEqual, 2)
|
||||
So(args[0], ShouldEqual, "username!")
|
||||
So(args[1], ShouldEqual, "password!")
|
||||
return nil, true
|
||||
}
|
||||
proto.Start()
|
||||
proto.Command(ParseCommand("EHLO localhost"))
|
||||
reply := proto.Command(ParseCommand("AUTH LOGIN"))
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 334)
|
||||
So(reply.Lines(), ShouldResemble, []string{"334 VXNlcm5hbWU6\n"})
|
||||
|
||||
_, reply = proto.Parse("username!\n")
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 334)
|
||||
So(reply.Lines(), ShouldResemble, []string{"334 UGFzc3dvcmQ6\n"})
|
||||
|
||||
_, reply = proto.Parse("password!\n")
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 235)
|
||||
So(reply.Lines(), ShouldResemble, []string{"235 Authentication successful\n"})
|
||||
So(handlerCalled, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("AUTH LOGIN ValidateAuthenticationHandler errors should be returned", t, func() {
|
||||
proto := NewProtocol()
|
||||
handlerCalled := false
|
||||
proto.ValidateAuthenticationHandler = func(mechanism string, args ...string) (*Reply, bool) {
|
||||
handlerCalled = true
|
||||
return ReplyError(errors.New("OINK :(")), false
|
||||
}
|
||||
proto.Start()
|
||||
proto.Command(ParseCommand("EHLO localhost"))
|
||||
reply := proto.Command(ParseCommand("AUTH LOGIN"))
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 334)
|
||||
So(reply.Lines(), ShouldResemble, []string{"334 VXNlcm5hbWU6\n"})
|
||||
|
||||
_, reply = proto.Parse("username!\n")
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 334)
|
||||
So(reply.Lines(), ShouldResemble, []string{"334 UGFzc3dvcmQ6\n"})
|
||||
|
||||
_, reply = proto.Parse("password!\n")
|
||||
So(reply, ShouldNotBeNil)
|
||||
So(reply.Status, ShouldEqual, 550)
|
||||
So(reply.Lines(), ShouldResemble, []string{"550 OINK :(\n"})
|
||||
So(handlerCalled, ShouldBeTrue)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue