libzmq  master
ZeroMQ C++ Core Engine (LIBZMQ)
test_security_plain.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 
4  This file is part of libzmq, the ZeroMQ core engine in C++.
5 
6  libzmq is free software; you can redistribute it and/or modify it under
7  the terms of the GNU Lesser General Public License (LGPL) as published
8  by the Free Software Foundation; either version 3 of the License, or
9  (at your option) any later version.
10 
11  As a special exception, the Contributors give you permission to link
12  this library with independent modules to produce an executable,
13  regardless of the license terms of these independent modules, and to
14  copy and distribute the resulting executable under terms of your choice,
15  provided that you also meet, for each linked independent module, the
16  terms and conditions of the license of that module. An independent
17  module is a module which is not derived from or based on this library.
18  If you modify this library, you must extend this exception to your
19  version of the library.
20 
21  libzmq is distributed in the hope that it will be useful, but WITHOUT
22  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24  License for more details.
25 
26  You should have received a copy of the GNU Lesser General Public License
27  along with this program. If not, see <http://www.gnu.org/licenses/>.
28 */
29 
30 #include "testutil.hpp"
31 #if defined (ZMQ_HAVE_WINDOWS)
32 # include <winsock2.h>
33 # include <ws2tcpip.h>
34 # include <stdexcept>
35 # define close closesocket
36 #else
37 # include <sys/socket.h>
38 # include <netinet/in.h>
39 # include <arpa/inet.h>
40 # include <unistd.h>
41 #endif
42 
43 static void
44 zap_handler (void *ctx)
45 {
46  // Create and bind ZAP socket
47  void *zap = zmq_socket (ctx, ZMQ_REP);
48  assert (zap);
49  int rc = zmq_bind (zap, "inproc://zeromq.zap.01");
50  assert (rc == 0);
51 
52  // Process ZAP requests forever
53  while (true) {
54  char *version = s_recv (zap);
55  if (!version)
56  break; // Terminating
57  char *sequence = s_recv (zap);
58  char *domain = s_recv (zap);
59  char *address = s_recv (zap);
60  char *identity = s_recv (zap);
61  char *mechanism = s_recv (zap);
62  char *username = s_recv (zap);
63  char *password = s_recv (zap);
64 
65  assert (streq (version, "1.0"));
66  assert (streq (mechanism, "PLAIN"));
67  assert (streq (identity, "IDENT"));
68 
69  s_sendmore (zap, version);
70  s_sendmore (zap, sequence);
71  if (streq (username, "admin")
72  && streq (password, "password")) {
73  s_sendmore (zap, "200");
74  s_sendmore (zap, "OK");
75  s_sendmore (zap, "anonymous");
76  s_send (zap, "");
77  }
78  else {
79  s_sendmore (zap, "400");
80  s_sendmore (zap, "Invalid username or password");
81  s_sendmore (zap, "");
82  s_send (zap, "");
83  }
84  free (version);
85  free (sequence);
86  free (domain);
87  free (address);
88  free (identity);
89  free (mechanism);
90  free (username);
91  free (password);
92  }
93  rc = zmq_close (zap);
94  assert (rc == 0);
95 }
96 
97 int main (void)
98 {
100  void *ctx = zmq_ctx_new ();
101  assert (ctx);
102 
103  // Spawn ZAP handler
104  void *zap_thread = zmq_threadstart (&zap_handler, ctx);
105 
106  // Server socket will accept connections
107  void *server = zmq_socket (ctx, ZMQ_DEALER);
108  assert (server);
109  int rc = zmq_setsockopt (server, ZMQ_IDENTITY, "IDENT", 6);
110  assert (rc == 0);
111  int as_server = 1;
112  rc = zmq_setsockopt (server, ZMQ_PLAIN_SERVER, &as_server, sizeof (int));
113  assert (rc == 0);
114  rc = zmq_bind (server, "tcp://127.0.0.1:9998");
115  assert (rc == 0);
116 
117  char username [256];
118  char password [256];
119 
120  // Check PLAIN security with correct username/password
121  void *client = zmq_socket (ctx, ZMQ_DEALER);
122  assert (client);
123  strcpy (username, "admin");
124  rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username));
125  assert (rc == 0);
126  strcpy (password, "password");
127  rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password));
128  assert (rc == 0);
129  rc = zmq_connect (client, "tcp://localhost:9998");
130  assert (rc == 0);
131  bounce (server, client);
132  rc = zmq_close (client);
133  assert (rc == 0);
134 
135  // Check PLAIN security with badly configured client (as_server)
136  // This will be caught by the plain_server class, not passed to ZAP
137  client = zmq_socket (ctx, ZMQ_DEALER);
138  assert (client);
139  as_server = 1;
140  rc = zmq_setsockopt (client, ZMQ_PLAIN_SERVER, &as_server, sizeof (int));
141  assert (rc == 0);
142  rc = zmq_connect (client, "tcp://localhost:9998");
143  assert (rc == 0);
144  expect_bounce_fail (server, client);
145  close_zero_linger (client);
146 
147  // Check PLAIN security -- failed authentication
148  client = zmq_socket (ctx, ZMQ_DEALER);
149  assert (client);
150  strcpy (username, "wronguser");
151  strcpy (password, "wrongpass");
152  rc = zmq_setsockopt (client, ZMQ_PLAIN_USERNAME, username, strlen (username));
153  assert (rc == 0);
154  rc = zmq_setsockopt (client, ZMQ_PLAIN_PASSWORD, password, strlen (password));
155  assert (rc == 0);
156  rc = zmq_connect (client, "tcp://localhost:9998");
157  assert (rc == 0);
158  expect_bounce_fail (server, client);
159  close_zero_linger (client);
160 
161  // Unauthenticated messages from a vanilla socket shouldn't be received
162  struct sockaddr_in ip4addr;
163  int s;
164 
165  ip4addr.sin_family = AF_INET;
166  ip4addr.sin_port = htons (9998);
167 #if defined (ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
168  ip4addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
169 #else
170  inet_pton (AF_INET, "127.0.0.1", &ip4addr.sin_addr);
171 #endif
172 
173  s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
174  rc = connect (s, (struct sockaddr*) &ip4addr, sizeof (ip4addr));
175  assert (rc > -1);
176  // send anonymous ZMTP/1.0 greeting
177  send (s, "\x01\x00", 2, 0);
178  // send sneaky message that shouldn't be received
179  send (s, "\x08\x00sneaky\0", 9, 0);
180  int timeout = 250;
181  zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (timeout));
182  char *buf = s_recv (server);
183  if (buf != NULL) {
184  printf ("Received unauthenticated message: %s\n", buf);
185  assert (buf == NULL);
186  }
187  close (s);
188 
189  // Shutdown
190  rc = zmq_close (server);
191  assert (rc == 0);
192  rc = zmq_ctx_term (ctx);
193  assert (rc == 0);
194 
195  // Wait until ZAP handler terminates
196  zmq_threadclose (zap_thread);
197 
198  return 0;
199 }
#define ZMQ_PLAIN_USERNAME
Definition: zmq.h:298
ZMQ_EXPORT int zmq_setsockopt(void *s, int option, const void *optval, size_t optvallen)
Definition: zmq.cpp:265
int s_sendmore(void *socket, const char *string)
Definition: testutil.hpp:190
ZMQ_EXPORT void * zmq_ctx_new(void)
Definition: zmq.cpp:115
#define ZMQ_DEALER
Definition: zmq.h:251
#define ZMQ_REP
Definition: zmq.h:250
void setup_test_environment(void)
Definition: testutil.hpp:285
void expect_bounce_fail(void *server, void *client)
Definition: testutil.hpp:128
#define ZMQ_PLAIN_PASSWORD
Definition: zmq.h:299
#define ZMQ_PLAIN_SERVER
Definition: zmq.h:297
ZMQ_EXPORT void * zmq_socket(void *, int type)
Definition: zmq.cpp:244
#define ZMQ_IDENTITY
Definition: zmq.h:265
ZMQ_EXPORT void zmq_threadclose(void *thread)
Definition: zmq_utils.cpp:85
#define streq(s1, s2)
Definition: testutil.hpp:195
ZMQ_EXPORT int zmq_connect(void *s, const char *addr)
Definition: zmq.cpp:332
ZMQ_EXPORT int zmq_close(void *s)
Definition: zmq.cpp:255
char * s_recv(void *socket)
Definition: testutil.hpp:170
int main(void)
void close_zero_linger(void *socket)
Definition: testutil.hpp:275
void bounce(void *server, void *client)
Definition: testutil.hpp:73
ZMQ_EXPORT int zmq_bind(void *s, const char *addr)
Definition: zmq.cpp:321
ZMQ_EXPORT int zmq_ctx_term(void *context)
Definition: zmq.cpp:162
int s_send(void *socket, const char *string)
Definition: testutil.hpp:183
ZMQ_EXPORT void * zmq_threadstart(zmq_thread_fn *func, void *arg)
Definition: zmq_utils.cpp:78
#define ZMQ_RCVTIMEO
Definition: zmq.h:284
const char * address
Definition: test_fork.cpp:32
static void zap_handler(void *ctx)