CVE-2018-16852 dcerpc dnsserver: Verification tests
[Samba.git] / auth / kerberos / gssapi_helper.c
blob52c953c07ab835ad4273b510e5c283bc580df319
1 /*
2 Unix SMB/CIFS implementation.
3 GSSAPI helper functions
5 Copyright (C) Stefan Metzmacher 2008,2015
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/gssapi.h"
23 #include "auth/kerberos/pac_utils.h"
24 #include "auth/kerberos/gssapi_helper.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_AUTH
29 size_t gssapi_get_sig_size(gss_ctx_id_t gssapi_context,
30 const gss_OID mech,
31 uint32_t gss_want_flags,
32 size_t data_size)
34 TALLOC_CTX *frame = talloc_stackframe();
35 size_t sig_size = 0;
37 if (gss_want_flags & GSS_C_CONF_FLAG) {
38 OM_uint32 min_stat, maj_stat;
39 bool want_sealing = true;
40 int sealed = 0;
41 gss_iov_buffer_desc iov[2];
43 if (!(gss_want_flags & GSS_C_DCE_STYLE)) {
44 TALLOC_FREE(frame);
45 return 0;
49 * gss_wrap_iov_length() only needs the type and length
51 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
52 iov[0].buffer.value = NULL;
53 iov[0].buffer.length = 0;
54 iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
55 iov[1].buffer.value = NULL;
56 iov[1].buffer.length = data_size;
58 maj_stat = gss_wrap_iov_length(&min_stat,
59 gssapi_context,
60 want_sealing,
61 GSS_C_QOP_DEFAULT,
62 &sealed,
63 iov, ARRAY_SIZE(iov));
64 if (maj_stat) {
65 DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
66 gssapi_error_string(frame,
67 maj_stat,
68 min_stat,
69 mech)));
70 TALLOC_FREE(frame);
71 return 0;
74 sig_size = iov[0].buffer.length;
75 } else if (gss_want_flags & GSS_C_INTEG_FLAG) {
76 NTSTATUS status;
77 uint32_t keytype;
79 status = gssapi_get_session_key(frame,
80 gssapi_context,
81 NULL, &keytype);
82 if (!NT_STATUS_IS_OK(status)) {
83 TALLOC_FREE(frame);
84 return 0;
87 switch (keytype) {
88 case ENCTYPE_DES_CBC_MD5:
89 case ENCTYPE_DES_CBC_CRC:
90 case ENCTYPE_ARCFOUR_HMAC:
91 case ENCTYPE_ARCFOUR_HMAC_EXP:
92 sig_size = 37;
93 break;
94 default:
95 sig_size = 28;
96 break;
100 TALLOC_FREE(frame);
101 return sig_size;
104 NTSTATUS gssapi_seal_packet(gss_ctx_id_t gssapi_context,
105 const gss_OID mech,
106 bool hdr_signing, size_t sig_size,
107 uint8_t *data, size_t length,
108 const uint8_t *whole_pdu, size_t pdu_length,
109 TALLOC_CTX *mem_ctx,
110 DATA_BLOB *sig)
112 OM_uint32 maj_stat, min_stat;
113 gss_iov_buffer_desc iov[4];
114 int req_seal = 1;
115 int sealed = 0;
116 const uint8_t *pre_sign_ptr = NULL;
117 size_t pre_sign_len = 0;
118 const uint8_t *post_sign_ptr = NULL;
119 size_t post_sign_len = 0;
121 if (hdr_signing) {
122 const uint8_t *de = data + length;
123 const uint8_t *we = whole_pdu + pdu_length;
125 if (data < whole_pdu) {
126 return NT_STATUS_INVALID_PARAMETER;
129 if (de > we) {
130 return NT_STATUS_INVALID_PARAMETER;
133 pre_sign_len = data - whole_pdu;
134 if (pre_sign_len > 0) {
135 pre_sign_ptr = whole_pdu;
137 post_sign_len = we - de;
138 if (post_sign_len > 0) {
139 post_sign_ptr = de;
143 sig->length = sig_size;
144 if (sig->length == 0) {
145 return NT_STATUS_ACCESS_DENIED;
148 sig->data = talloc_zero_array(mem_ctx, uint8_t, sig->length);
149 if (sig->data == NULL) {
150 return NT_STATUS_NO_MEMORY;
153 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
154 iov[0].buffer.length = sig->length;
155 iov[0].buffer.value = sig->data;
157 if (pre_sign_ptr != NULL) {
158 iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
159 iov[1].buffer.length = pre_sign_len;
160 iov[1].buffer.value = discard_const(pre_sign_ptr);
161 } else {
162 iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
163 iov[1].buffer.length = 0;
164 iov[1].buffer.value = NULL;
167 /* data is encrypted in place, which is ok */
168 iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
169 iov[2].buffer.length = length;
170 iov[2].buffer.value = data;
172 if (post_sign_ptr != NULL) {
173 iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
174 iov[3].buffer.length = post_sign_len;
175 iov[3].buffer.value = discard_const(post_sign_ptr);
176 } else {
177 iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
178 iov[3].buffer.length = 0;
179 iov[3].buffer.value = NULL;
182 maj_stat = gss_wrap_iov(&min_stat,
183 gssapi_context,
184 req_seal,
185 GSS_C_QOP_DEFAULT,
186 &sealed,
187 iov, ARRAY_SIZE(iov));
188 if (GSS_ERROR(maj_stat)) {
189 char *error_string = gssapi_error_string(mem_ctx,
190 maj_stat,
191 min_stat,
192 mech);
193 DEBUG(1, ("gss_wrap_iov failed: %s\n", error_string));
194 talloc_free(error_string);
195 data_blob_free(sig);
196 return NT_STATUS_ACCESS_DENIED;
199 if (req_seal == 1 && sealed == 0) {
200 DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
201 data_blob_free(sig);
202 return NT_STATUS_ACCESS_DENIED;
205 dump_data_pw("gssapi_seal_packet: sig\n", sig->data, sig->length);
206 dump_data_pw("gssapi_seal_packet: sealed\n", data, length);
208 DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
209 (int)iov[2].buffer.length, (int)iov[0].buffer.length));
211 return NT_STATUS_OK;
214 NTSTATUS gssapi_unseal_packet(gss_ctx_id_t gssapi_context,
215 const gss_OID mech,
216 bool hdr_signing,
217 uint8_t *data, size_t length,
218 const uint8_t *whole_pdu, size_t pdu_length,
219 const DATA_BLOB *sig)
221 OM_uint32 maj_stat, min_stat;
222 gss_iov_buffer_desc iov[4];
223 gss_qop_t qop_state;
224 int sealed = 0;
225 const uint8_t *pre_sign_ptr = NULL;
226 size_t pre_sign_len = 0;
227 const uint8_t *post_sign_ptr = NULL;
228 size_t post_sign_len = 0;
230 if (hdr_signing) {
231 const uint8_t *de = data + length;
232 const uint8_t *we = whole_pdu + pdu_length;
234 if (data < whole_pdu) {
235 return NT_STATUS_INVALID_PARAMETER;
238 if (de > we) {
239 return NT_STATUS_INVALID_PARAMETER;
242 pre_sign_len = data - whole_pdu;
243 if (pre_sign_len > 0) {
244 pre_sign_ptr = whole_pdu;
246 post_sign_len = we - de;
247 if (post_sign_len > 0) {
248 post_sign_ptr = de;
252 dump_data_pw("gssapi_unseal_packet: sig\n", sig->data, sig->length);
253 dump_data_pw("gssapi_unseal_packet: sealed\n", data, length);
255 iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
256 iov[0].buffer.length = sig->length;
257 iov[0].buffer.value = sig->data;
259 if (pre_sign_ptr != NULL) {
260 iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
261 iov[1].buffer.length = pre_sign_len;
262 iov[1].buffer.value = discard_const(pre_sign_ptr);
263 } else {
264 iov[1].type = GSS_IOV_BUFFER_TYPE_EMPTY;
265 iov[1].buffer.length = 0;
266 iov[1].buffer.value = NULL;
269 /* data is encrypted in place, which is ok */
270 iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
271 iov[2].buffer.length = length;
272 iov[2].buffer.value = data;
274 if (post_sign_ptr != NULL) {
275 iov[3].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
276 iov[3].buffer.length = post_sign_len;
277 iov[3].buffer.value = discard_const(post_sign_ptr);
278 } else {
279 iov[3].type = GSS_IOV_BUFFER_TYPE_EMPTY;
280 iov[3].buffer.length = 0;
281 iov[3].buffer.value = NULL;
284 maj_stat = gss_unwrap_iov(&min_stat,
285 gssapi_context,
286 &sealed,
287 &qop_state,
288 iov, ARRAY_SIZE(iov));
289 if (GSS_ERROR(maj_stat)) {
290 char *error_string = gssapi_error_string(NULL,
291 maj_stat,
292 min_stat,
293 mech);
294 DEBUG(1, ("gss_unwrap_iov failed: %s\n", error_string));
295 talloc_free(error_string);
297 return NT_STATUS_ACCESS_DENIED;
300 if (sealed == 0) {
301 DEBUG(0, ("gss_unwrap_iov says data was not sealed!\n"));
302 return NT_STATUS_ACCESS_DENIED;
305 DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
306 (int)iov[2].buffer.length, (int)iov[0].buffer.length));
308 return NT_STATUS_OK;
311 NTSTATUS gssapi_sign_packet(gss_ctx_id_t gssapi_context,
312 const gss_OID mech,
313 bool hdr_signing,
314 const uint8_t *data, size_t length,
315 const uint8_t *whole_pdu, size_t pdu_length,
316 TALLOC_CTX *mem_ctx,
317 DATA_BLOB *sig)
319 OM_uint32 maj_stat, min_stat;
320 gss_buffer_desc input_token, output_token;
322 if (hdr_signing) {
323 input_token.length = pdu_length;
324 input_token.value = discard_const_p(uint8_t *, whole_pdu);
325 } else {
326 input_token.length = length;
327 input_token.value = discard_const_p(uint8_t *, data);
330 maj_stat = gss_get_mic(&min_stat,
331 gssapi_context,
332 GSS_C_QOP_DEFAULT,
333 &input_token,
334 &output_token);
335 if (GSS_ERROR(maj_stat)) {
336 char *error_string = gssapi_error_string(mem_ctx,
337 maj_stat,
338 min_stat,
339 mech);
340 DEBUG(1, ("GSS GetMic failed: %s\n", error_string));
341 talloc_free(error_string);
342 return NT_STATUS_ACCESS_DENIED;
345 *sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, output_token.length);
346 gss_release_buffer(&min_stat, &output_token);
347 if (sig->data == NULL) {
348 return NT_STATUS_NO_MEMORY;
351 dump_data_pw("gssapi_sign_packet: sig\n", sig->data, sig->length);
353 return NT_STATUS_OK;
356 NTSTATUS gssapi_check_packet(gss_ctx_id_t gssapi_context,
357 const gss_OID mech,
358 bool hdr_signing,
359 const uint8_t *data, size_t length,
360 const uint8_t *whole_pdu, size_t pdu_length,
361 const DATA_BLOB *sig)
363 OM_uint32 maj_stat, min_stat;
364 gss_buffer_desc input_token;
365 gss_buffer_desc input_message;
366 gss_qop_t qop_state;
368 dump_data_pw("gssapi_check_packet: sig\n", sig->data, sig->length);
370 if (hdr_signing) {
371 input_message.length = pdu_length;
372 input_message.value = discard_const(whole_pdu);
373 } else {
374 input_message.length = length;
375 input_message.value = discard_const(data);
378 input_token.length = sig->length;
379 input_token.value = sig->data;
381 maj_stat = gss_verify_mic(&min_stat,
382 gssapi_context,
383 &input_message,
384 &input_token,
385 &qop_state);
386 if (GSS_ERROR(maj_stat)) {
387 char *error_string = gssapi_error_string(NULL,
388 maj_stat,
389 min_stat,
390 mech);
391 DEBUG(1, ("GSS VerifyMic failed: %s\n", error_string));
392 talloc_free(error_string);
394 return NT_STATUS_ACCESS_DENIED;
397 return NT_STATUS_OK;