Skip to content

Commit 78aebda

Browse files
committed
📚 Improve SASL::{ClientAdapter,ProtocolAdapters} rdoc
1 parent dc18728 commit 78aebda

File tree

2 files changed

+77
-18
lines changed

2 files changed

+77
-18
lines changed

lib/net/imap/sasl/client_adapter.rb

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,26 @@ module SASL
88
#
99
# TODO: use with more clients, to verify the API can accommodate them.
1010
#
11-
# An abstract base class for implementing a SASL authentication exchange.
12-
# Different clients will each have their own adapter subclass, overridden
13-
# to match their needs.
11+
# Represents the client to a SASL::AuthenticationExchange. By default,
12+
# most methods simply delegate to #client. Clients should subclass
13+
# SASL::ClientAdapter and override methods as needed to match the
14+
# semantics of this API to their API.
1415
#
15-
# Although the default implementations _may_ be sufficient, subclasses
16-
# will probably need to override some methods. Additionally, subclasses
17-
# may need to include a protocol adapter mixin, if the default
16+
# Subclasses should also include a protocol adapter mixin when the default
1817
# ProtocolAdapters::Generic isn't sufficient.
18+
#
19+
# === Protocol Requirements
20+
#
21+
# {RFC4422 §4}[https://www.rfc-editor.org/rfc/rfc4422.html#section-4]
22+
# lists requirements for protocol specifications to offer SASL. Where
23+
# possible, ClientAdapter delegates the handling of these requirements to
24+
# SASL::ProtocolAdapters.
1925
class ClientAdapter
2026
include ProtocolAdapters::Generic
2127

2228
# The client that handles communication with the protocol server.
29+
#
30+
# Most ClientAdapter methods are simply delegated to #client by default.
2331
attr_reader :client
2432

2533
# +command_proc+ can used to avoid exposing private methods on #client.
@@ -52,13 +60,9 @@ def initialize(client, &command_proc)
5260
def authenticate(...) AuthenticationExchange.authenticate(self, ...) end
5361

5462
# Do the protocol, server, and client all support an initial response?
55-
#
56-
# By default, this simply delegates to <tt>client.sasl_ir_capable?</tt>.
5763
def sasl_ir_capable?; client.sasl_ir_capable? end
5864

59-
# Does the server advertise support for the mechanism?
60-
#
61-
# By default, this simply delegates to <tt>client.auth_capable?</tt>.
65+
# Does the server advertise support for the +mechanism+?
6266
def auth_capable?(mechanism); client.auth_capable?(mechanism) end
6367

6468
# Calls command_proc with +command_name+ (see
@@ -89,15 +93,12 @@ def port; client.port end
8993
# Exceptions in this array won't drop the connection.
9094
def response_errors; [] end
9195

92-
# Drop the connection gracefully.
93-
#
94-
# By default, this simply delegates to <tt>client.drop_connection</tt>.
96+
# Drop the connection gracefully, sending a "LOGOUT" command as needed.
9597
def drop_connection; client.drop_connection end
9698

97-
# Drop the connection abruptly.
98-
#
99-
# By default, this simply delegates to <tt>client.drop_connection!</tt>.
99+
# Drop the connection abruptly, closing the socket without logging out.
100100
def drop_connection!; client.drop_connection! end
101+
101102
end
102103
end
103104
end

lib/net/imap/sasl/protocol_adapters.rb

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,72 @@ module Net
44
class IMAP
55
module SASL
66

7+
# SASL::ProtocolAdapters modules are meant to be used as mixins for
8+
# SASL::ClientAdapter and its subclasses. Where the client adapter must
9+
# be customized for each client library, the protocol adapter mixin
10+
# handles \SASL requirements that are part of the protocol specification,
11+
# but not specific to any particular client library. In particular, see
12+
# {RFC4422 §4}[https://www.rfc-editor.org/rfc/rfc4422.html#section-4]
13+
#
14+
# === Interface
15+
#
16+
# >>>
17+
# NOTE: This API is experimental, and may change.
18+
#
19+
# - {#command_name}[rdoc-ref:Generic#command_name] -- The name of the
20+
# command used to to initiate an authentication exchange.
21+
# - {#service}[rdoc-ref:Generic#service] -- The GSSAPI service name.
22+
# - {#encode_ir}[rdoc-ref:Generic#encode_ir]--Encodes an initial response.
23+
# - {#decode}[rdoc-ref:Generic#decode] -- Decodes a server challenge.
24+
# - {#encode}[rdoc-ref:Generic#encode] -- Encodes a client response.
25+
# - {#cancel_response}[rdoc-ref:Generic#cancel_response] -- The encoded
26+
# client response used to cancel an authentication exchange.
27+
#
28+
# Other protocol requirements of the \SASL authentication exchange are
29+
# handled by SASL::ClientAdapter.
30+
#
31+
# === Included protocol adapters
32+
#
33+
# - Generic -- a basic implementation of all of the methods listed above.
34+
# - IMAP -- An adapter for the IMAP4 protocol.
35+
# - SMTP -- An adapter for the \SMTP protocol with the +AUTH+ capability.
36+
# - POP -- An adapter for the POP3 protocol with the +SASL+ capability.
737
module ProtocolAdapters
8-
# This API is experimental, and may change.
38+
# See SASL::ProtocolAdapters@Interface.
939
module Generic
40+
# The name of the protocol command used to initiate a \SASL
41+
# authentication exchange.
42+
#
43+
# The generic implementation returns <tt>"AUTHENTICATE"</tt>.
1044
def command_name; "AUTHENTICATE" end
45+
46+
# A service name from the {GSSAPI/Kerberos/SASL Service Names
47+
# registry}[https://www.iana.org/assignments/gssapi-service-names/gssapi-service-names.xhtml].
48+
#
49+
# The generic implementation returns <tt>"host"</tt>, which is the
50+
# generic GSSAPI host-based service name.
1151
def service; "host" end
52+
53+
# Encodes an initial response string.
54+
#
55+
# The generic implementation returns the result of #encode, or returns
56+
# <tt>"="</tt> when +string+ is empty.
1257
def encode_ir(string) string.empty? ? "=" : encode(string) end
58+
59+
# Encodes a client response string.
60+
#
61+
# The generic implementation returns the Base64 encoding of +string+.
1362
def encode(string) [string].pack("m0") end
63+
64+
# Decodes a server challenge string.
65+
#
66+
# The generic implementation returns the Base64 decoding of +string+.
1467
def decode(string) string.unpack1("m0") end
68+
69+
# Returns the message used by the client to abort an authentication
70+
# exchange.
71+
#
72+
# The generic implementation returns <tt>"*"</tt>.
1573
def cancel_response; "*" end
1674
end
1775

0 commit comments

Comments
 (0)