s3:libsmb: Plumb cli_smb2_unlink() inside cli_unlink().
[Samba.git] / source3 / librpc / rpc / dcerpc_helpers.c
blobd36c2da3838fa931498c3aa3b00af58c5f099da0
1 /*
2 * DCERPC Helper routines
3 * Günther Deschner <gd@samba.org> 2010.
4 * Simo Sorce <idra@samba.org> 2010.
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.
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.
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/>.
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 "librpc/crypto/gse.h"
28 #include "auth/gensec/gensec.h"
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_PARSE
33 /**
34 * @brief NDR Encodes a ncacn_packet
36 * @param mem_ctx The memory context the blob will be allocated on
37 * @param ptype The DCERPC packet type
38 * @param pfc_flags The DCERPC PFC Falgs
39 * @param auth_length The length of the trailing auth blob
40 * @param call_id The call ID
41 * @param u The payload of the packet
42 * @param blob [out] The encoded blob if successful
44 * @return an NTSTATUS error code
46 NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx,
47 enum dcerpc_pkt_type ptype,
48 uint8_t pfc_flags,
49 uint16_t auth_length,
50 uint32_t call_id,
51 union dcerpc_payload *u,
52 DATA_BLOB *blob)
54 struct ncacn_packet r;
55 enum ndr_err_code ndr_err;
57 r.rpc_vers = 5;
58 r.rpc_vers_minor = 0;
59 r.ptype = ptype;
60 r.pfc_flags = pfc_flags;
61 r.drep[0] = DCERPC_DREP_LE;
62 r.drep[1] = 0;
63 r.drep[2] = 0;
64 r.drep[3] = 0;
65 r.auth_length = auth_length;
66 r.call_id = call_id;
67 r.u = *u;
69 ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
70 (ndr_push_flags_fn_t)ndr_push_ncacn_packet);
71 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
72 return ndr_map_error2ntstatus(ndr_err);
75 dcerpc_set_frag_length(blob, blob->length);
78 if (DEBUGLEVEL >= 10) {
79 /* set frag len for print function */
80 r.frag_length = blob->length;
81 NDR_PRINT_DEBUG(ncacn_packet, &r);
84 return NT_STATUS_OK;
87 /**
88 * @brief Decodes a ncacn_packet
90 * @param mem_ctx The memory context on which to allocate the packet
91 * elements
92 * @param blob The blob of data to decode
93 * @param r An empty ncacn_packet, must not be NULL
94 * @param bigendian Whether the packet is bignedian encoded
96 * @return a NTSTATUS error code
98 NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
99 const DATA_BLOB *blob,
100 struct ncacn_packet *r,
101 bool bigendian)
103 enum ndr_err_code ndr_err;
104 struct ndr_pull *ndr;
106 ndr = ndr_pull_init_blob(blob, mem_ctx);
107 if (!ndr) {
108 return NT_STATUS_NO_MEMORY;
110 if (bigendian) {
111 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
114 if (CVAL(blob->data, DCERPC_PFC_OFFSET) & DCERPC_PFC_FLAG_OBJECT_UUID) {
115 ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
118 ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, r);
120 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
121 talloc_free(ndr);
122 return ndr_map_error2ntstatus(ndr_err);
124 talloc_free(ndr);
126 if (DEBUGLEVEL >= 10) {
127 NDR_PRINT_DEBUG(ncacn_packet, r);
130 return NT_STATUS_OK;
134 * @brief NDR Encodes a NL_AUTH_MESSAGE
136 * @param mem_ctx The memory context the blob will be allocated on
137 * @param r The NL_AUTH_MESSAGE to encode
138 * @param blob [out] The encoded blob if successful
140 * @return a NTSTATUS error code
142 NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx,
143 struct NL_AUTH_MESSAGE *r,
144 DATA_BLOB *blob)
146 enum ndr_err_code ndr_err;
148 ndr_err = ndr_push_struct_blob(blob, mem_ctx, r,
149 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
150 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
151 return ndr_map_error2ntstatus(ndr_err);
154 if (DEBUGLEVEL >= 10) {
155 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r);
158 return NT_STATUS_OK;
162 * @brief NDR Encodes a dcerpc_auth structure
164 * @param mem_ctx The memory context the blob will be allocated on
165 * @param auth_type The DCERPC Authentication Type
166 * @param auth_level The DCERPC Authentication Level
167 * @param auth_pad_length The padding added to the packet this blob will be
168 * appended to.
169 * @param auth_context_id The context id
170 * @param credentials The authentication credentials blob (signature)
171 * @param blob [out] The encoded blob if successful
173 * @return a NTSTATUS error code
175 NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
176 enum dcerpc_AuthType auth_type,
177 enum dcerpc_AuthLevel auth_level,
178 uint8_t auth_pad_length,
179 uint32_t auth_context_id,
180 const DATA_BLOB *credentials,
181 DATA_BLOB *blob)
183 struct dcerpc_auth r;
184 enum ndr_err_code ndr_err;
186 r.auth_type = auth_type;
187 r.auth_level = auth_level;
188 r.auth_pad_length = auth_pad_length;
189 r.auth_reserved = 0;
190 r.auth_context_id = auth_context_id;
191 r.credentials = *credentials;
193 ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
194 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
195 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
196 return ndr_map_error2ntstatus(ndr_err);
199 if (DEBUGLEVEL >= 10) {
200 NDR_PRINT_DEBUG(dcerpc_auth, &r);
203 return NT_STATUS_OK;
207 * @brief Decodes a dcerpc_auth blob
209 * @param mem_ctx The memory context on which to allocate the packet
210 * elements
211 * @param blob The blob of data to decode
212 * @param r An empty dcerpc_auth structure, must not be NULL
214 * @return a NTSTATUS error code
216 NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
217 const DATA_BLOB *blob,
218 struct dcerpc_auth *r,
219 bool bigendian)
221 enum ndr_err_code ndr_err;
222 struct ndr_pull *ndr;
224 ndr = ndr_pull_init_blob(blob, mem_ctx);
225 if (!ndr) {
226 return NT_STATUS_NO_MEMORY;
228 if (bigendian) {
229 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
232 ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
234 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
235 talloc_free(ndr);
236 return ndr_map_error2ntstatus(ndr_err);
238 talloc_free(ndr);
240 if (DEBUGLEVEL >= 10) {
241 NDR_PRINT_DEBUG(dcerpc_auth, r);
244 return NT_STATUS_OK;
248 * @brief Calculate how much data we can in a packet, including calculating
249 * auth token and pad lengths.
251 * @param auth The pipe_auth_data structure for this pipe.
252 * @param header_len The length of the packet header
253 * @param data_left The data left in the send buffer
254 * @param max_xmit_frag The max fragment size.
255 * @param pad_alignment The NDR padding size.
256 * @param data_to_send [out] The max data we will send in the pdu
257 * @param frag_len [out] The total length of the fragment
258 * @param auth_len [out] The length of the auth trailer
259 * @param pad_len [out] The padding to be applied
261 * @return A NT Error status code.
263 NTSTATUS dcerpc_guess_sizes(struct pipe_auth_data *auth,
264 size_t header_len, size_t data_left,
265 size_t max_xmit_frag, size_t pad_alignment,
266 size_t *data_to_send, size_t *frag_len,
267 size_t *auth_len, size_t *pad_len)
269 size_t max_len;
270 size_t mod_len;
271 struct gensec_security *gensec_security;
272 struct schannel_state *schannel_auth;
274 /* no auth token cases first */
275 switch (auth->auth_level) {
276 case DCERPC_AUTH_LEVEL_NONE:
277 case DCERPC_AUTH_LEVEL_CONNECT:
278 case DCERPC_AUTH_LEVEL_PACKET:
279 max_len = max_xmit_frag - header_len;
280 *data_to_send = MIN(max_len, data_left);
281 *pad_len = 0;
282 *auth_len = 0;
283 *frag_len = header_len + *data_to_send;
284 return NT_STATUS_OK;
286 case DCERPC_AUTH_LEVEL_PRIVACY:
287 break;
289 case DCERPC_AUTH_LEVEL_INTEGRITY:
290 break;
292 default:
293 return NT_STATUS_INVALID_PARAMETER;
297 /* Sign/seal case, calculate auth and pad lengths */
299 max_len = max_xmit_frag - header_len - DCERPC_AUTH_TRAILER_LENGTH;
301 /* Treat the same for all authenticated rpc requests. */
302 switch (auth->auth_type) {
303 case DCERPC_AUTH_TYPE_SPNEGO:
304 case DCERPC_AUTH_TYPE_NTLMSSP:
305 case DCERPC_AUTH_TYPE_KRB5:
306 gensec_security = talloc_get_type_abort(auth->auth_ctx,
307 struct gensec_security);
308 *auth_len = gensec_sig_size(gensec_security, max_len);
309 break;
311 case DCERPC_AUTH_TYPE_SCHANNEL:
312 schannel_auth = talloc_get_type_abort(auth->auth_ctx,
313 struct schannel_state);
314 *auth_len = netsec_outgoing_sig_size(schannel_auth);
315 break;
316 default:
317 return NT_STATUS_INVALID_PARAMETER;
320 max_len -= *auth_len;
322 *data_to_send = MIN(max_len, data_left);
324 mod_len = (header_len + *data_to_send) % pad_alignment;
325 if (mod_len) {
326 *pad_len = pad_alignment - mod_len;
327 } else {
328 *pad_len = 0;
331 if (*data_to_send + *pad_len > max_len) {
332 *data_to_send -= pad_alignment;
335 *frag_len = header_len + *data_to_send + *pad_len
336 + DCERPC_AUTH_TRAILER_LENGTH + *auth_len;
338 return NT_STATUS_OK;
341 /*******************************************************************
342 Create and add the NTLMSSP sign/seal auth data.
343 ********************************************************************/
345 static NTSTATUS add_generic_auth_footer(struct gensec_security *gensec_security,
346 enum dcerpc_AuthLevel auth_level,
347 DATA_BLOB *rpc_out)
349 uint16_t data_and_pad_len = rpc_out->length
350 - DCERPC_RESPONSE_LENGTH
351 - DCERPC_AUTH_TRAILER_LENGTH;
352 DATA_BLOB auth_blob;
353 NTSTATUS status;
355 if (!gensec_security) {
356 return NT_STATUS_INVALID_PARAMETER;
359 switch (auth_level) {
360 case DCERPC_AUTH_LEVEL_PRIVACY:
361 /* Data portion is encrypted. */
362 status = gensec_seal_packet(gensec_security,
363 rpc_out->data,
364 rpc_out->data
365 + DCERPC_RESPONSE_LENGTH,
366 data_and_pad_len,
367 rpc_out->data,
368 rpc_out->length,
369 &auth_blob);
370 if (!NT_STATUS_IS_OK(status)) {
371 return status;
373 break;
375 case DCERPC_AUTH_LEVEL_INTEGRITY:
376 /* Data is signed. */
377 status = gensec_sign_packet(gensec_security,
378 rpc_out->data,
379 rpc_out->data
380 + DCERPC_RESPONSE_LENGTH,
381 data_and_pad_len,
382 rpc_out->data,
383 rpc_out->length,
384 &auth_blob);
385 if (!NT_STATUS_IS_OK(status)) {
386 return status;
388 break;
390 default:
391 /* Can't happen. */
392 smb_panic("bad auth level");
393 /* Notreached. */
394 return NT_STATUS_INVALID_PARAMETER;
397 /* Finally attach the blob. */
398 if (!data_blob_append(NULL, rpc_out,
399 auth_blob.data, auth_blob.length)) {
400 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
401 (unsigned int)auth_blob.length));
402 return NT_STATUS_NO_MEMORY;
404 data_blob_free(&auth_blob);
406 return NT_STATUS_OK;
409 /*******************************************************************
410 Check/unseal the NTLMSSP auth data. (Unseal in place).
411 ********************************************************************/
413 static NTSTATUS get_generic_auth_footer(struct gensec_security *gensec_security,
414 enum dcerpc_AuthLevel auth_level,
415 DATA_BLOB *data, DATA_BLOB *full_pkt,
416 DATA_BLOB *auth_token)
418 switch (auth_level) {
419 case DCERPC_AUTH_LEVEL_PRIVACY:
420 /* Data portion is encrypted. */
421 return gensec_unseal_packet(gensec_security,
422 data->data,
423 data->length,
424 full_pkt->data,
425 full_pkt->length,
426 auth_token);
428 case DCERPC_AUTH_LEVEL_INTEGRITY:
429 /* Data is signed. */
430 return gensec_check_packet(gensec_security,
431 data->data,
432 data->length,
433 full_pkt->data,
434 full_pkt->length,
435 auth_token);
437 default:
438 return NT_STATUS_INVALID_PARAMETER;
442 /*******************************************************************
443 Create and add the schannel sign/seal auth data.
444 ********************************************************************/
446 static NTSTATUS add_schannel_auth_footer(struct schannel_state *sas,
447 enum dcerpc_AuthLevel auth_level,
448 DATA_BLOB *rpc_out)
450 uint8_t *data_p = rpc_out->data + DCERPC_RESPONSE_LENGTH;
451 size_t data_and_pad_len = rpc_out->length
452 - DCERPC_RESPONSE_LENGTH
453 - DCERPC_AUTH_TRAILER_LENGTH;
454 DATA_BLOB auth_blob;
455 NTSTATUS status;
457 if (!sas) {
458 return NT_STATUS_INVALID_PARAMETER;
461 DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
462 sas->seq_num));
464 switch (auth_level) {
465 case DCERPC_AUTH_LEVEL_PRIVACY:
466 status = netsec_outgoing_packet(sas,
467 rpc_out->data,
468 true,
469 data_p,
470 data_and_pad_len,
471 &auth_blob);
472 break;
473 case DCERPC_AUTH_LEVEL_INTEGRITY:
474 status = netsec_outgoing_packet(sas,
475 rpc_out->data,
476 false,
477 data_p,
478 data_and_pad_len,
479 &auth_blob);
480 break;
481 default:
482 status = NT_STATUS_INTERNAL_ERROR;
483 break;
486 if (!NT_STATUS_IS_OK(status)) {
487 DEBUG(1,("add_schannel_auth_footer: failed to process packet: %s\n",
488 nt_errstr(status)));
489 return status;
492 if (DEBUGLEVEL >= 10) {
493 dump_NL_AUTH_SIGNATURE(talloc_tos(), &auth_blob);
496 /* Finally attach the blob. */
497 if (!data_blob_append(NULL, rpc_out,
498 auth_blob.data, auth_blob.length)) {
499 return NT_STATUS_NO_MEMORY;
501 data_blob_free(&auth_blob);
503 return NT_STATUS_OK;
506 /*******************************************************************
507 Check/unseal the Schannel auth data. (Unseal in place).
508 ********************************************************************/
510 static NTSTATUS get_schannel_auth_footer(TALLOC_CTX *mem_ctx,
511 struct schannel_state *auth_state,
512 enum dcerpc_AuthLevel auth_level,
513 DATA_BLOB *data, DATA_BLOB *full_pkt,
514 DATA_BLOB *auth_token)
516 switch (auth_level) {
517 case DCERPC_AUTH_LEVEL_PRIVACY:
518 /* Data portion is encrypted. */
519 return netsec_incoming_packet(auth_state,
520 true,
521 data->data,
522 data->length,
523 auth_token);
525 case DCERPC_AUTH_LEVEL_INTEGRITY:
526 /* Data is signed. */
527 return netsec_incoming_packet(auth_state,
528 false,
529 data->data,
530 data->length,
531 auth_token);
533 default:
534 return NT_STATUS_INVALID_PARAMETER;
539 * @brief Append an auth footer according to what is the current mechanism
541 * @param auth The pipe_auth_data associated with the connection
542 * @param pad_len The padding used in the packet
543 * @param rpc_out Packet blob up to and including the auth header
545 * @return A NTSTATUS error code.
547 NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
548 size_t pad_len, DATA_BLOB *rpc_out)
550 struct schannel_state *schannel_auth;
551 struct gensec_security *gensec_security;
552 char pad[CLIENT_NDR_PADDING_SIZE] = { 0, };
553 DATA_BLOB auth_info;
554 DATA_BLOB auth_blob;
555 NTSTATUS status;
557 if (auth->auth_type == DCERPC_AUTH_TYPE_NONE ||
558 auth->auth_type == DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM) {
559 return NT_STATUS_OK;
562 if (pad_len) {
563 /* Copy the sign/seal padding data. */
564 if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
565 return NT_STATUS_NO_MEMORY;
569 /* marshall the dcerpc_auth with an actually empty auth_blob.
570 * This is needed because the ntmlssp signature includes the
571 * auth header. We will append the actual blob later. */
572 auth_blob = data_blob_null;
573 status = dcerpc_push_dcerpc_auth(rpc_out->data,
574 auth->auth_type,
575 auth->auth_level,
576 pad_len,
577 1 /* context id. */,
578 &auth_blob,
579 &auth_info);
580 if (!NT_STATUS_IS_OK(status)) {
581 return status;
584 /* append the header */
585 if (!data_blob_append(NULL, rpc_out,
586 auth_info.data, auth_info.length)) {
587 DEBUG(0, ("Failed to add %u bytes auth blob.\n",
588 (unsigned int)auth_info.length));
589 return NT_STATUS_NO_MEMORY;
591 data_blob_free(&auth_info);
593 /* Generate any auth sign/seal and add the auth footer. */
594 switch (auth->auth_type) {
595 case DCERPC_AUTH_TYPE_NONE:
596 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
597 status = NT_STATUS_OK;
598 break;
599 case DCERPC_AUTH_TYPE_SPNEGO:
600 case DCERPC_AUTH_TYPE_KRB5:
601 case DCERPC_AUTH_TYPE_NTLMSSP:
602 gensec_security = talloc_get_type_abort(auth->auth_ctx,
603 struct gensec_security);
604 status = add_generic_auth_footer(gensec_security,
605 auth->auth_level,
606 rpc_out);
607 break;
608 case DCERPC_AUTH_TYPE_SCHANNEL:
609 schannel_auth = talloc_get_type_abort(auth->auth_ctx,
610 struct schannel_state);
611 status = add_schannel_auth_footer(schannel_auth,
612 auth->auth_level,
613 rpc_out);
614 break;
615 default:
616 status = NT_STATUS_INVALID_PARAMETER;
617 break;
620 return status;
624 * @brief Check authentication for request/response packets
626 * @param auth The auth data for the connection
627 * @param pkt The actual ncacn_packet
628 * @param pkt_trailer The stub_and_verifier part of the packet
629 * @param header_size The header size
630 * @param raw_pkt The whole raw packet data blob
631 * @param pad_len [out] The padding length used in the packet
633 * @return A NTSTATUS error code
635 NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
636 struct ncacn_packet *pkt,
637 DATA_BLOB *pkt_trailer,
638 size_t header_size,
639 DATA_BLOB *raw_pkt,
640 size_t *pad_len)
642 struct schannel_state *schannel_auth;
643 struct gensec_security *gensec_security;
644 NTSTATUS status;
645 struct dcerpc_auth auth_info;
646 uint32_t auth_length;
647 DATA_BLOB full_pkt;
648 DATA_BLOB data;
650 switch (auth->auth_level) {
651 case DCERPC_AUTH_LEVEL_PRIVACY:
652 DEBUG(10, ("Requested Privacy.\n"));
653 break;
655 case DCERPC_AUTH_LEVEL_INTEGRITY:
656 DEBUG(10, ("Requested Integrity.\n"));
657 break;
659 case DCERPC_AUTH_LEVEL_CONNECT:
660 if (pkt->auth_length != 0) {
661 break;
663 *pad_len = 0;
664 return NT_STATUS_OK;
666 case DCERPC_AUTH_LEVEL_NONE:
667 if (pkt->auth_length != 0) {
668 DEBUG(3, ("Got non-zero auth len on non "
669 "authenticated connection!\n"));
670 return NT_STATUS_INVALID_PARAMETER;
672 *pad_len = 0;
673 return NT_STATUS_OK;
675 default:
676 DEBUG(3, ("Unimplemented Auth Level %d",
677 auth->auth_level));
678 return NT_STATUS_INVALID_PARAMETER;
681 /* Paranioa checks for auth_length. */
682 if (pkt->auth_length > pkt->frag_length) {
683 return NT_STATUS_INFO_LENGTH_MISMATCH;
685 if (((unsigned int)pkt->auth_length
686 + DCERPC_AUTH_TRAILER_LENGTH < (unsigned int)pkt->auth_length) ||
687 ((unsigned int)pkt->auth_length
688 + DCERPC_AUTH_TRAILER_LENGTH < DCERPC_AUTH_TRAILER_LENGTH)) {
689 /* Integer wrap attempt. */
690 return NT_STATUS_INFO_LENGTH_MISMATCH;
693 status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
694 &auth_info, &auth_length, false);
695 if (!NT_STATUS_IS_OK(status)) {
696 return status;
699 data = data_blob_const(raw_pkt->data + header_size,
700 pkt_trailer->length - auth_length);
701 full_pkt = data_blob_const(raw_pkt->data,
702 raw_pkt->length - auth_info.credentials.length);
704 switch (auth->auth_type) {
705 case DCERPC_AUTH_TYPE_NONE:
706 case DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM:
707 return NT_STATUS_OK;
709 case DCERPC_AUTH_TYPE_SPNEGO:
710 case DCERPC_AUTH_TYPE_KRB5:
711 case DCERPC_AUTH_TYPE_NTLMSSP:
713 DEBUG(10, ("GENSEC auth\n"));
715 gensec_security = talloc_get_type_abort(auth->auth_ctx,
716 struct gensec_security);
717 status = get_generic_auth_footer(gensec_security,
718 auth->auth_level,
719 &data, &full_pkt,
720 &auth_info.credentials);
721 if (!NT_STATUS_IS_OK(status)) {
722 return status;
724 break;
726 case DCERPC_AUTH_TYPE_SCHANNEL:
728 DEBUG(10, ("SCHANNEL auth\n"));
730 schannel_auth = talloc_get_type_abort(auth->auth_ctx,
731 struct schannel_state);
732 status = get_schannel_auth_footer(pkt, schannel_auth,
733 auth->auth_level,
734 &data, &full_pkt,
735 &auth_info.credentials);
736 if (!NT_STATUS_IS_OK(status)) {
737 return status;
739 break;
741 default:
742 DEBUG(0, ("process_request_pdu: "
743 "unknown auth type %u set.\n",
744 (unsigned int)auth->auth_type));
745 return NT_STATUS_INVALID_PARAMETER;
748 /* TODO: remove later
749 * this is still needed because in the server code the
750 * pkt_trailer actually has a copy of the raw data, and they
751 * are still both used in later calls */
752 if (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
753 memcpy(pkt_trailer->data, data.data, data.length);
756 *pad_len = auth_info.auth_pad_length;
757 data_blob_free(&auth_info.credentials);
758 return NT_STATUS_OK;