dcerpc_util: let dcerpc_pull_auth_trailer() check that auth_offset is 4 bytes aligned
[metze/samba/wip.git] / librpc / rpc / dcerpc_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    raw dcerpc operations
4
5    Copyright (C) Andrew Tridgell 2003-2005
6    Copyright (C) Jelmer Vernooij 2004-2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "system/network.h"
24 #include <tevent.h>
25 #include "lib/tsocket/tsocket.h"
26 #include "lib/util/util_file.h"
27 #include "lib/util/tevent_ntstatus.h"
28 #include "librpc/rpc/dcerpc.h"
29 #include "librpc/rpc/dcerpc_util.h"
30 #include "librpc/gen_ndr/ndr_dcerpc.h"
31 #include "rpc_common.h"
32 #include "lib/util/bitmap.h"
33
34 #include "lib/crypto/gnutls_helpers.h"
35 #include <gnutls/gnutls.h>
36 #include <gnutls/crypto.h>
37
38 #undef strncasecmp
39
40
41 /* we need to be able to get/set the fragment length without doing a full
42    decode */
43 void dcerpc_set_frag_length(DATA_BLOB *blob, uint16_t v)
44 {
45         SMB_ASSERT(blob->length >= DCERPC_NCACN_PAYLOAD_OFFSET);
46
47         if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {
48                 SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v);
49         } else {
50                 RSSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v);
51         }
52 }
53
54 uint16_t dcerpc_get_frag_length(const DATA_BLOB *blob)
55 {
56         SMB_ASSERT(blob->length >= DCERPC_NCACN_PAYLOAD_OFFSET);
57
58         if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {
59                 return SVAL(blob->data, DCERPC_FRAG_LEN_OFFSET);
60         } else {
61                 return RSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET);
62         }
63 }
64
65 void dcerpc_set_auth_length(DATA_BLOB *blob, uint16_t v)
66 {
67         SMB_ASSERT(blob->length >= DCERPC_NCACN_PAYLOAD_OFFSET);
68
69         if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {
70                 SSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v);
71         } else {
72                 RSSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v);
73         }
74 }
75
76 uint16_t dcerpc_get_auth_length(const DATA_BLOB *blob)
77 {
78         SMB_ASSERT(blob->length >= DCERPC_NCACN_PAYLOAD_OFFSET);
79
80         if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {
81                 return SVAL(blob->data, DCERPC_AUTH_LEN_OFFSET);
82         } else {
83                 return RSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET);
84         }
85 }
86
87 uint8_t dcerpc_get_endian_flag(DATA_BLOB *blob)
88 {
89         SMB_ASSERT(blob->length >= DCERPC_NCACN_PAYLOAD_OFFSET);
90
91         return blob->data[DCERPC_DREP_OFFSET];
92 }
93
94 static uint16_t dcerpc_get_auth_context_offset(const DATA_BLOB *blob)
95 {
96         uint16_t frag_len = dcerpc_get_frag_length(blob);
97         uint16_t auth_len = dcerpc_get_auth_length(blob);
98         uint16_t min_offset;
99         uint16_t offset;
100
101         if (auth_len == 0) {
102                 return 0;
103         }
104
105         if (frag_len > blob->length) {
106                 return 0;
107         }
108
109         if (auth_len > frag_len) {
110                 return 0;
111         }
112
113         min_offset = DCERPC_NCACN_PAYLOAD_OFFSET + DCERPC_AUTH_TRAILER_LENGTH;
114         offset = frag_len - auth_len;
115         if (offset < min_offset) {
116                 return 0;
117         }
118         offset -= DCERPC_AUTH_TRAILER_LENGTH;
119
120         return offset;
121 }
122
123 uint8_t dcerpc_get_auth_type(const DATA_BLOB *blob)
124 {
125         uint16_t offset;
126
127         offset = dcerpc_get_auth_context_offset(blob);
128         if (offset == 0) {
129                 return 0;
130         }
131
132         /*
133          * auth_typw is in the 1st byte
134          * of the auth trailer
135          */
136         offset += 0;
137
138         return blob->data[offset];
139 }
140
141 uint8_t dcerpc_get_auth_level(const DATA_BLOB *blob)
142 {
143         uint16_t offset;
144
145         offset = dcerpc_get_auth_context_offset(blob);
146         if (offset == 0) {
147                 return 0;
148         }
149
150         /*
151          * auth_level is in 2nd byte
152          * of the auth trailer
153          */
154         offset += 1;
155
156         return blob->data[offset];
157 }
158
159 uint32_t dcerpc_get_auth_context_id(const DATA_BLOB *blob)
160 {
161         uint16_t offset;
162
163         offset = dcerpc_get_auth_context_offset(blob);
164         if (offset == 0) {
165                 return 0;
166         }
167
168         /*
169          * auth_context_id is in the last 4 byte
170          * of the auth trailer
171          */
172         offset += 4;
173
174         if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) {
175                 return IVAL(blob->data, offset);
176         } else {
177                 return RIVAL(blob->data, offset);
178         }
179 }
180
181 /**
182 * @brief Decodes a ncacn_packet
183 *
184 * @param mem_ctx        The memory context on which to allocate the packet
185 *                       elements
186 * @param blob           The blob of data to decode
187 * @param r              An empty ncacn_packet, must not be NULL
188 *
189 * @return a NTSTATUS error code
190 */
191 NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
192                                   const DATA_BLOB *blob,
193                                   struct ncacn_packet *r)
194 {
195         enum ndr_err_code ndr_err;
196         struct ndr_pull *ndr;
197
198         ndr = ndr_pull_init_blob(blob, mem_ctx);
199         if (!ndr) {
200                 return NT_STATUS_NO_MEMORY;
201         }
202
203         ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, r);
204
205         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
206                 talloc_free(ndr);
207                 return ndr_map_error2ntstatus(ndr_err);
208         }
209         talloc_free(ndr);
210
211         if (r->frag_length != blob->length) {
212                 return NT_STATUS_RPC_PROTOCOL_ERROR;
213         }
214
215         return NT_STATUS_OK;
216 }
217
218 /**
219 * @brief        Pull a dcerpc_auth structure, taking account of any auth
220 *               padding in the blob. For request/response packets we pass
221 *               the whole data blob, so auth_data_only must be set to false
222 *               as the blob contains data+pad+auth and no just pad+auth.
223 *
224 * @param pkt            - The ncacn_packet structure
225 * @param mem_ctx        - The mem_ctx used to allocate dcerpc_auth elements
226 * @param pkt_trailer    - The packet trailer data, usually the trailing
227 *                         auth_info blob, but in the request/response case
228 *                         this is the stub_and_verifier blob.
229 * @param auth           - A preallocated dcerpc_auth *empty* structure
230 * @param auth_length    - The length of the auth trail, sum of auth header
231 *                         length and pkt->auth_length
232 * @param auth_data_only - Whether the pkt_trailer includes only the auth_blob
233 *                         (+ padding) or also other data.
234 *
235 * @return               - A NTSTATUS error code.
236 */
237 NTSTATUS dcerpc_pull_auth_trailer(const struct ncacn_packet *pkt,
238                                   TALLOC_CTX *mem_ctx,
239                                   const DATA_BLOB *pkt_trailer,
240                                   struct dcerpc_auth *auth,
241                                   uint32_t *_auth_length,
242                                   bool auth_data_only)
243 {
244         struct ndr_pull *ndr;
245         enum ndr_err_code ndr_err;
246         uint16_t data_and_pad;
247         uint16_t auth_length;
248         uint16_t auth_offset;
249         uint32_t tmp_length;
250         uint32_t max_pad_len = 0;
251         DATA_BLOB auth_blob;
252
253         ZERO_STRUCTP(auth);
254         if (_auth_length != NULL) {
255                 *_auth_length = 0;
256
257                 if (auth_data_only) {
258                         return NT_STATUS_INTERNAL_ERROR;
259                 }
260         } else {
261                 if (!auth_data_only) {
262                         return NT_STATUS_INTERNAL_ERROR;
263                 }
264         }
265
266         /* Paranoia checks for auth_length. The caller should check this... */
267         if (pkt->auth_length == 0) {
268                 return NT_STATUS_INTERNAL_ERROR;
269         }
270
271         /* Paranoia checks for auth_length. The caller should check this... */
272         if (pkt->auth_length > pkt->frag_length) {
273                 return NT_STATUS_INTERNAL_ERROR;
274         }
275         tmp_length = DCERPC_NCACN_PAYLOAD_OFFSET;
276         tmp_length += DCERPC_AUTH_TRAILER_LENGTH;
277         tmp_length += pkt->auth_length;
278         if (tmp_length > pkt->frag_length) {
279                 return NT_STATUS_INTERNAL_ERROR;
280         }
281         if (pkt_trailer->length > UINT16_MAX) {
282                 return NT_STATUS_INTERNAL_ERROR;
283         }
284
285         auth_length = DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length;
286         if (pkt_trailer->length < auth_length) {
287                 return NT_STATUS_RPC_PROTOCOL_ERROR;
288         }
289
290         data_and_pad = pkt_trailer->length - auth_length;
291         auth_offset = pkt->frag_length - auth_length;
292         if ((auth_offset % 4) != 0) {
293                 DBG_WARNING("auth_offset[%u] not 4 byte aligned\n",
294                             (unsigned)auth_offset);
295                 return NT_STATUS_RPC_PROTOCOL_ERROR;
296         }
297
298         auth_blob = data_blob_const(pkt_trailer->data + data_and_pad,
299                                     auth_length);
300         ndr = ndr_pull_init_blob(&auth_blob, mem_ctx);
301         if (!ndr) {
302                 return NT_STATUS_NO_MEMORY;
303         }
304
305         if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
306                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
307         }
308
309         ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth);
310         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
311                 talloc_free(ndr);
312                 ZERO_STRUCTP(auth);
313                 return ndr_map_error2ntstatus(ndr_err);
314         }
315
316         /*
317          * Make sure the padding would not exceed
318          * the frag_length.
319          *
320          * Here we assume at least 24 bytes for the
321          * payload specific header the value of
322          * DCERPC_{REQUEST,RESPONSE}_LENGTH.
323          *
324          * We use this also for BIND_*, ALTER_* and AUTH3 pdus.
325          *
326          * We need this check before we ignore possible
327          * invalid values. See also bug #11982.
328          *
329          * This check is mainly used to generate the correct
330          * error for BIND_*, ALTER_* and AUTH3 pdus.
331          *
332          * We always have the 'if (data_and_pad < auth->auth_pad_length)'
333          * protection for REQUEST and RESPONSE pdus, where the
334          * auth_pad_length field is actually used by the caller.
335          */
336         tmp_length = DCERPC_REQUEST_LENGTH;
337         tmp_length += DCERPC_AUTH_TRAILER_LENGTH;
338         tmp_length += pkt->auth_length;
339         if (tmp_length < pkt->frag_length) {
340                 max_pad_len = pkt->frag_length - tmp_length;
341         }
342         if (max_pad_len < auth->auth_pad_length) {
343                 DEBUG(1, (__location__ ": ERROR: pad length too large. "
344                           "max %"PRIu32" got %"PRIu8"\n",
345                           max_pad_len,
346                           auth->auth_pad_length));
347                 talloc_free(ndr);
348                 ZERO_STRUCTP(auth);
349                 return NT_STATUS_RPC_PROTOCOL_ERROR;
350         }
351
352         /*
353          * This is a workaround for a bug in old
354          * Samba releases. For BIND_ACK <= 3.5.x
355          * and for ALTER_RESP <= 4.2.x (see bug #11061)
356          *
357          * See also bug #11982.
358          */
359         if (auth_data_only && data_and_pad == 0 &&
360             auth->auth_pad_length > 0) {
361                 /*
362                  * we need to ignore invalid auth_pad_length
363                  * values for BIND_*, ALTER_* and AUTH3 pdus.
364                  */
365                 auth->auth_pad_length = 0;
366         }
367
368         if (data_and_pad < auth->auth_pad_length) {
369                 DBG_WARNING(__location__ ": ERROR: pad length too long. "
370                             "Calculated %"PRIu16" (pkt_trailer->length=%zu - auth_length=%"PRIu16") "
371                             "was less than auth_pad_length=%"PRIu8"\n",
372                             data_and_pad,
373                             pkt_trailer->length,
374                             auth_length,
375                             auth->auth_pad_length);
376                 talloc_free(ndr);
377                 ZERO_STRUCTP(auth);
378                 return NT_STATUS_RPC_PROTOCOL_ERROR;
379         }
380
381         if (auth_data_only && data_and_pad > auth->auth_pad_length) {
382                 DBG_WARNING(__location__ ": ERROR: auth_data_only pad length mismatch. "
383                             "Client sent a longer BIND packet than expected by %"PRIu16" bytes "
384                             "(pkt_trailer->length=%zu - auth_length=%"PRIu16") "
385                             "= %"PRIu16" auth_pad_length=%"PRIu8"\n",
386                             data_and_pad - auth->auth_pad_length,
387                             pkt_trailer->length,
388                             auth_length,
389                             data_and_pad,
390                             auth->auth_pad_length);
391                 talloc_free(ndr);
392                 ZERO_STRUCTP(auth);
393                 return NT_STATUS_RPC_PROTOCOL_ERROR;
394         }
395
396         if (auth_data_only && data_and_pad != auth->auth_pad_length) {
397                 DBG_WARNING(__location__ ": ERROR: auth_data_only pad length mismatch. "
398                             "Calculated %"PRIu16" (pkt_trailer->length=%zu - auth_length=%"PRIu16") "
399                             "but auth_pad_length=%"PRIu8"\n",
400                             data_and_pad,
401                             pkt_trailer->length,
402                             auth_length,
403                             auth->auth_pad_length);
404                 talloc_free(ndr);
405                 ZERO_STRUCTP(auth);
406                 return NT_STATUS_RPC_PROTOCOL_ERROR;
407         }
408
409         DBG_DEBUG("auth_pad_length %"PRIu8"\n",
410                   auth->auth_pad_length);
411
412         talloc_steal(mem_ctx, auth->credentials.data);
413         talloc_free(ndr);
414
415         if (_auth_length != NULL) {
416                 *_auth_length = auth_length;
417         }
418
419         return NT_STATUS_OK;
420 }
421
422 /**
423 * @brief        Verify the fields in ncacn_packet header.
424 *
425 * @param pkt            - The ncacn_packet structure
426 * @param ptype          - The expected PDU type
427 * @param max_auth_info  - The maximum size of a possible auth trailer
428 * @param required_flags - The required flags for the pdu.
429 * @param optional_flags - The possible optional flags for the pdu.
430 *
431 * @return               - A NTSTATUS error code.
432 */
433 NTSTATUS dcerpc_verify_ncacn_packet_header(const struct ncacn_packet *pkt,
434                                            enum dcerpc_pkt_type ptype,
435                                            size_t max_auth_info,
436                                            uint8_t required_flags,
437                                            uint8_t optional_flags)
438 {
439         if (pkt->rpc_vers != 5) {
440                 return NT_STATUS_RPC_PROTOCOL_ERROR;
441         }
442
443         if (pkt->rpc_vers_minor != 0) {
444                 return NT_STATUS_RPC_PROTOCOL_ERROR;
445         }
446
447         if (pkt->auth_length > pkt->frag_length) {
448                 return NT_STATUS_RPC_PROTOCOL_ERROR;
449         }
450
451         if (pkt->ptype != ptype) {
452                 return NT_STATUS_RPC_PROTOCOL_ERROR;
453         }
454
455         if (max_auth_info > UINT16_MAX) {
456                 return NT_STATUS_INTERNAL_ERROR;
457         }
458
459         if (pkt->auth_length > 0) {
460                 size_t max_auth_length;
461
462                 if (max_auth_info <= DCERPC_AUTH_TRAILER_LENGTH) {
463                         return NT_STATUS_RPC_PROTOCOL_ERROR;
464                 }
465                 max_auth_length = max_auth_info - DCERPC_AUTH_TRAILER_LENGTH;
466
467                 if (pkt->auth_length > max_auth_length) {
468                         return NT_STATUS_RPC_PROTOCOL_ERROR;
469                 }
470         }
471
472         if ((pkt->pfc_flags & required_flags) != required_flags) {
473                 return NT_STATUS_RPC_PROTOCOL_ERROR;
474         }
475         if (pkt->pfc_flags & ~(optional_flags|required_flags)) {
476                 return NT_STATUS_RPC_PROTOCOL_ERROR;
477         }
478
479         if (pkt->drep[0] & ~DCERPC_DREP_LE) {
480                 return NT_STATUS_RPC_PROTOCOL_ERROR;
481         }
482         if (pkt->drep[1] != 0) {
483                 return NT_STATUS_RPC_PROTOCOL_ERROR;
484         }
485         if (pkt->drep[2] != 0) {
486                 return NT_STATUS_RPC_PROTOCOL_ERROR;
487         }
488         if (pkt->drep[3] != 0) {
489                 return NT_STATUS_RPC_PROTOCOL_ERROR;
490         }
491
492         return NT_STATUS_OK;
493 }
494
495 struct dcerpc_read_ncacn_packet_state {
496 #if 0
497         struct {
498         } caller;
499 #endif
500         DATA_BLOB buffer;
501         struct ncacn_packet *pkt;
502 };
503
504 static int dcerpc_read_ncacn_packet_next_vector(struct tstream_context *stream,
505                                                 void *private_data,
506                                                 TALLOC_CTX *mem_ctx,
507                                                 struct iovec **_vector,
508                                                 size_t *_count);
509 static void dcerpc_read_ncacn_packet_done(struct tevent_req *subreq);
510
511 struct tevent_req *dcerpc_read_ncacn_packet_send(TALLOC_CTX *mem_ctx,
512                                                  struct tevent_context *ev,
513                                                  struct tstream_context *stream)
514 {
515         struct tevent_req *req;
516         struct dcerpc_read_ncacn_packet_state *state;
517         struct tevent_req *subreq;
518
519         req = tevent_req_create(mem_ctx, &state,
520                                 struct dcerpc_read_ncacn_packet_state);
521         if (req == NULL) {
522                 return NULL;
523         }
524
525         state->pkt = talloc_zero(state, struct ncacn_packet);
526         if (tevent_req_nomem(state->pkt, req)) {
527                 goto post;
528         }
529
530         subreq = tstream_readv_pdu_send(state, ev,
531                                         stream,
532                                         dcerpc_read_ncacn_packet_next_vector,
533                                         state);
534         if (tevent_req_nomem(subreq, req)) {
535                 goto post;
536         }
537         tevent_req_set_callback(subreq, dcerpc_read_ncacn_packet_done, req);
538
539         return req;
540  post:
541         tevent_req_post(req, ev);
542         return req;
543 }
544
545 static int dcerpc_read_ncacn_packet_next_vector(struct tstream_context *stream,
546                                                 void *private_data,
547                                                 TALLOC_CTX *mem_ctx,
548                                                 struct iovec **_vector,
549                                                 size_t *_count)
550 {
551         struct dcerpc_read_ncacn_packet_state *state =
552                 talloc_get_type_abort(private_data,
553                 struct dcerpc_read_ncacn_packet_state);
554         struct iovec *vector;
555         off_t ofs = 0;
556
557         if (state->buffer.length == 0) {
558                 /*
559                  * first get enough to read the fragment length
560                  *
561                  * We read the full fixed ncacn_packet header
562                  * in order to make wireshark happy with
563                  * pcap files from socket_wrapper.
564                  */
565                 ofs = 0;
566                 state->buffer.length = DCERPC_NCACN_PAYLOAD_OFFSET;
567                 state->buffer.data = talloc_array(state, uint8_t,
568                                                   state->buffer.length);
569                 if (!state->buffer.data) {
570                         return -1;
571                 }
572         } else if (state->buffer.length == DCERPC_NCACN_PAYLOAD_OFFSET) {
573                 /* now read the fragment length and allocate the full buffer */
574                 size_t frag_len = dcerpc_get_frag_length(&state->buffer);
575
576                 ofs = state->buffer.length;
577
578                 if (frag_len <= ofs) {
579                         /*
580                          * With frag_len == ofs, we are done, this is likely
581                          * a DCERPC_PKT_CO_CANCEL and DCERPC_PKT_ORPHANED
582                          * without any payload.
583                          *
584                          * Otherwise it's a broken packet and we
585                          * let the caller deal with it.
586                          */
587                         *_vector = NULL;
588                         *_count = 0;
589                         return 0;
590                 }
591
592                 state->buffer.data = talloc_realloc(state,
593                                                     state->buffer.data,
594                                                     uint8_t, frag_len);
595                 if (!state->buffer.data) {
596                         return -1;
597                 }
598                 state->buffer.length = frag_len;
599         } else {
600                 /* if we reach this we have a full fragment */
601                 *_vector = NULL;
602                 *_count = 0;
603                 return 0;
604         }
605
606         /* now create the vector that we want to be filled */
607         vector = talloc_array(mem_ctx, struct iovec, 1);
608         if (!vector) {
609                 return -1;
610         }
611
612         vector[0].iov_base = (void *) (state->buffer.data + ofs);
613         vector[0].iov_len = state->buffer.length - ofs;
614
615         *_vector = vector;
616         *_count = 1;
617         return 0;
618 }
619
620 static void dcerpc_read_ncacn_packet_done(struct tevent_req *subreq)
621 {
622         struct tevent_req *req = tevent_req_callback_data(subreq,
623                                  struct tevent_req);
624         struct dcerpc_read_ncacn_packet_state *state = tevent_req_data(req,
625                                         struct dcerpc_read_ncacn_packet_state);
626         int ret;
627         int sys_errno;
628         NTSTATUS status;
629
630         ret = tstream_readv_pdu_recv(subreq, &sys_errno);
631         TALLOC_FREE(subreq);
632         if (ret == -1) {
633                 status = map_nt_error_from_unix_common(sys_errno);
634                 tevent_req_nterror(req, status);
635                 return;
636         }
637
638         status = dcerpc_pull_ncacn_packet(state->pkt,
639                                           &state->buffer,
640                                           state->pkt);
641         if (tevent_req_nterror(req, status)) {
642                 return;
643         }
644
645         tevent_req_done(req);
646 }
647
648 NTSTATUS dcerpc_read_ncacn_packet_recv(struct tevent_req *req,
649                                        TALLOC_CTX *mem_ctx,
650                                        struct ncacn_packet **pkt,
651                                        DATA_BLOB *buffer)
652 {
653         struct dcerpc_read_ncacn_packet_state *state = tevent_req_data(req,
654                                         struct dcerpc_read_ncacn_packet_state);
655         NTSTATUS status;
656
657         if (tevent_req_is_nterror(req, &status)) {
658                 tevent_req_received(req);
659                 return status;
660         }
661
662         *pkt = talloc_move(mem_ctx, &state->pkt);
663         if (buffer) {
664                 buffer->data = talloc_move(mem_ctx, &state->buffer.data);
665                 buffer->length = state->buffer.length;
666         }
667
668         tevent_req_received(req);
669         return NT_STATUS_OK;
670 }
671
672 const char *dcerpc_default_transport_endpoint(TALLOC_CTX *mem_ctx,
673                                               enum dcerpc_transport_t transport,
674                                               const struct ndr_interface_table *table)
675 {
676         NTSTATUS status;
677         const char *p = NULL;
678         const char *endpoint = NULL;
679         uint32_t i;
680         struct dcerpc_binding *default_binding = NULL;
681         TALLOC_CTX *frame = talloc_stackframe();
682
683         /* Find one of the default pipes for this interface */
684
685         for (i = 0; i < table->endpoints->count; i++) {
686                 enum dcerpc_transport_t dtransport;
687                 const char *dendpoint;
688
689                 status = dcerpc_parse_binding(frame, table->endpoints->names[i],
690                                               &default_binding);
691                 if (!NT_STATUS_IS_OK(status)) {
692                         continue;
693                 }
694
695                 dtransport = dcerpc_binding_get_transport(default_binding);
696                 dendpoint = dcerpc_binding_get_string_option(default_binding,
697                                                              "endpoint");
698                 if (dendpoint == NULL) {
699                         TALLOC_FREE(default_binding);
700                         continue;
701                 }
702
703                 if (transport == NCA_UNKNOWN) {
704                         transport = dtransport;
705                 }
706
707                 if (transport != dtransport) {
708                         TALLOC_FREE(default_binding);
709                         continue;
710                 }
711
712                 p = dendpoint;
713                 break;
714         }
715
716         if (p == NULL) {
717                 goto done;
718         }
719
720         /*
721          * extract the pipe name without \\pipe from for example
722          * ncacn_np:[\\pipe\\epmapper]
723          */
724         if (transport == NCACN_NP) {
725                 if (strncasecmp(p, "\\pipe\\", 6) == 0) {
726                         p += 6;
727                 }
728                 if (p[0] == '\\') {
729                         p += 1;
730                 }
731         }
732
733         endpoint = talloc_strdup(mem_ctx, p);
734
735  done:
736         talloc_free(frame);
737         return endpoint;
738 }
739
740 struct dcerpc_sec_vt_header2 dcerpc_sec_vt_header2_from_ncacn_packet(const struct ncacn_packet *pkt)
741 {
742         struct dcerpc_sec_vt_header2 ret;
743
744         ZERO_STRUCT(ret);
745         ret.ptype = pkt->ptype;
746         memcpy(&ret.drep, pkt->drep, sizeof(ret.drep));
747         ret.call_id = pkt->call_id;
748
749         switch (pkt->ptype) {
750         case DCERPC_PKT_REQUEST:
751                 ret.context_id = pkt->u.request.context_id;
752                 ret.opnum      = pkt->u.request.opnum;
753                 break;
754
755         case DCERPC_PKT_RESPONSE:
756                 ret.context_id = pkt->u.response.context_id;
757                 break;
758
759         case DCERPC_PKT_FAULT:
760                 ret.context_id = pkt->u.fault.context_id;
761                 break;
762
763         default:
764                 break;
765         }
766
767         return ret;
768 }
769
770 bool dcerpc_sec_vt_header2_equal(const struct dcerpc_sec_vt_header2 *v1,
771                                  const struct dcerpc_sec_vt_header2 *v2)
772 {
773         if (v1->ptype != v2->ptype) {
774                 return false;
775         }
776
777         if (memcmp(v1->drep, v2->drep, sizeof(v1->drep)) != 0) {
778                 return false;
779         }
780
781         if (v1->call_id != v2->call_id) {
782                 return false;
783         }
784
785         if (v1->context_id != v2->context_id) {
786                 return false;
787         }
788
789         if (v1->opnum != v2->opnum) {
790                 return false;
791         }
792
793         return true;
794 }
795
796 static bool dcerpc_sec_vt_is_valid(const struct dcerpc_sec_verification_trailer *r)
797 {
798         bool ret = false;
799         TALLOC_CTX *frame = talloc_stackframe();
800         struct bitmap *commands_seen;
801         int i;
802
803         if (r->count.count == 0) {
804                 ret = true;
805                 goto done;
806         }
807
808         if (memcmp(r->magic, DCERPC_SEC_VT_MAGIC, sizeof(r->magic)) != 0) {
809                 goto done;
810         }
811
812         commands_seen = bitmap_talloc(frame, DCERPC_SEC_VT_COMMAND_ENUM + 1);
813         if (commands_seen == NULL) {
814                 goto done;
815         }
816
817         for (i=0; i < r->count.count; i++) {
818                 enum dcerpc_sec_vt_command_enum cmd =
819                         r->commands[i].command & DCERPC_SEC_VT_COMMAND_ENUM;
820
821                 if (bitmap_query(commands_seen, cmd)) {
822                         /* Each command must appear at most once. */
823                         goto done;
824                 }
825                 bitmap_set(commands_seen, cmd);
826
827                 switch (cmd) {
828                 case DCERPC_SEC_VT_COMMAND_BITMASK1:
829                 case DCERPC_SEC_VT_COMMAND_PCONTEXT:
830                 case DCERPC_SEC_VT_COMMAND_HEADER2:
831                 case DCERPC_SEC_VT_COMMAND_PREAUTH:
832                         break;
833                 default:
834                         if ((r->commands[i].u._unknown.length % 4) != 0) {
835                                 goto done;
836                         }
837                         break;
838                 }
839         }
840         ret = true;
841 done:
842         TALLOC_FREE(frame);
843         return ret;
844 }
845
846 static bool dcerpc_sec_vt_bitmask_check(const uint32_t *bitmask1,
847                                         const struct dcerpc_sec_vt *c)
848 {
849         if (bitmask1 == NULL) {
850                 if (c->command & DCERPC_SEC_VT_MUST_PROCESS) {
851                         DEBUG(10, ("SEC_VT check Bitmask1 must_process_command "
852                                    "failed\n"));
853                         return false;
854                 }
855
856                 return true;
857         }
858
859         if ((c->u.bitmask1 & DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING)
860          && (!(*bitmask1 & DCERPC_SEC_VT_CLIENT_SUPPORTS_HEADER_SIGNING))) {
861                 DEBUG(10, ("SEC_VT check Bitmask1 client_header_signing "
862                            "failed\n"));
863                 return false;
864         }
865         return true;
866 }
867
868 static bool dcerpc_sec_vt_pctx_check(const struct dcerpc_sec_vt_pcontext *pcontext,
869                                      const struct dcerpc_sec_vt *c)
870 {
871         bool ok;
872
873         if (pcontext == NULL) {
874                 if (c->command & DCERPC_SEC_VT_MUST_PROCESS) {
875                         DEBUG(10, ("SEC_VT check Pcontext must_process_command "
876                                    "failed\n"));
877                         return false;
878                 }
879
880                 return true;
881         }
882
883         ok = ndr_syntax_id_equal(&pcontext->abstract_syntax,
884                                  &c->u.pcontext.abstract_syntax);
885         if (!ok) {
886                 struct ndr_syntax_id_buf buf1, buf2;
887                 DEBUG(10, ("SEC_VT check pcontext abstract_syntax failed: "
888                            "%s vs. %s\n",
889                            ndr_syntax_id_buf_string(
890                                    &pcontext->abstract_syntax, &buf1),
891                            ndr_syntax_id_buf_string(
892                                    &c->u.pcontext.abstract_syntax, &buf2)));
893                 return false;
894         }
895         ok = ndr_syntax_id_equal(&pcontext->transfer_syntax,
896                                  &c->u.pcontext.transfer_syntax);
897         if (!ok) {
898                 struct ndr_syntax_id_buf buf1, buf2;
899                 DEBUG(10, ("SEC_VT check pcontext transfer_syntax failed: "
900                            "%s vs. %s\n",
901                            ndr_syntax_id_buf_string(
902                                    &pcontext->transfer_syntax, &buf1),
903                            ndr_syntax_id_buf_string(
904                                    &c->u.pcontext.transfer_syntax, &buf2)));
905                 return false;
906         }
907
908         return true;
909 }
910
911 static bool dcerpc_sec_vt_hdr2_check(const struct dcerpc_sec_vt_header2 *header2,
912                                      const struct dcerpc_sec_vt *c)
913 {
914         if (header2 == NULL) {
915                 if (c->command & DCERPC_SEC_VT_MUST_PROCESS) {
916                         DEBUG(10, ("SEC_VT check Header2 must_process_command failed\n"));
917                         return false;
918                 }
919
920                 return true;
921         }
922
923         if (!dcerpc_sec_vt_header2_equal(header2, &c->u.header2)) {
924                 DEBUG(10, ("SEC_VT check Header2 failed\n"));
925                 return false;
926         }
927
928         return true;
929 }
930
931 NTSTATUS dcerpc_sec_vt_preauth_update(const struct dcerpc_sec_vt_preauth *in,
932                                       const struct ncacn_packet *pkt,
933                                       const DATA_BLOB *buffer,
934                                       struct dcerpc_sec_vt_preauth *out)
935 {
936         gnutls_hash_hd_t hash_hnd = NULL;
937         int rc;
938
939         if (pkt != NULL) {
940                 switch (pkt->ptype) {
941                 case DCERPC_PKT_BIND:
942                 case DCERPC_PKT_BIND_ACK:
943                 case DCERPC_PKT_ALTER:
944                 case DCERPC_PKT_ALTER_RESP:
945                 case DCERPC_PKT_AUTH3:
946                         break;
947                 default:
948                         return NT_STATUS_OK;
949                 }
950         }
951
952         rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_SHA512);
953         if (rc < 0) {
954                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
955         }
956         rc = gnutls_hash(hash_hnd, in->sha512, sizeof(in->sha512));
957         if (rc < 0) {
958                 gnutls_hash_deinit(hash_hnd, NULL);
959                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
960         }
961         rc = gnutls_hash(hash_hnd, buffer->data, buffer->length);
962         if (rc < 0) {
963                 gnutls_hash_deinit(hash_hnd, NULL);
964                 return gnutls_error_to_ntstatus(rc, NT_STATUS_HASH_NOT_SUPPORTED);
965         }
966
967         gnutls_hash_output(hash_hnd, out->sha512);
968
969         return NT_STATUS_OK;
970 }
971
972 static bool dcerpc_sec_vt_preauth_check(const struct dcerpc_sec_vt_preauth *preauth,
973                                         const struct dcerpc_sec_vt *c)
974 {
975         struct dcerpc_sec_vt_preauth result;
976         DATA_BLOB buffer = data_blob_null;
977         NTSTATUS status;
978         int cmp;
979
980         if (preauth == NULL) {
981                 if (c->command & DCERPC_SEC_VT_MUST_PROCESS) {
982                         DEBUG(10, ("SEC_VT check PREAUTH must_process_command failed\n"));
983                         return false;
984                 }
985
986                 return true;
987         }
988
989         buffer = data_blob_const(c->u.preauth.salt, sizeof(c->u.preauth.salt));
990
991         status = dcerpc_sec_vt_preauth_update(preauth, NULL, &buffer, &result);
992         if (!NT_STATUS_IS_OK(status)) {
993                 DBG_ERR("dcerpc_sec_vt_preauth_update() failed: %s\n",
994                         nt_errstr(status));
995                 return false;
996         }
997
998         cmp = memcmp(c->u.preauth.sha512, result.sha512, sizeof(result.sha512));
999         if (cmp != 0) {
1000                 DEBUG(10, ("SEC_VT check PREAUTH failed\n"));
1001                 return false;
1002         }
1003
1004         return true;
1005 }
1006
1007 bool dcerpc_sec_verification_trailer_check(
1008                 const struct dcerpc_sec_verification_trailer *vt,
1009                 const uint32_t *bitmask1,
1010                 const struct dcerpc_sec_vt_pcontext *pcontext,
1011                 const struct dcerpc_sec_vt_header2 *header2,
1012                 const struct dcerpc_sec_vt_preauth *preauth)
1013 {
1014         size_t i;
1015
1016         if (!dcerpc_sec_vt_is_valid(vt)) {
1017                 return false;
1018         }
1019
1020         for (i=0; i < vt->count.count; i++) {
1021                 bool ok;
1022                 struct dcerpc_sec_vt *c = &vt->commands[i];
1023
1024                 switch (c->command & DCERPC_SEC_VT_COMMAND_ENUM) {
1025                 case DCERPC_SEC_VT_COMMAND_BITMASK1:
1026                         ok = dcerpc_sec_vt_bitmask_check(bitmask1, c);
1027                         if (!ok) {
1028                                 return false;
1029                         }
1030                         break;
1031
1032                 case DCERPC_SEC_VT_COMMAND_PCONTEXT:
1033                         ok = dcerpc_sec_vt_pctx_check(pcontext, c);
1034                         if (!ok) {
1035                                 return false;
1036                         }
1037                         break;
1038
1039                 case DCERPC_SEC_VT_COMMAND_HEADER2: {
1040                         ok = dcerpc_sec_vt_hdr2_check(header2, c);
1041                         if (!ok) {
1042                                 return false;
1043                         }
1044                         break;
1045                 }
1046
1047                 case DCERPC_SEC_VT_COMMAND_PREAUTH: {
1048                         ok = dcerpc_sec_vt_preauth_check(preauth, c);
1049                         if (!ok) {
1050                                 return false;
1051                         }
1052                         break;
1053                 }
1054
1055                 default:
1056                         if (c->command & DCERPC_SEC_VT_MUST_PROCESS) {
1057                                 DEBUG(10, ("SEC_VT check Unknown must_process_command failed\n"));
1058                                 return false;
1059                         }
1060
1061                         break;
1062                 }
1063         }
1064
1065         return true;
1066 }
1067
1068 static const struct ndr_syntax_id dcerpc_bind_time_features_prefix  = {
1069         .uuid = {
1070                 .time_low = 0x6cb71c2c,
1071                 .time_mid = 0x9812,
1072                 .time_hi_and_version = 0x4540,
1073                 .clock_seq = {0x00, 0x00},
1074                 .node = {0x00,0x00,0x00,0x00,0x00,0x00}
1075         },
1076         .if_version = 1,
1077 };
1078
1079 bool dcerpc_extract_bind_time_features(struct ndr_syntax_id s, uint64_t *_features)
1080 {
1081         uint8_t values[8];
1082         uint64_t features = 0;
1083
1084         values[0] = s.uuid.clock_seq[0];
1085         values[1] = s.uuid.clock_seq[1];
1086         values[2] = s.uuid.node[0];
1087         values[3] = s.uuid.node[1];
1088         values[4] = s.uuid.node[2];
1089         values[5] = s.uuid.node[3];
1090         values[6] = s.uuid.node[4];
1091         values[7] = s.uuid.node[5];
1092
1093         ZERO_STRUCT(s.uuid.clock_seq);
1094         ZERO_STRUCT(s.uuid.node);
1095
1096         if (!ndr_syntax_id_equal(&s, &dcerpc_bind_time_features_prefix)) {
1097                 if (_features != NULL) {
1098                         *_features = 0;
1099                 }
1100                 return false;
1101         }
1102
1103         features = BVAL(values, 0);
1104
1105         if (_features != NULL) {
1106                 *_features = features;
1107         }
1108
1109         return true;
1110 }
1111
1112 struct ndr_syntax_id dcerpc_construct_bind_time_features(uint64_t features)
1113 {
1114         struct ndr_syntax_id s = dcerpc_bind_time_features_prefix;
1115         uint8_t values[8];
1116
1117         SBVAL(values, 0, features);
1118
1119         s.uuid.clock_seq[0] = values[0];
1120         s.uuid.clock_seq[1] = values[1];
1121         s.uuid.node[0]      = values[2];
1122         s.uuid.node[1]      = values[3];
1123         s.uuid.node[2]      = values[4];
1124         s.uuid.node[3]      = values[5];
1125         s.uuid.node[4]      = values[6];
1126         s.uuid.node[5]      = values[7];
1127
1128         return s;
1129 }
1130
1131 NTSTATUS dcerpc_generic_session_key(DATA_BLOB *session_key)
1132 {
1133         *session_key = data_blob_null;
1134
1135         /* this took quite a few CPU cycles to find ... */
1136         session_key->data = discard_const_p(unsigned char, "SystemLibraryDTC");
1137         session_key->length = 16;
1138         return NT_STATUS_OK;
1139 }
1140
1141 /*
1142    push a ncacn_packet into a blob, potentially with auth info
1143 */
1144 NTSTATUS dcerpc_ncacn_push_auth(DATA_BLOB *blob,
1145                                 TALLOC_CTX *mem_ctx,
1146                                 struct ncacn_packet *pkt,
1147                                 struct dcerpc_auth *auth_info)
1148 {
1149         struct ndr_push *ndr;
1150         enum ndr_err_code ndr_err;
1151
1152         ndr = ndr_push_init_ctx(mem_ctx);
1153         if (!ndr) {
1154                 return NT_STATUS_NO_MEMORY;
1155         }
1156
1157         if (auth_info) {
1158                 pkt->auth_length = auth_info->credentials.length;
1159         } else {
1160                 pkt->auth_length = 0;
1161         }
1162
1163         ndr_err = ndr_push_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt);
1164         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1165                 return ndr_map_error2ntstatus(ndr_err);
1166         }
1167
1168         if (auth_info) {
1169 #if 0
1170                 /* the s3 rpc server doesn't handle auth padding in
1171                    bind requests. Use zero auth padding to keep us
1172                    working with old servers */
1173                 uint32_t offset = ndr->offset;
1174                 ndr_err = ndr_push_align(ndr, 16);
1175                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1176                         return ndr_map_error2ntstatus(ndr_err);
1177                 }
1178                 auth_info->auth_pad_length = ndr->offset - offset;
1179 #else
1180                 auth_info->auth_pad_length = 0;
1181 #endif
1182                 ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
1183                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1184                         return ndr_map_error2ntstatus(ndr_err);
1185                 }
1186         }
1187
1188         *blob = ndr_push_blob(ndr);
1189
1190         /* fill in the frag length */
1191         dcerpc_set_frag_length(blob, blob->length);
1192
1193         return NT_STATUS_OK;
1194 }
1195
1196 /*
1197   log a rpc packet in a format suitable for ndrdump. This is especially useful
1198   for sealed packets, where ethereal cannot easily see the contents
1199
1200   this triggers if "dcesrv:stubs directory" is set and present
1201   for all packets that fail to parse
1202 */
1203 void dcerpc_log_packet(const char *packet_log_dir,
1204                        const char *interface_name,
1205                        uint32_t opnum, ndr_flags_type flags,
1206                        const DATA_BLOB *pkt,
1207                        const char *why)
1208 {
1209         const int num_examples = 20;
1210         int i;
1211
1212         if (packet_log_dir == NULL) {
1213                 return;
1214         }
1215
1216         for (i=0;i<num_examples;i++) {
1217                 char *name=NULL;
1218                 int ret;
1219                 bool saved;
1220                 ret = asprintf(&name, "%s/%s-%"PRIu32".%d.%s.%s",
1221                                packet_log_dir, interface_name, opnum, i,
1222                                (flags&NDR_IN)?"in":"out",
1223                                why);
1224                 if (ret == -1) {
1225                         return;
1226                 }
1227
1228                 saved = file_save(name, pkt->data, pkt->length);
1229                 if (saved) {
1230                         DBG_DEBUG("Logged rpc packet to %s\n", name);
1231                         free(name);
1232                         break;
1233                 }
1234                 free(name);
1235         }
1236 }