~lefteris-nikoltsios/+junk/samba-lp1016895

« back to all changes in this revision

Viewing changes to source4/torture/ntp/ntp_signd.c

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2011-12-21 13:18:04 UTC
  • mfrom: (0.39.21 sid)
  • Revision ID: package-import@ubuntu.com-20111221131804-xtlr39wx6njehxxr
Tags: 2:3.6.1-3ubuntu1
* Merge from Debian testing.  Remaining changes:
  + debian/patches/VERSION.patch:
    - set SAMBA_VERSION_SUFFIX to Ubuntu.
  + debian/patches/error-trans.fix-276472:
    - Add the translation of Unix Error code -ENOTSUP to NT Error Code
    - NT_STATUS_NOT_SUPPORTED to prevent the Permission denied error.
  + debian/smb.conf:
    - add "(Samba, Ubuntu)" to server string.
    - comment out the default [homes] share, and add a comment about
      "valid users = %S" to show users how to restrict access to
      \\server\username to only username.
    - Set 'usershare allow guests', so that usershare admins are 
      allowed to create public shares in addition to authenticated
      ones.
    - add map to guest = Bad user, maps bad username to guest access.
  + debian/samba-common.config:
    - Do not change priority to high if dhclient3 is installed.
    - Use priority medium instead of high for the workgroup question.
  + debian/control:
    - Don't build against or suggest ctdb.
    - Add dependency on samba-common-bin to samba.
  + Add ufw integration:
    - Created debian/samba.ufw.profile
    - debian/rules, debian/samba.dirs, debian/samba.files: install
      profile
    - debian/control: have samba suggest ufw
  + Add apport hook:
    - Created debian/source_samba.py.
    - debian/rules, debian/samba.dirs, debian/samba-common-bin.files: install
  + Switch to upstart:
    - Add debian/samba.{nmbd,smbd}.upstart.
  + debian/samba.logrotate, debian/samba-common.dhcp, debian/samba.if-up:
    - Make them upstart compatible
  + debian/samba.postinst: 
    - Avoid scary pdbedit warnings on first import.
  + debian/samba-common.postinst: Add more informative error message for
    the case where smb.conf was manually deleted
  + debian/patches/fix-debuglevel-name-conflict.patch: don't use 'debug_level'
    as a global variable name in an NSS module 
  + Dropped:
    - debian/patches/error-trans.fix-276472
    - debian/patches/fix-debuglevel-name-conflict.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
*/
21
21
 
22
22
#include "includes.h"
23
 
#include "torture/torture.h"
24
23
#include "torture/smbtorture.h"
25
24
#include <tevent.h>
26
 
#include "lib/socket/socket.h"
27
25
#include "lib/stream/packet.h"
28
 
#include "auth/credentials/credentials.h"
29
 
#include "torture/rpc/rpc.h"
30
 
#include "torture/rpc/netlogon.h"
 
26
#include "lib/tsocket/tsocket.h"
 
27
#include "libcli/util/tstream.h"
 
28
#include "torture/rpc/torture_rpc.h"
31
29
#include "../lib/crypto/crypto.h"
32
30
#include "libcli/auth/libcli_auth.h"
33
31
#include "librpc/gen_ndr/ndr_netlogon_c.h"
34
 
#include "librpc/gen_ndr/ndr_netlogon.h"
35
32
#include "librpc/gen_ndr/ndr_ntp_signd.h"
36
33
#include "param/param.h"
 
34
#include "system/network.h"
37
35
 
38
36
#define TEST_MACHINE_NAME "ntpsigndtest"
39
37
 
40
 
struct signd_client_socket {
41
 
        struct socket_context *sock;
42
 
        
43
 
        /* the fd event */
44
 
        struct tevent_fd *fde;
45
 
        
 
38
struct signd_client_state {
 
39
        struct tsocket_address *local_address;
 
40
        struct tsocket_address *remote_address;
 
41
 
 
42
        struct tstream_context *tstream;
 
43
        struct tevent_queue *send_queue;
 
44
 
 
45
        uint8_t request_hdr[4];
 
46
        struct iovec request_iov[2];
 
47
 
 
48
        DATA_BLOB reply;
 
49
 
46
50
        NTSTATUS status;
47
 
        DATA_BLOB request, reply;
48
 
        
49
 
        struct packet_context *packet;
50
 
                
51
 
