LCOV - code coverage report
Current view: top level - librpc/rpc - dcesrv_auth.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 242 296 81.8 %
Date: 2021-09-23 10:06:22 Functions: 13 13 100.0 %

          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       32235 : static NTSTATUS dcesrv_auth_negotiate_hdr_signing(struct dcesrv_call_state *call,
      35             :                                                   struct ncacn_packet *pkt)
      36             : {
      37       32235 :         struct dcesrv_connection *dce_conn = call->conn;
      38       32235 :         struct dcesrv_auth *a = NULL;
      39             : 
      40       32235 :         if (!(call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN)) {
      41       24999 :                 return NT_STATUS_OK;
      42             :         }
      43             : 
      44        7236 :         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        7236 :         dce_conn->client_hdr_signing = true;
      52        7236 :         dce_conn->negotiated_hdr_signing = dce_conn->support_hdr_signing;
      53             : 
      54        7236 :         if (!dce_conn->negotiated_hdr_signing) {
      55         506 :                 return NT_STATUS_OK;
      56             :         }
      57             : 
      58        6730 :         if (pkt != NULL) {
      59        6730 :                 pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
      60             :         }
      61             : 
      62        6730 :         a = call->conn->default_auth_state;
      63        6730 :         if (a->gensec_security != NULL) {
      64           0 :                 gensec_want_feature(a->gensec_security,
      65             :                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
      66             :         }
      67             : 
      68       13458 :         for (a = call->conn->auth_states; a != NULL; a = a->next) {
      69        6728 :                 if (a->gensec_security == NULL) {
      70           0 :                         continue;
      71             :                 }
      72             : 
      73        6728 :                 gensec_want_feature(a->gensec_security,
      74             :                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
      75             :         }
      76             : 
      77        6730 :         return NT_STATUS_OK;
      78             : }
      79             : 
      80        7790 : static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
      81             : {
      82        7790 :         struct dcesrv_connection *dce_conn = call->conn;
      83        7790 :         struct dcesrv_auth *auth = call->auth_state;
      84        7790 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
      85             :         NTSTATUS status;
      86             : 
      87        7790 :         if (auth->auth_started) {
      88           0 :                 return false;
      89             :         }
      90             : 
      91        7790 :         auth->auth_started = true;
      92             : 
      93        7790 :         if (auth->auth_invalid) {
      94           0 :                 return false;
      95             :         }
      96             : 
      97        7790 :         if (auth->auth_finished) {
      98           0 :                 return false;
      99             :         }
     100             : 
     101        7790 :         if (auth->gensec_security != NULL) {
     102           0 :                 return false;
     103             :         }
     104             : 
     105        7790 :         switch (call->in_auth_info.auth_level) {
     106        7358 :         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        7358 :                 break;
     115           8 :         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           8 :                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
     124           8 :                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
     125           8 :                 auth->auth_context_id = DCERPC_BIND_NAK_REASON_NOT_SPECIFIED;
     126           8 :                 return false;
     127             :         }
     128             : 
     129        7782 :         auth->auth_type = call->in_auth_info.auth_type;
     130        7782 :         auth->auth_level = call->in_auth_info.auth_level;
     131        7782 :         auth->auth_context_id = call->in_auth_info.auth_context_id;
     132             : 
     133        7782 :         status = cb->auth.gensec_prepare(
     134             :                 auth,
     135             :                 call,
     136             :                 &auth->gensec_security,
     137             :                 cb->auth.private_data);
     138        7782 :         if (!NT_STATUS_IS_OK(status)) {
     139           0 :                 DEBUG(1, ("Failed to call samba_server_gensec_start %s\n",
     140             :                           nt_errstr(status)));
     141           0 :                 return false;
     142             :         }
     143             : 
     144             :         /*
     145             :          * We have to call this because we set the target_service for
     146             :          * Kerberos to NULL above, and in any case we wish to log a
     147             :          * more specific service target.
     148             :          *
     149             :          */
     150        7782 :         status = gensec_set_target_service_description(auth->gensec_security,
     151             :                                                        "DCE/RPC");
     152        7782 :         if (!NT_STATUS_IS_OK(status)) {
     153           0 :                 DEBUG(1, ("Failed to call gensec_set_target_service_description %s\n",
     154             :                           nt_errstr(status)));
     155           0 :                 return false;
     156             :         }
     157             : 
     158        7782 :         if (call->conn->remote_address != NULL) {
     159        7782 :                 status = gensec_set_remote_address(auth->gensec_security,
     160        7358 :                                                 call->conn->remote_address);
     161        7782 :                 if (!NT_STATUS_IS_OK(status)) {
     162           0 :                         DEBUG(1, ("Failed to call gensec_set_remote_address() %s\n",
     163             :                                   nt_errstr(status)));
     164           0 :                         return false;
     165             :                 }
     166             :         }
     167             : 
     168        7782 :         if (call->conn->local_address != NULL) {
     169        7782 :                 status = gensec_set_local_address(auth->gensec_security,
     170        7358 :                                                   call->conn->local_address);
     171        7782 :                 if (!NT_STATUS_IS_OK(status)) {
     172           0 :                         DEBUG(1, ("Failed to call gensec_set_local_address() %s\n",
     173             :                                   nt_errstr(status)));
     174           0 :                         return false;
     175             :                 }
     176             :         }
     177             : 
     178        7782 :         status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
     179        7782 :                                                auth->auth_level);
     180        7782 :         if (!NT_STATUS_IS_OK(status)) {
     181           7 :                 const char *backend_name =
     182           7 :                         gensec_get_name_by_authtype(auth->gensec_security,
     183           7 :                                                     auth->auth_type);
     184             : 
     185           7 :                 DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: "
     186             :                           "auth_type=%d (%s), auth_level=%d: %s\n",
     187             :                           (int)auth->auth_type, backend_name,
     188             :                           (int)auth->auth_level,
     189             :                           nt_errstr(status)));
     190             : 
     191             :                 /*
     192             :                  * Setting DCERPC_AUTH_LEVEL_NONE,
     193             :                  * gives the caller the reject_reason
     194             :                  * as auth_context_id.
     195             :                  *
     196             :                  * Note: DCERPC_AUTH_LEVEL_NONE == 1
     197             :                  */
     198           7 :                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
     199           7 :                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
     200           7 :                 if (backend_name != NULL) {
     201           1 :                         auth->auth_context_id =
     202             :                                 DCERPC_BIND_NAK_REASON_INVALID_CHECKSUM;
     203             :                 } else {
     204           6 :                         auth->auth_context_id =
     205             :                                 DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE;
     206             :                 }
     207           7 :                 return false;
     208             :         }
     209             : 
     210        7775 :         if (dce_conn->negotiated_hdr_signing) {
     211           0 :                 gensec_want_feature(auth->gensec_security,
     212             :                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
     213             :         }
     214             : 
     215        7351 :         return true;
     216             : }
     217             : 
     218       27121 : static void dcesrv_default_auth_state_finish_bind(struct dcesrv_call_state *call)
     219             : {
     220       27121 :         SMB_ASSERT(call->pkt.ptype == DCERPC_PKT_BIND);
     221             : 
     222       27121 :         if (call->auth_state == call->conn->default_auth_state) {
     223       19516 :                 return;
     224             :         }
     225             : 
     226        7173 :         if (call->conn->default_auth_state->auth_started) {
     227           0 :                 return;
     228             :         }
     229             : 
     230        7173 :         if (call->conn->default_auth_state->auth_invalid) {
     231           0 :                 return;
     232             :         }
     233             : 
     234        7173 :         call->conn->default_auth_state->auth_type = DCERPC_AUTH_TYPE_NONE;
     235        7173 :         call->conn->default_auth_state->auth_level = DCERPC_AUTH_LEVEL_NONE;
     236        7173 :         call->conn->default_auth_state->auth_context_id = 0;
     237        7173 :         call->conn->default_auth_state->auth_started = true;
     238        7173 :         call->conn->default_auth_state->auth_finished = true;
     239             : 
     240             :         /*
     241             :          *
     242             :          * We defer log_successful_dcesrv_authz_event()
     243             :          * to dcesrv_default_auth_state_prepare_request()
     244             :          *
     245             :          * As we don't want to trigger authz_events
     246             :          * just for alter_context requests without authentication
     247             :          */
     248             : }
     249             : 
     250      380964 : void dcesrv_default_auth_state_prepare_request(struct dcesrv_call_state *call)
     251             : {
     252      380964 :         struct dcesrv_connection *dce_conn = call->conn;
     253      380964 :         struct dcesrv_auth *auth = call->auth_state;
     254      380964 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
     255             : 
     256      380964 :         if (auth->auth_audited) {
     257      289188 :                 return;
     258             :         }
     259             : 
     260       88342 :         if (call->pkt.ptype != DCERPC_PKT_REQUEST) {
     261           0 :                 return;
     262             :         }
     263             : 
     264       88342 :         if (auth != dce_conn->default_auth_state) {
     265       84617 :                 return;
     266             :         }
     267             : 
     268         572 :         if (auth->auth_invalid) {
     269           0 :                 return;
     270             :         }
     271             : 
     272         572 :         if (!auth->auth_finished) {
     273           0 :                 return;
     274             :         }
     275             : 
     276         572 :         if (cb->log.successful_authz == NULL) {
     277           0 :                 return;
     278             :         }
     279             : 
     280         572 :         cb->log.successful_authz(call, cb->log.private_data);
     281             : }
     282             : 
     283             : /*
     284             :   parse any auth information from a dcerpc bind request
     285             :   return false if we can't handle the auth request for some
     286             :   reason (in which case we send a bind_nak)
     287             : */
     288       27136 : bool dcesrv_auth_bind(struct dcesrv_call_state *call)
     289             : {
     290       27136 :         struct ncacn_packet *pkt = &call->pkt;
     291       27136 :         struct dcesrv_auth *auth = call->auth_state;
     292       27136 :         struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks;
     293             :         NTSTATUS status;
     294             : 
     295       27136 :         if (pkt->auth_length == 0) {
     296       19380 :                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
     297       19380 :                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
     298       19380 :                 auth->auth_context_id = 0;
     299       19380 :                 auth->auth_started = true;
     300             : 
     301       19380 :                 if (cb->log.successful_authz != NULL) {
     302       19380 :                         cb->log.successful_authz(call, cb->log.private_data);
     303             :                 }
     304             : 
     305       18948 :                 return true;
     306             :         }
     307             : 
     308        7756 :         status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
     309             :                                           &call->in_auth_info,
     310             :                                           NULL, true);
     311        7756 :         if (!NT_STATUS_IS_OK(status)) {
     312             :                 /*
     313             :                  * Setting DCERPC_AUTH_LEVEL_NONE,
     314             :                  * gives the caller the reject_reason
     315             :                  * as auth_context_id.
     316             :                  *
     317             :                  * Note: DCERPC_AUTH_LEVEL_NONE == 1
     318             :                  */
     319           1 :                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
     320           1 :                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
     321           1 :                 auth->auth_context_id =
     322             :                         DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED;
     323           1 :                 return false;
     324             :         }
     325             : 
     326        7755 :         return dcesrv_auth_prepare_gensec(call);
     327             : }
     328             : 
     329       12883 : NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
     330             : {
     331       12883 :         struct dcesrv_auth *auth = call->auth_state;
     332       12883 :         const char *pdu = "<unknown>";
     333             : 
     334       12883 :         switch (call->pkt.ptype) {
     335        7317 :         case DCERPC_PKT_BIND:
     336        7317 :                 pdu = "BIND";
     337        7317 :                 break;
     338        4987 :         case DCERPC_PKT_ALTER:
     339        4987 :                 pdu = "ALTER";
     340        4987 :                 break;
     341         155 :         case DCERPC_PKT_AUTH3:
     342         155 :                 pdu = "AUTH3";
     343         155 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     344           0 :                         DEBUG(4, ("GENSEC not finished at at %s\n", pdu));
     345           0 :                         return NT_STATUS_RPC_SEC_PKG_ERROR;
     346             :                 }
     347         155 :                 break;
     348           0 :         default:
     349           0 :                 return NT_STATUS_INTERNAL_ERROR;
     350             :         }
     351             : 
     352       12883 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     353        5117 :                 return NT_STATUS_OK;
     354             :         }
     355             : 
     356        7766 :         if (!NT_STATUS_IS_OK(status)) {
     357          15 :                 DEBUG(4, ("GENSEC mech rejected the incoming authentication "
     358             :                           "at %s: %s\n", pdu, nt_errstr(status)));
     359          15 :                 return status;
     360             :         }
     361             : 
     362        7751 :         status = gensec_session_info(auth->gensec_security,
     363             :                                      auth,
     364             :                                      &auth->session_info);
     365        7751 :         if (!NT_STATUS_IS_OK(status)) {
     366           0 :                 DEBUG(1, ("Failed to establish session_info: %s\n",
     367             :                           nt_errstr(status)));
     368           0 :                 return status;
     369             :         }
     370        7751 :         auth->auth_finished = true;
     371             : 
     372        8054 :         if (auth->auth_level == DCERPC_AUTH_LEVEL_CONNECT &&
     373         501 :             !call->conn->got_explicit_auth_level_connect)
     374             :         {
     375         495 :                 call->conn->default_auth_level_connect = auth;
     376             :         }
     377             : 
     378        7751 :         if (call->pkt.ptype != DCERPC_PKT_AUTH3) {
     379        7596 :                 return NT_STATUS_OK;
     380             :         }
     381             : 
     382         155 :         if (call->out_auth_info->credentials.length != 0) {
     383           1 :                 DEBUG(4, ("GENSEC produced output token (len=%zu) at %s\n",
     384             :                           call->out_auth_info->credentials.length, pdu));
     385           1 :                 return NT_STATUS_RPC_SEC_PKG_ERROR;
     386             :         }
     387             : 
     388         154 :         return NT_STATUS_OK;
     389             : }
     390             : 
     391             : /*
     392             :   add any auth information needed in a bind ack, and process the authentication
     393             :   information found in the bind.
     394             : */
     395       27121 : NTSTATUS dcesrv_auth_prepare_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
     396             : {
     397       27121 :         struct dcesrv_connection *dce_conn = call->conn;
     398       27121 :         struct dcesrv_auth *auth = call->auth_state;
     399             :         NTSTATUS status;
     400             : 
     401       27121 :         status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
     402       27121 :         if (!NT_STATUS_IS_OK(status)) {
     403           0 :                 return status;
     404             :         }
     405             : 
     406       27121 :         dce_conn->allow_alter = true;
     407       27121 :         dcesrv_default_auth_state_finish_bind(call);
     408             : 
     409       27121 :         if (call->pkt.auth_length == 0) {
     410       19380 :                 auth->auth_finished = true;
     411       19380 :                 return NT_STATUS_OK;
     412             :         }
     413             : 
     414             :         /* We can't work without an existing gensec state */
     415        7741 :         if (auth->gensec_security == NULL) {
     416           0 :                 return NT_STATUS_INTERNAL_ERROR;
     417             :         }
     418             : 
     419        7741 :         call->_out_auth_info = (struct dcerpc_auth) {
     420        7741 :                 .auth_type = auth->auth_type,
     421        7741 :                 .auth_level = auth->auth_level,
     422        7741 :                 .auth_context_id = auth->auth_context_id,
     423             :         };
     424        7741 :         call->out_auth_info = &call->_out_auth_info;
     425             : 
     426        7741 :         return NT_STATUS_OK;
     427             : }
     428             : 
     429             : /*
     430             :   process the final stage of a auth request
     431             : */
     432         156 : bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call)
     433             : {
     434         156 :         struct ncacn_packet *pkt = &call->pkt;
     435         156 :         struct dcesrv_auth *auth = call->auth_state;
     436             :         NTSTATUS status;
     437             : 
     438         156 :         if (pkt->auth_length == 0) {
     439           0 :                 return false;
     440             :         }
     441             : 
     442         156 :         if (auth->auth_finished) {
     443           0 :                 return false;
     444             :         }
     445             : 
     446             :         /* We can't work without an existing gensec state */
     447         156 :         if (auth->gensec_security == NULL) {
     448           0 :                 return false;
     449             :         }
     450             : 
     451         156 :         status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
     452             :                                           &call->in_auth_info, NULL, true);
     453         156 :         if (!NT_STATUS_IS_OK(status)) {
     454             :                 /*
     455             :                  * Windows returns DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY
     456             :                  * instead of DCERPC_NCA_S_PROTO_ERROR.
     457             :                  */
     458           1 :                 call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY;
     459           1 :                 return false;
     460             :         }
     461             : 
     462         155 :         if (call->in_auth_info.auth_type != auth->auth_type) {
     463           0 :                 return false;
     464             :         }
     465             : 
     466         155 :         if (call->in_auth_info.auth_level != auth->auth_level) {
     467           0 :                 return false;
     468             :         }
     469             : 
     470         155 :         if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
     471           0 :                 return false;
     472             :         }
     473             : 
     474         155 :         call->_out_auth_info = (struct dcerpc_auth) {
     475         155 :                 .auth_type = auth->auth_type,
     476         155 :                 .auth_level = auth->auth_level,
     477         155 :                 .auth_context_id = auth->auth_context_id,
     478             :         };
     479         155 :         call->out_auth_info = &call->_out_auth_info;
     480             : 
     481         155 :         return true;
     482             : }
     483             : 
     484             : /*
     485             :   parse any auth information from a dcerpc alter request
     486             :   return false if we can't handle the auth request for some
     487             :   reason (in which case we send a bind_nak (is this true for here?))
     488             : */
     489        5137 : bool dcesrv_auth_alter(struct dcesrv_call_state *call)
     490             : {
     491        5137 :         struct ncacn_packet *pkt = &call->pkt;
     492        5137 :         struct dcesrv_auth *auth = call->auth_state;
     493             :         NTSTATUS status;
     494             : 
     495             :         /* on a pure interface change there is no auth blob */
     496        5137 :         if (pkt->auth_length == 0) {
     497         144 :                 if (!auth->auth_finished) {
     498           0 :                         return false;
     499             :                 }
     500         144 :                 return true;
     501             :         }
     502             : 
     503        4993 :         if (auth->auth_finished) {
     504           1 :                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
     505           1 :                 return false;
     506             :         }
     507             : 
     508        4992 :         status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
     509             :                                           &call->in_auth_info, NULL, true);
     510        4992 :         if (!NT_STATUS_IS_OK(status)) {
     511           1 :                 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
     512           1 :                 return false;
     513             :         }
     514             : 
     515        4991 :         if (!auth->auth_started) {
     516             :                 bool ok;
     517             : 
     518          35 :                 ok = dcesrv_auth_prepare_gensec(call);
     519          35 :                 if (!ok) {
     520           1 :                         call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
     521           1 :                         return false;
     522             :                 }
     523             : 
     524          34 :                 return true;
     525             :         }
     526             : 
     527        4956 :         if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
     528           0 :                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
     529           0 :                 return false;
     530             :         }
     531             : 
     532        4956 :         if (call->in_auth_info.auth_type != auth->auth_type) {
     533           0 :                 return false;
     534             :         }
     535             : 
     536        4956 :         if (call->in_auth_info.auth_level != auth->auth_level) {
     537           3 :                 return false;
     538             :         }
     539             : 
     540        4953 :         if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
     541           0 :                 return false;
     542             :         }
     543             : 
     544        4953 :         return true;
     545             : }
     546             : 
     547             : /*
     548             :   add any auth information needed in a alter ack, and process the authentication
     549             :   information found in the alter.
     550             : */
     551        5114 : NTSTATUS dcesrv_auth_prepare_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
     552             : {
     553        5114 :         struct dcesrv_auth *auth = call->auth_state;
     554             :         NTSTATUS status;
     555             : 
     556        5114 :         status = dcesrv_auth_negotiate_hdr_signing(call, pkt);
     557        5114 :         if (!NT_STATUS_IS_OK(status)) {
     558           0 :                 return status;
     559             :         }
     560             : 
     561             :         /* on a pure interface change there is no auth_info structure
     562             :            setup */
     563        5114 :         if (call->pkt.auth_length == 0) {
     564         127 :                 return NT_STATUS_OK;
     565             :         }
     566             : 
     567        4987 :         if (auth->gensec_security == NULL) {
     568           0 :                 return NT_STATUS_INTERNAL_ERROR;
     569             :         }
     570             : 
     571        4987 :         call->_out_auth_info = (struct dcerpc_auth) {
     572        4987 :                 .auth_type = auth->auth_type,
     573        4987 :                 .auth_level = auth->auth_level,
     574        4987 :                 .auth_context_id = auth->auth_context_id,
     575             :         };
     576        4987 :         call->out_auth_info = &call->_out_auth_info;
     577             : 
     578        4987 :         return NT_STATUS_OK;
     579             : }
     580             : 
     581             : /*
     582             :   check credentials on a packet
     583             : */
     584      380940 : bool dcesrv_auth_pkt_pull(struct dcesrv_call_state *call,
     585             :                           DATA_BLOB *full_packet,
     586             :                           uint8_t required_flags,
     587             :                           uint8_t optional_flags,
     588             :                           uint8_t payload_offset,
     589             :                           DATA_BLOB *payload_and_verifier)
     590             : {
     591      380940 :         struct ncacn_packet *pkt = &call->pkt;
     592      380940 :         struct dcesrv_auth *auth = call->auth_state;
     593     1324497 :         const struct dcerpc_auth tmp_auth = {
     594      380940 :                 .auth_type = auth->auth_type,
     595      380940 :                 .auth_level = auth->auth_level,
     596      380940 :                 .auth_context_id = auth->auth_context_id,
     597             :         };
     598             :         NTSTATUS status;
     599             : 
     600      380940 :         if (!auth->auth_started) {
     601           8 :                 return false;
     602             :         }
     603             : 
     604      380932 :         if (!auth->auth_finished) {
     605           0 :                 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
     606           0 :                 return false;
     607             :         }
     608             : 
     609      380932 :         if (auth->auth_invalid) {
     610          13 :                 return false;
     611             :         }
     612             : 
     613      380916 :         status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
     614             :                                             auth->gensec_security,
     615             :                                             call,
     616             :                                             pkt->ptype,
     617             :                                             required_flags,
     618             :                                             optional_flags,
     619             :                                             payload_offset,
     620             :                                             payload_and_verifier,
     621             :                                             full_packet,
     622             :                                             pkt);
     623      380916 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
     624           0 :                 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
     625           0 :                 return false;
     626             :         }
     627      380916 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL)) {
     628           0 :                 call->fault_code = DCERPC_NCA_S_UNSUPPORTED_AUTHN_LEVEL;
     629           0 :                 return false;
     630             :         }
     631      380916 :         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
     632           6 :                 call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
     633           6 :                 return false;
     634             :         }
     635      380910 :         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
     636           0 :                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
     637           0 :                 return false;
     638             :         }
     639      380910 :         if (!NT_STATUS_IS_OK(status)) {
     640           0 :                 return false;
     641             :         }
     642             : 
     643      380910 :         return true;
     644             : }
     645             : 
     646             : /*
     647             :    push a signed or sealed dcerpc request packet into a blob
     648             : */
     649      572498 : bool dcesrv_auth_pkt_push(struct dcesrv_call_state *call,
     650             :                           DATA_BLOB *blob, size_t sig_size,
     651             :                           uint8_t payload_offset,
     652             :                           const DATA_BLOB *payload,
     653             :                           const struct ncacn_packet *pkt)
     654             : {
     655      572498 :         struct dcesrv_auth *auth = call->auth_state;
     656     2064749 :         const struct dcerpc_auth tmp_auth = {
     657      572498 :                 .auth_type = auth->auth_type,
     658      572498 :                 .auth_level = auth->auth_level,
     659      572498 :                 .auth_context_id = auth->auth_context_id,
     660             :         };
     661             :         NTSTATUS status;
     662             : 
     663      572498 :         status = dcerpc_ncacn_push_pkt_auth(&tmp_auth,
     664             :                                             auth->gensec_security,
     665             :                                             call, blob, sig_size,
     666             :                                             payload_offset,
     667             :                                             payload,
     668             :                                             pkt);
     669      572498 :         return NT_STATUS_IS_OK(status);
     670             : }

Generated by: LCOV version 1.13