~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/libcli/raw/rawrequest.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
   Unix SMB/CIFS implementation.
 
3
   
 
4
   Copyright (C) Andrew Tridgell  2003
 
5
   Copyright (C) James Myers 2003 <myersjj@samba.org>
 
6
   
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 3 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
   
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
*/
 
20
 
 
21
/*
 
22
  this file implements functions for manipulating the 'struct smbcli_request' structure in libsmb
 
23
*/
 
24
 
 
25
#include "includes.h"
 
26
#include "libcli/raw/libcliraw.h"
 
27
#include "libcli/raw/raw_proto.h"
 
28
#include "../lib/util/dlinklist.h"
 
29
#include "lib/events/events.h"
 
30
#include "librpc/ndr/libndr.h"
 
31
#include "librpc/gen_ndr/ndr_misc.h"
 
32
 
 
33
/* we over allocate the data buffer to prevent too many realloc calls */
 
34
#define REQ_OVER_ALLOCATION 0
 
35
 
 
36
/* assume that a character will not consume more than 3 bytes per char */
 
37
#define MAX_BYTES_PER_CHAR 3
 
38
 
 
39
/* setup the bufinfo used for strings and range checking */
 
40
void smb_setup_bufinfo(struct smbcli_request *req)
 
41
{
 
42
        req->in.bufinfo.mem_ctx    = req;
 
43
        req->in.bufinfo.flags      = 0;
 
44
        if (req->flags2 & FLAGS2_UNICODE_STRINGS) {
 
45
                req->in.bufinfo.flags = BUFINFO_FLAG_UNICODE;
 
46
        }
 
47
        req->in.bufinfo.align_base = req->in.buffer;
 
48
        req->in.bufinfo.data       = req->in.data;
 
49
        req->in.bufinfo.data_size  = req->in.data_size;
 
50
}
 
51
 
 
52
 
 
53
/* destroy a request structure and return final status */
 
54
_PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req)
 
55
{
 
56
        NTSTATUS status;
 
57
 
 
58
        /* this is the error code we give the application for when a
 
59
           _send() call fails completely */
 
60
        if (!req) return NT_STATUS_UNSUCCESSFUL;
 
61
 
 
62
        if (req->transport) {
 
63
                /* remove it from the list of pending requests (a null op if
 
64
                   its not in the list) */
 
65
                DLIST_REMOVE(req->transport->pending_recv, req);
 
66
        }
 
67
 
 
68
        if (req->state == SMBCLI_REQUEST_ERROR &&
 
69
            NT_STATUS_IS_OK(req->status)) {
 
70
                req->status = NT_STATUS_INTERNAL_ERROR;
 
71
        }
 
72
 
 
73
        status = req->status;
 
74
 
 
75
        if (!req->do_not_free) {
 
76
                talloc_free(req);
 
77
        }
 
78
 
 
79
        return status;
 
80
}
 
81
 
 
82
 
 
83
/*
 
84
  low-level function to setup a request buffer for a non-SMB packet 
 
85
  at the transport level
 
86
*/
 
87
struct smbcli_request *smbcli_request_setup_nonsmb(struct smbcli_transport *transport, size_t size)
 
88
{
 
89
        struct smbcli_request *req;
 
90
 
 
91
        req = talloc(transport, struct smbcli_request);
 
92
        if (!req) {
 
93
                return NULL;
 
94
        }
 
95
        ZERO_STRUCTP(req);
 
96
 
 
97
        /* setup the request context */
 
98
        req->state = SMBCLI_REQUEST_INIT;
 
99
        req->transport = transport;
 
100
        req->session = NULL;
 
101
        req->tree = NULL;
 
102
        req->out.size = size;
 
103
 
 
104
        /* over allocate by a small amount */
 
105
        req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; 
 
106
 
 
107
        req->out.buffer = talloc_array(req, uint8_t, req->out.allocated);
 
108
        if (!req->out.buffer) {
 
109
                return NULL;
 
110
        }
 
111
 
 
112
        SIVAL(req->out.buffer, 0, 0);
 
113
 
 
114
        return req;
 
115
}
 
116
 
 
117
 
 
118
/*
 
119
  setup a SMB packet at transport level
 
120
*/
 
121
struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport,
 
122
                                                      uint8_t command, uint_t wct, uint_t buflen)
 
123
{
 
124
        struct smbcli_request *req;
 
125
 
 
126
        req = smbcli_request_setup_nonsmb(transport, NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen);
 
127
 
 
128
        if (!req) return NULL;
 
129
        
 
130
        req->out.hdr = req->out.buffer + NBT_HDR_SIZE;
 
131
        req->out.vwv = req->out.hdr + HDR_VWV;
 
132
        req->out.wct = wct;
 
133
        req->out.data = req->out.vwv + VWV(wct) + 2;
 
134
        req->out.data_size = buflen;
 
135
        req->out.ptr = req->out.data;
 
136
 
 
137
        SCVAL(req->out.hdr, HDR_WCT, wct);
 
138
        SSVAL(req->out.vwv, VWV(wct), buflen);
 
139
 
 
140
        memcpy(req->out.hdr, "\377SMB", 4);
 
141
        SCVAL(req->out.hdr,HDR_COM,command);
 
142
 
 
143
        SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES);
 
