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