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 61443 : static NTSTATUS dcesrv_auth_negotiate_hdr_signing(struct dcesrv_call_state *call,
35 : struct ncacn_packet *pkt)
36 : {
37 61443 : struct dcesrv_connection *dce_conn = call->conn;
38 61443 : struct dcesrv_auth *a = NULL;
39 :
40 61443 : if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
41 53111 : return NT_STATUS_OK;
42 : }
43 :
44 8332 : 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 8332 : dce_conn->client_hdr_signing = true;
52 8332 : dce_conn->negotiated_hdr_signing = dce_conn->support_hdr_signing;
53 :
54 8332 : if (!dce_conn->negotiated_hdr_signing) {
55 512 : return NT_STATUS_OK;
56 : }
57 :
58 7820 : if (pkt != NULL) {
59 7820 : pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
60 : }
61 :
62 7820 : a = call->conn->default_auth_state;
63 7820 : if (a->gensec_security != NULL) {
64 0 : gensec_want_feature(a->gensec_security,
65 : GENSEC_FEATURE_SIGN_PKT_HEADER);
66 : }
67 :
68 15634 : for (a = call->conn->auth_states; a != NULL; a = a->next) {
69 7814 : if (a->gensec_security == NULL) {
70 0 : continue;
71 : }
72 :
73 7814 : gensec_want_feature(a->gensec_security,
74 : GENSEC_FEATURE_SIGN_PKT_HEADER);
75 : }
76 :
77 7820 : return NT_STATUS_OK;
78 : }
79 :
80 9276 : static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
81 : {
82 9276 : struct dcesrv_connection *dce_conn = call->conn;
83 9276 : struct dcesrv_auth *auth = call->auth_state;
84 9276 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
85 424 : NTSTATUS status;
86 :
87 9276 : if (auth->auth_started) {
88 0 : return false;
89 : }
90 :
91 9276 : auth->auth_started = true;
92 :
93 9276 : if (auth->auth_invalid) {
94 0 : return false;
95 : }
96 :
97 9276 : if (auth->auth_finished) {
98 0 : return false;
99 : }
100 :
101 9276 : if (auth->gensec_security != NULL) {
102 0 : return false;
103 : }
104 :
105 9276 : switch (call->in_auth_info.auth_level) {
106 8828 : 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 9252 : 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 9252 : auth->auth_type = call->in_auth_info.auth_type;
130 9252 : auth->auth_level = call->in_auth_info.auth_level;
131 9252 : auth->auth_context_id = call->in_auth_info.auth_context_id;
132 :
133 9252 : cb->auth.become_root();
134 9252 : status = cb->auth.gensec_prepare(
135 : auth,
136 : call,
137 : &auth->gensec_security,
138 : cb->auth.private_data);
139 9252 : cb->auth.unbecome_root();
140 9252 : 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 9252 : status = gensec_set_target_service_description(auth->gensec_security,
153 : "DCE/RPC");
154 9252 : 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 9252 : if (call->conn->remote_address != NULL) {
161 9252 : status = gensec_set_remote_address(auth->gensec_security,
162 8828 : call->conn->remote_address);
163 9252 : 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 9252 : if (call->conn->local_address != NULL) {
171 9252 : status = gensec_set_local_address(auth->gensec_security,
172 8828 : call->conn->local_address);
173 9252 : 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 9676 : status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
181 9252 : auth->auth_level);
182 9252 : 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 9234 : if (dce_conn->negotiated_hdr_signing) {
213 0 : gensec_want_feature(auth->gensec_security,
214 : GENSEC_FEATURE_SIGN_PKT_HEADER);
215 : }
216 :
217 8810 : return true;
218 : }
219 :
220 55156 : static void dcesrv_default_auth_state_finish_bind(struct dcesrv_call_state *call)
221 : {
222 55156 : SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_BIND);
223 :
224 55156 : if (call->auth_state == call->conn->default_auth_state) {
225 46241 : return;
226 : }
227 :
228 8479 : if (call->conn->default_auth_state->auth_started) {
229 0 : return;
230 : }
231 :
232 8479 : if (call->conn->default_auth_state->auth_invalid) {
233 0 : return;
234 : }
235 :
236 8479 : call->conn->default_auth_state->auth_type = DCERPC_AUTH_TYPE_NONE;
237 8479 : call->conn->default_auth_state->auth_level = DCERPC_AUTH_LEVEL_NONE;
238 8479 : call->conn->default_auth_state->auth_context_id = 0;
239 8479 : call->conn->default_auth_state->auth_started = true;
240 8479 : 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 851746 : void dcesrv_default_auth_state_prepare_request(struct dcesrv_call_state *call)
253 : {
254 851746 : struct dcesrv_connection *dce_conn = call->conn;
255 851746 : struct dcesrv_auth *auth = call->auth_state;
256 851746 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
257 :
258 851746 : if (auth->auth_audited) {
259 749437 : return;
260 : }
261 :
262 98877 : if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
263 0 : return;
264 : }
265 :
266 98877 : if (auth != dce_conn->default_auth_state) {
267 94738 : 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 55201 : bool dcesrv_auth_bind(struct dcesrv_call_state *call)
291 : {
292 55201 : struct ncacn_packet *pkt = &call->pkt;
293 55201 : struct dcesrv_auth *auth = call->auth_state;
294 55201 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
295 860 : NTSTATUS status;
296 :
297 55201 : if (pkt->auth_length == 0) {
298 46103 : auth->auth_type = DCERPC_AUTH_TYPE_NONE;
299 46103 : auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
300 46103 : auth->auth_context_id = 0;
301 46103 : auth->auth_started = true;
302 :
303 46103 : if (cb->log.successful_authz != NULL) {
304 46103 : cb->log.successful_authz(call, cb->log.private_data);
305 : }
306 :
307 46103 : return true;
308 : }
309 :
310 9098 : status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
311 : &call->in_auth_info,
312 : NULL, true);
313 9098 : 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 9095 : return dcesrv_auth_prepare_gensec(call);
329 : }
330 :
331 15369 : NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
332 : {
333 15369 : struct dcesrv_auth *auth = call->auth_state;
334 15369 : struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
335 15369 : const char *pdu = "<unknown>";
336 :
337 15369 : switch (call->pkt.ptype) {
338 8629 : case DCERPC_PKT_BIND:
339 8629 : pdu = "BIND";
340 8629 : break;
341 6092 : case DCERPC_PKT_ALTER:
342 6092 : pdu = "ALTER";
343 6092 : break;
344 224 : case DCERPC_PKT_AUTH3:
345 224 : pdu = "AUTH3";
346 224 : 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 224 : break;
351 0 : default:
352 0 : return NT_STATUS_INTERNAL_ERROR;
353 : }
354 :
355 15369 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
356 6162 : return NT_STATUS_OK;
357 : }
358 :
359 9207 : 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 9200 : cb->auth.become_root();
366 9200 : status = gensec_session_info(auth->gensec_security,
367 : auth,
368 : &auth->session_info);
369 9200 : cb->auth.unbecome_root();
370 9200 : 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 9200 : auth->auth_finished = true;
376 :
377 9200 : if (auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT &&
378 673 : !call->conn->got_explicit_auth_level_connect)
379 : {
380 667 : call->conn->default_auth_level_connect = auth;
381 : }
382 :
383 9200 : if (call->pkt.ptype != DCERPC_PKT_AUTH3) {
384 8976 : return NT_STATUS_OK;
385 : }
386 :
387 224 : 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 221 : 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 55156 : NTSTATUS dcesrv_auth_prepare_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
401 : {
402 55156 : struct dcesrv_connection *dce_conn = call->conn;
403 55156 : struct dcesrv_auth *auth = call->auth_state;
404 860 : NTSTATUS status;
405 :
406 55156 : status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
407 55156 : if (!NT_STATUS_IS_OK(status)) {
408 0 : return status;
409 : }
410 :
411 55156 : dce_conn->allow_alter = true;
412 55156 : dcesrv_default_auth_state_finish_bind(call);
413 :
414 55156 : if (call->pkt.auth_length == 0) {
415 46103 : auth->auth_finished = true;
416 46103 : return NT_STATUS_OK;
417 : }
418 :
419 : /* We can't work without an existing gensec state */
420 9053 : if (auth->gensec_security == NULL) {
421 0 : return NT_STATUS_INTERNAL_ERROR;
422 : }
423 :
424 9053 : call->_out_auth_info = (struct dcerpc_auth) {
425 9053 : .auth_type = auth->auth_type,
426 9053 : .auth_level = auth->auth_level,
427 9053 : .auth_context_id = auth->auth_context_id,
428 : };
429 9053 : call->out_auth_info = &call->_out_auth_info;
430 :
431 9053 : return NT_STATUS_OK;
432 : }
433 :
434 : /*
435 : process the final stage of a auth request
436 : */
437 227 : bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call)
438 : {
439 227 : struct ncacn_packet *pkt = &call->pkt;
440 227 : struct dcesrv_auth *auth = call->auth_state;
441 0 : NTSTATUS status;
442 :
443 227 : if (pkt->auth_length == 0) {
444 0 : return false;
445 : }
446 :
447 227 : if (auth->auth_finished) {
448 0 : return false;
449 : }
450 :
451 227 : if (auth->auth_invalid) {
452 0 : return false;
453 : }
454 :
455 : /* We can't work without an existing gensec state */
456 227 : if (auth->gensec_security == NULL) {
457 0 : return false;
458 : }
459 :
460 227 : status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
461 : &call->in_auth_info, NULL, true);
462 227 : 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 224 : if (call->in_auth_info.auth_type != auth->auth_type) {
472 0 : return false;
473 : }
474 :
475 224 : if (call->in_auth_info.auth_level != auth->auth_level) {
476 0 : return false;
477 : }
478 :
479 224 : if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
480 0 : return false;
481 : }
482 :
483 224 : call->_out_auth_info = (struct dcerpc_auth) {
484 224 : .auth_type = auth->auth_type,
485 224 : .auth_level = auth->auth_level,
486 224 : .auth_context_id = auth->auth_context_id,
487 : };
488 224 : call->out_auth_info = &call->_out_auth_info;
489 :
490 224 : 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 6332 : bool dcesrv_auth_alter(struct dcesrv_call_state *call)
499 : {
500 6332 : struct ncacn_packet *pkt = &call->pkt;
501 6332 : struct dcesrv_auth *auth = call->auth_state;
502 117 : NTSTATUS status;
503 :
504 : /* on a pure interface change there is no auth blob */
505 6332 : if (pkt->auth_length == 0) {
506 216 : if (!auth->auth_finished) {
507 0 : return false;
508 : }
509 216 : return true;
510 : }
511 :
512 6116 : if (auth->auth_finished) {
513 3 : call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
514 3 : return false;
515 : }
516 :
517 6113 : status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
518 : &call->in_auth_info, NULL, true);
519 6113 : if (!NT_STATUS_IS_OK(status)) {
520 3 : call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
521 3 : return false;
522 : }
523 :
524 6110 : 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 5929 : 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 5926 : if (auth->auth_invalid) {
542 15 : return false;
543 : }
544 :
545 5911 : if (call->in_auth_info.auth_type != auth->auth_type) {
546 0 : return false;
547 : }
548 :
549 5911 : if (call->in_auth_info.auth_level != auth->auth_level) {
550 0 : return false;
551 : }
552 :
553 5911 : if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
554 0 : return false;
555 : }
556 :
557 5815 : 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 6287 : NTSTATUS dcesrv_auth_prepare_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
565 : {
566 6287 : struct dcesrv_auth *auth = call->auth_state;
567 114 : NTSTATUS status;
568 :
569 6287 : status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
570 6287 : 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 6287 : if (call->pkt.auth_length == 0) {
577 195 : return NT_STATUS_OK;
578 : }
579 :
580 6092 : if (auth->gensec_security == NULL) {
581 0 : return NT_STATUS_INTERNAL_ERROR;
582 : }
583 :
584 6092 : call->_out_auth_info = (struct dcerpc_auth) {
585 6092 : .auth_type = auth->auth_type,
586 6092 : .auth_level = auth->auth_level,
587 6092 : .auth_context_id = auth->auth_context_id,
588 : };
589 6092 : call->out_auth_info = &call->_out_auth_info;
590 :
591 6092 : return NT_STATUS_OK;
592 : }
593 :
594 : /*
595 : check credentials on a packet
596 : */
597 851595 : 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 851595 : struct ncacn_packet *pkt = &call->pkt;
605 851595 : struct dcesrv_auth *auth = call->auth_state;
606 851595 : const struct dcerpc_auth tmp_auth = {
607 851595 : .auth_type = auth->auth_type,
608 851595 : .auth_level = auth->auth_level,
609 851595 : .auth_context_id = auth->auth_context_id,
610 : };
611 6993 : bool check_pkt_auth_fields;
612 6993 : NTSTATUS status;
613 :
614 851595 : if (!auth->auth_started) {
615 12 : return false;
616 : }
617 :
618 851583 : if (!auth->auth_finished) {
619 0 : call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
620 0 : return false;
621 : }
622 :
623 851583 : if (auth->auth_invalid) {
624 27 : return false;
625 : }
626 :
627 851553 : 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 828091 : 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 16555 : check_pkt_auth_fields = false;
643 : }
644 :
645 851553 : 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 851553 : 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 851541 : 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 851541 : 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 851520 : if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
669 0 : call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
670 0 : return false;
671 : }
672 851520 : if (!NT_STATUS_IS_OK(status)) {
673 0 : return false;
674 : }
675 :
676 844530 : return true;
677 : }
678 :
679 : /*
680 : push a signed or sealed dcerpc request packet into a blob
681 : */
682 1123362 : 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 1123362 : struct dcesrv_auth *auth = call->auth_state;
689 1123362 : const struct dcerpc_auth tmp_auth = {
690 1123362 : .auth_type = auth->auth_type,
691 1123362 : .auth_level = auth->auth_level,
692 1123362 : .auth_context_id = auth->auth_context_id,
693 : };
694 6649 : NTSTATUS status;
695 :
696 1123362 : 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 1123362 : return NT_STATUS_IS_OK(status);
703 : }
|