144
        SSVAL(req->out.hdr,HDR_FLG2, 0);
 
145
 
 
146
        if (command != SMBtranss && command != SMBtranss2) {
 
147
                /* assign a mid */
 
148
                req->mid = smbcli_transport_next_mid(transport);
 
149
        }
 
150
 
 
151
        /* copy the pid, uid and mid to the request */
 
152
        SSVAL(req->out.hdr, HDR_PID, 0);
 
153
        SSVAL(req->out.hdr, HDR_UID, 0);
 
154
        SSVAL(req->out.hdr, HDR_MID, req->mid);
 
155
        SSVAL(req->out.hdr, HDR_TID,0);
 
156
        SSVAL(req->out.hdr, HDR_PIDHIGH,0);
 
157
        SIVAL(req->out.hdr, HDR_RCLS, 0);
 
158
        memset(req->out.hdr+HDR_SS_FIELD, 0, 10);
 
159
        
 
160
        return req;
 
161
}
 
162
 
 
163
/*
 
164
  setup a reply in req->out with the given word count and initial data
 
165
  buffer size.  the caller will then fill in the command words and
 
166
  data before calling smbcli_request_send() to send the reply on its
 
167
  way. This interface is used before a session is setup.
 
168
*/
 
169
struct smbcli_request *smbcli_request_setup_session(struct smbcli_session *session,
 
170
                                                    uint8_t command, uint_t wct, size_t buflen)
 
171
{
 
172
        struct smbcli_request *req;
 
173
 
 
174
        req = smbcli_request_setup_transport(session->transport, command, wct, buflen);
 
175
 
 
176
        if (!req) return NULL;
 
177
 
 
178
        req->session = session;
 
179
 
 
180
        SSVAL(req->out.hdr, HDR_FLG2, session->flags2);
 
181
        SSVAL(req->out.hdr, HDR_PID, session->pid & 0xFFFF);
 
182
        SSVAL(req->out.hdr, HDR_PIDHIGH, session->pid >> 16);
 
183
        SSVAL(req->out.hdr, HDR_UID, session->vuid);
 
184
        
 
185
        return req;
 
186
}
 
187
 
 
188
/*
 
189
  setup a request for tree based commands
 
190
*/
 
191
struct smbcli_request *smbcli_request_setup(struct smbcli_tree *tree,
 
192
                                            uint8_t command, 
 
193
                                            uint_t wct, uint_t buflen)
 
194
{
 
195
        struct smbcli_request *req;
 
196
 
 
197
        req = smbcli_request_setup_session(tree->session, command, wct, buflen);
 
198
        if (req) {
 
199
                req->tree = tree;
 
200
                SSVAL(req->out.hdr,HDR_TID,tree->tid);
 
201
        }
 
202
        return req;
 
203
}
 
204
 
 
205
 
 
206
/*
 
207
  grow the allocation of the data buffer portion of a reply
 
208
  packet. Note that as this can reallocate the packet buffer this
 
209
  invalidates any local pointers into the packet.
 
210
 
 
211
  To cope with this req->out.ptr is supplied. This will be updated to
 
212
  point at the same offset into the packet as before this call
 
213
*/
 
214
static void smbcli_req_grow_allocation(struct smbcli_request *req, uint_t new_size)
 
215
{
 
216
        int delta;
 
217
        uint8_t *buf2;
 
218
 
 
219
        delta = new_size - req->out.data_size;
 
220
        if (delta + req->out.size <= req->out.allocated) {
 
221
                /* it fits in the preallocation */
 
222
                return;
 
223
        }
 
224
 
 
225
        /* we need to realloc */
 
226
        req->out.allocated = req->out.size + delta + REQ_OVER_ALLOCATION;
 
227
        buf2 = talloc_realloc(req, req->out.buffer, uint8_t, req->out.allocated);
 
228
        if (buf2 == NULL) {
 
229
                smb_panic("out of memory in req_grow_allocation");
 
230
        }
 
231
 
 
232
        if (buf2 == req->out.buffer) {
 
233
                /* the malloc library gave us the same pointer */
 
234
                return;
 
235
        }
 
236
        
 
237
        /* update the pointers into the packet */
 
238
        req->out.data = buf2 + PTR_DIFF(req->out.data, req->out.buffer);
 
239
        req->out.ptr  = buf2 + PTR_DIFF(req->out.ptr,  req->out.buffer);
 
240
        req->out.vwv  = buf2 + PTR_DIFF(req->out.vwv,  req->out.buffer);
 
241
        req->out.hdr  = buf2 + PTR_DIFF(req->out.hdr,  req->out.buffer);
 
242
 
 
243
        req->out.buffer = buf2;
 
244
}
 
245
 
 
246
 
 
247
/*
 
248
  grow the data buffer portion of a reply packet. Note that as this
 
249
  can reallocate the packet buffer this invalidates any local pointers
 
250
  into the packet. 
 
251
 
 
252
  To cope with this req->out.ptr is supplied. This will be updated to
 
253
  point at the same offset into the packet as before this call
 
254
*/
 
255
static void smbcli_req_grow_data(struct smbcli_request *req, uint_t new_size)
 
