mirror of
https://gitlab.com/ric_harvey/MailHog.git
synced 2024-11-30 09:44:03 +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
|
state State
|
||||||
message *data.SMTPMessage
|
message *data.SMTPMessage
|
||||||
|
|
||||||
|
lastCommand *Command
|
||||||
|
|
||||||
Hostname string
|
Hostname string
|
||||||
Ident 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
|
// Command applies an SMTP verb and arguments to the state machine
|
||||||
func (proto *Protocol) Command(command *Command) (reply *Reply) {
|
func (proto *Protocol) Command(command *Command) (reply *Reply) {
|
||||||
|
defer func() {
|
||||||
|
proto.lastCommand = command
|
||||||
|
}()
|
||||||
switch {
|
switch {
|
||||||
case "RSET" == command.verb:
|
case "RSET" == command.verb:
|
||||||
proto.logf("Got RSET command, switching to MAIL state")
|
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.logf("Got LOGIN authentication response: '%s', switching to MAIL state", command.args)
|
||||||
proto.state = MAIL
|
proto.state = MAIL
|
||||||
if proto.ValidateAuthenticationHandler != nil {
|
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
|
return reply
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -802,3 +802,108 @@ func TestAuthPlain(t *testing.T) {
|
||||||
So(handlerCalled, ShouldBeTrue)
|
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