libcouchbase 1.2.8 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -4
- data/README.md +16 -8
- data/ext/libcouchbase/CMakeLists.txt +34 -32
- data/ext/libcouchbase/RELEASE_NOTES.markdown +277 -6
- data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +14 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +2 -0
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +2 -1
- data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -0
- data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +8 -1
- data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
- data/ext/libcouchbase/cmake/config-cmake.h.in +14 -0
- data/ext/libcouchbase/cmake/configure +8 -26
- data/ext/libcouchbase/cmake/defs.mk.in +2 -2
- data/ext/libcouchbase/cmake/libcouchbase.stp.in +829 -0
- data/ext/libcouchbase/cmake/source_files.cmake +11 -2
- data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +18 -2
- data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +44 -2
- data/ext/libcouchbase/contrib/cbsasl/src/client.c +285 -73
- data/ext/libcouchbase/contrib/cbsasl/src/common.c +4 -0
- data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.c +500 -0
- data/ext/libcouchbase/contrib/cbsasl/src/scram-sha/scram_utils.h +99 -0
- data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +1 -1
- data/ext/libcouchbase/contrib/cliopts/cliopts.h +14 -1
- data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +2 -3
- data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +4 -0
- data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +7 -5
- data/ext/libcouchbase/contrib/snappy/snappy.cc +7 -2
- data/ext/libcouchbase/example/crypto/.gitignore +2 -0
- data/ext/libcouchbase/example/crypto/Makefile +13 -0
- data/ext/libcouchbase/example/crypto/common_provider.c +24 -0
- data/ext/libcouchbase/example/crypto/common_provider.h +31 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_decrypt.c +139 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_encrypt.c +147 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.c +281 -0
- data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.h +29 -0
- data/ext/libcouchbase/example/tracing/.gitignore +2 -0
- data/ext/libcouchbase/example/tracing/Makefile +8 -0
- data/ext/libcouchbase/example/tracing/cJSON.c +1 -0
- data/ext/libcouchbase/example/tracing/cJSON.h +1 -0
- data/ext/libcouchbase/example/tracing/tracing.c +439 -0
- data/ext/libcouchbase/example/tracing/views.c +444 -0
- data/ext/libcouchbase/include/libcouchbase/auth.h +56 -4
- data/ext/libcouchbase/include/libcouchbase/cbft.h +8 -0
- data/ext/libcouchbase/include/libcouchbase/cntl-private.h +55 -1
- data/ext/libcouchbase/include/libcouchbase/cntl.h +101 -1
- data/ext/libcouchbase/include/libcouchbase/configuration.h.in +6 -0
- data/ext/libcouchbase/include/libcouchbase/couchbase.h +109 -6
- data/ext/libcouchbase/include/libcouchbase/crypto.h +140 -0
- data/ext/libcouchbase/include/libcouchbase/error.h +38 -2
- data/ext/libcouchbase/include/libcouchbase/kvbuf.h +6 -1
- data/ext/libcouchbase/include/libcouchbase/metrics.h +79 -0
- data/ext/libcouchbase/include/libcouchbase/n1ql.h +9 -0
- data/ext/libcouchbase/include/libcouchbase/tracing.h +319 -0
- data/ext/libcouchbase/include/libcouchbase/vbucket.h +1 -1
- data/ext/libcouchbase/include/libcouchbase/views.h +8 -0
- data/ext/libcouchbase/include/memcached/protocol_binary.h +40 -10
- data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +6 -14
- data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +3 -0
- data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +1 -0
- data/ext/libcouchbase/plugins/io/select/plugin-select.c +4 -1
- data/ext/libcouchbase/src/auth-priv.h +36 -4
- data/ext/libcouchbase/src/auth.cc +66 -27
- data/ext/libcouchbase/src/bootstrap.cc +1 -1
- data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +12 -7
- data/ext/libcouchbase/src/bucketconfig/bc_http.cc +26 -17
- data/ext/libcouchbase/src/bucketconfig/bc_http.h +1 -1
- data/ext/libcouchbase/src/bucketconfig/clconfig.h +4 -2
- data/ext/libcouchbase/src/bucketconfig/confmon.cc +6 -3
- data/ext/libcouchbase/src/cbft.cc +48 -0
- data/ext/libcouchbase/src/cntl.cc +138 -2
- data/ext/libcouchbase/src/config_static.h +17 -0
- data/ext/libcouchbase/src/connspec.cc +54 -6
- data/ext/libcouchbase/src/connspec.h +9 -1
- data/ext/libcouchbase/src/crypto.cc +386 -0
- data/ext/libcouchbase/src/ctx-log-inl.h +23 -6
- data/ext/libcouchbase/src/dump.cc +4 -0
- data/ext/libcouchbase/src/getconfig.cc +1 -2
- data/ext/libcouchbase/src/handler.cc +65 -27
- data/ext/libcouchbase/src/hostlist.cc +35 -7
- data/ext/libcouchbase/src/hostlist.h +7 -0
- data/ext/libcouchbase/src/http/http-priv.h +2 -0
- data/ext/libcouchbase/src/http/http.cc +77 -37
- data/ext/libcouchbase/src/http/http_io.cc +19 -2
- data/ext/libcouchbase/src/instance.cc +90 -17
- data/ext/libcouchbase/src/internal.h +5 -0
- data/ext/libcouchbase/src/lcbio/connect.cc +39 -4
- data/ext/libcouchbase/src/lcbio/connect.h +27 -0
- data/ext/libcouchbase/src/lcbio/ctx.c +49 -23
- data/ext/libcouchbase/src/lcbio/ioutils.cc +30 -3
- data/ext/libcouchbase/src/lcbio/ioutils.h +2 -0
- data/ext/libcouchbase/src/lcbio/manager.cc +44 -8
- data/ext/libcouchbase/src/lcbio/manager.h +2 -0
- data/ext/libcouchbase/src/lcbio/rw-inl.h +1 -0
- data/ext/libcouchbase/src/lcbio/ssl.h +3 -5
- data/ext/libcouchbase/src/logging.c +1 -1
- data/ext/libcouchbase/src/logging.h +2 -0
- data/ext/libcouchbase/src/mc/compress.cc +164 -0
- data/ext/libcouchbase/src/mc/compress.h +7 -12
- data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +5 -1
- data/ext/libcouchbase/src/mc/mcreq.c +11 -1
- data/ext/libcouchbase/src/mc/mcreq.h +35 -4
- data/ext/libcouchbase/src/mcserver/mcserver.cc +30 -7
- data/ext/libcouchbase/src/mcserver/mcserver.h +7 -0
- data/ext/libcouchbase/src/mcserver/negotiate.cc +103 -57
- data/ext/libcouchbase/src/mcserver/negotiate.h +2 -2
- data/ext/libcouchbase/src/mctx-helper.h +11 -0
- data/ext/libcouchbase/src/metrics.cc +132 -0
- data/ext/libcouchbase/src/n1ql/ixmgmt.cc +2 -1
- data/ext/libcouchbase/src/n1ql/n1ql.cc +66 -0
- data/ext/libcouchbase/src/newconfig.cc +9 -2
- data/ext/libcouchbase/src/operations/counter.cc +2 -1
- data/ext/libcouchbase/src/operations/durability-cas.cc +11 -0
- data/ext/libcouchbase/src/operations/durability-seqno.cc +3 -0
- data/ext/libcouchbase/src/operations/durability.cc +24 -2
- data/ext/libcouchbase/src/operations/durability_internal.h +19 -0
- data/ext/libcouchbase/src/operations/get.cc +4 -2
- data/ext/libcouchbase/src/operations/observe-seqno.cc +1 -0
- data/ext/libcouchbase/src/operations/observe.cc +113 -62
- data/ext/libcouchbase/src/operations/ping.cc +246 -67
- data/ext/libcouchbase/src/operations/remove.cc +2 -1
- data/ext/libcouchbase/src/operations/store.cc +17 -14
- data/ext/libcouchbase/src/operations/touch.cc +3 -0
- data/ext/libcouchbase/src/packetutils.h +68 -4
- data/ext/libcouchbase/src/probes.d +132 -161
- data/ext/libcouchbase/src/rdb/bigalloc.c +1 -1
- data/ext/libcouchbase/src/retryq.cc +6 -2
- data/ext/libcouchbase/src/rnd.cc +68 -0
- data/ext/libcouchbase/src/rnd.h +39 -0
- data/ext/libcouchbase/src/settings.c +27 -0
- data/ext/libcouchbase/src/settings.h +67 -3
- data/ext/libcouchbase/src/ssl/CMakeLists.txt +0 -12
- data/ext/libcouchbase/src/ssl/ssl_common.c +23 -4
- data/ext/libcouchbase/src/strcodecs/base64.c +141 -16
- data/ext/libcouchbase/src/strcodecs/strcodecs.h +16 -1
- data/ext/libcouchbase/src/trace.h +68 -61
- data/ext/libcouchbase/src/tracing/span.cc +289 -0
- data/ext/libcouchbase/src/tracing/threshold_logging_tracer.cc +171 -0
- data/ext/libcouchbase/src/tracing/tracer.cc +53 -0
- data/ext/libcouchbase/src/tracing/tracing-internal.h +213 -0
- data/ext/libcouchbase/src/utilities.c +5 -0
- data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -2
- data/ext/libcouchbase/src/vbucket/vbucket.c +50 -18
- data/ext/libcouchbase/src/views/docreq.cc +26 -1
- data/ext/libcouchbase/src/views/docreq.h +17 -0
- data/ext/libcouchbase/src/views/viewreq.cc +64 -1
- data/ext/libcouchbase/src/views/viewreq.h +21 -0
- data/ext/libcouchbase/tests/CMakeLists.txt +6 -6
- data/ext/libcouchbase/tests/basic/t_base64.cc +34 -6
- data/ext/libcouchbase/tests/basic/t_connstr.cc +14 -0
- data/ext/libcouchbase/tests/basic/t_creds.cc +10 -10
- data/ext/libcouchbase/tests/basic/t_host.cc +22 -2
- data/ext/libcouchbase/tests/basic/t_scram.cc +514 -0
- data/ext/libcouchbase/tests/check-all.cc +6 -2
- data/ext/libcouchbase/tests/iotests/mock-environment.cc +64 -0
- data/ext/libcouchbase/tests/iotests/mock-environment.h +27 -1
- data/ext/libcouchbase/tests/iotests/t_confmon.cc +2 -2
- data/ext/libcouchbase/tests/iotests/t_forward.cc +8 -0
- data/ext/libcouchbase/tests/iotests/t_netfail.cc +124 -0
- data/ext/libcouchbase/tests/iotests/t_smoke.cc +1 -1
- data/ext/libcouchbase/tests/iotests/t_snappy.cc +316 -0
- data/ext/libcouchbase/tests/socktests/socktest.cc +2 -2
- data/ext/libcouchbase/tests/socktests/t_basic.cc +6 -6
- data/ext/libcouchbase/tests/socktests/t_manager.cc +1 -1
- data/ext/libcouchbase/tests/socktests/t_ssl.cc +1 -1
- data/ext/libcouchbase/tools/CMakeLists.txt +1 -1
- data/ext/libcouchbase/tools/cbc-handlers.h +17 -0
- data/ext/libcouchbase/tools/cbc-n1qlback.cc +7 -4
- data/ext/libcouchbase/tools/cbc-pillowfight.cc +408 -100
- data/ext/libcouchbase/tools/cbc-proxy.cc +134 -3
- data/ext/libcouchbase/tools/cbc-subdoc.cc +1 -2
- data/ext/libcouchbase/tools/cbc.cc +113 -8
- data/ext/libcouchbase/tools/common/histogram.cc +1 -0
- data/ext/libcouchbase/tools/common/options.cc +28 -1
- data/ext/libcouchbase/tools/common/options.h +5 -0
- data/ext/libcouchbase/tools/docgen/docgen.h +36 -10
- data/ext/libcouchbase/tools/docgen/loc.h +5 -4
- data/ext/libcouchbase/tools/docgen/seqgen.h +28 -0
- data/lib/libcouchbase/ext/libcouchbase/enums.rb +10 -0
- data/lib/libcouchbase/n1ql.rb +6 -1
- data/lib/libcouchbase/version.rb +1 -1
- data/spec/connection_spec.rb +6 -6
- metadata +38 -5
- data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +0 -11
- data/ext/libcouchbase/src/mc/compress.c +0 -90
- data/ext/libcouchbase/tools/common/my_inttypes.h +0 -22
@@ -21,6 +21,7 @@ FILE(GLOB LCB_OP_SRC src/operations/*.c)
|
|
21
21
|
|
22
22
|
# memcached packets
|
23
23
|
FILE(GLOB LCB_MC_SRC src/mc/*.c)
|
24
|
+
FILE(GLOB LCB_MC_CXXSRC src/mc/*.cc)
|
24
25
|
|
25
26
|
# read buffer management
|
26
27
|
FILE(GLOB LCB_RDB_SRC src/rdb/*.c)
|
@@ -40,11 +41,14 @@ SET(LCB_CORE_SRC
|
|
40
41
|
${LCB_N1QL_SRC}
|
41
42
|
src/callbacks.c
|
42
43
|
src/legacy.c
|
43
|
-
# src/mcserver/negotiate.c
|
44
44
|
src/iofactory.c
|
45
45
|
src/settings.c
|
46
46
|
src/utilities.c)
|
47
47
|
|
48
|
+
IF (LCB_TRACING)
|
49
|
+
FILE(GLOB LCB_TRACING_SRC src/tracing/*.cc)
|
50
|
+
ENDIF()
|
51
|
+
|
48
52
|
SET(LCB_CORE_CXXSRC
|
49
53
|
src/instance.cc
|
50
54
|
src/auth.cc
|
@@ -55,6 +59,7 @@ SET(LCB_CORE_CXXSRC
|
|
55
59
|
src/bucketconfig/bc_static.cc
|
56
60
|
src/bucketconfig/confmon.cc
|
57
61
|
src/connspec.cc
|
62
|
+
src/crypto.cc
|
58
63
|
src/dns-srv.cc
|
59
64
|
src/dump.cc
|
60
65
|
src/errmap.cc
|
@@ -87,9 +92,13 @@ SET(LCB_CORE_CXXSRC
|
|
87
92
|
src/operations/ping.cc
|
88
93
|
src/mcserver/mcserver.cc
|
89
94
|
src/mcserver/negotiate.cc
|
95
|
+
src/metrics.cc
|
90
96
|
src/retrychk.cc
|
91
97
|
src/retryq.cc
|
98
|
+
src/rnd.cc
|
92
99
|
src/views/docreq.cc
|
93
100
|
src/views/viewreq.cc
|
94
101
|
src/cntl.cc
|
95
|
-
src/wait.cc
|
102
|
+
src/wait.cc
|
103
|
+
${LCB_TRACING_SRC}
|
104
|
+
)
|
@@ -1,9 +1,25 @@
|
|
1
|
+
INCLUDE (CheckCSourceCompiles)
|
1
2
|
INCLUDE_DIRECTORIES(src)
|
2
3
|
FILE(GLOB CBSASL_SRC src/*.c)
|
3
4
|
FILE(GLOB CRAM_SRC src/cram-md5/*.c)
|
5
|
+
FILE(GLOB SCRAM_SRC src/scram-sha/*.c)
|
4
6
|
|
5
|
-
ADD_LIBRARY(cbsasl OBJECT ${CBSASL_SRC} ${CRAM_SRC})
|
6
|
-
SET_TARGET_PROPERTIES(cbsasl
|
7
|
+
ADD_LIBRARY(cbsasl-lcb OBJECT ${CBSASL_SRC} ${CRAM_SRC} ${SCRAM_SRC})
|
8
|
+
SET_TARGET_PROPERTIES(cbsasl-lcb
|
7
9
|
PROPERTIES
|
8
10
|
POSITION_INDEPENDENT_CODE TRUE
|
9
11
|
COMPILE_FLAGS "${LCB_CORE_CFLAGS}")
|
12
|
+
|
13
|
+
IF(OPENSSL_FOUND AND (NOT LCB_NO_SSL))
|
14
|
+
INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
|
15
|
+
ADD_DEFINITIONS(${OPENSSL_DEFINITIONS})
|
16
|
+
# Check if the system have a usable version of PKCS5_PBKDF2_HMAC
|
17
|
+
CMAKE_PUSH_CHECK_STATE(RESET)
|
18
|
+
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${OPENSSL_LIBRARIES})
|
19
|
+
SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${OPENSSL_INCLUDE_DIR})
|
20
|
+
CHECK_C_SOURCE_COMPILES("
|
21
|
+
#include <openssl/evp.h>
|
22
|
+
int main() {
|
23
|
+
PKCS5_PBKDF2_HMAC(NULL, 0, NULL, 0, 0, NULL, 0, NULL);
|
24
|
+
}" HAVE_PKCS5_PBKDF2_HMAC)
|
25
|
+
ENDIF()
|
@@ -22,6 +22,19 @@
|
|
22
22
|
extern "C" {
|
23
23
|
#endif
|
24
24
|
|
25
|
+
#define MECH_PLAIN "PLAIN"
|
26
|
+
#define MECH_CRAM_MD5 "CRAM-MD5"
|
27
|
+
#define MECH_SCRAM_SHA1 "SCRAM-SHA1"
|
28
|
+
#define MECH_SCRAM_SHA256 "SCRAM-SHA256"
|
29
|
+
#define MECH_SCRAM_SHA512 "SCRAM-SHA512"
|
30
|
+
|
31
|
+
// size in bytes - to double if the nonce is displayed in hexadecimal
|
32
|
+
#define SCRAM_NONCE_SIZE 8
|
33
|
+
|
34
|
+
#define CBSASL_SHA1_DIGEST_SIZE 20
|
35
|
+
#define CBSASL_SHA256_DIGEST_SIZE 32
|
36
|
+
#define CBSASL_SHA512_DIGEST_SIZE 64
|
37
|
+
|
25
38
|
typedef enum cbsasl_error {
|
26
39
|
SASL_OK,
|
27
40
|
SASL_CONTINUE,
|
@@ -33,6 +46,15 @@ extern "C" {
|
|
33
46
|
}
|
34
47
|
cbsasl_error_t;
|
35
48
|
|
49
|
+
typedef enum cbsasl_auth_mechanism {
|
50
|
+
SASL_AUTH_MECH_PLAIN,
|
51
|
+
SASL_AUTH_MECH_CRAM_MD5, // deprecated
|
52
|
+
SASL_AUTH_MECH_SCRAM_SHA1,
|
53
|
+
SASL_AUTH_MECH_SCRAM_SHA256,
|
54
|
+
SASL_AUTH_MECH_SCRAM_SHA512
|
55
|
+
}
|
56
|
+
cbsasl_auth_mechanism_t;
|
57
|
+
|
36
58
|
typedef struct {
|
37
59
|
unsigned long len;
|
38
60
|
unsigned char data[1];
|
@@ -60,13 +82,18 @@ extern "C" {
|
|
60
82
|
|
61
83
|
struct cbsasl_client_conn_t {
|
62
84
|
char *userdata;
|
63
|
-
|
85
|
+
cbsasl_auth_mechanism_t auth_mech; // authentication mechanism
|
64
86
|
int (*get_username)(void *context, int id, const char **result,
|
65
87
|
unsigned int *len);
|
66
88
|
void *get_username_ctx;
|
67
89
|
int (*get_password)(cbsasl_conn_t *conn, void *context, int id,
|
68
90
|
cbsasl_secret_t **psecret);
|
69
91
|
void *get_password_ctx;
|
92
|
+
char *nonce; // client nonce for SCRAM-SHA authentication
|
93
|
+
char *client_first_message_bare; // for SCRAM-SHA authentication
|
94
|
+
unsigned char *saltedpassword; // for SCRAM-SHA authentication
|
95
|
+
unsigned int saltedpasslen; // length of the salted password field
|
96
|
+
char *auth_message; // for SCRAM-SHA authentication
|
70
97
|
};
|
71
98
|
|
72
99
|
struct cbsasl_server_conn_t {
|
@@ -143,6 +170,20 @@ extern "C" {
|
|
143
170
|
const char **output,
|
144
171
|
unsigned *outputlen);
|
145
172
|
|
173
|
+
/**
|
174
|
+
* Final authentication step, if need to be (depending on the mechanism).
|
175
|
+
*
|
176
|
+
* This is mainly use for SCRAM-SHA authentication family, to verify the
|
177
|
+
* server signature. Even if the server accepted the authentication, if
|
178
|
+
* we can't verify its signature, we must reject the connection.
|
179
|
+
*
|
180
|
+
* @return Whether or not the sasl check was successful
|
181
|
+
*/
|
182
|
+
CBSASL_PUBLIC_API
|
183
|
+
cbsasl_error_t cbsasl_client_check(cbsasl_conn_t *conn,
|
184
|
+
const char *input,
|
185
|
+
unsigned int inputlen);
|
186
|
+
|
146
187
|
/**
|
147
188
|
* Frees up funushed sasl connections
|
148
189
|
*
|
@@ -199,7 +240,8 @@ extern "C" {
|
|
199
240
|
void **prompt_need,
|
200
241
|
const char **clientout,
|
201
242
|
unsigned int *clientoutlen,
|
202
|
-
const char **mech
|
243
|
+
const char **mech,
|
244
|
+
int allow_scram_sha);
|
203
245
|
|
204
246
|
CBSASL_PUBLIC_API
|
205
247
|
cbsasl_error_t cbsasl_client_step(cbsasl_conn_t *conn,
|
@@ -14,24 +14,23 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
+
#include "config.h"
|
17
18
|
#include "cbsasl/cbsasl.h"
|
18
19
|
#include "cram-md5/hmac.h"
|
20
|
+
#include "scram-sha/scram_utils.h"
|
19
21
|
#include "util.h"
|
20
22
|
#include <time.h>
|
21
23
|
#include <stdlib.h>
|
22
24
|
#include <string.h>
|
25
|
+
#include <stdio.h>
|
23
26
|
|
24
27
|
CBSASL_PUBLIC_API
|
25
|
-
cbsasl_error_t cbsasl_client_new(const char *service,
|
26
|
-
const char *
|
27
|
-
const char *iplocalport,
|
28
|
-
const char *ipremoteport,
|
29
|
-
const cbsasl_callback_t *prompt_supp,
|
30
|
-
unsigned flags,
|
28
|
+
cbsasl_error_t cbsasl_client_new(const char *service, const char *serverFQDN, const char *iplocalport,
|
29
|
+
const char *ipremoteport, const cbsasl_callback_t *prompt_supp, unsigned flags,
|
31
30
|
cbsasl_conn_t **pconn)
|
32
31
|
{
|
33
32
|
cbsasl_conn_t *conn;
|
34
|
-
cbsasl_callback_t *callbacks = (cbsasl_callback_t*)prompt_supp;
|
33
|
+
cbsasl_callback_t *callbacks = (cbsasl_callback_t *)prompt_supp;
|
35
34
|
int ii;
|
36
35
|
|
37
36
|
if (prompt_supp == NULL) {
|
@@ -85,63 +84,138 @@ cbsasl_error_t cbsasl_client_new(const char *service,
|
|
85
84
|
}
|
86
85
|
|
87
86
|
CBSASL_PUBLIC_API
|
88
|
-
cbsasl_error_t cbsasl_client_start(cbsasl_conn_t *conn,
|
89
|
-
const char *
|
90
|
-
|
91
|
-
const char **clientout,
|
92
|
-
unsigned int *clientoutlen,
|
93
|
-
const char **mech)
|
87
|
+
cbsasl_error_t cbsasl_client_start(cbsasl_conn_t *conn, const char *mechlist, void **prompt_need,
|
88
|
+
const char **clientout, unsigned int *clientoutlen, const char **mech,
|
89
|
+
int allow_scram_sha)
|
94
90
|
{
|
95
91
|
if (conn->client == 0) {
|
96
92
|
return SASL_BADPARAM;
|
97
93
|
}
|
98
94
|
|
99
|
-
|
100
|
-
|
95
|
+
*mech = NULL;
|
96
|
+
if (allow_scram_sha) {
|
97
|
+
#if !defined(LCB_NO_SSL) && defined(HAVE_PKCS5_PBKDF2_HMAC)
|
98
|
+
// we use SCRAM-SHA only if OpenSSL is linked and has support for PBKDF2_HMAC functions
|
99
|
+
if (strstr(mechlist, MECH_SCRAM_SHA512) != NULL) {
|
100
|
+
*mech = MECH_SCRAM_SHA512;
|
101
|
+
conn->c.client.auth_mech = SASL_AUTH_MECH_SCRAM_SHA512;
|
102
|
+
} else if (strstr(mechlist, MECH_SCRAM_SHA256) != NULL) {
|
103
|
+
*mech = MECH_SCRAM_SHA256;
|
104
|
+
conn->c.client.auth_mech = SASL_AUTH_MECH_SCRAM_SHA256;
|
105
|
+
} else if (strstr(mechlist, MECH_SCRAM_SHA1) != NULL) {
|
106
|
+
*mech = MECH_SCRAM_SHA1;
|
107
|
+
conn->c.client.auth_mech = SASL_AUTH_MECH_SCRAM_SHA1;
|
108
|
+
}
|
109
|
+
#endif
|
110
|
+
}
|
111
|
+
if (*mech == NULL) {
|
112
|
+
if (strstr(mechlist, MECH_CRAM_MD5) != NULL) {
|
113
|
+
*mech = MECH_CRAM_MD5;
|
114
|
+
conn->c.client.auth_mech = SASL_AUTH_MECH_CRAM_MD5;
|
115
|
+
} else if (strstr(mechlist, MECH_PLAIN) != NULL) {
|
116
|
+
*mech = MECH_PLAIN;
|
117
|
+
conn->c.client.auth_mech = SASL_AUTH_MECH_PLAIN;
|
118
|
+
} else {
|
101
119
|
return SASL_NOMECH;
|
102
120
|
}
|
103
|
-
|
104
|
-
*mech = "PLAIN";
|
105
|
-
conn->c.client.plain = 1;
|
106
|
-
} else {
|
107
|
-
*mech = "CRAM-MD5";
|
108
|
-
conn->c.client.plain = 0;
|
109
121
|
}
|
110
122
|
|
123
|
+
switch (conn->c.client.auth_mech) {
|
124
|
+
case SASL_AUTH_MECH_PLAIN: {
|
125
|
+
const char *usernm = NULL;
|
126
|
+
unsigned int usernmlen;
|
127
|
+
cbsasl_secret_t *pass;
|
128
|
+
cbsasl_error_t ret;
|
111
129
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
130
|
+
ret = conn->c.client.get_username(conn->c.client.get_username_ctx, CBSASL_CB_USER, &usernm, &usernmlen);
|
131
|
+
if (ret != SASL_OK) {
|
132
|
+
return ret;
|
133
|
+
}
|
116
134
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
if (ret != SASL_OK) {
|
122
|
-
return ret;
|
123
|
-
}
|
135
|
+
ret = conn->c.client.get_password(conn, conn->c.client.get_password_ctx, CBSASL_CB_PASS, &pass);
|
136
|
+
if (ret != SASL_OK) {
|
137
|
+
return ret;
|
138
|
+
}
|
124
139
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
return ret;
|
130
|
-
}
|
140
|
+
conn->c.client.userdata = calloc(usernmlen + 1 + pass->len + 1, 1);
|
141
|
+
if (conn->c.client.userdata == NULL) {
|
142
|
+
return SASL_NOMEM;
|
143
|
+
}
|
131
144
|
|
132
|
-
|
133
|
-
|
134
|
-
|
145
|
+
memcpy(conn->c.client.userdata + 1, usernm, usernmlen);
|
146
|
+
memcpy(conn->c.client.userdata + usernmlen + 2, pass->data, pass->len);
|
147
|
+
*clientout = conn->c.client.userdata;
|
148
|
+
*clientoutlen = (unsigned int)(usernmlen + 2 + pass->len);
|
149
|
+
break;
|
135
150
|
}
|
151
|
+
case SASL_AUTH_MECH_SCRAM_SHA1:
|
152
|
+
case SASL_AUTH_MECH_SCRAM_SHA256:
|
153
|
+
case SASL_AUTH_MECH_SCRAM_SHA512: {
|
154
|
+
const char *usernm = NULL;
|
155
|
+
unsigned int usernmlen;
|
156
|
+
int usernmspeccharsnb;
|
157
|
+
char binnonce[SCRAM_NONCE_SIZE]; // binary nonce
|
158
|
+
cbsasl_error_t ret;
|
159
|
+
|
160
|
+
ret = conn->c.client.get_username(conn->c.client.get_username_ctx, CBSASL_CB_USER, &usernm, &usernmlen);
|
161
|
+
if (ret != SASL_OK) {
|
162
|
+
return ret;
|
163
|
+
}
|
164
|
+
usernmspeccharsnb = compute_special_chars(usernm, usernmlen);
|
165
|
+
if (usernmspeccharsnb < 0) {
|
166
|
+
// invalid characters in the username
|
167
|
+
return SASL_BADPARAM;
|
168
|
+
}
|
169
|
+
|
170
|
+
generate_nonce(binnonce, SCRAM_NONCE_SIZE);
|
171
|
+
conn->c.client.nonce = calloc(SCRAM_NONCE_SIZE * 2 + 1, 1);
|
172
|
+
if (conn->c.client.nonce == NULL) {
|
173
|
+
return SASL_NOMEM;
|
174
|
+
}
|
175
|
+
// stores binary nonce in hexadecimal format into conn->c.client.nonce array
|
176
|
+
cbsasl_hex_encode(conn->c.client.nonce, binnonce, SCRAM_NONCE_SIZE);
|
177
|
+
conn->c.client.nonce[SCRAM_NONCE_SIZE * 2] = '\0';
|
136
178
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
179
|
+
#define GS2_HEADER "n,,n=" // "no binding" + start of name attribute
|
180
|
+
#define NONCE_ATTR ",r=" // start of nonce attribute
|
181
|
+
conn->c.client.userdata = calloc(
|
182
|
+
strlen(GS2_HEADER) + usernmlen + usernmspeccharsnb * 2 + strlen(NONCE_ATTR) + SCRAM_NONCE_SIZE * 2, 1);
|
183
|
+
if (conn->c.client.userdata == NULL) {
|
184
|
+
return SASL_NOMEM;
|
185
|
+
}
|
186
|
+
|
187
|
+
memcpy(conn->c.client.userdata, GS2_HEADER, strlen(GS2_HEADER));
|
188
|
+
if (!usernmspeccharsnb) {
|
189
|
+
// no special char, we can do a direct copy
|
190
|
+
memcpy(conn->c.client.userdata + strlen(GS2_HEADER), usernm, usernmlen);
|
191
|
+
} else {
|
192
|
+
// copy with substitution of special characters
|
193
|
+
usernmcpy(conn->c.client.userdata + strlen(GS2_HEADER), usernm, usernmlen);
|
194
|
+
}
|
195
|
+
memcpy(conn->c.client.userdata + strlen(GS2_HEADER) + usernmlen + usernmspeccharsnb * 2, NONCE_ATTR,
|
196
|
+
strlen(NONCE_ATTR));
|
197
|
+
memcpy(conn->c.client.userdata + strlen(GS2_HEADER) + usernmlen + usernmspeccharsnb * 2 +
|
198
|
+
strlen(NONCE_ATTR),
|
199
|
+
conn->c.client.nonce, SCRAM_NONCE_SIZE * 2);
|
200
|
+
|
201
|
+
*clientout = conn->c.client.userdata;
|
202
|
+
*clientoutlen = (unsigned int)(strlen(GS2_HEADER) + usernmlen + usernmspeccharsnb * 2 + strlen(NONCE_ATTR) +
|
203
|
+
SCRAM_NONCE_SIZE * 2);
|
204
|
+
|
205
|
+
// save the client first message for later step (without the first three characters)
|
206
|
+
conn->c.client.client_first_message_bare = calloc(*clientoutlen - 3 + 1, 1); // +1 for the binary zero
|
207
|
+
if (conn->c.client.client_first_message_bare == NULL) {
|
208
|
+
return SASL_NOMEM;
|
209
|
+
}
|
210
|
+
memcpy(conn->c.client.client_first_message_bare, *clientout + 3, *clientoutlen - 3);
|
211
|
+
// no need to add a final binary zero, as calloc already sets the memory to zero
|
212
|
+
break;
|
213
|
+
}
|
214
|
+
case SASL_AUTH_MECH_CRAM_MD5:
|
215
|
+
// no data in the first CRAM-MD5 message
|
216
|
+
*clientout = NULL;
|
217
|
+
*clientoutlen = 0;
|
218
|
+
break;
|
145
219
|
}
|
146
220
|
|
147
221
|
(void)prompt_need;
|
@@ -149,15 +223,9 @@ cbsasl_error_t cbsasl_client_start(cbsasl_conn_t *conn,
|
|
149
223
|
}
|
150
224
|
|
151
225
|
CBSASL_PUBLIC_API
|
152
|
-
cbsasl_error_t cbsasl_client_step(cbsasl_conn_t *conn,
|
153
|
-
const char *
|
154
|
-
unsigned int serverinlen,
|
155
|
-
void **not_used,
|
156
|
-
const char **clientout,
|
157
|
-
unsigned int *clientoutlen)
|
226
|
+
cbsasl_error_t cbsasl_client_step(cbsasl_conn_t *conn, const char *serverin, unsigned int serverinlen, void **not_used,
|
227
|
+
const char **clientout, unsigned int *clientoutlen)
|
158
228
|
{
|
159
|
-
unsigned char digest[DIGEST_LENGTH];
|
160
|
-
char md5string[DIGEST_LENGTH * 2];
|
161
229
|
const char *usernm = NULL;
|
162
230
|
unsigned int usernmlen;
|
163
231
|
cbsasl_secret_t *pass;
|
@@ -169,39 +237,183 @@ cbsasl_error_t cbsasl_client_step(cbsasl_conn_t *conn,
|
|
169
237
|
return SASL_BADPARAM;
|
170
238
|
}
|
171
239
|
|
172
|
-
if (conn->c.client.
|
240
|
+
if (conn->c.client.auth_mech == SASL_AUTH_MECH_PLAIN) {
|
173
241
|
/* Shouldn't be called during plain auth */
|
174
242
|
return SASL_BADPARAM;
|
175
243
|
}
|
176
244
|
|
177
|
-
ret = conn->c.client.get_username(conn->c.client.get_username_ctx,
|
178
|
-
CBSASL_CB_USER, &usernm, &usernmlen);
|
245
|
+
ret = conn->c.client.get_username(conn->c.client.get_username_ctx, CBSASL_CB_USER, &usernm, &usernmlen);
|
179
246
|
if (ret != SASL_OK) {
|
180
247
|
return ret;
|
181
248
|
}
|
182
249
|
|
183
|
-
ret = conn->c.client.get_password(conn, conn->c.client.get_password_ctx,
|
184
|
-
CBSASL_CB_PASS, &pass);
|
250
|
+
ret = conn->c.client.get_password(conn, conn->c.client.get_password_ctx, CBSASL_CB_PASS, &pass);
|
185
251
|
if (ret != SASL_OK) {
|
186
252
|
return ret;
|
187
253
|
}
|
188
254
|
|
189
255
|
free(conn->c.client.userdata);
|
190
|
-
conn->c.client.userdata =
|
191
|
-
|
192
|
-
|
193
|
-
|
256
|
+
conn->c.client.userdata = NULL;
|
257
|
+
switch (conn->c.client.auth_mech) {
|
258
|
+
case SASL_AUTH_MECH_CRAM_MD5: {
|
259
|
+
unsigned char digest[DIGEST_LENGTH];
|
260
|
+
char md5string[DIGEST_LENGTH * 2];
|
261
|
+
conn->c.client.userdata = calloc(usernmlen + 1 + sizeof(md5string) + 1, 1);
|
262
|
+
if (conn->c.client.userdata == NULL) {
|
263
|
+
return SASL_NOMEM;
|
264
|
+
}
|
194
265
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
266
|
+
cbsasl_hmac_md5((unsigned char *)serverin, serverinlen, pass->data, pass->len, digest);
|
267
|
+
cbsasl_hex_encode(md5string, (char *)digest, DIGEST_LENGTH);
|
268
|
+
memcpy(conn->c.client.userdata, usernm, usernmlen);
|
269
|
+
conn->c.client.userdata[usernmlen] = ' ';
|
270
|
+
memcpy(conn->c.client.userdata + usernmlen + 1, md5string, sizeof(md5string));
|
271
|
+
break;
|
272
|
+
}
|
273
|
+
case SASL_AUTH_MECH_SCRAM_SHA1:
|
274
|
+
case SASL_AUTH_MECH_SCRAM_SHA256:
|
275
|
+
case SASL_AUTH_MECH_SCRAM_SHA512: {
|
276
|
+
if (!conn->c.client.auth_message) {
|
277
|
+
const char *combinednonce = NULL; // nonce extracted from server's first reply
|
278
|
+
unsigned int noncelen = 0;
|
279
|
+
const char *salt = NULL; // salt extracted from server's first reply
|
280
|
+
unsigned int saltlen = 0;
|
281
|
+
unsigned int itcount = 0;
|
282
|
+
unsigned char saltedpassword[CBSASL_SHA512_DIGEST_SIZE]; // max digest size
|
283
|
+
unsigned int saltedpasslen = 0;
|
284
|
+
unsigned int prooflen = 0; // proof size in base64
|
202
285
|
|
286
|
+
ret =
|
287
|
+
parse_server_challenge(serverin, serverinlen, &combinednonce, &noncelen, &salt, &saltlen, &itcount);
|
288
|
+
if (ret != SASL_OK) {
|
289
|
+
return ret;
|
290
|
+
}
|
291
|
+
if (!combinednonce || !noncelen || !salt || !saltlen || !itcount) {
|
292
|
+
// missing or invalid value in server challenge
|
293
|
+
return SASL_BADPARAM;
|
294
|
+
}
|
295
|
+
if (noncelen < SCRAM_NONCE_SIZE * 2 ||
|
296
|
+
memcmp(combinednonce, conn->c.client.nonce, SCRAM_NONCE_SIZE * 2)) {
|
297
|
+
// the combined nonce doesn't start with the client nonce we sent previously
|
298
|
+
return SASL_BADPARAM;
|
299
|
+
}
|
300
|
+
// ok, now we can compute the client proof
|
301
|
+
ret = generate_salted_password(conn->c.client.auth_mech, pass, salt, saltlen, itcount, saltedpassword,
|
302
|
+
&saltedpasslen);
|
303
|
+
if (ret != SASL_OK) {
|
304
|
+
return ret;
|
305
|
+
}
|
306
|
+
// save salted password for later use
|
307
|
+
conn->c.client.saltedpassword = calloc(saltedpasslen, 1);
|
308
|
+
if (conn->c.client.saltedpassword == NULL) {
|
309
|
+
return SASL_NOMEM;
|
310
|
+
}
|
311
|
+
memcpy(conn->c.client.saltedpassword, saltedpassword, saltedpasslen);
|
312
|
+
conn->c.client.saltedpasslen = saltedpasslen;
|
313
|
+
|
314
|
+
// before building the client proof, we start building the client final message,
|
315
|
+
// as it is used for the computation of the proof
|
316
|
+
// The final message starts with the base64-encoded GS2 header from the initial message.
|
317
|
+
// As we always use "n,,", we can hardcode directly its base64-counterpart, so "biws".
|
318
|
+
#define FINAL_HEADER "c=biws,r="
|
319
|
+
#define PROOF_ATTR ",p="
|
320
|
+
switch (conn->c.client.auth_mech) {
|
321
|
+
case SASL_AUTH_MECH_SCRAM_SHA1:
|
322
|
+
prooflen = (CBSASL_SHA1_DIGEST_SIZE / 3 + 1) * 4;
|
323
|
+
break;
|
324
|
+
case SASL_AUTH_MECH_SCRAM_SHA256:
|
325
|
+
prooflen = (CBSASL_SHA256_DIGEST_SIZE / 3 + 1) * 4;
|
326
|
+
break;
|
327
|
+
case SASL_AUTH_MECH_SCRAM_SHA512:
|
328
|
+
prooflen = (CBSASL_SHA512_DIGEST_SIZE / 3 + 1) * 4;
|
329
|
+
break;
|
330
|
+
default:
|
331
|
+
break;
|
332
|
+
}
|
333
|
+
conn->c.client.userdata =
|
334
|
+
calloc(strlen(FINAL_HEADER) + noncelen + strlen(PROOF_ATTR) + prooflen + 1, 1);
|
335
|
+
if (conn->c.client.userdata == NULL) {
|
336
|
+
return SASL_NOMEM;
|
337
|
+
}
|
338
|
+
memcpy(conn->c.client.userdata, FINAL_HEADER, strlen(FINAL_HEADER));
|
339
|
+
memcpy(conn->c.client.userdata + strlen(FINAL_HEADER), combinednonce, noncelen);
|
340
|
+
memcpy(conn->c.client.userdata + strlen(FINAL_HEADER) + noncelen, PROOF_ATTR, strlen(PROOF_ATTR));
|
341
|
+
|
342
|
+
ret = compute_client_proof(
|
343
|
+
conn->c.client.auth_mech, saltedpassword, saltedpasslen, conn->c.client.client_first_message_bare,
|
344
|
+
strlen(conn->c.client.client_first_message_bare), serverin, serverinlen, conn->c.client.userdata,
|
345
|
+
strlen(FINAL_HEADER) + noncelen, &(conn->c.client.auth_message),
|
346
|
+
conn->c.client.userdata + strlen(FINAL_HEADER) + noncelen + strlen(PROOF_ATTR), prooflen + 1);
|
347
|
+
if (ret != SASL_OK) {
|
348
|
+
return ret;
|
349
|
+
}
|
350
|
+
} else {
|
351
|
+
// auth_message should not be already set
|
352
|
+
return SASL_FAIL;
|
353
|
+
}
|
354
|
+
break;
|
355
|
+
}
|
356
|
+
default:
|
357
|
+
break;
|
358
|
+
}
|
203
359
|
*clientout = conn->c.client.userdata;
|
204
360
|
*clientoutlen = strlen(conn->c.client.userdata);
|
205
361
|
|
206
362
|
return SASL_CONTINUE;
|
207
363
|
}
|
364
|
+
|
365
|
+
cbsasl_error_t cbsasl_client_check(cbsasl_conn_t *conn, const char *serverin, unsigned int serverinlen)
|
366
|
+
{
|
367
|
+
switch (conn->c.client.auth_mech) {
|
368
|
+
case SASL_AUTH_MECH_SCRAM_SHA1:
|
369
|
+
case SASL_AUTH_MECH_SCRAM_SHA256:
|
370
|
+
case SASL_AUTH_MECH_SCRAM_SHA512: {
|
371
|
+
if (conn->c.client.auth_message) {
|
372
|
+
char serversign[(CBSASL_SHA512_DIGEST_SIZE / 3 + 1) * 4 + 1]; // max sign len
|
373
|
+
unsigned int serversignlen = 0;
|
374
|
+
cbsasl_error_t ret;
|
375
|
+
|
376
|
+
// Last step: we have to verify the server's proof.
|
377
|
+
// In case of positive answer from the server, its final reply must start with "v=".
|
378
|
+
if (serverinlen <= 2 || memcmp(serverin, "v=", 2)) {
|
379
|
+
return SASL_FAIL;
|
380
|
+
}
|
381
|
+
switch (conn->c.client.auth_mech) {
|
382
|
+
case SASL_AUTH_MECH_SCRAM_SHA1:
|
383
|
+
serversignlen = (CBSASL_SHA1_DIGEST_SIZE / 3 + 1) * 4;
|
384
|
+
break;
|
385
|
+
case SASL_AUTH_MECH_SCRAM_SHA256:
|
386
|
+
serversignlen = (CBSASL_SHA256_DIGEST_SIZE / 3 + 1) * 4;
|
387
|
+
break;
|
388
|
+
case SASL_AUTH_MECH_SCRAM_SHA512:
|
389
|
+
serversignlen = (CBSASL_SHA512_DIGEST_SIZE / 3 + 1) * 4;
|
390
|
+
break;
|
391
|
+
default:
|
392
|
+
break;
|
393
|
+
}
|
394
|
+
ret = compute_server_signature(conn->c.client.auth_mech, conn->c.client.saltedpassword,
|
395
|
+
conn->c.client.saltedpasslen, conn->c.client.auth_message, serversign,
|
396
|
+
sizeof(serversign));
|
397
|
+
if (ret != SASL_OK) {
|
398
|
+
return ret;
|
399
|
+
}
|
400
|
+
|
401
|
+
// ok, we can now compare the two values
|
402
|
+
if ((serverinlen - 2 < serversignlen) || (memcmp(serverin + 2, serversign, serversignlen))) {
|
403
|
+
return SASL_FAIL;
|
404
|
+
}
|
405
|
+
} else {
|
406
|
+
// we have an issue: auth_message should not have been cleared
|
407
|
+
return SASL_FAIL;
|
408
|
+
}
|
409
|
+
break;
|
410
|
+
}
|
411
|
+
case SASL_AUTH_MECH_CRAM_MD5:
|
412
|
+
case SASL_AUTH_MECH_PLAIN:
|
413
|
+
default:
|
414
|
+
// nothing to do
|
415
|
+
break;
|
416
|
+
}
|
417
|
+
|
418
|
+
return SASL_OK;
|
419
|
+
}
|