256
{
 
257
        int delta;
 
258
 
 
259
        smbcli_req_grow_allocation(req, new_size);
 
260
 
 
261
        delta = new_size - req->out.data_size;
 
262
 
 
263
        req->out.size += delta;
 
264
        req->out.data_size += delta;
 
265
 
 
266
        /* set the BCC to the new data size */
 
267
        SSVAL(req->out.vwv, VWV(req->out.wct), new_size);
 
268
}
 
269
 
 
270
 
 
271
/*
 
272
  setup a chained reply in req->out with the given word count and
 
273
  initial data buffer size.
 
274
*/
 
275
NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req,
 
276
                                      uint8_t command, 
 
277
                                      uint_t wct, size_t buflen)
 
278
{
 
279
        uint_t new_size = 1 + (wct*2) + 2 + buflen;
 
280
 
 
281
        SSVAL(req->out.vwv, VWV(0), command);
 
282
        SSVAL(req->out.vwv, VWV(1), req->out.size - NBT_HDR_SIZE);
 
283
 
 
284
        smbcli_req_grow_allocation(req, req->out.data_size + new_size);
 
285
 
 
286
        req->out.vwv = req->out.buffer + req->out.size + 1;
 
287
        SCVAL(req->out.vwv, -1, wct);
 
288
        SSVAL(req->out.vwv, VWV(wct), buflen);
 
289
 
 
290
        req->out.size += new_size;
 
291
        req->out.data_size += new_size;
 
292
 
 
293
        return NT_STATUS_OK;
 
294
}
 
295
 
 
296
/*
 
297
  aadvance to the next chained reply in a request
 
298
*/
 
299
NTSTATUS smbcli_chained_advance(struct smbcli_request *req)
 
300
{
 
301
        uint8_t *buffer;
 
302
 
 
303
        if (CVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) {
 
304
                return NT_STATUS_NOT_FOUND;
 
305
        }
 
306
 
 
307
        buffer = req->in.hdr + SVAL(req->in.vwv, VWV(1));
 
308
 
 
309
        if (buffer + 3 > req->in.buffer + req->in.size) {
 
310
                return NT_STATUS_BUFFER_TOO_SMALL;
 
311
        }
 
312
 
 
313
        req->in.vwv = buffer + 1;
 
314
        req->in.wct = CVAL(buffer, 0);
 
315
        if (buffer + 3 + req->in.wct*2 > req->in.buffer + req->in.size) {
 
316
                return NT_STATUS_BUFFER_TOO_SMALL;
 
317
        }
 
318
        req->in.data = req->in.vwv + 2 + req->in.wct * 2;
 
319
        req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct));
 
320
 
 
321
        /* fix the bufinfo */
 
322
        smb_setup_bufinfo(req);
 
323
 
 
324
        if (buffer + 3 + req->in.wct*2 + req->in.data_size > 
 
325
            req->in.buffer + req->in.size) {
 
326
                return NT_STATUS_BUFFER_TOO_SMALL;
 
327
        }
 
328
 
 
329
        return NT_STATUS_OK;
 
330
}
 
331
 
 
332
 
 
333
/*
 
334
  send a message
 
335
*/
 
336
bool smbcli_request_send(struct smbcli_request *req)
 
337
{
 
338
        if (IVAL(req->out.buffer, 0) == 0) {
 
339
                _smb_setlen(req->out.buffer, req->out.size - NBT_HDR_SIZE);
 
340
        }
 
341
 
 
342
        smbcli_request_calculate_sign_mac(req);
 
343
 
 
344
        smbcli_transport_send(req);
 
345
 
 
346
        return true;
 
347
}
 
348
 
 
349
 
 
350
/*
 
351
  receive a response to a packet
 
352
*/
 
353
bool smbcli_request_receive(struct smbcli_request *req)
 
354
{
 
355
        /* req can be NULL when a send has failed. This eliminates lots of NULL
 
356
           checks in each module */
 
357
        if (!req) return false;
 
358
 
 
359
        /* keep receiving packets until this one is replied to */
 
360
        while (req->state <= SMBCLI_REQUEST_RECV) {
 
361
                if (event_loop_once(req->transport->socket->event.ctx) != 0) {
 
362
                        return false;
 
363
                }
 
364
        }
 
365
 
 
366
        return req->state == SMBCLI_REQUEST_DONE;
 
367
}
 
368
 
 
369
 
 
370
/*
 
371
  handle oplock break requests from the server - return true if the request was
 
372
  an oplock break
 
373
*/
 
374
bool smbcli_handle_oplock_break(struct smbcli_transport *transport, uint_t len, const uint8_t *hdr, const uint8_t *vwv)
 
