Couchbase use SASL (Simple Authentication and Security Layer) as the mechanism to authenticate to the data nodes in the system. Couchbase does not utilize the system authentication database (at the time of writing), but utilizes a library called cbsasl which provides an API that mostly identical with the SASL library provided on MacOS and Solaris. The biggest difference is that the internal one prefix all methods and constants with cb.
This document is not intended to give you all the information in order to fully understand SASL, but contains information on the protocol framing for the SASL authentication within the memcached binary protocol.
The command LIST_MECH
is used to determine which SASL mechanisms the
server supplies. A "well written client" should run this method in order
to determine the supported mechanisms rather than bypassing this step and
use a hardcoded mechanism (that would not allow the client to use more
secure mechanisms when they're added / enabled on the server).
- MUST NOT have extras.
- MUST NOT have key.
- MUST NOT have value.
The following is a packet dump of the LIST_MECH request.
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x80 | 0x20 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
Total 24 bytes
Field (offset) (value)
Magic (0) : 0x80
Opcode (1) : 0x20
Key length (2,3) : 0x0000
Extra length (4) : 0x00
Data type (5) : 0x00
Vbucket (6,7) : 0x0000
Total body (8-11) : 0x00000000
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000
Response (for success):
- MUST NOT have extras.
- MUST NOT have key.
- MAY have value.
The value is a textual string separated by space containing the available
mechanisms. The client should use this string to determine the mechanism
to use (this is the string you would feed to cbsasl_client_start
in C,
or createClient
in Java).
The following is a packet dump of the response packet sent from a server
supporting SCRAM-SHA1
, CRAM-MD5
and PLAIN
:
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x81 | 0x20 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x19 |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
24| 0x53 ('S') | 0x43 ('C') | 0x52 ('R') | 0x41 ('A') |
+---------------+---------------+---------------+---------------+
28| 0x4d ('M') | 0x2d ('-') | 0x53 ('S') | 0x48 ('H') |
+---------------+---------------+---------------+---------------+
32| 0x41 ('A') | 0x31 ('1') | 0x20 (' ') | 0x43 ('C') |
+---------------+---------------+---------------+---------------+
36| 0x52 ('R') | 0x41 ('A') | 0x4d ('M') | 0x2d ('-') |
+---------------+---------------+---------------+---------------+
40| 0x4d ('M') | 0x44 ('D') | 0x35 ('5') | 0x20 (' ') |
+---------------+---------------+---------------+---------------+
44| 0x50 ('P') | 0x4c ('L') | 0x41 ('A') | 0x49 ('I') |
+---------------+---------------+---------------+---------------+
48| 0x4e ('N') |
+---------------+
Total 49 bytes (24 bytes header and 25 value)
Field (offset) (value)
Magic (0) : 0x81
Opcode (1) : 0x20
Key length (2,3) : 0x0000
Extra length (4) : 0x00
Data type (5) : 0x00
Status (6,7) : 0x0000
Total body (8-11) : 0x00000019
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000
Note: CRAM-MD5 is no longer supported by Couchbase Server
The SASL_AUTH request initiates the SASL authentication, and contains the authentication mechanism to use and possibly some user data (depending on the mechanism in use).
- MUST NOT have extras.
- MUST have key.
- MAY have value.
The key field SHALL contain the mechanism to use. The challenge generated from the sasl client should be passed in the value.
See the example section below for various examples of the SASL_AUTH
packet.
- MUST NOT have extras.
- MUST NOT have key.
- MAY have value.
The value contains the response returned from the sasl server and should be fed to the sasl client to generate a new challenge.
If the status field contains AUTH_CONTINUE
(0x21
) the server expects the
client to continue the authentication by sending another challenge through
a SASL_STEP
packet.
The encoding for the SASL_STEP
command and response is identical to
SASL_AUTH
(except for the opcode of course). The only reason for it
to exist is for the server to determine if the packet is a continuation
of an authentication or the start of a new one).
The following sections provides a few examples showing the variants when using the different authentication schemes.
When using PLAIN authentication the username and password is sent in clear text in the first message, and no SASL_STEP messages is used.
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x80 | 0x21 | 0x00 | 0x05 |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x11 |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
24| 0x50 ('P') | 0x4c ('L') | 0x41 ('A') | 0x49 ('I') |
+---------------+---------------+---------------+---------------+
28| 0x4e ('N') | 0x00 | 0x75 ('u') | 0x73 ('s') |
+---------------+---------------+---------------+---------------+
32| 0x65 ('e') | 0x72 ('r') | 0x00 | 0x70 ('p') |
+---------------+---------------+---------------+---------------+
36| 0x65 ('e') | 0x6e ('n') | 0x63 ('c') | 0x69 ('i') |
+---------------+---------------+---------------+---------------+
40| 0x6c ('l') |
+---------------+
Total 41 bytes (24 bytes header, 5 bytes key and 12 value)
Field (offset) (value)
Magic (0) : 0x80
Opcode (1) : 0x21
Key length (2,3) : 0x0005
Extra length (4) : 0x00
Data type (5) : 0x00
Vbucket (6,7) : 0x0000
Total body (8-11) : 0x00000011
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x81 | 0x21 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
Total 24 bytes
Field (offset) (value)
Magic (0) : 0x81
Opcode (1) : 0x21
Key length (2,3) : 0x0000
Extra length (4) : 0x00
Data type (5) : 0x00
Status (6,7) : 0x0000
Total body (8-11) : 0x00000000
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000
When using SCRAM-SHA1 the client initiates the authentication by sending the username to authenticate as with its nonce, then the server replies with more information the client should use to calculate the client proof that it sends back to the server. The server calculates the client proof and verifies that it is "correct" and calculates the server proof which it returns to the client. The client may calculate the server proof to verify that the reply was received from the correct server.
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x80 | 0x21 | 0x00 | 0x0a |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x26 |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
24| 0x53 ('S') | 0x43 ('C') | 0x52 ('R') | 0x41 ('A') |
+---------------+---------------+---------------+---------------+
28| 0x4d ('M') | 0x2d ('-') | 0x53 ('S') | 0x48 ('H') |
+---------------+---------------+---------------+---------------+
32| 0x41 ('A') | 0x31 ('1') | 0x6e ('n') | 0x2c (',') |
+---------------+---------------+---------------+---------------+
36| 0x2c (',') | 0x6e ('n') | 0x3d ('=') | 0x75 ('u') |
+---------------+---------------+---------------+---------------+
40| 0x73 ('s') | 0x65 ('e') | 0x72 ('r') | 0x2c (',') |
+---------------+---------------+---------------+---------------+
44| 0x72 ('r') | 0x3d ('=') | 0x64 ('d') | 0x34 ('4') |
+---------------+---------------+---------------+---------------+
48| 0x30 ('0') | 0x61 ('a') | 0x30 ('0') | 0x32 ('2') |
+---------------+---------------+---------------+---------------+
52| 0x65 ('e') | 0x33 ('3') | 0x34 ('4') | 0x38 ('8') |
+---------------+---------------+---------------+---------------+
56| 0x30 ('0') | 0x34 ('4') | 0x30 ('0') | 0x35 ('5') |
+---------------+---------------+---------------+---------------+
60| 0x39 ('9') | 0x30 ('0') |
+---------------+---------------+
Total 62 bytes (24 bytes header, 10 bytes key and 28 value)
Field (offset) (value)
Magic (0) : 0x80
Opcode (1) : 0x21
Key length (2,3) : 0x000a
Extra length (4) : 0x00
Data type (5) : 0x00
Vbucket (6,7) : 0x0000
Total body (8-11) : 0x00000026
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x81 | 0x21 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x21 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x46 |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
24| 0x72 ('r') | 0x3d ('=') | 0x64 ('d') | 0x34 ('4') |
+---------------+---------------+---------------+---------------+
28| 0x30 ('0') | 0x61 ('a') | 0x30 ('0') | 0x32 ('2') |
+---------------+---------------+---------------+---------------+
32| 0x65 ('e') | 0x33 ('3') | 0x34 ('4') | 0x38 ('8') |
+---------------+---------------+---------------+---------------+
36| 0x30 ('0') | 0x34 ('4') | 0x30 ('0') | 0x35 ('5') |
+---------------+---------------+---------------+---------------+
40| 0x39 ('9') | 0x30 ('0') | 0x65 ('e') | 0x63 ('c') |
+---------------+---------------+---------------+---------------+
44| 0x38 ('8') | 0x61 ('a') | 0x63 ('c') | 0x37 ('7') |
+---------------+---------------+---------------+---------------+
48| 0x38 ('8') | 0x34 ('4') | 0x64 ('d') | 0x34 ('4') |
+---------------+---------------+---------------+---------------+
52| 0x36 ('6') | 0x66 ('f') | 0x61 ('a') | 0x66 ('f') |
+---------------+---------------+---------------+---------------+
56| 0x39 ('9') | 0x64 ('d') | 0x2c (',') | 0x73 ('s') |
+---------------+---------------+---------------+---------------+
60| 0x3d ('=') | 0x66 ('f') | 0x77 ('w') | 0x33 ('3') |
+---------------+---------------+---------------+---------------+
64| 0x47 ('G') | 0x52 ('R') | 0x51 ('Q') | 0x59 ('Y') |
+---------------+---------------+---------------+---------------+
68| 0x6c ('l') | 0x46 ('F') | 0x79 ('y') | 0x36 ('6') |
+---------------+---------------+---------------+---------------+
72| 0x51 ('Q') | 0x45 ('E') | 0x71 ('q') | 0x54 ('T') |
+---------------+---------------+---------------+---------------+
76| 0x35 ('5') | 0x79 ('y') | 0x37 ('7') | 0x4f ('O') |
+---------------+---------------+---------------+---------------+
80| 0x66 ('f') | 0x34 ('4') | 0x58 ('X') | 0x62 ('b') |
+---------------+---------------+---------------+---------------+
84| 0x47 ('G') | 0x61 ('a') | 0x47 ('G') | 0x67 ('g') |
+---------------+---------------+---------------+---------------+
88| 0x3d ('=') | 0x2c (',') | 0x69 ('i') | 0x3d ('=') |
+---------------+---------------+---------------+---------------+
92| 0x31 ('1') | 0x30 ('0') |
+---------------+---------------+
Total 94 bytes (24 bytes header and 70 value)
Field (offset) (value)
Magic (0) : 0x81
Opcode (1) : 0x21
Key length (2,3) : 0x0000
Extra length (4) : 0x00
Data type (5) : 0x00
Status (6,7) : 0x0021
Total body (8-11) : 0x00000046
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x80 | 0x22 | 0x00 | 0x0a |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x52 |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
24| 0x53 ('S') | 0x43 ('C') | 0x52 ('R') | 0x41 ('A') |
+---------------+---------------+---------------+---------------+
28| 0x4d ('M') | 0x2d ('-') | 0x53 ('S') | 0x48 ('H') |
+---------------+---------------+---------------+---------------+
32| 0x41 ('A') | 0x31 ('1') | 0x63 ('c') | 0x3d ('=') |
+---------------+---------------+---------------+---------------+
36| 0x62 ('b') | 0x69 ('i') | 0x77 ('w') | 0x73 ('s') |
+---------------+---------------+---------------+---------------+
40| 0x2c (',') | 0x72 ('r') | 0x3d ('=') | 0x64 ('d') |
+---------------+---------------+---------------+---------------+
44| 0x34 ('4') | 0x30 ('0') | 0x61 ('a') | 0x30 ('0') |
+---------------+---------------+---------------+---------------+
48| 0x32 ('2') | 0x65 ('e') | 0x33 ('3') | 0x34 ('4') |
+---------------+---------------+---------------+---------------+
52| 0x38 ('8') | 0x30 ('0') | 0x34 ('4') | 0x30 ('0') |
+---------------+---------------+---------------+---------------+
56| 0x35 ('5') | 0x39 ('9') | 0x30 ('0') | 0x65 ('e') |
+---------------+---------------+---------------+---------------+
60| 0x63 ('c') | 0x38 ('8') | 0x61 ('a') | 0x63 ('c') |
+---------------+---------------+---------------+---------------+
64| 0x37 ('7') | 0x38 ('8') | 0x34 ('4') | 0x64 ('d') |
+---------------+---------------+---------------+---------------+
68| 0x34 ('4') | 0x36 ('6') | 0x66 ('f') | 0x61 ('a') |
+---------------+---------------+---------------+---------------+
72| 0x66 ('f') | 0x39 ('9') | 0x64 ('d') | 0x2c (',') |
+---------------+---------------+---------------+---------------+
76| 0x70 ('p') | 0x3d ('=') | 0x63 ('c') | 0x6f ('o') |
+---------------+---------------+---------------+---------------+
80| 0x36 ('6') | 0x6b ('k') | 0x57 ('W') | 0x77 ('w') |
+---------------+---------------+---------------+---------------+
84| 0x4e ('N') | 0x68 ('h') | 0x70 ('p') | 0x56 ('V') |
+---------------+---------------+---------------+---------------+
88| 0x59 ('Y') | 0x75 ('u') | 0x75 ('u') | 0x46 ('F') |
+---------------+---------------+---------------+---------------+
92| 0x48 ('H') | 0x57 ('W') | 0x51 ('Q') | 0x76 ('v') |
+---------------+---------------+---------------+---------------+
96| 0x35 ('5') | 0x56 ('V') | 0x56 ('V') | 0x63 ('c') |
+---------------+---------------+---------------+---------------+
100| 0x57 ('W') | 0x72 ('r') | 0x50 ('P') | 0x4a ('J') |
+---------------+---------------+---------------+---------------+
104| 0x4d ('M') | 0x3d ('=') |
+---------------+---------------+
Total 106 bytes (24 bytes header, 10 bytes key and 72 value)
Field (offset) (value)
Magic (0) : 0x80
Opcode (1) : 0x22
Key length (2,3) : 0x000a
Extra length (4) : 0x00
Data type (5) : 0x00
Vbucket (6,7) : 0x0000
Total body (8-11) : 0x00000052
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000
Byte/ 0 | 1 | 2 | 3 |
/ | | | |
|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
+---------------+---------------+---------------+---------------+
0| 0x81 | 0x22 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
4| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
8| 0x00 | 0x00 | 0x00 | 0x1e |
+---------------+---------------+---------------+---------------+
12| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
16| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
20| 0x00 | 0x00 | 0x00 | 0x00 |
+---------------+---------------+---------------+---------------+
24| 0x76 ('v') | 0x3d ('=') | 0x69 ('i') | 0x6e ('n') |
+---------------+---------------+---------------+---------------+
28| 0x5a ('Z') | 0x4a ('J') | 0x32 ('2') | 0x64 ('d') |
+---------------+---------------+---------------+---------------+
32| 0x30 ('0') | 0x4d ('M') | 0x73 ('s') | 0x34 ('4') |
+---------------+---------------+---------------+---------------+
36| 0x64 ('d') | 0x6e ('n') | 0x45 ('E') | 0x4e ('N') |
+---------------+---------------+---------------+---------------+
40| 0x6e ('n') | 0x48 ('H') | 0x77 ('w') | 0x50 ('P') |
+---------------+---------------+---------------+---------------+
44| 0x61 ('a') | 0x71 ('q') | 0x56 ('V') | 0x66 ('f') |
+---------------+---------------+---------------+---------------+
48| 0x4e ('N') | 0x6e ('n') | 0x37 ('7') | 0x44 ('D') |
+---------------+---------------+---------------+---------------+
52| 0x59 ('Y') | 0x3d ('=') |
+---------------+---------------+
Total 54 bytes (24 bytes header and 30 value)
Field (offset) (value)
Magic (0) : 0x81
Opcode (1) : 0x22
Key length (2,3) : 0x0000
Extra length (4) : 0x00
Data type (5) : 0x00
Status (6,7) : 0x0000
Total body (8-11) : 0x0000001e
Opaque (12-15): 0x00000000
CAS (16-23): 0x00000000