test_security_curve.cpp 7.26 KB
Newer Older
Ian Barber's avatar
Ian Barber committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
    Copyright (c) 2007-2013 Contributors as noted in the AUTHORS file

    This file is part of 0MQ.

    0MQ is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    0MQ is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "testutil.hpp"
21

22 23 24 25 26
//  We'll generate random test keys at startup
static char client_public [41];
static char client_secret [41];
static char server_public [41];
static char server_secret [41];
Ian Barber's avatar
Ian Barber committed
27

28 29 30 31 32
//  --------------------------------------------------------------------------
//  Encode a binary frame as a string; destination string MUST be at least
//  size * 5 / 4 bytes long plus 1 byte for the null terminator. Returns
//  dest. Size must be a multiple of 4.

33
static void zap_handler (void *handler)
Ian Barber's avatar
Ian Barber committed
34
{
35 36
    //  Process ZAP requests forever
    while (true) {
37
        char *version = s_recv (handler);
38 39 40
        if (!version)
            break;          //  Terminating

41 42 43 44 45
        char *sequence = s_recv (handler);
        char *domain = s_recv (handler);
        char *address = s_recv (handler);
        char *identity = s_recv (handler);
        char *mechanism = s_recv (handler);
46
        uint8_t client_key [32];
47
        int size = zmq_recv (handler, client_key, 32, 0);
48 49
        assert (size == 32);

50
        char client_key_text [41];
51
        zmq_z85_encode (client_key_text, client_key, 32);
52

53 54 55 56
        assert (streq (version, "1.0"));
        assert (streq (mechanism, "CURVE"));
        assert (streq (identity, "IDENT"));

57 58
        s_sendmore (handler, version);
        s_sendmore (handler, sequence);
59

60
        if (streq (client_key_text, client_public)) {
61 62 63 64
            s_sendmore (handler, "200");
            s_sendmore (handler, "OK");
            s_sendmore (handler, "anonymous");
            s_send     (handler, "");
65 66
        }
        else {
67 68 69 70
            s_sendmore (handler, "400");
            s_sendmore (handler, "Invalid client public key");
            s_sendmore (handler, "");
            s_send     (handler, "");
71
        }
72 73 74 75 76 77
        free (version);
        free (sequence);
        free (domain);
        free (address);
        free (identity);
        free (mechanism);
MinRK's avatar
MinRK committed
78
    }
79
    zmq_close (handler);
Ian Barber's avatar
Ian Barber committed
80 81
}

MinRK's avatar
MinRK committed
82

Ian Barber's avatar
Ian Barber committed
83 84 85
int main (void)
{
#ifndef HAVE_LIBSODIUM
Pieter Hintjens's avatar
Pieter Hintjens committed
86
    printf ("libsodium not installed, skipping CURVE test\n");
Ian Barber's avatar
Ian Barber committed
87 88
    return 0;
#endif
89 90 91 92 93 94 95

    //  Generate new keypairs for this test
    int rc = zmq_curve_keypair (client_public, client_secret);
    assert (rc == 0);
    rc = zmq_curve_keypair (server_public, server_secret);
    assert (rc == 0);

96
    setup_test_environment ();
Ian Barber's avatar
Ian Barber committed
97 98 99
    void *ctx = zmq_ctx_new ();
    assert (ctx);

100
    //  Spawn ZAP handler
101 102 103 104
    //  We create and bind ZAP socket in main thread to avoid case
    //  where child thread does not start up fast enough.
    void *handler = zmq_socket (ctx, ZMQ_REP);
    assert (handler);
105
    rc = zmq_bind (handler, "inproc://zeromq.zap.01");
106 107
    assert (rc == 0);
    void *zap_thread = zmq_threadstart (&zap_handler, handler);
Ian Barber's avatar
Ian Barber committed
108

109 110 111
    //  Server socket will accept connections
    void *server = zmq_socket (ctx, ZMQ_DEALER);
    assert (server);
112
    int as_server = 1;
113
    rc = zmq_setsockopt (server, ZMQ_CURVE_SERVER, &as_server, sizeof (int));
Pieter Hintjens's avatar
Pieter Hintjens committed
114
    assert (rc == 0);
115
    rc = zmq_setsockopt (server, ZMQ_CURVE_SECRETKEY, server_secret, 40);
Pieter Hintjens's avatar
Pieter Hintjens committed
116
    assert (rc == 0);
117 118
    rc = zmq_setsockopt (server, ZMQ_IDENTITY, "IDENT", 6);
    assert (rc == 0);
119
    rc = zmq_bind (server, "tcp://127.0.0.1:9998");
120
    assert (rc == 0);
Ian Barber's avatar
Ian Barber committed
121

122 123 124
    //  Check CURVE security with valid credentials
    void *client = zmq_socket (ctx, ZMQ_DEALER);
    assert (client);
125
    rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
Pieter Hintjens's avatar
Pieter Hintjens committed
126
    assert (rc == 0);
127
    rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40);