375
{
 
376
        /* we must be very fussy about what we consider an oplock break to avoid
 
377
           matching readbraw replies */
 
378
        if (len != MIN_SMB_SIZE + VWV(8) + NBT_HDR_SIZE ||
 
379
            (CVAL(hdr, HDR_FLG) & FLAG_REPLY) ||
 
380
            CVAL(hdr,HDR_COM) != SMBlockingX ||
 
381
            SVAL(hdr, HDR_MID) != 0xFFFF ||
 
382
            SVAL(vwv,VWV(6)) != 0 ||
 
383
            SVAL(vwv,VWV(7)) != 0) {
 
384
                return false;
 
385
        }
 
386
 
 
387
        if (transport->oplock.handler) {
 
388
                uint16_t tid = SVAL(hdr, HDR_TID);
 
389
                uint16_t fnum = SVAL(vwv,VWV(2));
 
390
                uint8_t level = CVAL(vwv,VWV(3)+1);
 
391
                transport->oplock.handler(transport, tid, fnum, level, transport->oplock.private_data);
 
392
        }
 
393
 
 
394
        return true;
 
395
}
 
396
 
 
397
/*
 
398
  wait for a reply to be received for a packet that just returns an error
 
399
  code and nothing more
 
400
*/
 
401
_PUBLIC_ NTSTATUS smbcli_request_simple_recv(struct smbcli_request *req)
 
402
{
 
403
        (void) smbcli_request_receive(req);
 
404
        return smbcli_request_destroy(req);
 
405
}
 
406
 
 
407
 
 
408
/* Return true if the last packet was in error */
 
409
bool smbcli_request_is_error(struct smbcli_request *req)
 
410
{
 
411
        return NT_STATUS_IS_ERR(req->status);
 
412
}
 
413
 
 
414
/*
 
415
  append a string into the data portion of the request packet
 
416
 
 
417
  return the number of bytes added to the packet
 
418
*/
 
419
size_t smbcli_req_append_string(struct smbcli_request *req, const char *str, uint_t flags)
 
420
{
 
421
        size_t len;
 
422
 
 
423
        /* determine string type to use */
 
424
        if (!(flags & (STR_ASCII|STR_UNICODE))) {
 
425
                flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
 
426
        }
 
427
 
 
428
        len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;             
 
429
 
 
430
        smbcli_req_grow_allocation(req, len + req->out.data_size);
 
431
 
 
432
        len = push_string(req->out.data + req->out.data_size, str, len, flags);
 
433
 
 
434
        smbcli_req_grow_data(req, len + req->out.data_size);
 
435
 
 
436
        return len;
 
437
}
 
438
 
 
439
 
 
440
/*
 
441
  this is like smbcli_req_append_string but it also return the
 
442
  non-terminated string byte length, which can be less than the number
 
443
  of bytes consumed in the packet for 2 reasons:
 
444
 
 
445
   1) the string in the packet may be null terminated
 
446
   2) the string in the packet may need a 1 byte UCS2 alignment
 
447
 
 
448
 this is used in places where the non-terminated string byte length is
 
449
 placed in the packet as a separate field  
 
450
*/
 
451
size_t smbcli_req_append_string_len(struct smbcli_request *req, const char *str, uint_t flags, int *len)
 
