1 /* Copyright (c) 2012, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
22 
23 // First include (the generated) my_config.h, to get correct platform defines.
24 #include "my_config.h"
25 #include <gtest/gtest.h>
26 #include "test_utils.h"
27 
28 #include "my_global.h"
29 #include "named_pipe.h"
30 #include "log.h"
31 #include "my_thread.h"
32 #include <sddl.h>
33 
34 namespace win_unittest {
35 using my_testing::Server_initializer;
36 using my_testing::Mock_error_handler;
37 
38 class NamedPipeTest : public ::testing::Test
39 {
40 protected:
SetUpTestCase()41   static void SetUpTestCase()
42   {
43     m_old_error_handler_hook = error_handler_hook;
44     // Make sure my_error() ends up calling my_message_sql so that
45     // Mock_error_handler is actually triggered.
46     error_handler_hook = my_message_sql;
47   }
48 
TearDownTestCase()49   static void TearDownTestCase()
50   {
51     error_handler_hook = m_old_error_handler_hook;
52   }
53 
SetUp()54   virtual void SetUp()
55   {
56     m_initializer.SetUp();
57 
58     char pipe_rand_name[256];
59 
60     m_pipe_handle= INVALID_HANDLE_VALUE;
61 
62     /*
63       Generate a Unique Pipe Name incase multiple instances of the test is run.
64     */
65     sprintf_s(pipe_rand_name, sizeof(pipe_rand_name), "Pipe-%x",
66               GetTickCount());
67 
68     const ::testing::TestInfo* const test_info =
69       ::testing::UnitTest::GetInstance()->current_test_info();
70 
71     m_name.append(pipe_rand_name);
72     m_name.append("gunit");
73     m_name.append(test_info->name());
74   }
75 
TearDown()76   virtual void TearDown()
77   {
78     if (m_pipe_handle != INVALID_HANDLE_VALUE)
79     {
80       EXPECT_TRUE(CloseHandle(m_pipe_handle));
81     }
82     m_initializer.TearDown();
83   }
84 
85   SECURITY_ATTRIBUTES *mp_sec_attr;
86   char                m_pipe_name[256];
87   HANDLE              m_pipe_handle;
88   std::string         m_name;
89   Server_initializer  m_initializer;
90 
91   static void(*m_old_error_handler_hook)(uint, const char *, myf);
92 };
93 void(*NamedPipeTest::m_old_error_handler_hook)(uint, const char *, myf);
94 
95 
96 // Basic test: create a named pipe.
TEST_F(NamedPipeTest,CreatePipe)97 TEST_F(NamedPipeTest, CreatePipe)
98 {
99   char exp_pipe_name[256];
100 
101   m_pipe_handle= create_server_named_pipe(&mp_sec_attr,
102                                           1024,
103                                           m_name.c_str(),
104                                           m_pipe_name,
105                                           sizeof(m_pipe_name));
106 
107   strxnmov(exp_pipe_name, sizeof(exp_pipe_name) - 1, "\\\\.\\pipe\\",
108            m_name.c_str(), NullS);
109 
110   EXPECT_STREQ(m_pipe_name, exp_pipe_name);
111   EXPECT_NE(INVALID_HANDLE_VALUE, m_pipe_handle);
112 }
113 
114 
115 // Verify that we fail if we try to create the same named pipe twice.
TEST_F(NamedPipeTest,CreatePipeTwice)116 TEST_F(NamedPipeTest, CreatePipeTwice)
117 {
118   m_pipe_handle= create_server_named_pipe(&mp_sec_attr,
119                                           1024,
120                                           m_name.c_str(),
121                                           m_pipe_name,
122                                           sizeof(m_pipe_name));
123   EXPECT_NE(INVALID_HANDLE_VALUE, m_pipe_handle);
124 
125   Mock_error_handler error_handler(m_initializer.thd(),
126                                    ER_CANT_START_SERVER_NAMED_PIPE);
127   HANDLE handle= create_server_named_pipe(&mp_sec_attr,
128                                           1024,
129                                           m_name.c_str(),
130                                           m_pipe_name,
131                                           sizeof(m_pipe_name));
132   EXPECT_EQ(INVALID_HANDLE_VALUE, handle);
133 }
134 
135 // Verify that a warning is written to the error log when using
136 // "*everyone* as the full access group name.
TEST_F(NamedPipeTest,CreatePipeForEveryone)137 TEST_F(NamedPipeTest, CreatePipeForEveryone)
138 {
139   Mock_error_handler error_handler(m_initializer.thd(),
140                                    WARN_NAMED_PIPE_ACCESS_EVERYONE);
141   m_pipe_handle = create_server_named_pipe(&mp_sec_attr,
142                                            1024,
143                                            m_name.c_str(),
144                                            m_pipe_name,
145                                            sizeof(m_pipe_name),
146                                            "*everyone*");
147   EXPECT_NE(INVALID_HANDLE_VALUE, m_pipe_handle);
148 }
149 
150 // Verify that a warning is written to the error log when using
151 // the group name corresponding to the built in Windows group
152 // with SID S-1-1-0  (i.e. "everyone" on English systems)
TEST_F(NamedPipeTest,CreatePipeForEveryoneSid)153 TEST_F(NamedPipeTest, CreatePipeForEveryoneSid)
154 {
155   PSID everyone_SID;
156   EXPECT_TRUE(ConvertStringSidToSid("S-1-1-0", &everyone_SID));
157   const DWORD max_name_len = 256;
158   char everyone_name[max_name_len];
159   DWORD everyone_name_size = max_name_len;
160   char domain_name[max_name_len];
161   DWORD domain_name_size = max_name_len;
162   SID_NAME_USE name_use;
163 
164   EXPECT_TRUE(LookupAccountSid(NULL, everyone_SID, everyone_name, &everyone_name_size,
165                                domain_name, &domain_name_size, &name_use));
166   // The "S-1-1-0" SID is well known, so we expect the domain_name to empty and
167   // the name_use to be SidTypeWellKnownGroup
168   EXPECT_EQ(domain_name_size, 0);
169   EXPECT_EQ(name_use, SidTypeWellKnownGroup);
170 
171   Mock_error_handler error_handler(m_initializer.thd(),
172                                    WARN_NAMED_PIPE_ACCESS_EVERYONE);
173   m_pipe_handle = create_server_named_pipe(&mp_sec_attr,
174                                            1024,
175                                            m_name.c_str(),
176                                            m_pipe_name,
177                                            sizeof(m_pipe_name),
178                                            everyone_name);
179   EXPECT_NE(INVALID_HANDLE_VALUE, m_pipe_handle);
180 }
181 
182 }
183