1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2016 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 
18 #ifdef WIN32
19 #error "This file should not be included on windows"
20 #endif
21 
22 #include <atomic>
23 #include <thread>
24 #include "testapp.h"
25 #include "testapp_client_test.h"
26 #include "saslauthd_mock.h"
27 
28 static char cbauth_env_var[256];
29 
30 std::unique_ptr<SaslauthdMock> authdMock;
31 
32 // This class acts as a "guard". If we get an exception we can be sure that
33 // the thread will be joined, and that thread::~thread() won't abort because
34 // it wasn't join()d yet.
35 class MockAuthServer {
36 public:
MockAuthServer()37     MockAuthServer() : thread([](){authdMock->processOne();}){
38     }
39 
~MockAuthServer()40     ~MockAuthServer() {
41         thread.join();
42     }
43 
44 private:
45     std::thread thread;
46 };
47 
48 class SaslauthdTest : public TestappClientTest {
49 public:
SetUpTestCase()50     static void SetUpTestCase() {
51         authdMock.reset(new SaslauthdMock);
52         std::string env{"CBAUTH_SOCKPATH=" + authdMock->getSockfile() };
53         if (env.size() + 1 > sizeof(cbauth_env_var)) {
54             throw std::overflow_error("SaslauthdTest::SetUpTestCase: "
55                                           "buffer for socket path is too"
56                                           " small");
57         }
58         strcpy(cbauth_env_var, env.c_str());
59         putenv(cbauth_env_var);
60         TestappClientTest::SetUpTestCase();
61     }
62 
TearDownTestCase()63     static void TearDownTestCase() {
64         unsetenv("CBAUTH_SOCKPATH");
65         TestappClientTest::TearDownTestCase();
66     }
67 };
68 
69 INSTANTIATE_TEST_CASE_P(TransportProtocols,
70                         SaslauthdTest,
71     ::testing::Values(TransportProtocols::McbpPlain,
72                       TransportProtocols::McbpIpv6Plain,
73                       TransportProtocols::McbpSsl,
74                       TransportProtocols::McbpIpv6Ssl
75                      ),
76     ::testing::PrintToStringParamName());
77 
TEST_P(SaslauthdTest, TestSuccessfulSaslauthd)78 TEST_P(SaslauthdTest, TestSuccessfulSaslauthd) {
79     MemcachedConnection& conn = getConnection();
80     MockAuthServer saslauthd;
81     conn.authenticate("superman", "<3LoisLane<3", "PLAIN");
82 }
83 
TEST_P(SaslauthdTest, TestIncorrectSaslauthd)84 TEST_P(SaslauthdTest, TestIncorrectSaslauthd) {
85     MemcachedConnection& conn = getConnection();
86     MockAuthServer saslauthd;
87 
88     EXPECT_THROW(conn.authenticate("superman", "Lane<3", "PLAIN"),
89                  std::runtime_error);
90 }
91 
TEST_P(SaslauthdTest, TestUnknownUser)92 TEST_P(SaslauthdTest, TestUnknownUser) {
93     MemcachedConnection& conn = getConnection();
94     MockAuthServer saslauthd;
95     EXPECT_THROW(conn.authenticate("godzilla", "Lane<3", "PLAIN"),
96                  std::runtime_error);
97 }
98 
TEST_P(SaslauthdTest, TestKnownSaslauthdUnknownMech)99 TEST_P(SaslauthdTest, TestKnownSaslauthdUnknownMech) {
100     MemcachedConnection& conn = getConnection();
101     EXPECT_THROW(conn.authenticate("superman", "<3LoisLane<3", "SCRAM-SHA1"),
102                  std::runtime_error);
103 }
104