452
{
 
453
        int diff = 0;
 
454
        size_t ret;
 
455
 
 
456
        /* determine string type to use */
 
457
        if (!(flags & (STR_ASCII|STR_UNICODE))) {
 
458
                flags |= (req->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
 
459
        }
 
460
 
 
461
        /* see if an alignment byte will be used */
 
462
        if ((flags & STR_UNICODE) && !(flags & STR_NOALIGN)) {
 
463
                diff = ucs2_align(NULL, req->out.data + req->out.data_size, flags);
 
464
        }
 
465
 
 
466
        /* do the hard work */
 
467
        ret = smbcli_req_append_string(req, str, flags);
 
468
 
 
469
        /* see if we need to subtract the termination */
 
470
        if (flags & STR_TERMINATE) {
 
471
                diff += (flags & STR_UNICODE) ? 2 : 1;
 
472
        }
 
473
 
 
474
        if (ret >= diff) {
 
475
                (*len) = ret - diff;
 
476
        } else {
 
477
                (*len) = ret;
 
478
        }
 
479
 
 
480
        return ret;
 
481
}
 
482
 
 
483
 
 
484
/*
 
485
  push a string into the data portion of the request packet, growing it if necessary
 
486
  this gets quite tricky - please be very careful to cover all cases when modifying this
 
487
 
 
488
  if dest is NULL, then put the string at the end of the data portion of the packet
 
489
 
 
490
  if dest_len is -1 then no limit applies
 
491
*/
 
492
size_t smbcli_req_append_ascii4(struct smbcli_request *req, const char *str, uint_t flags)
 
493
{
 
494
        size_t size;
 
495
        smbcli_req_append_bytes(req, (const uint8_t *)"\4", 1);
 
496
        size = smbcli_req_append_string(req, str, flags);
 
497
        return size + 1;
 
498
}
 
499
 
 
500
 
 
501
/*
 
502
  push a blob into the data portion of the request packet, growing it if necessary
 
503
  this gets quite tricky - please be very careful to cover all cases when modifying this
 
504
 
 
505
  if dest is NULL, then put the blob at the end of the data portion of the packet
 
506
*/
 
507
size_t smbcli_req_append_blob(struct smbcli_request *req, const DATA_BLOB *blob)
 
508
{
 
509
        smbcli_req_grow_allocation(req, req->out.data_size + blob->length);
 
510
        memcpy(req->out.data + req->out.data_size, blob->data, blob->length);
 
511
        smbcli_req_grow_data(req, req->out.data_size + blob->length);
 
512
        return blob->length;
 
513
}
 
514
 
 
515
/*
 
516
  append raw bytes into the data portion of the request packet
 
517
  return the number of bytes added
 
518
*/
 
519
size_t smbcli_req_append_bytes(struct smbcli_request *req, const uint8_t *bytes, size_t byte_len)
 
520
{
 
521
        smbcli_req_grow_allocation(req, byte_len + req->out.data_size);
 
522
        memcpy(req->out.data + req->out.data_size, bytes, byte_len);
 
523
        smbcli_req_grow_data(req, byte_len + req->out.data_size);
 
524
        return byte_len;
 
525
}
 
526
 
 
527
/*
 
528
  append variable block (type 5 buffer) into the data portion of the request packet
 
529
  return the number of bytes added
 
530
*/
 
531
size_t smbcli_req_append_var_block(struct smbcli_request *req, const uint8_t *bytes, uint16_t byte_len)
 
532
{
 
533
        smbcli_req_grow_allocation(req, byte_len + 3 + req->out.data_size);
 
534
        SCVAL(req->out.data + req->out.data_size, 0, 5);
 
535
        SSVAL(req->out.data + req->out.data_size, 1, byte_len);         /* add field length */
 
536
        if (byte_len > 0) {
 
537
                memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
 
538
        }
 
539
        smbcli_req_grow_data(req, byte_len + 3 + req->out.data_size);
 
540
        return byte_len + 3;
 
541
}
 
542
 
 
543
 
 
544
/*
 
545
  pull a UCS2 string from a request packet, returning a talloced unix string
 
546
 
 
547
  the string length is limited by the 3 things:
 
548
   - the data size in the request (end of packet)
 
549
   - the passed 'byte_len' if it is not -1
 
550
   - the end of string (null termination)
 
551
 
 
552
  Note that 'byte_len' is the number of bytes in the packet
 
553
 
 
554
  on failure zero is returned and *dest is set to NULL, otherwise the number
 
555
  of bytes consumed in the packet is returned
 
556
*/
 
557
static size_t smbcli_req_pull_ucs2(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
 
558
                                char **dest, const uint8_t *src, int byte_len, uint_t flags)
 
559
{
 
560
        int src_len, src_len2, alignment=0;
 
561
        bool ret;
 
562
        size_t ret_size;
 
563
 
 
564
        if (!(flags & STR_NOALIGN) && ucs2_align(bufinfo->align_base, src, flags)) {
 
565
                src++;
 
566
                alignment=1;
 
567
                if (byte_len != -1) {
 
568
                        byte_len--;
 
569
                }
 
570
        }
 
571
 
 
572
        src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
 
573
        if (src_len < 0) {
 
574
                *dest = NULL;
 
575
                return 0;
 
576
        }
 
577
        if (byte_len != -1 && src_len > byte_len) {
 
578
                src_len = byte_len;
 
579
        }
 
580
 
 
581
        src_len2 = utf16_len_n(src, src_len);
 
582
 
 
583
        /* ucs2 strings must be at least 2 bytes long */
 
584
        if (src_len2 < 2) {
 
585
                *dest = NULL;
 
586
                return 0;
 
587
        }
 
588
 
 
589
        ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
 
590
        if (!ret) {
 
591
                *dest = NULL;
 
592
                return 0;
 
593
        }
 
594
 
 
595
        return src_len2 + alignment;
 
596
}
 
597
 
 
598
/*
 
599
  pull a ascii string from a request packet, returning a talloced string
 
600
 
 
601
  the string length is limited by the 3 things:
 
602
   - the data size in the request (end of packet)
 
603
   - the passed 'byte_len' if it is not -1
 
604
   - the end of string (null termination)
 
605
 
 
606
  Note that 'byte_len' is the number of bytes in the packet
 
607
 
 
608
  on failure zero is returned and *dest is set to NULL, otherwise the number
 
609
  of bytes consumed in the packet is returned
 
610
*/
 
611
size_t smbcli_req_pull_ascii(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx,
 
612
                             char **dest, const uint8_t *src, int byte_len, uint_t flags)
 
613
{
 
614
        int src_len, src_len2;
 
615
        bool ret;
 
616
        size_t ret_size;
 
617
 
 
618
        src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
 
619
        if (src_len < 0) {
 
620
                *dest = NULL;
 
621
                return 0;
 
622
        }
 
623
        if (byte_len != -1 && src_len > byte_len) {
 
624
                src_len = byte_len;
 
625
        }
 
626
        src_len2 = strnlen((const char *)src, src_len);
 
627
        if (src_len2 < src_len - 1) {
 
628
                /* include the termination if we didn't reach the end of the packet */
 
629
                src_len2++;
 
630
        }
 
631
 
 
632
        ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)dest, &ret_size, false);
 
633
 
 
634
        if (!ret) {
 
635
                *dest = NULL;
 
636
                return 0;
 
637
        }
 
638
 
 
639
        return ret_size;
 
640
}
 