        size_t partial_read;
52
51
};
53
52
 
54
 
static NTSTATUS signd_client_full_packet(void *private_data, DATA_BLOB data)
55
 
{
56
 
        struct signd_client_socket *signd_client = talloc_get_type(private_data, struct signd_client_socket);
57
 
        talloc_steal(signd_client, data.data);
58
 
        signd_client->reply = data;
59
 
        signd_client->reply.length -= 4;
60
 
        signd_client->reply.data += 4;
61
 
        return NT_STATUS_OK;
62
 
}
63
 
 
64
 
static void signd_client_error_handler(void *private_data, NTSTATUS status)
65
 
{
66
 
        struct signd_client_socket *signd_client = talloc_get_type(private_data, struct signd_client_socket);
67
 
        signd_client->status = status;
68
 
}
69
 
 
70
53
/*
71
 
  handle fd events on a signd_client_socket
72
 
*/
73
 
static void signd_client_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
74
 
                                 uint16_t flags, void *private_data)
75
 
{
76
 
        struct signd_client_socket *signd_client = talloc_get_type(private_data, struct signd_client_socket);
77
 
        if (flags & TEVENT_FD_READ) {
78
 
                packet_recv(signd_client->packet);
79
 
                return;
80
 
        }
81
 
        if (flags & TEVENT_FD_WRITE) {
82
 
                packet_queue_run(signd_client->packet);
83
 
                return;
84
 
        }
85
 
        /* not reached */
86
 
        return;
87
 
}
88
 
 
89
 
/* A torture test to show that the unix domain socket protocol is
90
 
 * operating correctly, and the signatures are as expected */
91
 
 
92
 