Pieter Hintjens's avatar
Pieter Hintjens committed
128
    assert (rc == 0);
129
    rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40);
Pieter Hintjens's avatar
Pieter Hintjens committed
130
    assert (rc == 0);
Ian Barber's avatar
Ian Barber committed
131 132 133 134 135
    rc = zmq_connect (client, "tcp://localhost:9998");
    assert (rc == 0);
    bounce (server, client);
    rc = zmq_close (client);
    assert (rc == 0);
136

137 138 139
    //  Check CURVE security with a garbage server key
    //  This will be caught by the curve_server class, not passed to ZAP
    char garbage_key [] = "0000111122223333444455556666777788889999";
MinRK's avatar
MinRK committed
140 141
    client = zmq_socket (ctx, ZMQ_DEALER);
    assert (client);
142
    rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, garbage_key, 40);
MinRK's avatar
MinRK committed
143
    assert (rc == 0);
144
    rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40);
MinRK's avatar
MinRK committed
145
    assert (rc == 0);
146
    rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40);
MinRK's avatar
MinRK committed
147
    assert (rc == 0);
148 149 150 151
    rc = zmq_connect (client, "tcp://localhost:9998");
    assert (rc == 0);
    expect_bounce_fail (server, client);
    close_zero_linger (client);
152

153 154 155 156
    //  Check CURVE security with a garbage client public key
    //  This will be caught by the curve_server class, not passed to ZAP
    client = zmq_socket (ctx, ZMQ_DEALER);
    assert (client);
157
    rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
MinRK's avatar
MinRK committed
158
    assert (rc == 0);
159
    rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, garbage_key, 40);
MinRK's avatar
MinRK committed
160
    assert (rc == 0);
161
    rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, client_secret, 40);
MinRK's avatar
MinRK committed
162
    assert (rc == 0);
163
    rc = zmq_connect (client, "tcp://localhost:9998");
MinRK's avatar
MinRK committed
164
    assert (rc == 0);
165 166
    expect_bounce_fail (server, client);
    close_zero_linger (client);
167

168 169 170 171
    //  Check CURVE security with a garbage client secret key
    //  This will be caught by the curve_server class, not passed to ZAP
    client = zmq_socket (ctx, ZMQ_DEALER);
    assert (client);
172
    rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
MinRK's avatar
MinRK committed
173
    assert (rc == 0);
174
    rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, client_public, 40);
MinRK's avatar
MinRK committed
175
    assert (rc == 0);
176
    rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, garbage_key, 40);
MinRK's avatar
MinRK committed
177
    assert (rc == 0);
178
    rc = zmq_connect (client, "tcp://localhost:9998");
MinRK's avatar
MinRK committed
179
    assert (rc == 0);
180 181
    expect_bounce_fail (server, client);
    close_zero_linger (client);
182

183 184
    //  Check CURVE security with bogus client credentials
    //  This must be caught by the ZAP handler
185 186 187
    char bogus_public [41];
    char bogus_secret [41];
    zmq_curve_keypair (bogus_public, bogus_secret);
188

189 190
    client = zmq_socket (ctx, ZMQ_DEALER);
    assert (client);
191
    rc = zmq_setsockopt (client, ZMQ_CURVE_SERVERKEY, server_public, 40);
MinRK's avatar
MinRK committed
192
    assert (rc == 0);
193
    rc = zmq_setsockopt (client, ZMQ_CURVE_PUBLICKEY, bogus_public, 40);
MinRK's avatar
MinRK committed
194
    assert (rc == 0);
195
    rc = zmq_setsockopt (client, ZMQ_CURVE_SECRETKEY, bogus_secret, 40);
MinRK's avatar
MinRK committed
196
    assert (rc == 0);
197 198
    rc = zmq_connect (client, "tcp://localhost:9998");
    assert (rc == 0);
199
    expect_bounce_fail (server, client);
200
    close_zero_linger (client);
201

Ian Barber's avatar
Ian Barber committed
202
    //  Shutdown
203 204
    rc = zmq_close (server);
    assert (rc == 0);
Ian Barber's avatar
Ian Barber committed
205 206
    rc = zmq_ctx_term (ctx);
    assert (rc == 0);
207

208 209
    //  Wait until ZAP handler terminates
    zmq_threadclose (zap_thread);
Ian Barber's avatar
Ian Barber committed
210 211 212

    return 0;
}