641
 
 
642
/**
 
643
  pull a string from a request packet, returning a talloced string
 
644
 
 
645
  the string length is limited by the 3 things:
 
646
   - the data size in the request (end of packet)
 
647
   - the passed 'byte_len' if it is not -1
 
648
   - the end of string (null termination)
 
649
 
 
650
  Note that 'byte_len' is the number of bytes in the packet
 
651
 
 
652
  on failure zero is returned and *dest is set to NULL, otherwise the number
 
653
  of bytes consumed in the packet is returned
 
654
*/
 
655
size_t smbcli_req_pull_string(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, 
 
656
                           char **dest, const uint8_t *src, int byte_len, uint_t flags)
 
657
{
 
658
        if (!(flags & STR_ASCII) && 
 
659
            (((flags & STR_UNICODE) || (bufinfo->flags & BUFINFO_FLAG_UNICODE)))) {
 
660
                return smbcli_req_pull_ucs2(bufinfo, mem_ctx, dest, src, byte_len, flags);
 
661
        }
 
662
 
 
663
        return smbcli_req_pull_ascii(bufinfo, mem_ctx, dest, src, byte_len, flags);
 
664
}
 
665
 
 
666
 
 
667
/**
 
668
  pull a DATA_BLOB from a reply packet, returning a talloced blob
 
669
  make sure we don't go past end of packet
 
670
 
 
671
  if byte_len is -1 then limit the blob only by packet size
 
672
*/
 
673
DATA_BLOB smbcli_req_pull_blob(struct request_bufinfo *bufinfo, TALLOC_CTX *mem_ctx, const uint8_t *src, int byte_len)
 
674
{
 
675
        int src_len;
 
676
 
 
677
        src_len = bufinfo->data_size - PTR_DIFF(src, bufinfo->data);
 
678
 
 
679
        if (src_len < 0) {
 
680
                return data_blob(NULL, 0);
 
681
        }
 
682
 
 
683
        if (byte_len != -1 && src_len > byte_len) {
 
684
                src_len = byte_len;
 
685
        }
 
686
 
 
687
        return data_blob_talloc(mem_ctx, src, src_len);
 
688
}
 
689
 
 
690
/* check that a lump of data in a request is within the bounds of the data section of
 
691
   the packet */
 
692
static bool smbcli_req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t count)
 