static bool test_ntp_signd(struct torture_context *tctx, 
 
54
 * A torture test to show that the unix domain socket protocol is
 
55
 * operating correctly, and the signatures are as expected
 
56
 */
 
57
static bool test_ntp_signd(struct torture_context *tctx,
93
58
                           struct dcerpc_pipe *p,
94
59
                           struct cli_credentials *credentials)
95
60
{
96
61
        struct netlogon_creds_CredentialState *creds;
97
62
        TALLOC_CTX *mem_ctx = talloc_new(tctx);
98
63
 
99
 
        NTSTATUS status;
100
64
        struct netr_ServerReqChallenge r;
101
65
        struct netr_ServerAuthenticate3 a;
102
66
        struct netr_Credential credentials1, credentials2, credentials3;
109
73
        struct signed_reply signed_reply;
110
74
        DATA_BLOB sign_req_blob;
111
75
 
112
 
        struct signd_client_socket *signd_client;
113
 
        char *signd_socket_address;
 
76
        struct signd_client_state *signd_client;
 
77
        struct tevent_req *req;
 
78
        char *unix_address;
 
79
        int sys_errno;
114
80
 
115
81
        struct MD5Context ctx;
116
82
        uint8_t sig[16];
117
83
        enum ndr_err_code ndr_err;
 
84
        bool ok;
 
85
        int rc;
118
86
 
119
87
        machine_name = cli_credentials_get_workstation(credentials);
120
88
 
127
95
 
128
96
        generate_random_buffer(credentials1.data, sizeof(credentials1.data));
129
97
 
130
 
        status = dcerpc_netr_ServerReqChallenge(p, tctx, &r);
131
 
        torture_assert_ntstatus_ok(tctx, status, "ServerReqChallenge");
 
98
        torture_assert_ntstatus_ok(tctx,
 
99
                dcerpc_netr_ServerReqChallenge_r(p->binding_handle, tctx, &r),
 
100
                "ServerReqChallenge failed");
 
101
        torture_assert_ntstatus_ok(tctx, r.out.result,
 
102
                "ServerReqChallenge failed");
132
103
 
133
104
        a.in.server_name = NULL;
134
105
        a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
150
121
 
151
122
        torture_comment(tctx, "Testing ServerAuthenticate3\n");
152
123
 
153
 
        status = dcerpc_netr_ServerAuthenticate3(p, tctx, &a);
154
 
        torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate3");
155
 
        torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
 
124
        torture_assert_ntstatus_ok(tctx,
 
125
                dcerpc_netr_ServerAuthenticate3_r(p->binding_handle, tctx, &a),
 
126
                "ServerAuthenticate3 failed");
 
127
        torture_assert_ntstatus_ok(tctx, a.out.result,
 
128
                "ServerAuthenticate3 failed");
 
129
        torture_assert(tctx,
 
130
                       netlogon_creds_client_check(creds, &credentials3),
 
131
                       "Credential chaining failed");
156
132
 
157
133
        sign_req.op = SIGN_TO_CLIENT;
158
134
        sign_req.packet_id = 1;
159
135
        sign_req.key_id = rid;
160
136
        sign_req.packet_to_sign = data_blob_string_const("I am a tea pot");
161
137
        
162
 
        ndr_err = ndr_push_struct_blob(&sign_req_blob, mem_ctx, NULL, &sign_req, (ndr_push_flags_fn_t)ndr_push_sign_request);
163
 
        torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "Failed to push sign_req");
164
 
        
165
 
        signd_client = talloc(mem_ctx, struct signd_client_socket);
166
 
 
167
 
        status = socket_create("unix", SOCKET_TYPE_STREAM, &signd_client->sock, 0);
168
 
        
169
 
        signd_socket_address = talloc_asprintf(signd_client, "%s/socket", 
170
 
                                               lp_ntp_signd_socket_directory(tctx->lp_ctx));
171
 
 
172
 
        status = socket_connect_ev(signd_client->sock, NULL, 
173
 
                                   socket_address_from_strings(signd_client, 
174
 
                                                               "unix", signd_socket_address, 0), 0, tctx->ev);
175
 
        torture_assert_ntstatus_ok(tctx, status, "Failed to connect to signd!");
176
 
        
177
 
        /* Setup the FDE, start listening for read events
178
 
         * from the start (otherwise we may miss a socket
179
 
         * drop) and mark as AUTOCLOSE along with the fde */
180
 
        
181
 
        /* Ths is equivilant to EVENT_FD_READABLE(signd_client->fde) */
182
 
        signd_client->fde = tevent_add_fd(tctx->ev, signd_client->sock,
183
 
                            socket_get_fd(signd_client->sock),
184
 
                            TEVENT_FD_READ,
185
 
                            signd_client_socket_handler, signd_client);
186
 
        /* its now the job of the event layer to close the socket */
187
 
        tevent_fd_set_close_fn(signd_client->fde, socket_tevent_fd_close_fn);
188
 
        socket_set_flags(signd_client->sock, SOCKET_FLAG_NOCLOSE);
189
 
        
190
 
        signd_client->status = NT_STATUS_OK;
191
 
        signd_client->reply = data_blob(NULL, 0);
192
 
 
193
 
        signd_client->packet = packet_init(signd_client);
194
 
        if (signd_client->packet == NULL) {
195
 
                talloc_free(signd_client);
196
 
                return ENOMEM;
197
 
        }
198
 
        packet_set_private(signd_client->packet, signd_client);
199
 
        packet_set_socket(signd_client->packet, signd_client->sock);
200
 
        packet_set_callback(signd_client->packet, signd_client_full_packet);
201
 
        packet_set_full_request(signd_client->packet, packet_full_request_u32);
202
 
        packet_set_error_handler(signd_client->packet, signd_client_error_handler);
203
 
        packet_set_event_context(signd_client->packet, tctx->ev);
204
 
        packet_set_fde(signd_client->packet, signd_client->fde);
205
 
        
206
 
        signd_client->request = data_blob_talloc(signd_client, NULL, sign_req_blob.length + 4);
207
 
        RSIVAL(signd_client->request.data, 0, sign_req_blob.length);
208
 
        memcpy(signd_client->request.data+4, sign_req_blob.data, sign_req_blob.length);
209
 
        packet_send(signd_client->packet, signd_client->request);
210
 
 
211
 
        while ((NT_STATUS_IS_OK(signd_client->status)) && !signd_client->reply.length) {
212
 
                if (tevent_loop_once(tctx->ev) != 0) {
213
 
                        talloc_free(signd_client);
214
 
                        return EINVAL;
215
 
                }
216
 
        }
217
 
 
218
 
        torture_assert_ntstatus_ok(tctx, signd_client->status, "Error reading signd_client reply packet");
219
 
 
220
 
        ndr_err = ndr_pull_struct_blob_all(&signd_client->reply, mem_ctx, 
221
 
                                           lp_iconv_convenience(tctx->lp_ctx),
 
138
        ndr_err = ndr_push_struct_blob(&sign_req_blob,
 
139
                                       mem_ctx,
 
140
                                       &sign_req,
 
141
                                       (ndr_push_flags_fn_t)ndr_push_sign_request);
 
142
        torture_assert(tctx,
 
143
                       NDR_ERR_CODE_IS_SUCCESS(ndr_err),
 
144
                       "Failed to push sign_req");
 
145
 
 
146
        signd_client = talloc(mem_ctx, struct signd_client_state);
 
147
 
 
148
        /* Create socket addresses */
 
149
        torture_comment(tctx, "Creating the socket addresses\n");
 
150
        rc = tsocket_address_unix_from_path(signd_client, "",
 
151
                                       &signd_client->local_address);
 
152
        torture_assert(tctx, rc == 0,
 
153
                       "Failed to create local address from unix path.");
 
154
 
 
155
        unix_address = talloc_asprintf(signd_client,
 
156
                                        "%s/socket",
 
157
                                        lpcfg_ntp_signd_socket_directory(tctx->lp_ctx));
 
158
        rc = tsocket_address_unix_from_path(mem_ctx,
 
159
                                            unix_address,
 
160
                                            &signd_client->remote_address);
 
161
        torture_assert(tctx, rc == 0,
 
162
                       "Failed to create remote address from unix path.");
 
163
 
 
164
        /* Connect to the unix socket */
 
165
        torture_comment(tctx, "Connecting to the unix socket\n");
 
166
        req = tstream_unix_connect_send(signd_client,
 
167
                                        tctx->ev,
 
168
                                        signd_client->local_address,
 
169
                                        signd_client->remote_address);
 
170
        torture_assert(tctx, req != NULL,
 
171
                       "Failed to create a tstream unix connect request.");
 
172
 
 
173
        ok = tevent_req_poll(req, tctx->ev);
 
174
        torture_assert(tctx, ok == true,
 
175
                       "Failed to poll for tstream_unix_connect_send.");
 
176
 
 
177
        rc = tstream_unix_connect_recv(req,
 
178
                                       &sys_errno,
 
179
                                       signd_client,
 
180
                                       &signd_client->tstream);
 
181
        TALLOC_FREE(req);
 
182
        torture_assert(tctx, rc == 0, "Failed to connect to signd!");
 
183
 
 
184
        /* Allocate the send queue */
 
185
        signd_client->send_queue = tevent_queue_create(signd_client,
 
186
                                                       "signd_client_queue");
 
187
        torture_assert(tctx, signd_client->send_queue != NULL,
 
188
                       "Failed to create send queue!");
 
189
 
 
190
        /*
 
191
         * Create the request buffer.
 
192
         * First add the length of the request buffer
 
193
         */
 
194
        RSIVAL(signd_client->request_hdr, 0, sign_req_blob.length);
 
195
        signd_client->request_iov[0].iov_base = (char *) signd_client->request_hdr;
 
196
        signd_client->request_iov[0].iov_len = 4;
 
197
 
 
198
        signd_client->request_iov[1].iov_base = (char *) sign_req_blob.data;
 
199
        signd_client->request_iov[1].iov_len = sign_req_blob.length;
 
200
 
 
201
        /* Fire the request buffer */
 
202
        torture_comment(tctx, "Sending the request\n");
 
203
        req = tstream_writev_queue_send(signd_client,
 
204
                                        tctx->ev,
 
205
                                        signd_client->tstream,
 
206
                                        signd_client->send_queue,
 
207
                                        signd_client->request_iov, 2);
 
208
        torture_assert(tctx, req != NULL,
 
209
                       "Failed to send the signd request.");
 
210
 
 
211
        ok = tevent_req_poll(req, tctx->ev);
 
212
        torture_assert(tctx, ok == true,
 
213
                       "Failed to poll for tstream_writev_queue_send.");
 
214
 
 
215
        rc = tstream_writev_queue_recv(req, &sys_errno);
 
216
        TALLOC_FREE(req);
 
217
        torture_assert(tctx, rc > 0, "Failed to send data");
 
218
 
 
219
        /* Wait for a reply */
 
220
        torture_comment(tctx, "Waiting for the reply\n");
 
221
        req = tstream_read_pdu_blob_send(signd_client,
 
222
                                         tctx->ev,
 
223
                                         signd_client->tstream,
 
224
                                         4, /*initial_read_size */
 
225
                                         packet_full_request_u32,
 
226
                                         NULL);
 
227
        torture_assert(tctx, req != NULL,
 
228
                       "Failed to setup a read for pdu_blob.");
 
229
 
 
230
        ok = tevent_req_poll(req, tctx->ev);
 
231
        torture_assert(tctx, ok == true,
 
232
                       "Failed to poll for tstream_read_pdu_blob_send.");
 
233
 
 
234
        signd_client->status = tstream_read_pdu_blob_recv(req,
 
235
                                                          signd_client,
 
236
                                                          &signd_client->reply);
 
237
        torture_assert_ntstatus_ok(tctx, signd_client->status,
 
238
                                   "Error reading signd_client reply packet");
 
239
 
 
240
        /* Skip length header */
 
241
        signd_client->reply.data += 4;
 
242
        signd_client->reply.length -= 4;
 
243
 
 
244
        /* Check if the reply buffer is valid */
 
245
        torture_comment(tctx, "Validating the reply buffer\n");
 
246
        ndr_err = ndr_pull_struct_blob_all(&signd_client->reply,
 
247
                                           mem_ctx,
222
248
                                           &signed_reply,
223
249
                                           (ndr_pull_flags_fn_t)ndr_pull_signed_reply);
224
 
        torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), ndr_map_error2string(ndr_err));
 
