libcouchbase 1.2.8 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
@@ -189,6 +189,20 @@ TEST_F(ConnstrTest, testParseHosts)
|
|
|
189
189
|
ASSERT_FALSE(NULL == findHost(¶ms, "foo.com"));
|
|
190
190
|
ASSERT_FALSE(NULL == findHost(¶ms, "bar.com"));
|
|
191
191
|
ASSERT_FALSE(NULL == findHost(¶ms, "baz.com"));
|
|
192
|
+
|
|
193
|
+
reinit();
|
|
194
|
+
err = params.parse("couchbase://"
|
|
195
|
+
"::a15:f2df:3fef:51bb:212a:8cec,[::a15:f2df:3fef:51bb:212a:8ced],[::a15:f2df:3fef:51bb:212a:"
|
|
196
|
+
"8cee]:9001",
|
|
197
|
+
&errmsg);
|
|
198
|
+
ASSERT_EQ(LCB_SUCCESS, err) << "Cannot parse IPv6";
|
|
199
|
+
ASSERT_EQ(3, countHosts(¶ms));
|
|
200
|
+
ASSERT_FALSE(NULL == findHost(¶ms, "::a15:f2df:3fef:51bb:212a:8cec"));
|
|
201
|
+
ASSERT_FALSE(NULL == findHost(¶ms, "::a15:f2df:3fef:51bb:212a:8ced"));
|
|
202
|
+
dh = findHost(¶ms, "::a15:f2df:3fef:51bb:212a:8cee");
|
|
203
|
+
ASSERT_FALSE(dh == NULL);
|
|
204
|
+
ASSERT_EQ("::a15:f2df:3fef:51bb:212a:8cee", dh->hostname);
|
|
205
|
+
ASSERT_EQ(9001, dh->port);
|
|
192
206
|
}
|
|
193
207
|
|
|
194
208
|
TEST_F(ConnstrTest, testParseBucket)
|
|
@@ -30,16 +30,16 @@ TEST_F(CredsTest, testLegacyCreds)
|
|
|
30
30
|
|
|
31
31
|
ASSERT_EQ(1, auth.buckets().size());
|
|
32
32
|
ASSERT_TRUE(auth.buckets().find("default")->second.empty());
|
|
33
|
-
ASSERT_EQ("", auth.password_for("default"));
|
|
34
|
-
ASSERT_EQ("default", auth.username_for("default"));
|
|
33
|
+
ASSERT_EQ("", auth.password_for(NULL, NULL, "default"));
|
|
34
|
+
ASSERT_EQ("default", auth.username_for(NULL, NULL, "default"));
|
|
35
35
|
|
|
36
36
|
// Try to add another user/password:
|
|
37
37
|
lcb_BUCKETCRED creds = { "user2", "pass2" };
|
|
38
38
|
ASSERT_EQ(LCB_SUCCESS, lcb_cntl(instance, LCB_CNTL_SET, LCB_CNTL_BUCKET_CRED, creds));
|
|
39
39
|
ASSERT_EQ(2, auth.buckets().size());
|
|
40
40
|
ASSERT_EQ("pass2", auth.buckets().find("user2")->second);
|
|
41
|
-
ASSERT_EQ("user2", auth.username_for("user2"));
|
|
42
|
-
ASSERT_EQ("pass2", auth.password_for("user2"));
|
|
41
|
+
ASSERT_EQ("user2", auth.username_for(NULL, NULL, "user2"));
|
|
42
|
+
ASSERT_EQ("pass2", auth.password_for(NULL, NULL, "user2"));
|
|
43
43
|
|
|
44
44
|
ASSERT_TRUE(auth.username().empty());
|
|
45
45
|
ASSERT_TRUE(auth.password().empty());
|
|
@@ -52,10 +52,10 @@ TEST_F(CredsTest, testRbacCreds) {
|
|
|
52
52
|
ASSERT_EQ("mark", auth.username());
|
|
53
53
|
ASSERT_EQ(LCBAUTH_MODE_RBAC, auth.mode());
|
|
54
54
|
ASSERT_TRUE(auth.buckets().empty());
|
|
55
|
-
ASSERT_EQ("mark", auth.username_for("default"));
|
|
56
|
-
ASSERT_EQ("", auth.password_for("default"));
|
|
57
|
-
ASSERT_EQ("mark", auth.username_for("jane"));
|
|
58
|
-
ASSERT_EQ("", auth.password_for("jane"));
|
|
55
|
+
ASSERT_EQ("mark", auth.username_for(NULL, NULL, "default"));
|
|
56
|
+
ASSERT_EQ("", auth.password_for(NULL, NULL, "default"));
|
|
57
|
+
ASSERT_EQ("mark", auth.username_for(NULL, NULL, "jane"));
|
|
58
|
+
ASSERT_EQ("", auth.password_for(NULL, NULL, "jane"));
|
|
59
59
|
|
|
60
60
|
// Try adding a new bucket, it should fail
|
|
61
61
|
ASSERT_EQ(LCB_OPTIONS_CONFLICT, auth.add("users", "secret", LCBAUTH_F_BUCKET));
|
|
@@ -68,8 +68,8 @@ TEST_F(CredsTest, testRbacCreds) {
|
|
|
68
68
|
|
|
69
69
|
// Try *changing* the credentials
|
|
70
70
|
ASSERT_EQ(LCB_SUCCESS, auth.add("jane", "seekrit", LCBAUTH_F_CLUSTER));
|
|
71
|
-
ASSERT_EQ("jane", auth.username_for("default"));
|
|
72
|
-
ASSERT_EQ("seekrit", auth.password_for("default"));
|
|
71
|
+
ASSERT_EQ("jane", auth.username_for(NULL, NULL, "default"));
|
|
72
|
+
ASSERT_EQ("seekrit", auth.password_for(NULL, NULL, "default"));
|
|
73
73
|
lcb_destroy(instance);
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -30,7 +30,7 @@ static bool hostEquals(const lcb_host_t &host, const char *addr, const char *por
|
|
|
30
30
|
|
|
31
31
|
TEST_F(Hostlist, testParseBasic)
|
|
32
32
|
{
|
|
33
|
-
lcb_host_t curhost;
|
|
33
|
+
lcb_host_t curhost = {0};
|
|
34
34
|
lcb_error_t err;
|
|
35
35
|
|
|
36
36
|
err = lcb_host_parsez(&curhost, "1.2.3.4", 8091);
|
|
@@ -59,12 +59,24 @@ TEST_F(Hostlist, testParseBasic)
|
|
|
59
59
|
|
|
60
60
|
err = lcb_host_parsez(&curhost, "localhost:1111111111111111111111111111", 100);
|
|
61
61
|
ASSERT_EQ(LCB_INVALID_HOST_FORMAT, err);
|
|
62
|
+
|
|
63
|
+
err = lcb_host_parsez(&curhost, "[::a15:f2df:4854:9ac6:8ceb:30a5]:9000", 8091);
|
|
64
|
+
ASSERT_EQ(LCB_SUCCESS, err);
|
|
65
|
+
ASSERT_TRUE(hostEquals(curhost, "::a15:f2df:4854:9ac6:8ceb:30a5", "9000"));
|
|
66
|
+
|
|
67
|
+
err = lcb_host_parsez(&curhost, "::a15:f2df:4854:9ac6:8ceb:30a5", 8091);
|
|
68
|
+
ASSERT_EQ(LCB_SUCCESS, err);
|
|
69
|
+
ASSERT_TRUE(hostEquals(curhost, "::a15:f2df:4854:9ac6:8ceb:30a5", "8091"));
|
|
70
|
+
|
|
71
|
+
err = lcb_host_parsez(&curhost, "::1", 8091);
|
|
72
|
+
ASSERT_EQ(LCB_SUCCESS, err);
|
|
73
|
+
ASSERT_TRUE(hostEquals(curhost, "::1", "8091"));
|
|
62
74
|
}
|
|
63
75
|
|
|
64
76
|
|
|
65
77
|
TEST_F(Hostlist, testEquals)
|
|
66
78
|
{
|
|
67
|
-
lcb_host_t host_a, host_b;
|
|
79
|
+
lcb_host_t host_a = {0}, host_b = {0};
|
|
68
80
|
strcpy(host_a.host, "foo.com");
|
|
69
81
|
strcpy(host_a.port, "1234");
|
|
70
82
|
strcpy(host_b.host, "foo.com");
|
|
@@ -149,6 +161,14 @@ TEST_F(Hostlist, testParseList)
|
|
|
149
161
|
hosts.randomize();
|
|
150
162
|
hosts.clear();
|
|
151
163
|
hosts.randomize();
|
|
164
|
+
|
|
165
|
+
hosts.clear();
|
|
166
|
+
err = hosts.add("fe80::dc59:5260:117d:33ec;[::a15:f2df:4854:9ac6:8ceb:30a5]:9000;::1:9000", 8091);
|
|
167
|
+
ASSERT_EQ(LCB_SUCCESS, err);
|
|
168
|
+
ASSERT_EQ(3, hosts.size());
|
|
169
|
+
ASSERT_TRUE(hosts.exists("[fe80::dc59:5260:117d:33ec]:8091"));
|
|
170
|
+
ASSERT_TRUE(hosts.exists("[::a15:f2df:4854:9ac6:8ceb:30a5]:9000"));
|
|
171
|
+
ASSERT_TRUE(hosts.exists("[::1:9000]:8091"));
|
|
152
172
|
}
|
|
153
173
|
|
|
154
174
|
TEST_F(Hostlist, testCycle)
|
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2018 Couchbase, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
#include "config.h"
|
|
18
|
+
#include <gtest/gtest.h>
|
|
19
|
+
|
|
20
|
+
#include "contrib/cbsasl/src/scram-sha/scram_utils.h"
|
|
21
|
+
|
|
22
|
+
class ScramTest : public ::testing::Test
|
|
23
|
+
{
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Tests the parse_server_challenge function.
|
|
28
|
+
*/
|
|
29
|
+
TEST_F(ScramTest, ParseValidServerChallenge)
|
|
30
|
+
{
|
|
31
|
+
const char *serverin = "r=CCCCSSSS,s=xxxx,i=4096";
|
|
32
|
+
const char *nonce = NULL;
|
|
33
|
+
unsigned int noncelength = 0;
|
|
34
|
+
const char *salt = NULL;
|
|
35
|
+
unsigned int saltlength = 0;
|
|
36
|
+
unsigned int itcount = 0;
|
|
37
|
+
|
|
38
|
+
cbsasl_error_t ret =
|
|
39
|
+
parse_server_challenge(serverin, strlen(serverin), &nonce, &noncelength, &salt, &saltlength, &itcount);
|
|
40
|
+
|
|
41
|
+
ASSERT_EQ(SASL_OK, ret);
|
|
42
|
+
EXPECT_EQ(8, noncelength);
|
|
43
|
+
EXPECT_EQ("CCCCSSSS", std::string(nonce, noncelength));
|
|
44
|
+
EXPECT_EQ(4, saltlength);
|
|
45
|
+
EXPECT_EQ("xxxx", std::string(salt, saltlength));
|
|
46
|
+
EXPECT_EQ(4096, itcount);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
TEST_F(ScramTest, ParseInvalidServerChallenge_WithWrongAttribute)
|
|
50
|
+
{
|
|
51
|
+
const char *serverin = "r=CCCCSSSS,t=xxxx,i=4096"; // 't' is not a valid attribute
|
|
52
|
+
const char *nonce = NULL;
|
|
53
|
+
unsigned int noncelength = 0;
|
|
54
|
+
const char *salt = NULL;
|
|
55
|
+
unsigned int saltlength = 0;
|
|
56
|
+
unsigned int itcount = 0;
|
|
57
|
+
|
|
58
|
+
cbsasl_error_t ret =
|
|
59
|
+
parse_server_challenge(serverin, strlen(serverin), &nonce, &noncelength, &salt, &saltlength, &itcount);
|
|
60
|
+
|
|
61
|
+
ASSERT_EQ(SASL_BADPARAM, ret);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
TEST_F(ScramTest, ParseInvalidServerChallenge_WithMissingAttributeType)
|
|
65
|
+
{
|
|
66
|
+
const char *serverin = "r=CCCCSSSS,xxxx,i=4096"; // no "s="
|
|
67
|
+
const char *nonce = NULL;
|
|
68
|
+
unsigned int noncelength = 0;
|
|
69
|
+
const char *salt = NULL;
|
|
70
|
+
unsigned int saltlength = 0;
|
|
71
|
+
unsigned int itcount = 0;
|
|
72
|
+
|
|
73
|
+
cbsasl_error_t ret =
|
|
74
|
+
parse_server_challenge(serverin, strlen(serverin), &nonce, &noncelength, &salt, &saltlength, &itcount);
|
|
75
|
+
|
|
76
|
+
ASSERT_EQ(SASL_BADPARAM, ret);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
TEST_F(ScramTest, ParseInvalidServerChallenge_WithVoidField)
|
|
80
|
+
{
|
|
81
|
+
const char *serverin = ",s=xxxx,i=4096";
|
|
82
|
+
const char *nonce = NULL;
|
|
83
|
+
unsigned int noncelength = 0;
|
|
84
|
+
const char *salt = NULL;
|
|
85
|
+
unsigned int saltlength = 0;
|
|
86
|
+
unsigned int itcount = 0;
|
|
87
|
+
|
|
88
|
+
cbsasl_error_t ret =
|
|
89
|
+
parse_server_challenge(serverin, strlen(serverin), &nonce, &noncelength, &salt, &saltlength, &itcount);
|
|
90
|
+
|
|
91
|
+
ASSERT_EQ(SASL_BADPARAM, ret);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
TEST_F(ScramTest, ParseInvalidServerChallenge_WithInvalidIterationCount)
|
|
95
|
+
{
|
|
96
|
+
const char *serverin = "r=CCCCSSSS,s=xxxx,i=123456789012345"; // value too big for an integer
|
|
97
|
+
const char *nonce = NULL;
|
|
98
|
+
unsigned int noncelength = 0;
|
|
99
|
+
const char *salt = NULL;
|
|
100
|
+
unsigned int saltlength = 0;
|
|
101
|
+
unsigned int itcount = 0;
|
|
102
|
+
|
|
103
|
+
cbsasl_error_t ret =
|
|
104
|
+
parse_server_challenge(serverin, strlen(serverin), &nonce, &noncelength, &salt, &saltlength, &itcount);
|
|
105
|
+
|
|
106
|
+
ASSERT_EQ(SASL_BADPARAM, ret);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
TEST_F(ScramTest, ParseInvalidServerChallenge_WithDuplicateAttribute)
|
|
110
|
+
{
|
|
111
|
+
const char *serverin = "r=CCCCSSSS,r=CCCCSSSS,s=xxxx,i=4096"; // "r" field appearing twice
|
|
112
|
+
const char *nonce = NULL;
|
|
113
|
+
unsigned int noncelength = 0;
|
|
114
|
+
const char *salt = NULL;
|
|
115
|
+
unsigned int saltlength = 0;
|
|
116
|
+
unsigned int itcount = 0;
|
|
117
|
+
|
|
118
|
+
cbsasl_error_t ret =
|
|
119
|
+
parse_server_challenge(serverin, strlen(serverin), &nonce, &noncelength, &salt, &saltlength, &itcount);
|
|
120
|
+
|
|
121
|
+
ASSERT_EQ(SASL_BADPARAM, ret);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// the following tests are valid only if OpenSSL is linked to the library
|
|
125
|
+
#ifndef LCB_NO_SSL
|
|
126
|
+
TEST_F(ScramTest, GenerateSaltedPasswordWithSHA512)
|
|
127
|
+
{
|
|
128
|
+
// here we check that the generate_salted_password function returns the expected output
|
|
129
|
+
// for a predefined password/salt/iteration count combination
|
|
130
|
+
union {
|
|
131
|
+
cbsasl_secret_t secret;
|
|
132
|
+
char buffer[30];
|
|
133
|
+
} u_auth;
|
|
134
|
+
unsigned char outbuffer[CBSASL_SHA512_DIGEST_SIZE];
|
|
135
|
+
unsigned int outlen;
|
|
136
|
+
const char *salt = "c2FsdA=="; // "salt" in base64
|
|
137
|
+
memcpy(u_auth.secret.data, "password", 8);
|
|
138
|
+
u_auth.secret.len = 8; // strlen("password")
|
|
139
|
+
// expected output was generated using the following Python algorithm:
|
|
140
|
+
// import hashlib, binascii
|
|
141
|
+
// dk = hashlib.pbkdf2_hmac('sha512', b'password', b'salt', 1000)
|
|
142
|
+
// print binascii.hexlify(dk)
|
|
143
|
+
const char *expectedoutput = "\xaf\xe6\xc5\x53\x07\x85\xb6\xcc\x6b\x1c\x64\x53\x38\x47\x31"
|
|
144
|
+
"\xbd\x5e\xe4\x32\xee\x54\x9f\xd4\x2f\xb6\x69\x57\x79\xad\x8a"
|
|
145
|
+
"\x1c\x5b\xf5\x9d\xe6\x9c\x48\xf7\x74\xef\xc4\x00\x7d\x52\x98"
|
|
146
|
+
"\xf9\x03\x3c\x02\x41\xd5\xab\x69\x30\x5e\x7b\x64\xec\xee\xb8"
|
|
147
|
+
"\xd8\x34\xcf\xec";
|
|
148
|
+
// warning: the expected output contains a binary zero, so don't use strlen()
|
|
149
|
+
|
|
150
|
+
cbsasl_error_t ret = generate_salted_password(SASL_AUTH_MECH_SCRAM_SHA512, &u_auth.secret, salt, strlen(salt), 1000,
|
|
151
|
+
outbuffer, &outlen);
|
|
152
|
+
ASSERT_EQ(SASL_OK, ret);
|
|
153
|
+
EXPECT_EQ(CBSASL_SHA512_DIGEST_SIZE, outlen);
|
|
154
|
+
EXPECT_EQ(std::string(expectedoutput, CBSASL_SHA512_DIGEST_SIZE),
|
|
155
|
+
std::string((const char *)outbuffer, CBSASL_SHA512_DIGEST_SIZE));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
TEST_F(ScramTest, GenerateSaltedPasswordWithSHA256)
|
|
159
|
+
{
|
|
160
|
+
// here we check that the generate_salted_password function returns the expected output
|
|
161
|
+
// for a predefined password/salt/iteration count combination
|
|
162
|
+
union {
|
|
163
|
+
cbsasl_secret_t secret;
|
|
164
|
+
char buffer[30];
|
|
165
|
+
} u_auth;
|
|
166
|
+
unsigned char outbuffer[CBSASL_SHA256_DIGEST_SIZE];
|
|
167
|
+
unsigned int outlen;
|
|
168
|
+
const char *salt = "c2FsdA=="; // "salt" in base64
|
|
169
|
+
memcpy(u_auth.secret.data, "password", 8);
|
|
170
|
+
u_auth.secret.len = 8; // strlen("password")
|
|
171
|
+
// expected output was generated using the following Python algorithm:
|
|
172
|
+
// import hashlib, binascii
|
|
173
|
+
// dk = hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 1000)
|
|
174
|
+
// print binascii.hexlify(dk)
|
|
175
|
+
const char *expectedoutput = "\x63\x2c\x28\x12\xe4\x6d\x46\x04\x10\x2b\xa7\x61\x8e\x9d\x6d"
|
|
176
|
+
"\x7d\x2f\x81\x28\xf6\x26\x6b\x4a\x03\x26\x4d\x2a\x04\x60\xb7"
|
|
177
|
+
"\xdc\xb3";
|
|
178
|
+
|
|
179
|
+
cbsasl_error_t ret = generate_salted_password(SASL_AUTH_MECH_SCRAM_SHA256, &u_auth.secret, salt, strlen(salt), 1000,
|
|
180
|
+
outbuffer, &outlen);
|
|
181
|
+
ASSERT_EQ(SASL_OK, ret);
|
|
182
|
+
EXPECT_EQ(CBSASL_SHA256_DIGEST_SIZE, outlen);
|
|
183
|
+
EXPECT_EQ(std::string(expectedoutput, CBSASL_SHA256_DIGEST_SIZE),
|
|
184
|
+
std::string((const char *)outbuffer, CBSASL_SHA256_DIGEST_SIZE));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
TEST_F(ScramTest, GenerateSaltedPasswordWithSHA1)
|
|
188
|
+
{
|
|
189
|
+
// here we check that the generate_salted_password function returns the expected output
|
|
190
|
+
// for a predefined password/salt/iteration count combination
|
|
191
|
+
union {
|
|
192
|
+
cbsasl_secret_t secret;
|
|
193
|
+
char buffer[30];
|
|
194
|
+
} u_auth;
|
|
195
|
+
unsigned char outbuffer[CBSASL_SHA1_DIGEST_SIZE];
|
|
196
|
+
unsigned int outlen;
|
|
197
|
+
const char *salt = "c2FsdA=="; // "salt" in base64
|
|
198
|
+
memcpy(u_auth.secret.data, "password", 8);
|
|
199
|
+
u_auth.secret.len = 8; // strlen("password")
|
|
200
|
+
// expected output was generated using the following Python algorithm:
|
|
201
|
+
// import hashlib, binascii
|
|
202
|
+
// dk = hashlib.pbkdf2_hmac('sha1', b'password', b'salt', 1000)
|
|
203
|
+
// print binascii.hexlify(dk)
|
|
204
|
+
const char *expectedoutput = "\x6e\x88\xbe\x8b\xad\x7e\xae\x9d\x9e\x10\xaa\x06\x12\x24\x03"
|
|
205
|
+
"\x4f\xed\x48\xd0\x3f";
|
|
206
|
+
|
|
207
|
+
cbsasl_error_t ret = generate_salted_password(SASL_AUTH_MECH_SCRAM_SHA1, &u_auth.secret, salt, strlen(salt), 1000,
|
|
208
|
+
outbuffer, &outlen);
|
|
209
|
+
ASSERT_EQ(SASL_OK, ret);
|
|
210
|
+
EXPECT_EQ(CBSASL_SHA1_DIGEST_SIZE, outlen);
|
|
211
|
+
EXPECT_EQ(std::string(expectedoutput, CBSASL_SHA1_DIGEST_SIZE),
|
|
212
|
+
std::string((const char *)outbuffer, CBSASL_SHA1_DIGEST_SIZE));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
TEST_F(ScramTest, ComputeClientProof_SHA512)
|
|
216
|
+
{
|
|
217
|
+
// we use the salted password computed in GenerateSaltedPasswordWithSHA512
|
|
218
|
+
const unsigned char *saltedpassword =
|
|
219
|
+
(const unsigned char *)"\xaf\xe6\xc5\x53\x07\x85\xb6\xcc\x6b\x1c\x64\x53\x38\x47\x31"
|
|
220
|
+
"\xbd\x5e\xe4\x32\xee\x54\x9f\xd4\x2f\xb6\x69\x57\x79\xad\x8a"
|
|
221
|
+
"\x1c\x5b\xf5\x9d\xe6\x9c\x48\xf7\x74\xef\xc4\x00\x7d\x52\x98"
|
|
222
|
+
"\xf9\x03\x3c\x02\x41\xd5\xab\x69\x30\x5e\x7b\x64\xec\xee\xb8"
|
|
223
|
+
"\xd8\x34\xcf\xec";
|
|
224
|
+
const char *clientfirstbare = "n=foo,r=001122334455667788";
|
|
225
|
+
const char *serverfirstmess = "r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000";
|
|
226
|
+
const char *clientfinalwithoutproof = "c=biws,r=00112233445566778899aabbccddeeff";
|
|
227
|
+
char *authmessage = NULL;
|
|
228
|
+
char outclientproof[(CBSASL_SHA512_DIGEST_SIZE / 3 + 1) * 4 + 1];
|
|
229
|
+
|
|
230
|
+
cbsasl_error_t ret =
|
|
231
|
+
compute_client_proof(SASL_AUTH_MECH_SCRAM_SHA512, saltedpassword, CBSASL_SHA512_DIGEST_SIZE, clientfirstbare,
|
|
232
|
+
strlen(clientfirstbare), serverfirstmess, strlen(serverfirstmess), clientfinalwithoutproof,
|
|
233
|
+
strlen(clientfinalwithoutproof), &authmessage, outclientproof, sizeof(outclientproof));
|
|
234
|
+
|
|
235
|
+
EXPECT_EQ(SASL_OK, ret);
|
|
236
|
+
// expected authentication message: concatenation of clientfirstbare, serverfirstmess and
|
|
237
|
+
// clientfinalwithoutproof (with commas)
|
|
238
|
+
const char *expectedauth = "n=foo,r=001122334455667788,"
|
|
239
|
+
"r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
240
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
241
|
+
|
|
242
|
+
EXPECT_TRUE(authmessage != NULL);
|
|
243
|
+
EXPECT_STREQ(expectedauth, authmessage);
|
|
244
|
+
|
|
245
|
+
// expected client proof
|
|
246
|
+
// Here is how to generate the same value in Python 2.7:
|
|
247
|
+
// import hmac, hashlib, base64
|
|
248
|
+
// saltedpassword = '\xaf\xe6\xc5\x53\x07\x85\xb6\xcc\x6b\x1c\x64\x53\x38\x47\x31\xbd\x5e\xe4\x32\xee'\
|
|
249
|
+
// '\x54\x9f\xd4\x2f\xb6\x69\x57\x79\xad\x8a\x1c\x5b\xf5\x9d\xe6\x9c\x48\xf7\x74\xef'\
|
|
250
|
+
// '\xc4\x00\x7d\x52\x98\xf9\x03\x3c\x02\x41\xd5\xab\x69\x30\x5e\x7b\x64\xec\xee\xb8\xd8\x34\xcf\xec'
|
|
251
|
+
// clientkey = hmac.new(saltedpassword, 'Client Key', hashlib.sha512).digest()
|
|
252
|
+
// storedkey = hashlib.sha512(clientkey).digest()
|
|
253
|
+
// authmess='n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,c=biws,r=00112233445566778899aabbccddeeff'
|
|
254
|
+
// clientsign = hmac.new(storedkey, authmess, hashlib.sha512).digest()
|
|
255
|
+
// clientproof = ''.join(chr(ord(cs) ^ ord(ck)) for cs,ck in zip(clientsign, clientkey))
|
|
256
|
+
// print base64.b64encode(clientproof)
|
|
257
|
+
EXPECT_STREQ("dbXLc1MsNIdWj1AgSHRi/6E0OhWG2j6MwLKHR+UyVotT3G7VgYPlkQjwaewpH7v5BMXgkIqKRP/IUEbNA0M40w==",
|
|
258
|
+
outclientproof);
|
|
259
|
+
|
|
260
|
+
free(authmessage);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
TEST_F(ScramTest, ComputeClientProof_SHA256)
|
|
264
|
+
{
|
|
265
|
+
// we use the salted password computed in GenerateSaltedPasswordWithSHA256
|
|
266
|
+
const unsigned char *saltedpassword =
|
|
267
|
+
(const unsigned char *)"\x63\x2c\x28\x12\xe4\x6d\x46\x04\x10\x2b\xa7\x61\x8e\x9d\x6d"
|
|
268
|
+
"\x7d\x2f\x81\x28\xf6\x26\x6b\x4a\x03\x26\x4d\x2a\x04\x60\xb7"
|
|
269
|
+
"\xdc\xb3";
|
|
270
|
+
const char *clientfirstbare = "n=foo,r=001122334455667788";
|
|
271
|
+
const char *serverfirstmess = "r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000";
|
|
272
|
+
const char *clientfinalwithoutproof = "c=biws,r=00112233445566778899aabbccddeeff";
|
|
273
|
+
char *authmessage = NULL;
|
|
274
|
+
char outclientproof[(CBSASL_SHA256_DIGEST_SIZE / 3 + 1) * 4 + 1];
|
|
275
|
+
|
|
276
|
+
cbsasl_error_t ret =
|
|
277
|
+
compute_client_proof(SASL_AUTH_MECH_SCRAM_SHA256, saltedpassword, CBSASL_SHA256_DIGEST_SIZE, clientfirstbare,
|
|
278
|
+
strlen(clientfirstbare), serverfirstmess, strlen(serverfirstmess), clientfinalwithoutproof,
|
|
279
|
+
strlen(clientfinalwithoutproof), &authmessage, outclientproof, sizeof(outclientproof));
|
|
280
|
+
|
|
281
|
+
EXPECT_EQ(SASL_OK, ret);
|
|
282
|
+
// expected authentication message: concatenation of clientfirstbare, serverfirstmess and
|
|
283
|
+
// clientfinalwithoutproof (with commas)
|
|
284
|
+
const char *expectedauth = "n=foo,r=001122334455667788,"
|
|
285
|
+
"r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
286
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
287
|
+
|
|
288
|
+
EXPECT_TRUE(authmessage != NULL);
|
|
289
|
+
EXPECT_STREQ(expectedauth, authmessage);
|
|
290
|
+
|
|
291
|
+
// expected client proof
|
|
292
|
+
// Here is how to generate the same value in Python 2.7:
|
|
293
|
+
// import hmac, hashlib, base64
|
|
294
|
+
// saltedpassword = '\x63\x2c\x28\x12\xe4\x6d\x46\x04\x10\x2b\xa7\x61\x8e\x9d\x6d'\
|
|
295
|
+
// '\x7d\x2f\x81\x28\xf6\x26\x6b\x4a\x03\x26\x4d\x2a\x04\x60\xb7'\
|
|
296
|
+
// '\xdc\xb3'
|
|
297
|
+
// clientkey = hmac.new(saltedpassword, 'Client Key', hashlib.sha256).digest()
|
|
298
|
+
// storedkey = hashlib.sha256(clientkey).digest()
|
|
299
|
+
// authmess='n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,c=biws,r=00112233445566778899aabbccddeeff'
|
|
300
|
+
// clientsign = hmac.new(storedkey, authmess, hashlib.sha256).digest()
|
|
301
|
+
// clientproof = ''.join(chr(ord(cs) ^ ord(ck)) for cs,ck in zip(clientsign, clientkey))
|
|
302
|
+
// print base64.b64encode(clientproof)
|
|
303
|
+
EXPECT_STREQ("V2VMc1luh0OKg7VgRO2Wt7BoBUaW8ZxUhNav2RUbAHc=", outclientproof);
|
|
304
|
+
|
|
305
|
+
free(authmessage);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
TEST_F(ScramTest, ComputeClientProof_SHA1)
|
|
309
|
+
{
|
|
310
|
+
// we use the salted password computed in GenerateSaltedPasswordWithSHA1
|
|
311
|
+
const unsigned char *saltedpassword =
|
|
312
|
+
(const unsigned char *)"\x6e\x88\xbe\x8b\xad\x7e\xae\x9d\x9e\x10\xaa\x06\x12\x24\x03"
|
|
313
|
+
"\x4f\xed\x48\xd0\x3f";
|
|
314
|
+
const char *clientfirstbare = "n=foo,r=001122334455667788";
|
|
315
|
+
const char *serverfirstmess = "r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000";
|
|
316
|
+
const char *clientfinalwithoutproof = "c=biws,r=00112233445566778899aabbccddeeff";
|
|
317
|
+
char *authmessage = NULL;
|
|
318
|
+
char outclientproof[(CBSASL_SHA1_DIGEST_SIZE / 3 + 1) * 4 + 1];
|
|
319
|
+
|
|
320
|
+
cbsasl_error_t ret =
|
|
321
|
+
compute_client_proof(SASL_AUTH_MECH_SCRAM_SHA1, saltedpassword, CBSASL_SHA1_DIGEST_SIZE, clientfirstbare,
|
|
322
|
+
strlen(clientfirstbare), serverfirstmess, strlen(serverfirstmess), clientfinalwithoutproof,
|
|
323
|
+
strlen(clientfinalwithoutproof), &authmessage, outclientproof, sizeof(outclientproof));
|
|
324
|
+
|
|
325
|
+
EXPECT_EQ(SASL_OK, ret);
|
|
326
|
+
// expected authentication message: concatenation of clientfirstbare, serverfirstmess and
|
|
327
|
+
// clientfinalwithoutproof (with commas)
|
|
328
|
+
const char *expectedauth = "n=foo,r=001122334455667788,"
|
|
329
|
+
"r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
330
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
331
|
+
|
|
332
|
+
EXPECT_TRUE(authmessage != NULL);
|
|
333
|
+
EXPECT_STREQ(expectedauth, authmessage);
|
|
334
|
+
|
|
335
|
+
// expected client proof
|
|
336
|
+
// Here is how to generate the same value in Python 2.7:
|
|
337
|
+
// import hmac, hashlib, base64
|
|
338
|
+
// saltedpassword = '\x6e\x88\xbe\x8b\xad\x7e\xae\x9d\x9e\x10\xaa\x06\x12\x24\x03'\
|
|
339
|
+
// '\x4f\xed\x48\xd0\x3f'
|
|
340
|
+
// clientkey = hmac.new(saltedpassword, 'Client Key', hashlib.sha1).digest()
|
|
341
|
+
// storedkey = hashlib.sha1(clientkey).digest()
|
|
342
|
+
// authmess='n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,c=biws,r=00112233445566778899aabbccddeeff'
|
|
343
|
+
// clientsign = hmac.new(storedkey, authmess, hashlib.sha1).digest()
|
|
344
|
+
// clientproof = ''.join(chr(ord(cs) ^ ord(ck)) for cs,ck in zip(clientsign, clientkey))
|
|
345
|
+
// print base64.b64encode(clientproof)
|
|
346
|
+
EXPECT_STREQ("Iu9QH+CO2nAtVwmJaQe55UzlBEQ=", outclientproof);
|
|
347
|
+
|
|
348
|
+
free(authmessage);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
TEST_F(ScramTest, ComputeServerSignature_SHA512)
|
|
352
|
+
{
|
|
353
|
+
// we use the salted password computed in GenerateSaltedPasswordWithSHA512
|
|
354
|
+
const unsigned char *saltedpassword =
|
|
355
|
+
(const unsigned char *)"\xaf\xe6\xc5\x53\x07\x85\xb6\xcc\x6b\x1c\x64\x53\x38\x47\x31"
|
|
356
|
+
"\xbd\x5e\xe4\x32\xee\x54\x9f\xd4\x2f\xb6\x69\x57\x79\xad\x8a"
|
|
357
|
+
"\x1c\x5b\xf5\x9d\xe6\x9c\x48\xf7\x74\xef\xc4\x00\x7d\x52\x98"
|
|
358
|
+
"\xf9\x03\x3c\x02\x41\xd5\xab\x69\x30\x5e\x7b\x64\xec\xee\xb8"
|
|
359
|
+
"\xd8\x34\xcf\xec";
|
|
360
|
+
const char *authmessage = "n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
361
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
362
|
+
char outserversign[(CBSASL_SHA512_DIGEST_SIZE / 3 + 1) * 4 + 1];
|
|
363
|
+
|
|
364
|
+
cbsasl_error_t ret =
|
|
365
|
+
compute_server_signature(SASL_AUTH_MECH_SCRAM_SHA512, saltedpassword, CBSASL_SHA512_DIGEST_SIZE, authmessage,
|
|
366
|
+
outserversign, sizeof(outserversign));
|
|
367
|
+
|
|
368
|
+
EXPECT_EQ(SASL_OK, ret);
|
|
369
|
+
|
|
370
|
+
// expected client proof
|
|
371
|
+
// Here is how to generate the same value in Python 2.7:
|
|
372
|
+
// import hmac, hashlib, base64
|
|
373
|
+
// saltedpassword = '\xaf\xe6\xc5\x53\x07\x85\xb6\xcc\x6b\x1c\x64\x53\x38\x47\x31\xbd\x5e\xe4\x32\xee'\
|
|
374
|
+
// '\x54\x9f\xd4\x2f\xb6\x69\x57\x79\xad\x8a\x1c\x5b\xf5\x9d\xe6\x9c\x48\xf7\x74\xef'\
|
|
375
|
+
// '\xc4\x00\x7d\x52\x98\xf9\x03\x3c\x02\x41\xd5\xab\x69\x30\x5e\x7b\x64\xec\xee\xb8\xd8\x34\xcf\xec'
|
|
376
|
+
// serverkey = hmac.new(saltedpassword, 'Server Key', hashlib.sha512).digest()
|
|
377
|
+
// authmess='n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,c=biws,r=00112233445566778899aabbccddeeff'
|
|
378
|
+
// serversign = hmac.new(serverkey, authmess, hashlib.sha512).digest()
|
|
379
|
+
// print base64.b64encode(serversign)
|
|
380
|
+
EXPECT_STREQ("qonE7dZI6HvlX7nzSxbwmXBnr8xbw1pLhcwGFfnh+q1kqT+VoIood7EReeGXSog9Q9UNxqYKITudfYvSxJCQzg==",
|
|
381
|
+
outserversign);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
TEST_F(ScramTest, ComputeServerSignature_SHA256)
|
|
385
|
+
{
|
|
386
|
+
// we use the salted password computed in GenerateSaltedPasswordWithSHA256
|
|
387
|
+
const unsigned char *saltedpassword =
|
|
388
|
+
(const unsigned char *)"\x63\x2c\x28\x12\xe4\x6d\x46\x04\x10\x2b\xa7\x61\x8e\x9d\x6d"
|
|
389
|
+
"\x7d\x2f\x81\x28\xf6\x26\x6b\x4a\x03\x26\x4d\x2a\x04\x60\xb7"
|
|
390
|
+
"\xdc\xb3";
|
|
391
|
+
const char *authmessage = "n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
392
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
393
|
+
char outserversign[(CBSASL_SHA256_DIGEST_SIZE / 3 + 1) * 4 + 1];
|
|
394
|
+
|
|
395
|
+
cbsasl_error_t ret =
|
|
396
|
+
compute_server_signature(SASL_AUTH_MECH_SCRAM_SHA256, saltedpassword, CBSASL_SHA256_DIGEST_SIZE, authmessage,
|
|
397
|
+
outserversign, sizeof(outserversign));
|
|
398
|
+
|
|
399
|
+
EXPECT_EQ(SASL_OK, ret);
|
|
400
|
+
|
|
401
|
+
// expected client proof
|
|
402
|
+
// Here is how to generate the same value in Python 2.7:
|
|
403
|
+
// import hmac, hashlib, base64
|
|
404
|
+
// saltedpassword = '\x63\x2c\x28\x12\xe4\x6d\x46\x04\x10\x2b\xa7\x61\x8e\x9d\x6d'\
|
|
405
|
+
// '\x7d\x2f\x81\x28\xf6\x26\x6b\x4a\x03\x26\x4d\x2a\x04\x60\xb7'\
|
|
406
|
+
// '\xdc\xb3'
|
|
407
|
+
// serverkey = hmac.new(saltedpassword, 'Server Key', hashlib.sha256).digest()
|
|
408
|
+
// authmess='n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,c=biws,r=00112233445566778899aabbccddeeff'
|
|
409
|
+
// serversign = hmac.new(serverkey, authmess, hashlib.sha256).digest()
|
|
410
|
+
// print base64.b64encode(serversign)
|
|
411
|
+
EXPECT_STREQ("iPG9IiKPBI9165j9aGfbGM9FwHsANnspy5pMGJUbaS8=", outserversign);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
TEST_F(ScramTest, ComputeServerSignature_SHA1)
|
|
415
|
+
{
|
|
416
|
+
// we use the salted password computed in GenerateSaltedPasswordWithSHA1
|
|
417
|
+
const unsigned char *saltedpassword =
|
|
418
|
+
(const unsigned char *)"\x6e\x88\xbe\x8b\xad\x7e\xae\x9d\x9e\x10\xaa\x06\x12\x24\x03"
|
|
419
|
+
"\x4f\xed\x48\xd0\x3f";
|
|
420
|
+
const char *authmessage = "n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
421
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
422
|
+
char outserversign[(CBSASL_SHA1_DIGEST_SIZE / 3 + 1) * 4 + 1];
|
|
423
|
+
|
|
424
|
+
cbsasl_error_t ret = compute_server_signature(SASL_AUTH_MECH_SCRAM_SHA1, saltedpassword, CBSASL_SHA1_DIGEST_SIZE,
|
|
425
|
+
authmessage, outserversign, sizeof(outserversign));
|
|
426
|
+
|
|
427
|
+
EXPECT_EQ(SASL_OK, ret);
|
|
428
|
+
|
|
429
|
+
// expected client proof
|
|
430
|
+
// Here is how to generate the same value in Python 2.7:
|
|
431
|
+
// import hmac, hashlib, base64
|
|
432
|
+
// saltedpassword = '\x6e\x88\xbe\x8b\xad\x7e\xae\x9d\x9e\x10\xaa\x06\x12\x24\x03'\
|
|
433
|
+
// '\x4f\xed\x48\xd0\x3f'
|
|
434
|
+
// serverkey = hmac.new(saltedpassword, 'Server Key', hashlib.sha1).digest()
|
|
435
|
+
// authmess='n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,c=biws,r=00112233445566778899aabbccddeeff'
|
|
436
|
+
// serversign = hmac.new(serverkey, authmess, hashlib.sha1).digest()
|
|
437
|
+
// print base64.b64encode(serversign)
|
|
438
|
+
EXPECT_STREQ("WfiXP3zx55r8GXP1n2Bz/FVk/hk=", outserversign);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
TEST_F(ScramTest, FinalServerCheck_SHA512)
|
|
442
|
+
{
|
|
443
|
+
// Testing cbsasl_client_check
|
|
444
|
+
cbsasl_conn_t ctx;
|
|
445
|
+
ctx.client = 1;
|
|
446
|
+
ctx.c.client.auth_mech = SASL_AUTH_MECH_SCRAM_SHA512;
|
|
447
|
+
// for computing the server signature, we only need the salted password and
|
|
448
|
+
// the authentication message
|
|
449
|
+
ctx.c.client.saltedpassword = (unsigned char *)"\xaf\xe6\xc5\x53\x07\x85\xb6\xcc\x6b\x1c\x64\x53\x38\x47\x31"
|
|
450
|
+
"\xbd\x5e\xe4\x32\xee\x54\x9f\xd4\x2f\xb6\x69\x57\x79\xad\x8a"
|
|
451
|
+
"\x1c\x5b\xf5\x9d\xe6\x9c\x48\xf7\x74\xef\xc4\x00\x7d\x52\x98"
|
|
452
|
+
"\xf9\x03\x3c\x02\x41\xd5\xab\x69\x30\x5e\x7b\x64\xec\xee\xb8"
|
|
453
|
+
"\xd8\x34\xcf\xec";
|
|
454
|
+
ctx.c.client.saltedpasslen = CBSASL_SHA512_DIGEST_SIZE;
|
|
455
|
+
ctx.c.client.auth_message =
|
|
456
|
+
(char *)"n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
457
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
458
|
+
const char *invalid_sign =
|
|
459
|
+
"v=USEHlpFIwMJu0ytKPTmXPTXzZag82/F9qkAT2gB0gVaA00RTdQeSgCPhMVWcmvp7dhscVnkE/ZYLbDpMaeMp6g==";
|
|
460
|
+
EXPECT_EQ(SASL_FAIL, cbsasl_client_check(&ctx, invalid_sign, strlen(invalid_sign)));
|
|
461
|
+
|
|
462
|
+
const char *valid_sign =
|
|
463
|
+
"v=qonE7dZI6HvlX7nzSxbwmXBnr8xbw1pLhcwGFfnh+q1kqT+VoIood7EReeGXSog9Q9UNxqYKITudfYvSxJCQzg==";
|
|
464
|
+
EXPECT_EQ(SASL_OK, cbsasl_client_check(&ctx, valid_sign, strlen(valid_sign)));
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
TEST_F(ScramTest, FinalServerCheck_SHA256)
|
|
468
|
+
{
|
|
469
|
+
// Testing cbsasl_client_check
|
|
470
|
+
cbsasl_conn_t ctx;
|
|
471
|
+
ctx.client = 1;
|
|
472
|
+
ctx.c.client.auth_mech = SASL_AUTH_MECH_SCRAM_SHA256;
|
|
473
|
+
// for computing the server signature, we only need the salted password and
|
|
474
|
+
// the authentication message
|
|
475
|
+
ctx.c.client.saltedpassword = (unsigned char *)"\x63\x2c\x28\x12\xe4\x6d\x46\x04\x10\x2b\xa7\x61\x8e\x9d\x6d"
|
|
476
|
+
"\x7d\x2f\x81\x28\xf6\x26\x6b\x4a\x03\x26\x4d\x2a\x04\x60\xb7"
|
|
477
|
+
"\xdc\xb3";
|
|
478
|
+
ctx.c.client.saltedpasslen = CBSASL_SHA256_DIGEST_SIZE;
|
|
479
|
+
ctx.c.client.auth_message =
|
|
480
|
+
(char *)"n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
481
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
482
|
+
|
|
483
|
+
const char *invalid_sign =
|
|
484
|
+
"v=USEHlpFIwMJu0ytKPTmXPTXzZag82/F9qkAT2gB0gVaA00RTdQeSgCPhMVWcmvp7dhscVnkE/ZYLbDpMaeMp6g==";
|
|
485
|
+
EXPECT_EQ(SASL_FAIL, cbsasl_client_check(&ctx, invalid_sign, strlen(invalid_sign)));
|
|
486
|
+
|
|
487
|
+
const char *valid_sign = "v=iPG9IiKPBI9165j9aGfbGM9FwHsANnspy5pMGJUbaS8=";
|
|
488
|
+
EXPECT_EQ(SASL_OK, cbsasl_client_check(&ctx, valid_sign, strlen(valid_sign)));
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
TEST_F(ScramTest, FinalServerCheck_SHA1)
|
|
492
|
+
{
|
|
493
|
+
// Testing cbsasl_client_check
|
|
494
|
+
cbsasl_conn_t ctx;
|
|
495
|
+
ctx.client = 1;
|
|
496
|
+
ctx.c.client.auth_mech = SASL_AUTH_MECH_SCRAM_SHA1;
|
|
497
|
+
// for computing the server signature, we only need the salted password and
|
|
498
|
+
// the authentication message
|
|
499
|
+
ctx.c.client.saltedpassword = (unsigned char *)"\x6e\x88\xbe\x8b\xad\x7e\xae\x9d\x9e\x10\xaa\x06\x12\x24\x03"
|
|
500
|
+
"\x4f\xed\x48\xd0\x3f";
|
|
501
|
+
ctx.c.client.saltedpasslen = CBSASL_SHA1_DIGEST_SIZE;
|
|
502
|
+
ctx.c.client.auth_message =
|
|
503
|
+
(char *)"n=foo,r=001122334455667788,r=00112233445566778899aabbccddeeff,s=c2FsdA==,i=1000,"
|
|
504
|
+
"c=biws,r=00112233445566778899aabbccddeeff";
|
|
505
|
+
|
|
506
|
+
const char *invalid_sign =
|
|
507
|
+
"v=USEHlpFIwMJu0ytKPTmXPTXzZag82/F9qkAT2gB0gVaA00RTdQeSgCPhMVWcmvp7dhscVnkE/ZYLbDpMaeMp6g==";
|
|
508
|
+
EXPECT_EQ(SASL_FAIL, cbsasl_client_check(&ctx, invalid_sign, strlen(invalid_sign)));
|
|
509
|
+
|
|
510
|
+
const char *valid_sign = "v=WfiXP3zx55r8GXP1n2Bz/FVk/hk=";
|
|
511
|
+
EXPECT_EQ(SASL_OK, cbsasl_client_check(&ctx, valid_sign, strlen(valid_sign)));
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
#endif // LCB_NO_SSL
|