693
{
 
694
        /* be careful with wraparound! */
 
695
        if ((uintptr_t)ptr < (uintptr_t)bufinfo->data ||
 
696
            (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size ||
 
697
            count > bufinfo->data_size ||
 
698
            (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) {
 
699
                return true;
 
700
        }
 
701
        return false;
 
702
}
 
703
 
 
704
/*
 
705
  pull a lump of data from a request packet
 
706
 
 
707
  return false if any part is outside the data portion of the packet
 
708
*/
 
709
bool smbcli_raw_pull_data(struct request_bufinfo *bufinfo, const uint8_t *src, int len, uint8_t *dest)
 
710
{
 
711
        if (len == 0) return true;
 
712
 
 
713
        if (smbcli_req_data_oob(bufinfo, src, len)) {
 
714
                return false;
 
715
        }
 
716
 
 
717
        memcpy(dest, src, len);
 
718
        return true;
 
719
}
 
720
 
 
721
 
 
722
/*
 
723
  put a NTTIME into a packet
 
724
*/
 
725
void smbcli_push_nttime(void *base, uint16_t offset, NTTIME t)
 
726
{
 
727
        SBVAL(base, offset, t);
 
728
}
 
729
 
 
730
/*
 
731
  pull a NTTIME from a packet
 
732
*/
 
733
NTTIME smbcli_pull_nttime(void *base, uint16_t offset)
 
734
{
 
735
        NTTIME ret = BVAL(base, offset);
 
736
        return ret;
 
737
}
 
738
 
 
739
/**
 
740
  pull a UCS2 string from a blob, returning a talloced unix string
 
741
 
 
742
  the string length is limited by the 3 things:
 
743
   - the data size in the blob
 
744
   - the passed 'byte_len' if it is not -1
 
745
   - the end of string (null termination)
 
746
 
 
747
  Note that 'byte_len' is the number of bytes in the packet
 
748
 
 
749
  on failure zero is returned and *dest is set to NULL, otherwise the number
 
750
  of bytes consumed in the blob is returned
 
751
*/
 
752
size_t smbcli_blob_pull_ucs2(TALLOC_CTX* mem_ctx,
 
753
                             const DATA_BLOB *blob, const char **dest, 
 
754
                             const uint8_t *src, int byte_len, uint_t flags)
 
755
{
 
756
        int src_len, src_len2, alignment=0;
 
757
        size_t ret_size;
 
758
        bool ret;
 
759
        char *dest2;
 
760
 
 
761
        if (src < blob->data ||
 
762
            src >= (blob->data + blob->length)) {
 
763
                *dest = NULL;
 
764
                return 0;
 
765
        }
 
766
 
 
767
        src_len = blob->length - PTR_DIFF(src, blob->data);
 
768
 
 
769
        if (byte_len != -1 && src_len > byte_len) {
 
770
                src_len = byte_len;
 
771
        }
 
772
 
 
773
        if (!(flags & STR_NOALIGN) && ucs2_align(blob->data, src, flags)) {
 
774
                src++;
 
775
                alignment=1;
 
776
                src_len--;
 
777
        }
 
778
 
 
779
        if (src_len < 2) {
 
780
                *dest = NULL;
 
781
                return 0;
 
782
        }
 
783
 
 
784
        src_len2 = utf16_len_n(src, src_len);
 
785
 
 
786
        ret = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size, false);
 
787
        if (!ret) {
 
788
                *dest = NULL;
 
789
                return 0;
 
790
        }
 
791
        *dest = dest2;
 
792
 
 
793
        return src_len2 + alignment;
 
794
}
 
795
 
 
796
/**
 
797
  pull a ascii string from a blob, returning a talloced string
 
798
 
 
799
  the string length is limited by the 3 things:
 
800
   - the data size in the blob
 
801
   - the passed 'byte_len' if it is not -1
 
802
   - the end of string (null termination)
 
803
 
 
804
  Note that 'byte_len' is the number of bytes in the blob
 
805
 
 
806
  on failure zero is returned and *dest is set to NULL, otherwise the number
 
807
  of bytes consumed in the blob is returned
 
808
*/
 
809
static size_t smbcli_blob_pull_ascii(TALLOC_CTX *mem_ctx,
 
810
                                     const DATA_BLOB *blob, const char **dest, 
 
811
                                     const uint8_t *src, int byte_len, uint_t flags)
 
812
{
 
813
        int src_len, src_len2;
 
814
        size_t ret_size;
 
815
        bool ret;
 
816
        char *dest2;
 
817
 
 
818
        src_len = blob->length - PTR_DIFF(src, blob->data);
 
819
        if (src_len < 0) {
 
820
                *dest = NULL;
 
821
                return 0;
 
822
        }
 
823
        if (byte_len != -1 && src_len > byte_len) {
 
824
                src_len = byte_len;
 
825
        }
 
826
        src_len2 = strnlen((const char *)src, src_len);
 
827
 
 
828
        if (src_len2 < src_len - 1) {
 
829
                /* include the termination if we didn't reach the end of the packet */
 
830
                src_len2++;
 
831
        }
 
832
 
 
833
        ret = convert_string_talloc(mem_ctx, CH_DOS, CH_UNIX, src, src_len2, (void **)&dest2, &ret_size, false);
 
834
 
 
835
        if (!ret) {
 
836
                *dest = NULL;
 
837
                return 0;
 
838
        }
 
839
        *dest = dest2;
 
840
 
 
841
        return ret_size;
 
842
}
 
843
 
 
844
/**
 
845
  pull a string from a blob, returning a talloced struct smb_wire_string
 
846
 
 
847
  the string length is limited by the 3 things:
 
848
   - the data size in the blob
 
849
   - length field on the wire
 
850
   - the end of string (null termination)
 
851
 
 
852
   if STR_LEN8BIT is set in the flags then assume the length field is
 
853
   8 bits, instead of 32
 
854
 
 
855
  on failure zero is returned and dest->s is set to NULL, otherwise the number
 
856
  of bytes consumed in the blob is returned
 
857
*/
 
858
size_t smbcli_blob_pull_string(struct smbcli_session *session,
 
859
                               TALLOC_CTX *mem_ctx,
 
860
                               const DATA_BLOB *blob, 
 
861
                               struct smb_wire_string *dest, 
 
862
                               uint16_t len_offset, uint16_t str_offset, 
 
863
                               uint_t flags)
 
864
{
 
865
        int extra;
 
866
        dest->s = NULL;
 
867
 
 
868
        if (!(flags & STR_ASCII)) {
 
869
                /* this is here to cope with SMB2 calls using the SMB
 
870
                   parsers. SMB2 will pass smbcli_session==NULL, which forces
 
871
                   unicode on (as used by SMB2) */
 
872
                if (session == NULL) {
 
873
                        flags |= STR_UNICODE;
 
874
                } else if (session->transport->negotiate.capabilities & CAP_UNICODE) {
 
875
                        flags |= STR_UNICODE;
 
876
                }
 
877
        }
 
878
 
 
879
        if (flags & STR_LEN8BIT) {
 
880
                if (len_offset > blob->length-1) {
 
881
                        return 0;
 
882
                }
 
883
                dest->private_length = CVAL(blob->data, len_offset);
 
884
        } else {
 
885
                if (len_offset > blob->length-4) {
 
886
                        return 0;
 
887
                }
 
888
                dest->private_length = IVAL(blob->data, len_offset);
 
889
        }
 
890
        extra = 0;
 
891
        dest->s = NULL;
 
892
        if (!(flags & STR_ASCII) && (flags & STR_UNICODE)) {
 
893
                int align = 0;
 
894
                if ((str_offset&1) && !(flags & STR_NOALIGN)) {
 
895
                        align = 1;
 
896
                }
 
897
                if (flags & STR_LEN_NOTERM) {
 
898
                        extra = 2;
 
899
                }
 
900
                return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, &dest->s, 
 
901
                                                          blob->data+str_offset+align, 
 
902
                                                          dest->private_length, flags);
 
903
        }
 
904
 
 
905
        if (flags & STR_LEN_NOTERM) {
 
906
                extra = 1;
 
907
        }
 
908
 
 
909
        return extra + smbcli_blob_pull_ascii(mem_ctx, blob, &dest->s, 
 
910
                                           blob->data+str_offset, dest->private_length, flags);
 
911
}
 
