73 lines
1.3 KiB
Go
73 lines
1.3 KiB
Go
package responses
|
|
|
|
import (
|
|
"encoding/base64"
|
|
|
|
"github.com/emersion/go-imap"
|
|
"github.com/emersion/go-sasl"
|
|
)
|
|
|
|
// An AUTHENTICATE response.
|
|
type Authenticate struct {
|
|
Mechanism sasl.Client
|
|
InitialResponse []byte
|
|
Writer *imap.Writer
|
|
}
|
|
|
|
func (r *Authenticate) HandleFrom(hdlr imap.RespHandler) (err error) {
|
|
w := r.Writer
|
|
|
|
// Cancel auth if an error occurs
|
|
defer (func() {
|
|
if err != nil {
|
|
w.Write([]byte("*\r\n"))
|
|
w.Flush()
|
|
}
|
|
})()
|
|
|
|
for h := range hdlr {
|
|
cont, ok := h.Resp.(*imap.ContinuationResp)
|
|
if !ok {
|
|
h.Reject()
|
|
continue
|
|
}
|
|
h.Accept()
|
|
|
|
// Empty challenge, send initial response as stated in RFC 2222 section 5.1
|
|
if cont.Info == "" && r.InitialResponse != nil {
|
|
encoded := base64.StdEncoding.EncodeToString(r.InitialResponse)
|
|
if _, err = w.Write([]byte(encoded + "\r\n")); err != nil {
|
|
return
|
|
}
|
|
if err = w.Flush(); err != nil {
|
|
return
|
|
}
|
|
|
|
r.InitialResponse = nil
|
|
continue
|
|
}
|
|
|
|
var challenge []byte
|
|
challenge, err = base64.StdEncoding.DecodeString(cont.Info)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
var res []byte
|
|
res, err = r.Mechanism.Next(challenge)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
encoded := base64.StdEncoding.EncodeToString(res)
|
|
if _, err = w.Write([]byte(encoded + "\r\n")); err != nil {
|
|
return
|
|
}
|
|
if err = w.Flush(); err != nil {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|