Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : server side dcerpc authentication code
5 :
6 : Copyright (C) Andrew Tridgell 2003
7 : Copyright (C) Stefan (metze) Metzmacher 2004
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "librpc/rpc/dcesrv_core.h"
25 : #include "librpc/rpc/dcesrv_core_proto.h"
26 : #include "librpc/rpc/dcerpc_util.h"
27 : #include "librpc/rpc/dcerpc_pkt_auth.h"
28 : #include "librpc/gen_ndr/ndr_dcerpc.h"
29 : #include "auth/credentials/credentials.h"
30 : #include "auth/gensec/gensec.h"
31 : #include "auth/auth.h"
32 : #include "param/param.h"
33 :
34 61633 : static NTSTATUS dcesrv_auth_negotiate_hdr_signing(struct dcesrv_call_state *call,
35 : struct ncacn_packet *pkt)
36 : {
37 61633 : struct dcesrv_connection *dce_conn = call->conn;
38 61633 : struct dcesrv_auth *a = NULL;
39 :
40 61633 : if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
41 53168 : return NT_STATUS_OK;
42 : }
43 :
44 8465 : if (dce_conn->client_hdr_signing) {
45 0 : if (dce_conn->negotiated_hdr_signing && pkt != NULL) {
46 0 : pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
47 : }
48 0 : return NT_STATUS_OK;
49 : }
50 :
51 8465 : dce_conn->client_hdr_signing = true;
52 8465 : dce_conn->negotiated_hdr_signing = dce_conn->support_hdr_signing;
53 :
54 8465 : if (!dce_conn->negotiated_hdr_signing) {
55 512 : return NT_STATUS_OK;
56 : }
57 :
58 7953 : if (pkt != NULL) {
59 7953 : pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
60 : }
61 :
62 7953 : a = call->conn->default_auth_state;
63 7953 : if (a->gensec_security != NULL) {
64 0 : gensec_want_feature(a->gensec_security,
65 : GENSEC_FEATURE_SIGN_PKT_HEADER);
66 : }
67 :
68 15900 : for (a = call->conn->auth_states; a != NULL; a = a->next) {
69 7947 : if (a->gensec_security == NULL) {
70 0 : continue;
71 : }
72 :
73 7947 : gensec_want_feature(a->gensec_security,
74 : GENSEC_FEATURE_SIGN_PKT_HEADER);
75 : }
76 :
77 7953 : return NT_STATUS_OK;
78 : }
79 :
80 9405 : static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
81 : {
82 9405 : struct dcesrv_connection *dce_conn = call->conn;
83 9405 : struct dcesrv_auth *auth = call->auth_state;
84 9405 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
85 424 : NTSTATUS status;
86 :
87 9405 : if (auth->auth_started) {
88 0 : return false;
89 : }
90 :
91 9405 : auth->auth_started = true;
92 :
93 9405 : if (auth->auth_invalid) {
94 0 : return false;
95 : }
96 :
97 9405 : if (auth->auth_finished) {
98 0 : return false;
99 : }
100 :
101 9405 : if (auth->gensec_security != NULL) {
102 0 : return false;
103 : }
104 :
105 9405 : switch (call->in_auth_info.auth_level) {
106 8957 : case DCERPC_AUTH_LEVEL_CONNECT:
107 : case DCERPC_AUTH_LEVEL_CALL:
108 : case DCERPC_AUTH_LEVEL_PACKET:
109 : case DCERPC_AUTH_LEVEL_INTEGRITY:
110 : case DCERPC_AUTH_LEVEL_PRIVACY:
111 : /*
112 : * We evaluate auth_type only if auth_level was valid
113 : */
114 9381 : break;
115 24 : default:
116 : /*
117 : * Setting DCERPC_AUTH_LEVEL_NONE,
118 : * gives the caller the reject_reason
119 : * as auth_context_id.
120 : *
121 : * Note: DCERPC_AUTH_LEVEL_NONE == 1
122 : */
123 24 : auth->auth_type = DCERPC_AUTH_TYPE_NONE;
124 24 : auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
125 24 : auth->auth_context_id = DCERPC_BIND_NAK_REASON_NOT_SPECIFIED;
126 24 : return false;
127 : }
128 :
129 9381 : auth->auth_type = call->in_auth_info.auth_type;
130 9381 : auth->auth_level = call->in_auth_info.auth_level;
131 9381 : auth->auth_context_id = call->in_auth_info.auth_context_id;
132 :
133 9381 : cb->auth.become_root();
134 9381 : status = cb->auth.gensec_prepare(
135 : auth,
136 : call,
137 : &auth->gensec_security,
138 : cb->auth.private_data);
139 9381 : cb->auth.unbecome_root();
140 9381 : if (!NT_STATUS_IS_OK(status)) {
141 0 : DEBUG(1, ("Failed to call samba_server_gensec_start %s\n",
142 : nt_errstr(status)));
143 0 : return false;
144 : }
145 :
146 : /*
147 : * We have to call this because we set the target_service for
148 : * Kerberos to NULL above, and in any case we wish to log a
149 : * more specific service target.
150 : *
151 : */
152 9381 : status = gensec_set_target_service_description(auth->gensec_security,
153 : "DCE/RPC");
154 9381 : if (!NT_STATUS_IS_OK(status)) {
155 0 : DEBUG(1, ("Failed to call gensec_set_target_service_description %s\n",
156 : nt_errstr(status)));
157 0 : return false;
158 : }
159 :
160 9381 : if (call->conn->remote_address != NULL) {
161 9381 : status = gensec_set_remote_address(auth->gensec_security,
162 8957 : call->conn->remote_address);
163 9381 : if (!NT_STATUS_IS_OK(status)) {
164 0 : DEBUG(1, ("Failed to call gensec_set_remote_address() %s\n",
165 : nt_errstr(status)));
166 0 : return false;
167 : }
168 : }
169 :
170 9381 : if (call->conn->local_address != NULL) {
171 9381 : status = gensec_set_local_address(auth->gensec_security,
172 8957 : call->conn->local_address);
173 9381 : if (!NT_STATUS_IS_OK(status)) {
174 0 : DEBUG(1, ("Failed to call gensec_set_local_address() %s\n",
175 : nt_errstr(status)));
176 0 : return false;
177 : }
178 : }
179 :
180 9805 : status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
181 9381 : auth->auth_level);
182 9381 : if (!NT_STATUS_IS_OK(status)) {
183 0 : const char *backend_name =
184 18 : gensec_get_name_by_authtype(auth->gensec_security,
185 18 : auth->auth_type);
186 :
187 18 : DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: "
188 : "auth_type=%d (%s), auth_level=%d: %s\n",
189 : (int)auth->auth_type, backend_name,
190 : (int)auth->auth_level,
191 : nt_errstr(status)));
192 :
193 : /*
194 : * Setting DCERPC_AUTH_LEVEL_NONE,
195 : * gives the caller the reject_reason
196 : * as auth_context_id.
197 : *
198 : * Note: DCERPC_AUTH_LEVEL_NONE == 1
199 : */
200 18 : auth->auth_type = DCERPC_AUTH_TYPE_NONE;
201 18 : auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
202 18 : if (backend_name != NULL) {
203 3 : auth->auth_context_id =
204 : DCERPC_BIND_NAK_REASON_INVALID_CHECKSUM;
205 : } else {
206 15 : auth->auth_context_id =
207 : DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE;
208 : }
209 18 : return false;
210 : }
211 :
212 9363 : if (dce_conn->negotiated_hdr_signing) {
213 0 : gensec_want_feature(auth->gensec_security,
214 : GENSEC_FEATURE_SIGN_PKT_HEADER);
215 : }
216 :
217 8939 : return true;
218 : }
219 :
220 55185 : static void dcesrv_default_auth_state_finish_bind(struct dcesrv_call_state *call)
221 : {
222 55185 : SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_BIND);
223 :
224 55185 : if (call->auth_state == call->conn->default_auth_state) {
225 46141 : return;
226 : }
227 :
228 8608 : if (call->conn->default_auth_state->auth_started) {
229 0 : return;
230 : }
231 :
232 8608 : if (call->conn->default_auth_state->auth_invalid) {
233 0 : return;
234 : }
235 :
236 8608 : call->conn->default_auth_state->auth_type = DCERPC_AUTH_TYPE_NONE;
237 8608 : call->conn->default_auth_state->auth_level = DCERPC_AUTH_LEVEL_NONE;
238 8608 : call->conn->default_auth_state->auth_context_id = 0;
239 8608 : call->conn->default_auth_state->auth_started = true;
240 8608 : call->conn->default_auth_state->auth_finished = true;
241 :
242 : /*
243 : *
244 : * We defer log_successful_dcesrv_authz_event()
245 : * to dcesrv_default_auth_state_prepare_request()
246 : *
247 : * As we don't want to trigger authz_events
248 : * just for alter_context requests without authentication
249 : */
250 : }
251 :
252 852675 : void dcesrv_default_auth_state_prepare_request(struct dcesrv_call_state *call)
253 : {
254 852675 : struct dcesrv_connection *dce_conn = call->conn;
255 852675 : struct dcesrv_auth *auth = call->auth_state;
256 852675 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
257 :
258 852675 : if (auth->auth_audited) {
259 748673 : return;
260 : }
261 :
262 100728 : if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
263 0 : return;
264 : }
265 :
266 100728 : if (auth != dce_conn->default_auth_state) {
267 96589 : return;
268 : }
269 :
270 578 : if (auth->auth_invalid) {
271 0 : return;
272 : }
273 :
274 578 : if (!auth->auth_finished) {
275 0 : return;
276 : }
277 :
278 578 : if (cb->log.successful_authz == NULL) {
279 0 : return;
280 : }
281 :
282 578 : cb->log.successful_authz(call, cb->log.private_data);
283 : }
284 :
285 : /*
286 : parse any auth information from a dcerpc bind request
287 : return false if we can't handle the auth request for some
288 : reason (in which case we send a bind_nak)
289 : */
290 55230 : bool dcesrv_auth_bind(struct dcesrv_call_state *call)
291 : {
292 55230 : struct ncacn_packet *pkt = &call->pkt;
293 55230 : struct dcesrv_auth *auth = call->auth_state;
294 55230 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
295 860 : NTSTATUS status;
296 :
297 55230 : if (pkt->auth_length == 0) {
298 46003 : auth->auth_type = DCERPC_AUTH_TYPE_NONE;
299 46003 : auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
300 46003 : auth->auth_context_id = 0;
301 46003 : auth->auth_started = true;
302 :
303 46003 : if (cb->log.successful_authz != NULL) {
304 46003 : cb->log.successful_authz(call, cb->log.private_data);
305 : }
306 :
307 46003 : return true;
308 : }
309 :
310 9227 : status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
311 : &call->in_auth_info,
312 : NULL, true);
313 9227 : if (!NT_STATUS_IS_OK(status)) {
314 : /*
315 : * Setting DCERPC_AUTH_LEVEL_NONE,
316 : * gives the caller the reject_reason
317 : * as auth_context_id.
318 : *
319 : * Note: DCERPC_AUTH_LEVEL_NONE == 1
320 : */
321 3 : auth->auth_type = DCERPC_AUTH_TYPE_NONE;
322 3 : auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
323 3 : auth->auth_context_id =
324 : DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED;
325 3 : return false;
326 : }
327 :
328 9224 : return dcesrv_auth_prepare_gensec(call);
329 : }
330 :
331 15663 : NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
332 : {
333 15663 : struct dcesrv_auth *auth = call->auth_state;
334 15663 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
335 15663 : const char *pdu = "<unknown>";
336 :
337 15663 : switch (call->pkt.ptype) {
338 8758 : case DCERPC_PKT_BIND:
339 8758 : pdu = "BIND";
340 8758 : break;
341 6253 : case DCERPC_PKT_ALTER:
342 6253 : pdu = "ALTER";
343 6253 : break;
344 228 : case DCERPC_PKT_AUTH3:
345 228 : pdu = "AUTH3";
346 228 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
347 0 : DEBUG(4, ("GENSEC not finished at %s\n", pdu));
348 0 : return NT_STATUS_RPC_SEC_PKG_ERROR;
349 : }
350 228 : break;
351 0 : default:
352 0 : return NT_STATUS_INTERNAL_ERROR;
353 : }
354 :
355 15663 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
356 6327 : return NT_STATUS_OK;
357 : }
358 :
359 9336 : if (!NT_STATUS_IS_OK(status)) {
360 7 : DEBUG(4, ("GENSEC mech rejected the incoming authentication "
361 : "at %s: %s\n", pdu, nt_errstr(status)));
362 7 : return status;
363 : }
364 :
365 9329 : cb->auth.become_root();
366 9329 : status = gensec_session_info(auth->gensec_security,
367 : auth,
368 : &auth->session_info);
369 9329 : cb->auth.unbecome_root();
370 9329 : if (!NT_STATUS_IS_OK(status)) {
371 0 : DEBUG(1, ("Failed to establish session_info: %s\n",
372 : nt_errstr(status)));
373 0 : return status;
374 : }
375 9329 : auth->auth_finished = true;
376 :
377 9329 : if (auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT &&
378 669 : !call->conn->got_explicit_auth_level_connect)
379 : {
380 663 : call->conn->default_auth_level_connect = auth;
381 : }
382 :
383 9329 : if (call->pkt.ptype != DCERPC_PKT_AUTH3) {
384 9101 : return NT_STATUS_OK;
385 : }
386 :
387 228 : if (call->out_auth_info->credentials.length != 0) {
388 3 : DEBUG(4, ("GENSEC produced output token (len=%zu) at %s\n",
389 : call->out_auth_info->credentials.length, pdu));
390 3 : return NT_STATUS_RPC_SEC_PKG_ERROR;
391 : }
392 :
393 225 : return NT_STATUS_OK;
394 : }
395 :
396 : /*
397 : add any auth information needed in a bind ack, and process the authentication
398 : information found in the bind.
399 : */
400 55185 : NTSTATUS dcesrv_auth_prepare_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
401 : {
402 55185 : struct dcesrv_connection *dce_conn = call->conn;
403 55185 : struct dcesrv_auth *auth = call->auth_state;
404 860 : NTSTATUS status;
405 :
406 55185 : status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
407 55185 : if (!NT_STATUS_IS_OK(status)) {
408 0 : return status;
409 : }
410 :
411 55185 : dce_conn->allow_alter = true;
412 55185 : dcesrv_default_auth_state_finish_bind(call);
413 :
414 55185 : if (call->pkt.auth_length == 0) {
415 46003 : auth->auth_finished = true;
416 46003 : return NT_STATUS_OK;
417 : }
418 :
419 : /* We can't work without an existing gensec state */
420 9182 : if (auth->gensec_security == NULL) {
421 0 : return NT_STATUS_INTERNAL_ERROR;
422 : }
423 :
424 9182 : call->_out_auth_info = (struct dcerpc_auth) {
425 9182 : .auth_type = auth->auth_type,
426 9182 : .auth_level = auth->auth_level,
427 9182 : .auth_context_id = auth->auth_context_id,
428 : };
429 9182 : call->out_auth_info = &call->_out_auth_info;
430 :
431 9182 : return NT_STATUS_OK;
432 : }
433 :
434 : /*
435 : process the final stage of a auth request
436 : */
437 231 : bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call)
438 : {
439 231 : struct ncacn_packet *pkt = &call->pkt;
440 231 : struct dcesrv_auth *auth = call->auth_state;
441 0 : NTSTATUS status;
442 :
443 231 : if (pkt->auth_length == 0) {
444 0 : return false;
445 : }
446 :
447 231 : if (auth->auth_finished) {
448 0 : return false;
449 : }
450 :
451 231 : if (auth->auth_invalid) {
452 0 : return false;
453 : }
454 :
455 : /* We can't work without an existing gensec state */
456 231 : if (auth->gensec_security == NULL) {
457 0 : return false;
458 : }
459 :
460 231 : status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
461 : &call->in_auth_info, NULL, true);
462 231 : if (!NT_STATUS_IS_OK(status)) {
463 : /*
464 : * Windows returns DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY
465 : * instead of DCERPC_NCA_S_PROTO_ERROR.
466 : */
467 3 : call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY;
468 3 : return false;
469 : }
470 :
471 228 : if (call->in_auth_info.auth_type != auth->auth_type) {
472 0 : return false;
473 : }
474 :
475 228 : if (call->in_auth_info.auth_level != auth->auth_level) {
476 0 : return false;
477 : }
478 :
479 228 : if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
480 0 : return false;
481 : }
482 :
483 228 : call->_out_auth_info = (struct dcerpc_auth) {
484 228 : .auth_type = auth->auth_type,
485 228 : .auth_level = auth->auth_level,
486 228 : .auth_context_id = auth->auth_context_id,
487 : };
488 228 : call->out_auth_info = &call->_out_auth_info;
489 :
490 228 : return true;
491 : }
492 :
493 : /*
494 : parse any auth information from a dcerpc alter request
495 : return false if we can't handle the auth request for some
496 : reason (in which case we send a bind_nak (is this true for here?))
497 : */
498 6493 : bool dcesrv_auth_alter(struct dcesrv_call_state *call)
499 : {
500 6493 : struct ncacn_packet *pkt = &call->pkt;
501 6493 : struct dcesrv_auth *auth = call->auth_state;
502 117 : NTSTATUS status;
503 :
504 : /* on a pure interface change there is no auth blob */
505 6493 : if (pkt->auth_length == 0) {
506 216 : if (!auth->auth_finished) {
507 0 : return false;
508 : }
509 216 : return true;
510 : }
511 :
512 6277 : if (auth->auth_finished) {
513 3 : call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
514 3 : return false;
515 : }
516 :
517 6274 : status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
518 : &call->in_auth_info, NULL, true);
519 6274 : if (!NT_STATUS_IS_OK(status)) {
520 3 : call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
521 3 : return false;
522 : }
523 :
524 6271 : if (!auth->auth_started) {
525 0 : bool ok;
526 :
527 181 : ok = dcesrv_auth_prepare_gensec(call);
528 181 : if (!ok) {
529 0 : call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
530 0 : return false;
531 : }
532 :
533 181 : return true;
534 : }
535 :
536 6090 : if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
537 3 : call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
538 3 : return false;
539 : }
540 :
541 6087 : if (auth->auth_invalid) {
542 15 : return false;
543 : }
544 :
545 6072 : if (call->in_auth_info.auth_type != auth->auth_type) {
546 0 : return false;
547 : }
548 :
549 6072 : if (call->in_auth_info.auth_level != auth->auth_level) {
550 0 : return false;
551 : }
552 :
553 6072 : if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
554 0 : return false;
555 : }
556 :
557 5976 : return true;
558 : }
559 :
560 : /*
561 : add any auth information needed in a alter ack, and process the authentication
562 : information found in the alter.
563 : */
564 6448 : NTSTATUS dcesrv_auth_prepare_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
565 : {
566 6448 : struct dcesrv_auth *auth = call->auth_state;
567 114 : NTSTATUS status;
568 :
569 6448 : status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
570 6448 : if (!NT_STATUS_IS_OK(status)) {
571 0 : return status;
572 : }
573 :
574 : /* on a pure interface change there is no auth_info structure
575 : setup */
576 6448 : if (call->pkt.auth_length == 0) {
577 195 : return NT_STATUS_OK;
578 : }
579 :
580 6253 : if (auth->gensec_security == NULL) {
581 0 : return NT_STATUS_INTERNAL_ERROR;
582 : }
583 :
584 6253 : call->_out_auth_info = (struct dcerpc_auth) {
585 6253 : .auth_type = auth->auth_type,
586 6253 : .auth_level = auth->auth_level,
587 6253 : .auth_context_id = auth->auth_context_id,
588 : };
589 6253 : call->out_auth_info = &call->_out_auth_info;
590 :
591 6253 : return NT_STATUS_OK;
592 : }
593 :
594 : /*
595 : check credentials on a packet
596 : */
597 852524 : bool dcesrv_auth_pkt_pull(struct dcesrv_call_state *call,
598 : DATA_BLOB *full_packet,
599 : uint8_t required_flags,
600 : uint8_t optional_flags,
601 : uint8_t payload_offset,
602 : DATA_BLOB *payload_and_verifier)
603 : {
604 852524 : struct ncacn_packet *pkt = &call->pkt;
605 852524 : struct dcesrv_auth *auth = call->auth_state;
606 852524 : const struct dcerpc_auth tmp_auth = {
607 852524 : .auth_type = auth->auth_type,
608 852524 : .auth_level = auth->auth_level,
609 852524 : .auth_context_id = auth->auth_context_id,
610 : };
611 6835 : bool check_pkt_auth_fields;
612 6835 : NTSTATUS status;
613 :
614 852524 : if (!auth->auth_started) {
615 12 : return false;
616 : }
617 :
618 852512 : if (!auth->auth_finished) {
619 0 : call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
620 0 : return false;
621 : }
622 :
623 852512 : if (auth->auth_invalid) {
624 27 : return false;
625 : }
626 :
627 852482 : if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) {
628 : /*
629 : * The caller most likely checked this
630 : * already, but we better double check.
631 : */
632 829187 : check_pkt_auth_fields = true;
633 : } else {
634 : /*
635 : * The caller already found first fragment
636 : * and is passing the auth_state of it.
637 : * A server is supposed to use the
638 : * setting of the first fragment and
639 : * completely ignore the values
640 : * on the remaining fragments
641 : */
642 16546 : check_pkt_auth_fields = false;
643 : }
644 :
645 852482 : status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
646 : auth->gensec_security,
647 : check_pkt_auth_fields,
648 : call,
649 : pkt->ptype,
650 : required_flags,
651 : optional_flags,
652 : payload_offset,
653 : payload_and_verifier,
654 : full_packet,
655 : pkt);
656 852482 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
657 12 : call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
658 12 : return false;
659 : }
660 852470 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL)) {
661 0 : call->fault_code = DCERPC_NCA_S_UNSUPPORTED_AUTHN_LEVEL;
662 0 : return false;
663 : }
664 852470 : if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
665 21 : call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
666 21 : return false;
667 : }
668 852449 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
669 0 : call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
670 0 : return false;
671 : }
672 852449 : if (!NT_STATUS_IS_OK(status)) {
673 0 : return false;
674 : }
675 :
676 845617 : return true;
677 : }
678 :
679 : /*
680 : push a signed or sealed dcerpc request packet into a blob
681 : */
682 1123994 : bool dcesrv_auth_pkt_push(struct dcesrv_call_state *call,
683 : DATA_BLOB *blob, size_t sig_size,
684 : uint8_t payload_offset,
685 : const DATA_BLOB *payload,
686 : const struct ncacn_packet *pkt)
687 : {
688 1123994 : struct dcesrv_auth *auth = call->auth_state;
689 1123994 : const struct dcerpc_auth tmp_auth = {
690 1123994 : .auth_type = auth->auth_type,
691 1123994 : .auth_level = auth->auth_level,
692 1123994 : .auth_context_id = auth->auth_context_id,
693 : };
694 6491 : NTSTATUS status;
695 :
696 1123994 : status = dcerpc_ncacn_push_pkt_auth(&tmp_auth,
697 : auth->gensec_security,
698 : call, blob, sig_size,
699 : payload_offset,
700 : payload,
701 : pkt);
702 1123994 : return NT_STATUS_IS_OK(status);
703 : }
|