commit 0099823

delthas  ·  2022-04-20 17:16:52 +0000 UTC
parent af89d12
Send SASL PLAIN authentication on connect

This saves one round trip by letting us send BOUNCER LISTNETWORKS right
away and speeds up startup time.
1 files changed,  +29, -7
+29, -7
 1@@ -16,6 +16,7 @@ import (
 2 )
 3 
 4 type SASLClient interface {
 5+	Early() bool
 6 	Handshake() (mech string)
 7 	Respond(challenge string) (res string, err error)
 8 }
 9@@ -25,6 +26,10 @@ type SASLPlain struct {
10 	Password string
11 }
12 
13+func (auth *SASLPlain) Early() bool {
14+	return true
15+}
16+
17 func (auth *SASLPlain) Handshake() (mech string) {
18 	mech = "PLAIN"
19 	return
20@@ -175,6 +180,17 @@ func NewSession(out chan<- Message, params SessionParams) *Session {
21 	}
22 	s.out <- NewMessage("NICK", s.nick)
23 	s.out <- NewMessage("USER", s.user, "0", "*", s.real)
24+	if s.auth != nil && s.auth.Early() {
25+		h := s.auth.Handshake()
26+		s.out <- NewMessage("AUTHENTICATE", h)
27+		res, err := s.auth.Respond("+")
28+		if err != nil {
29+			s.out <- NewMessage("AUTHENTICATE", "*")
30+		} else {
31+			s.out <- NewMessage("AUTHENTICATE", res)
32+		}
33+		s.auth = nil
34+	}
35 
36 	if s.auth == nil {
37 		s.endRegistration()
38@@ -574,7 +590,9 @@ func (s *Session) handleUnregistered(msg Message) (Event, error) {
39 
40 		s.out <- NewMessage("NICK", nick+"_")
41 	case rplSaslsuccess:
42-		s.endRegistration()
43+		if s.auth != nil {
44+			s.endRegistration()
45+		}
46 	default:
47 		return s.handleRegistered(msg)
48 	}
49@@ -647,7 +665,9 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
50 		s.user = prefix.User
51 		s.host = prefix.Host
52 	case errNicklocked, errSaslfail, errSasltoolong, errSaslaborted, errSaslalready, rplSaslmechs:
53-		s.endRegistration()
54+		if s.auth != nil {
55+			s.endRegistration()
56+		}
57 		return ErrorEvent{
58 			Severity: SeverityFail,
59 			Code:     msg.Command,
60@@ -1350,6 +1370,10 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er
61 			if len(msg.Params) < 2 {
62 				return nil, msg.errNotEnoughParams(2)
63 			}
64+			if msg.Command == errUnknowncommand && msg.Params[1] == "BOUNCER" {
65+				// ignore any error in response to unconditional BOUNCER LISTNETWORKS
66+				return nil, nil
67+			}
68 			return ErrorEvent{
69 				Severity: ReplySeverity(msg.Command),
70 				Code:     msg.Command,
71@@ -1488,13 +1512,11 @@ func (s *Session) endRegistration() {
72 	if s.registered {
73 		return
74 	}
75-	if _, ok := s.enabledCaps["soju.im/bouncer-networks"]; !ok {
76-		s.out <- NewMessage("CAP", "END")
77-	} else if s.netID == "" {
78+	if s.netID != "" {
79+		s.out <- NewMessage("BOUNCER", "BIND", s.netID)
80 		s.out <- NewMessage("CAP", "END")
81-		s.out <- NewMessage("BOUNCER", "LISTNETWORKS")
82 	} else {
83-		s.out <- NewMessage("BOUNCER", "BIND", s.netID)
84 		s.out <- NewMessage("CAP", "END")
85+		s.out <- NewMessage("BOUNCER", "LISTNETWORKS")
86 	}
87 }