s3-dcerpc: Fix ability to receive Big Endian PDUs
[ddiss/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
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_PARSE
28
29 /**
30 * @brief NDR Encodes a ncacn_packet
31 *
32 * @param mem_ctx        The memory context the blob will be allocated on
33 * @param ptype          The DCERPC packet type
34 * @param pfc_flags      The DCERPC PFC Falgs
35 * @param auth_length    The length of the trailing auth blob
36 * @param call_id        The call ID
37 * @param u              The payload of the packet
38 * @param blob [out]     The encoded blob if successful
39 *
40 * @return an NTSTATUS error code
41 */
42 NTSTATUS dcerpc_push_ncacn_packet(TALLOC_CTX *mem_ctx,
43                                   enum dcerpc_pkt_type ptype,
44                                   uint8_t pfc_flags,
45                                   uint16_t auth_length,
46                                   uint32_t call_id,
47                                   union dcerpc_payload *u,
48                                   DATA_BLOB *blob)
49 {
50         struct ncacn_packet r;
51         enum ndr_err_code ndr_err;
52
53         r.rpc_vers              = 5;
54         r.rpc_vers_minor        = 0;
55         r.ptype                 = ptype;
56         r.pfc_flags             = pfc_flags;
57         r.drep[0]               = DCERPC_DREP_LE;
58         r.drep[1]               = 0;
59         r.drep[2]               = 0;
60         r.drep[3]               = 0;
61         r.auth_length           = auth_length;
62         r.call_id               = call_id;
63         r.u                     = *u;
64
65         ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
66                 (ndr_push_flags_fn_t)ndr_push_ncacn_packet);
67         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
68                 return ndr_map_error2ntstatus(ndr_err);
69         }
70
71         dcerpc_set_frag_length(blob, blob->length);
72
73
74         if (DEBUGLEVEL >= 10) {
75                 /* set frag len for print function */
76                 r.frag_length = blob->length;
77                 NDR_PRINT_DEBUG(ncacn_packet, &r);
78         }
79
80         return NT_STATUS_OK;
81 }
82
83 /**
84 * @brief Decodes a ncacn_packet
85 *
86 * @param mem_ctx        The memory context on which to allocate the packet
87 *                       elements
88 * @param blob           The blob of data to decode
89 * @param r              An empty ncacn_packet, must not be NULL
90 *
91 * @return a NTSTATUS error code
92 */
93 NTSTATUS dcerpc_pull_ncacn_packet(TALLOC_CTX *mem_ctx,
94                                   const DATA_BLOB *blob,
95                                   struct ncacn_packet *r,
96                                   bool bigendian)
97 {
98         enum ndr_err_code ndr_err;
99         struct ndr_pull *ndr;
100
101         ndr = ndr_pull_init_blob(blob, mem_ctx);
102         if (!ndr) {
103                 return NT_STATUS_NO_MEMORY;
104         }
105         if (bigendian) {
106                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
107         }
108
109         ndr_err = ndr_pull_ncacn_packet(ndr, NDR_SCALARS|NDR_BUFFERS, r);
110
111         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
112                 talloc_free(ndr);
113                 return ndr_map_error2ntstatus(ndr_err);
114         }
115         talloc_free(ndr);
116
117         if (DEBUGLEVEL >= 10) {
118                 NDR_PRINT_DEBUG(ncacn_packet, r);
119         }
120
121         return NT_STATUS_OK;
122 }
123
124 /**
125 * @brief NDR Encodes a NL_AUTH_MESSAGE
126 *
127 * @param mem_ctx        The memory context the blob will be allocated on
128 * @param r              The NL_AUTH_MESSAGE to encode
129 * @param blob [out]     The encoded blob if successful
130 *
131 * @return a NTSTATUS error code
132 */
133 NTSTATUS dcerpc_push_schannel_bind(TALLOC_CTX *mem_ctx,
134                                    struct NL_AUTH_MESSAGE *r,
135                                    DATA_BLOB *blob)
136 {
137         enum ndr_err_code ndr_err;
138
139         ndr_err = ndr_push_struct_blob(blob, mem_ctx, r,
140                 (ndr_push_flags_fn_t)ndr_push_NL_AUTH_MESSAGE);
141         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
142                 return ndr_map_error2ntstatus(ndr_err);
143         }
144
145         if (DEBUGLEVEL >= 10) {
146                 NDR_PRINT_DEBUG(NL_AUTH_MESSAGE, r);
147         }
148
149         return NT_STATUS_OK;
150 }
151
152 /**
153 * @brief NDR Encodes a dcerpc_auth structure
154 *
155 * @param mem_ctx          The memory context the blob will be allocated on
156 * @param auth_type        The DCERPC Authentication Type
157 * @param auth_level       The DCERPC Authentication Level
158 * @param auth_pad_length  The padding added to the packet this blob will be
159 *                          appended to.
160 * @param auth_context_id  The context id
161 * @param credentials      The authentication credentials blob (signature)
162 * @param blob [out]       The encoded blob if successful
163 *
164 * @return a NTSTATUS error code
165 */
166 NTSTATUS dcerpc_push_dcerpc_auth(TALLOC_CTX *mem_ctx,
167                                  enum dcerpc_AuthType auth_type,
168                                  enum dcerpc_AuthLevel auth_level,
169                                  uint8_t auth_pad_length,
170                                  uint32_t auth_context_id,
171                                  const DATA_BLOB *credentials,
172                                  DATA_BLOB *blob)
173 {
174         struct dcerpc_auth r;
175         enum ndr_err_code ndr_err;
176
177         r.auth_type             = auth_type;
178         r.auth_level            = auth_level;
179         r.auth_pad_length       = auth_pad_length;
180         r.auth_reserved         = 0;
181         r.auth_context_id       = auth_context_id;
182         r.credentials           = *credentials;
183
184         ndr_err = ndr_push_struct_blob(blob, mem_ctx, &r,
185                 (ndr_push_flags_fn_t)ndr_push_dcerpc_auth);
186         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
187                 return ndr_map_error2ntstatus(ndr_err);
188         }
189
190         if (DEBUGLEVEL >= 10) {
191                 NDR_PRINT_DEBUG(dcerpc_auth, &r);
192         }
193
194         return NT_STATUS_OK;
195 }
196
197 /**
198 * @brief Decodes a dcerpc_auth blob
199 *
200 * @param mem_ctx        The memory context on which to allocate the packet
201 *                       elements
202 * @param blob           The blob of data to decode
203 * @param r              An empty dcerpc_auth structure, must not be NULL
204 *
205 * @return a NTSTATUS error code
206 */
207 NTSTATUS dcerpc_pull_dcerpc_auth(TALLOC_CTX *mem_ctx,
208                                  const DATA_BLOB *blob,
209                                  struct dcerpc_auth *r,
210                                  bool bigendian)
211 {
212         enum ndr_err_code ndr_err;
213         struct ndr_pull *ndr;
214
215         ndr = ndr_pull_init_blob(blob, mem_ctx);
216         if (!ndr) {
217                 return NT_STATUS_NO_MEMORY;
218         }
219         if (bigendian) {
220                 ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
221         }
222
223         ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, r);
224
225         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
226                 talloc_free(ndr);
227                 return ndr_map_error2ntstatus(ndr_err);
228         }
229         talloc_free(ndr);
230
231         if (DEBUGLEVEL >= 10) {
232                 NDR_PRINT_DEBUG(dcerpc_auth, r);
233         }
234
235         return NT_STATUS_OK;
236 }