LCOV - code coverage report
Current view: top level - librpc/rpc - dcesrv_auth.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 261 318 82.1 %
Date: 2024-04-21 15:09:00 Functions: 12 12 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       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             : }

Generated by: LCOV version 1.14