912
 
 
913
/**
 
914
  pull a string from a blob, returning a talloced char *
 
915
 
 
916
  Currently only used by the UNIX search info level.
 
917
 
 
918
  the string length is limited by 2 things:
 
919
   - the data size in the blob
 
920
   - the end of string (null termination)
 
921
 
 
922
  on failure zero is returned and dest->s is set to NULL, otherwise the number
 
923
  of bytes consumed in the blob is returned
 
924
*/
 
925
size_t smbcli_blob_pull_unix_string(struct smbcli_session *session,
 
926
                            TALLOC_CTX *mem_ctx,
 
927
                            DATA_BLOB *blob, 
 
928
                            const char **dest, 
 
929
                            uint16_t str_offset, 
 
930
                            uint_t flags)
 
931
{
 
932
        int extra = 0;
 
933
        *dest = NULL;
 
934
        
 
935
        if (!(flags & STR_ASCII) && 
 
936
            ((flags & STR_UNICODE) || 
 
937
             (session->transport->negotiate.capabilities & CAP_UNICODE))) {
 
938
                int align = 0;
 
939
                if ((str_offset&1) && !(flags & STR_NOALIGN)) {
 
940
                        align = 1;
 
941
                }
 
942
                if (flags & STR_LEN_NOTERM) {
 
943
                        extra = 2;
 
944
                }
 
945
                return align + extra + smbcli_blob_pull_ucs2(mem_ctx, blob, dest, 
 
946
                                                          blob->data+str_offset+align, 
 
947
                                                          -1, flags);
 
948
        }
 
949
 
 
950
        if (flags & STR_LEN_NOTERM) {
 
951
                extra = 1;
 
952
        }
 
953
 
 
954
        return extra + smbcli_blob_pull_ascii(mem_ctx, blob, dest,
 
955
                                           blob->data+str_offset, -1, flags);
 
956
}
 
957
 
 
958
 
 
959
/*
 
960
  append a string into a blob
 
961
*/
 
962
size_t smbcli_blob_append_string(struct smbcli_session *session,
 
963
                              TALLOC_CTX *mem_ctx, DATA_BLOB *blob, 
 
964
                              const char *str, uint_t flags)
 
965
{
 
966
        size_t max_len;
 
967
        int len;
 
968
 
 
969
        if (!str) return 0;
 
970
 
 
971
        /* determine string type to use */
 
972
        if (!(flags & (STR_ASCII|STR_UNICODE))) {
 
973
                flags |= (session->transport->negotiate.capabilities & CAP_UNICODE) ? STR_UNICODE : STR_ASCII;
 
974
        }
 
975
 
 
976
        max_len = (strlen(str)+2) * MAX_BYTES_PER_CHAR;         
 
977
 
 
978
        blob->data = talloc_realloc(mem_ctx, blob->data, uint8_t, blob->length + max_len);
 
979
        if (!blob->data) {
 
980
                return 0;
 
981
        }
 
982
 
 
983
        len = push_string(blob->data + blob->length, str, max_len, flags);
 
984
 
 
985
        blob->length += len;
 
986
 
 
987
        return len;
 
988
}
 
989
 
 
990
/*
 
991
  pull a GUID structure from the wire. The buffer must be at least 16
 
992
  bytes long
 
993
 */
 
994
enum ndr_err_code smbcli_pull_guid(void *base, uint16_t offset, 
 
995
                                   struct GUID *guid)
 
996
{
 
997
        DATA_BLOB blob;
 
998
        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
 
999
        enum ndr_err_code ndr_err;
 
1000
 
 
1001
        ZERO_STRUCTP(guid);
 
1002
 
 
1003
        blob.data       = offset + (uint8_t *)base;
 
1004
        blob.length     = 16;
 
1005
        ndr_err = ndr_pull_struct_blob(&blob, tmp_ctx, NULL, guid, 
 
1006
                                       (ndr_pull_flags_fn_t)ndr_pull_GUID);
 
1007
        talloc_free(tmp_ctx);
 
1008
        return ndr_err;
 
1009
}
 
1010
 
 
1011
/*
 
1012
  push a guid onto the wire. The buffer must hold 16 bytes
 
1013
 */
 
1014
enum ndr_err_code smbcli_push_guid(void *base, uint16_t offset, 
 
1015
                                   const struct GUID *guid)
 
1016
{
 
1017
        TALLOC_CTX *tmp_ctx = talloc_new(NULL);
 
1018
        enum ndr_err_code ndr_err;
 
1019
        DATA_BLOB blob;
 
1020
        ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL,
 
1021
                                       guid, (ndr_push_flags_fn_t)ndr_push_GUID);
 
1022
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err) || blob.length != 16) {
 
1023
                talloc_free(tmp_ctx);
 
1024
                return ndr_err;
 
1025
        }
 
1026
        memcpy(offset + (uint8_t *)base, blob.data, blob.length);
 
1027
        talloc_free(tmp_ctx);
 
1028
        return ndr_err;
 
1029
}