250
        torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err),
 
251
                        ndr_map_error2string(ndr_err));
225
252
 
226
 
        torture_assert_u64_equal(tctx, signed_reply.version, 
227
 
                                 NTP_SIGND_PROTOCOL_VERSION_0, "Invalid Version");
228
 
        torture_assert_u64_equal(tctx, signed_reply.packet_id, 
 
253
        torture_assert_u64_equal(tctx, signed_reply.version,
 
254
                                 NTP_SIGND_PROTOCOL_VERSION_0,
 
255
                                 "Invalid Version");
 
256
        torture_assert_u64_equal(tctx, signed_reply.packet_id,
229
257
                                 sign_req.packet_id, "Invalid Packet ID");
230
 
        torture_assert_u64_equal(tctx, signed_reply.op, 
231
 
                                 SIGNING_SUCCESS, "Should have replied with signing success");
232
 
        torture_assert_u64_equal(tctx, signed_reply.signed_packet.length, 
233
 
                                 sign_req.packet_to_sign.length + 20, "Invalid reply length from signd");
234
 
        torture_assert_u64_equal(tctx, rid, 
235
 
                                 IVAL(signed_reply.signed_packet.data, sign_req.packet_to_sign.length), 
 
258
        torture_assert_u64_equal(tctx, signed_reply.op,
 
259
                                 SIGNING_SUCCESS,
 
260
                                 "Should have replied with signing success");
 
261
        torture_assert_u64_equal(tctx, signed_reply.signed_packet.length,
 
262
                                 sign_req.packet_to_sign.length + 20,
 
263
                                 "Invalid reply length from signd");
 
264
        torture_assert_u64_equal(tctx, rid,
 
265
                                 IVAL(signed_reply.signed_packet.data,
 
266
                                 sign_req.packet_to_sign.length),
236
267
                                 "Incorrect RID in reply");
237
268
 
238
269
        /* Check computed signature */
239
 
 
240
270
        MD5Init(&ctx);
241
271
        MD5Update(&ctx, pwhash->hash, sizeof(pwhash->hash));
242
 
        MD5Update(&ctx, sign_req.packet_to_sign.data, sign_req.packet_to_sign.length);
 
272
        MD5Update(&ctx, sign_req.packet_to_sign.data,
 
273
                  sign_req.packet_to_sign.length);
243
274
        MD5Final(sig, &ctx);
244
275
 
245
 
        torture_assert_mem_equal(tctx, &signed_reply.signed_packet.data[sign_req.packet_to_sign.length + 4],
 
276
        torture_assert_mem_equal(tctx,
 
277
                                 &signed_reply.signed_packet.data[sign_req.packet_to_sign.length + 4],
246
278
                                 sig, 16, "Signature on reply was incorrect!");
247
 
        
 
279
 
248
280
        talloc_free(mem_ctx);
249
 
                
 
281
 
250
282
        return true;
251
283
}
252
284
 
253
285
NTSTATUS torture_ntp_init(void)
254
286
{
255
 
        struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "NTP");
 
287
        struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "ntp");
256
288
        struct torture_rpc_tcase *tcase;
257
289
 
258
 
        tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "SIGND",
259
 
                                                                      &ndr_table_netlogon, TEST_MACHINE_NAME);
 
290
        tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite,
 
291
                                  "signd", &ndr_table_netlogon, TEST_MACHINE_NAME);
260
292
 
261
293
        torture_rpc_tcase_add_test_creds(tcase, "ntp_signd", test_ntp_signd);
262
294