s3-dcerpc: Add sign/seal with gssapi
[kai/samba.git] / source3 / librpc / rpc / dcerpc_helpers.c
1 /*
2  *  DCERPC Helper routines
3  *  Günther Deschner <gd@samba.org> 2010.
4  *  Simo Sorce <idra@samba.org> 2010.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20
21 #include "includes.h"
22 #include "librpc/rpc/dcerpc.h"
23 #include "librpc/gen_ndr/ndr_dcerpc.h"
24 #include "librpc/gen_ndr/ndr_schannel.h"
25 #include "../libcli/auth/schannel.h"
26 #include "../libcli/auth/spnego.h"
27 #include "../libcli/auth/ntlmssp.h"
28 #include "ntlmssp_wrap.h"
29 #include "librpc/rpc/dcerpc_gssapi.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_RPC_PARSE
33
34 /**
35 * @brief NDR Encodes a ncacn_packet
36 *
37 * @param mem_ctx        The memory context the blob will be allocated on
38 * @param ptype          The DCERPC packet type
39 * @param pfc_flags      The DCERPC PFC Falgs
40 * @param auth_length    The length of the trailing auth blob
41 * @param call_id        The call ID
42 * @param u              The payload of the packet
43 * @param blob [out]     The encoded blob if successful
44 *
45 * @return an NTSTATUS error code
46 */
47 NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx,
48                                   enum dcerpc_pkt_type ptype,
49                                   uint8_t pfc_flags,
50                                   uint16_t auth_length,
51                                   uint32_t call_id,
52                                   union dcerpc_payload *u,
53                                   DATA_BLOB *blob)
54 {
55         struct ncacn_packet r;
56         enum ndr_err_code ndr_err;
57
58         r.rpc_vers              = 5;
59         r.rpc_vers_minor        = 0;
60         r.ptype                 = ptype;
61         r.pfc_flags             = pfc_flags;
62         r.drep[0]               = DCERPC_DREP_LE;
63         r.drep[1]               = 0;
64         r.drep[2]               = 0;
65         r.drep[3]               = 0;
66         r.auth_length           = auth_length;
67         r.call_id               = call_id;
68         r.u                     = *u;
69
70         ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
71                 (ndr_push_flags_fn_t)ndr_push_ncacn_packet);
72         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
73                 return ndr_map_error2ntstatus(ndr_err);
74         }
75
76         dcerpc_set_frag_length(blob, blob->length);
77
78
79         if (DEBUGLEVEL >= 10) {
80                 /* set frag len for print function */
81                 r.frag_length = blob->length;
82                 NDR_PRINT_DEBUG(ncacn_packet, &r);
83         }
84
85         return NT_STATUS_OK;
86 }
87
88 /**
89 * @brief Decodes a ncacn_packet
90 *
91 * @param mem_ctx        The memory context on which to allocate the packet
92 *                       elements
93 * @param blob           The blob of data to decode
94 * @param r              An empty ncacn_packet, must not be NULL
95 *
96 * @return a NTSTATUS error code
97 */
98 NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
99                                   const DATA_BLOB *blob,
100                                   struct ncacn_packet *r,
101                                   bool bigendian)
102 {
103         enum ndr_err_code ndr_err;
104         struct ndr_pull *ndr;
105
106         ndr = ndr_pull_init_blob(blob, mem_ctx);
107         if (!ndr) {
108                 return NT_STATUS_NO_MEMORY;
109         }
110         if (bigendian) {
111                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
112         }
113
114         ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, r);
115
116         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
117                 talloc_free(ndr);
118                 return ndr_map_error2ntstatus(ndr_err);
119         }
120         talloc_free(ndr);
121
122         if (DEBUGLEVEL >= 10) {
123                 NDR_PRINT_DEBUG(ncacn_packet, r);
124         }
125
126         return NT_STATUS_OK;
127 }
128
129 /**
130 * @brief NDR Encodes a NL_AUTH_MESSAGE
131 *
132 * @param mem_ctx        The memory context the blob will be allocated on
133 * @param r              The NL_AUTH_MESSAGE to encode
134 * @param blob [out]     The encoded blob if successful
135 *
136 * @return a NTSTATUS error code
137 */
138 NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx,
139                                    struct NL_AUTH_MESSAGE *r,
140                                    DATA_BLOB *blob)
141 {
142         enum ndr_err_code ndr_err;
143
144         ndr_err = ndr_push_struct_blob(blob, mem_ctx, r,
145                 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
146         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
147                 return ndr_map_error2ntstatus(ndr_err);
148         }
149
150         if (DEBUGLEVEL >= 10) {
151                 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r);
152         }
153
154         return NT_STATUS_OK;
155 }
156
157 /**
158 * @brief NDR Encodes a dcerpc_auth structure
159 *
160 * @param mem_ctx          The memory context the blob will be allocated on
161 * @param auth_type        The DCERPC Authentication Type
162 * @param auth_level       The DCERPC Authentication Level
163 * @param auth_pad_length  The padding added to the packet this blob will be
164 *                          appended to.
165 * @param auth_context_id  The context id
166 * @param credentials      The authentication credentials blob (signature)
167 * @param blob [out]       The encoded blob if successful
168 *
169 * @return a NTSTATUS error code
170 */
171 NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
172                                  enum dcerpc_AuthType auth_type,
173                                  enum dcerpc_AuthLevel auth_level,
174                                  uint8_t auth_pad_length,
175                                  uint32_t auth_context_id,
176                                  const DATA_BLOB *credentials,
177                                  DATA_BLOB *blob)
178 {
179         struct dcerpc_auth r;
180         enum ndr_err_code ndr_err;
181
182         r.auth_type             = auth_type;
183         r.auth_level            = auth_level;
184         r.auth_pad_length       = auth_pad_length;
185         r.auth_reserved         = 0;
186         r.auth_context_id       = auth_context_id;
187         r.credentials           = *credentials;
188
189         ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
190                 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
191         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
192                 return ndr_map_error2ntstatus(ndr_err);
193         }
194
195         if (DEBUGLEVEL >= 10) {
196                 NDR_PRINT_DEBUG(dcerpc_auth, &r);
197         }
198
199         return NT_STATUS_OK;
200 }
201
202 /**
203 * @brief Decodes a dcerpc_auth blob
204 *
205 * @param mem_ctx        The memory context on which to allocate the packet
206 *                       elements
207 * @param blob           The blob of data to decode
208 * @param r              An empty dcerpc_auth structure, must not be NULL
209 *
210 * @return a NTSTATUS error code
211 */
212 NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
213                                  const DATA_BLOB *blob,
214                                  struct dcerpc_auth *r,
215                                  bool bigendian)
216 {
217         enum ndr_err_code ndr_err;
218         struct ndr_pull *ndr;
219
220         ndr = ndr_pull_init_blob(blob, mem_ctx);
221         if (!ndr) {
222                 return NT_STATUS_NO_MEMORY;
223         }
224         if (bigendian) {
225                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
226         }
227
228         ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
229
230         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
231                 talloc_free(ndr);
232                 return ndr_map_error2ntstatus(ndr_err);
233         }
234         talloc_free(ndr);
235
236         if (DEBUGLEVEL >= 10) {
237                 NDR_PRINT_DEBUG(dcerpc_auth, r);
238         }
239
240         return NT_STATUS_OK;
241 }
242
243 /*******************************************************************
244  Create and add the NTLMSSP sign/seal auth data.
245  ********************************************************************/
246
247 static NTSTATUS add_ntlmssp_auth_footer(struct auth_ntlmssp_state *auth_state,
248                                         enum dcerpc_AuthLevel auth_level,
249                                         DATA_BLOB *rpc_out)
250 {
251         uint16_t data_and_pad_len = rpc_out->length
252                                         - DCERPC_RESPONSE_LENGTH
253                                         - DCERPC_AUTH_TRAILER_LENGTH;
254         DATA_BLOB auth_blob;
255         NTSTATUS status;
256
257         if (!auth_state) {
258                 return NT_STATUS_INVALID_PARAMETER;
259         }
260
261         switch (auth_level) {
262         case DCERPC_AUTH_LEVEL_PRIVACY:
263                 /* Data portion is encrypted. */
264                 status = auth_ntlmssp_seal_packet(auth_state,
265                                              rpc_out->data,
266                                              rpc_out->data
267                                                 + DCERPC_RESPONSE_LENGTH,
268                                              data_and_pad_len,
269                                              rpc_out->data,
270                                              rpc_out->length,
271                                              &auth_blob);
272                 if (!NT_STATUS_IS_OK(status)) {
273                         return status;
274                 }
275                 break;
276
277         case DCERPC_AUTH_LEVEL_INTEGRITY:
278                 /* Data is signed. */
279                 status = auth_ntlmssp_sign_packet(auth_state,
280                                              rpc_out->data,
281                                              rpc_out->data
282                                                 + DCERPC_RESPONSE_LENGTH,
283                                              data_and_pad_len,
284                                              rpc_out->data,
285                                              rpc_out->length,
286                                              &auth_blob);
287                 if (!NT_STATUS_IS_OK(status)) {
288                         return status;
289                 }
290                 break;
291
292         default:
293                 /* Can't happen. */
294                 smb_panic("bad auth level");
295                 /* Notreached. */
296                 return NT_STATUS_INVALID_PARAMETER;
297         }
298
299         /* Finally attach the blob. */
300         if (!data_blob_append(NULL, rpc_out,
301                                 auth_blob.data, auth_blob.length)) {
302                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
303                           (unsigned int)auth_blob.length));
304                 return NT_STATUS_NO_MEMORY;
305         }
306         data_blob_free(&auth_blob);
307
308         return NT_STATUS_OK;
309 }
310
311 /*******************************************************************
312  Create and add the schannel sign/seal auth data.
313  ********************************************************************/
314
315 static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas,
316                                         enum dcerpc_AuthLevel auth_level,
317                                         DATA_BLOB *rpc_out)
318 {
319         uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
320         size_t data_and_pad_len = rpc_out->length
321                                         - DCERPC_RESPONSE_LENGTH
322                                         - DCERPC_AUTH_TRAILER_LENGTH;
323         DATA_BLOB auth_blob;
324         NTSTATUS status;
325
326         if (!sas) {
327                 return NT_STATUS_INVALID_PARAMETER;
328         }
329
330         DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
331                         sas->seq_num));
332
333         switch (auth_level) {
334         case DCERPC_AUTH_LEVEL_PRIVACY:
335                 status = netsec_outgoing_packet(sas,
336                                                 rpc_out->data,
337                                                 true,
338                                                 data_p,
339                                                 data_and_pad_len,
340                                                 &auth_blob);
341                 break;
342         case DCERPC_AUTH_LEVEL_INTEGRITY:
343                 status = netsec_outgoing_packet(sas,
344                                                 rpc_out->data,
345                                                 false,
346                                                 data_p,
347                                                 data_and_pad_len,
348                                                 &auth_blob);
349                 break;
350         default:
351                 status = NT_STATUS_INTERNAL_ERROR;
352                 break;
353         }
354
355         if (!NT_STATUS_IS_OK(status)) {
356                 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
357                         nt_errstr(status)));
358                 return status;
359         }
360
361         if (DEBUGLEVEL >= 10) {
362                 dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob);
363         }
364
365         /* Finally attach the blob. */
366         if (!data_blob_append(NULL, rpc_out,
367                                 auth_blob.data, auth_blob.length)) {
368                 return NT_STATUS_NO_MEMORY;
369         }
370         data_blob_free(&auth_blob);
371
372         return NT_STATUS_OK;
373 }
374
375 /*******************************************************************
376  Create and add the gssapi sign/seal auth data.
377  ********************************************************************/
378
379 static NTSTATUS add_gssapi_auth_footer(struct gse_context *gse_ctx,
380                                         enum dcerpc_AuthLevel auth_level,
381                                         DATA_BLOB *rpc_out)
382 {
383         DATA_BLOB data;
384         DATA_BLOB auth_blob;
385         NTSTATUS status;
386
387         if (!gse_ctx) {
388                 return NT_STATUS_INVALID_PARAMETER;
389         }
390
391         data.data = rpc_out->data + DCERPC_RESPONSE_LENGTH;
392         data.length = rpc_out->length - DCERPC_RESPONSE_LENGTH
393                                         - DCERPC_AUTH_TRAILER_LENGTH;
394
395         switch (auth_level) {
396         case DCERPC_AUTH_LEVEL_PRIVACY:
397                 status = gse_seal(talloc_tos(), gse_ctx, &data, &auth_blob);
398                 break;
399         case DCERPC_AUTH_LEVEL_INTEGRITY:
400                 status = gse_sign(talloc_tos(), gse_ctx, &data, &auth_blob);
401                 break;
402         default:
403                 status = NT_STATUS_INTERNAL_ERROR;
404                 break;
405         }
406
407         if (!NT_STATUS_IS_OK(status)) {
408                 DEBUG(1, ("Failed to process packet: %s\n",
409                           nt_errstr(status)));
410                 return status;
411         }
412
413         /* Finally attach the blob. */
414         if (!data_blob_append(NULL, rpc_out,
415                                 auth_blob.data, auth_blob.length)) {
416                 return NT_STATUS_NO_MEMORY;
417         }
418
419         data_blob_free(&auth_blob);
420
421         return NT_STATUS_OK;
422 }
423
424 /**
425 * @brief   Append an auth footer according to what is the current mechanism
426 *
427 * @param auth           The pipe_auth_data associated with the connection
428 * @param pad_len        The padding used in the packet
429 * @param rpc_out        Packet blob up to and including the auth header
430 *
431 * @return A NTSTATUS error code.
432 */
433 NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
434                                 size_t pad_len, DATA_BLOB *rpc_out)
435 {
436         char pad[CLIENT_NDR_PADDING_SIZE] = { 0, };
437         DATA_BLOB auth_info;
438         DATA_BLOB auth_blob;
439         NTSTATUS status;
440
441         if (auth->auth_type == DCERPC_AUTH_TYPE_NONE) {
442                 return NT_STATUS_OK;
443         }
444
445         if (pad_len) {
446                 /* Copy the sign/seal padding data. */
447                 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
448                         return NT_STATUS_NO_MEMORY;
449                 }
450         }
451
452         /* marshall the dcerpc_auth with an actually empty auth_blob.
453          * This is needed because the ntmlssp signature includes the
454          * auth header. We will append the actual blob later. */
455         auth_blob = data_blob_null;
456         status = dcerpc_push_dcerpc_auth(rpc_out->data,
457                                          auth->auth_type,
458                                          auth->auth_level,
459                                          pad_len,
460                                          1 /* context id. */,
461                                          &auth_blob,
462                                          &auth_info);
463         if (!NT_STATUS_IS_OK(status)) {
464                 return status;
465         }
466
467         /* append the header */
468         if (!data_blob_append(NULL, rpc_out,
469                                 auth_info.data, auth_info.length)) {
470                 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
471                           (unsigned int)auth_info.length));
472                 return NT_STATUS_NO_MEMORY;
473         }
474         data_blob_free(&auth_info);
475
476         /* Generate any auth sign/seal and add the auth footer. */
477         switch (auth->auth_type) {
478         case DCERPC_AUTH_TYPE_NONE:
479                 status = NT_STATUS_OK;
480                 break;
481         case DCERPC_AUTH_TYPE_SPNEGO:
482                 if (auth->spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
483                         return NT_STATUS_INVALID_PARAMETER;
484                 }
485                 /* fall thorugh */
486         case DCERPC_AUTH_TYPE_NTLMSSP:
487                 status = add_ntlmssp_auth_footer(auth->a_u.auth_ntlmssp_state,
488                                                  auth->auth_level,
489                                                  rpc_out);
490                 break;
491         case DCERPC_AUTH_TYPE_SCHANNEL:
492                 status = add_schannel_auth_footer(auth->a_u.schannel_auth,
493                                                   auth->auth_level,
494                                                   rpc_out);
495                 break;
496         case DCERPC_AUTH_TYPE_KRB5:
497                 status = add_gssapi_auth_footer(auth->a_u.gssapi_state,
498                                                 auth->auth_level,
499                                                 rpc_out);
500                 break;
501         default:
502                 status = NT_STATUS_INVALID_PARAMETER;
503                 break;
504         }
505
506         return status;
507 }
508
509 /**
510 * @brief Check authentication for request/response packets
511 *
512 * @param auth           The auth data for the connection
513 * @param pkt            The actual ncacn_packet
514 * @param pkt_trailer    The stub_and_verifier part of the packet
515 * @param header_size    The header size
516 * @param raw_pkt        The whole raw packet data blob
517 * @param pad_len        [out] The padding length used in the packet
518 *
519 * @return A NTSTATUS error code
520 */
521 NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
522                            struct ncacn_packet *pkt,
523                            DATA_BLOB *pkt_trailer,
524                            size_t header_size,
525                            DATA_BLOB *raw_pkt,
526                            size_t *pad_len)
527 {
528         NTSTATUS status;
529         struct dcerpc_auth auth_info;
530         uint32_t auth_length;
531         DATA_BLOB full_pkt;
532         DATA_BLOB data;
533
534         switch (auth->auth_level) {
535         case DCERPC_AUTH_LEVEL_PRIVACY:
536                 DEBUG(10, ("Requested Privacy.\n"));
537                 break;
538
539         case DCERPC_AUTH_LEVEL_INTEGRITY:
540                 DEBUG(10, ("Requested Integrity.\n"));
541                 break;
542
543         case DCERPC_AUTH_LEVEL_CONNECT:
544                 if (pkt->auth_length != 0) {
545                         break;
546                 }
547                 *pad_len = 0;
548                 return NT_STATUS_OK;
549
550         case DCERPC_AUTH_LEVEL_NONE:
551                 if (pkt->auth_length != 0) {
552                         DEBUG(3, ("Got non-zero auth len on non "
553                                   "authenticated connection!\n"));
554                         return NT_STATUS_INVALID_PARAMETER;
555                 }
556                 *pad_len = 0;
557                 return NT_STATUS_OK;
558
559         default:
560                 DEBUG(3, ("Unimplemented Auth Level %d",
561                           auth->auth_level));
562                 return NT_STATUS_INVALID_PARAMETER;
563         }
564
565         /* Paranioa checks for auth_length. */
566         if (pkt->auth_length > pkt->frag_length) {
567                 return NT_STATUS_INFO_LENGTH_MISMATCH;
568         }
569         if ((pkt->auth_length
570              + DCERPC_AUTH_TRAILER_LENGTH < pkt->auth_length) ||
571             (pkt->auth_length
572              + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
573                 /* Integer wrap attempt. */
574                 return NT_STATUS_INFO_LENGTH_MISMATCH;
575         }
576
577         status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
578                                           &auth_info, &auth_length, false);
579         if (!NT_STATUS_IS_OK(status)) {
580                 return status;
581         }
582
583         data = data_blob_const(raw_pkt->data + header_size,
584                                 pkt_trailer->length - auth_length);
585         full_pkt = data_blob_const(raw_pkt->data,
586                                 raw_pkt->length - auth_info.credentials.length);
587
588         switch (auth->auth_type) {
589         case DCERPC_AUTH_TYPE_NONE:
590                 return NT_STATUS_OK;
591
592         case DCERPC_AUTH_TYPE_SPNEGO:
593                 if (auth->spnego_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
594                         DEBUG(0, ("Currently only NTLMSSP is supported "
595                                   "with SPNEGO\n"));
596                         return NT_STATUS_INVALID_PARAMETER;
597                 }
598                 /* fall through */
599         case DCERPC_AUTH_TYPE_NTLMSSP:
600
601                 DEBUG(10, ("NTLMSSP auth\n"));
602
603                 if (!auth->a_u.auth_ntlmssp_state) {
604                         DEBUG(0, ("Invalid auth level, "
605                                   "failed to process packet auth.\n"));
606                         return NT_STATUS_INVALID_PARAMETER;
607                 }
608
609                 switch (auth->auth_level) {
610                 case DCERPC_AUTH_LEVEL_PRIVACY:
611                         status = auth_ntlmssp_unseal_packet(
612                                         auth->a_u.auth_ntlmssp_state,
613                                         data.data, data.length,
614                                         full_pkt.data, full_pkt.length,
615                                         &auth_info.credentials);
616                         if (!NT_STATUS_IS_OK(status)) {
617                                 return status;
618                         }
619                         memcpy(pkt_trailer->data, data.data, data.length);
620                         break;
621
622                 case DCERPC_AUTH_LEVEL_INTEGRITY:
623                         status = auth_ntlmssp_check_packet(
624                                         auth->a_u.auth_ntlmssp_state,
625                                         data.data, data.length,
626                                         full_pkt.data, full_pkt.length,
627                                         &auth_info.credentials);
628                         if (!NT_STATUS_IS_OK(status)) {
629                                 return status;
630                         }
631                         break;
632
633                 default:
634                         DEBUG(0, ("Invalid auth level, "
635                                   "failed to process packet auth.\n"));
636                         return NT_STATUS_INVALID_PARAMETER;
637                 }
638                 break;
639
640         case DCERPC_AUTH_TYPE_SCHANNEL:
641
642                 DEBUG(10, ("SCHANNEL auth\n"));
643
644                 switch (auth->auth_level) {
645                 case DCERPC_AUTH_LEVEL_PRIVACY:
646                         status = netsec_incoming_packet(
647                                         auth->a_u.schannel_auth,
648                                         pkt, true,
649                                         data.data, data.length,
650                                         &auth_info.credentials);
651                         if (!NT_STATUS_IS_OK(status)) {
652                                 return status;
653                         }
654                         memcpy(pkt_trailer->data, data.data, data.length);
655                         break;
656
657                 case DCERPC_AUTH_LEVEL_INTEGRITY:
658                         status = netsec_incoming_packet(
659                                         auth->a_u.schannel_auth,
660                                         pkt, false,
661                                         data.data, data.length,
662                                         &auth_info.credentials);
663                         if (!NT_STATUS_IS_OK(status)) {
664                                 return status;
665                         }
666                         break;
667
668                 default:
669                         DEBUG(0, ("Invalid auth level, "
670                                   "failed to process packet auth.\n"));
671                         return NT_STATUS_INVALID_PARAMETER;
672                 }
673                 break;
674
675         case DCERPC_AUTH_TYPE_KRB5:
676
677                 DEBUG(10, ("KRB5 auth\n"));
678
679                 switch (auth->auth_level) {
680                 case DCERPC_AUTH_LEVEL_PRIVACY:
681                         status = gse_unseal(pkt, auth->a_u.gssapi_state,
682                                             &data, &auth_info.credentials);
683                         if (!NT_STATUS_IS_OK(status)) {
684                                 return status;
685                         }
686                         memcpy(pkt_trailer->data, data.data, data.length);
687                         break;
688
689                 case DCERPC_AUTH_LEVEL_INTEGRITY:
690                         /* TODO: pass in full_pkt when
691                          * DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN is set */
692                         status = gse_sigcheck(pkt, auth->a_u.gssapi_state,
693                                               &data, &auth_info.credentials);
694                         if (!NT_STATUS_IS_OK(status)) {
695                                 return status;
696                         }
697                         break;
698
699                 default:
700                         DEBUG(0, ("Invalid auth level, "
701                                   "failed to process packet auth.\n"));
702                         return NT_STATUS_INVALID_PARAMETER;
703                 }
704                 break;
705
706         default:
707                 DEBUG(0, ("process_request_pdu: "
708                           "unknown auth type %u set.\n",
709                           (unsigned int)auth->auth_type));
710                 return NT_STATUS_INVALID_PARAMETER;
711         }
712
713         *pad_len = auth_info.auth_pad_length;
714         data_blob_free(&auth_info.credentials);
715         return NT_STATUS_OK;
716 }
717