LCOV - code coverage report
Current view: top level - auth/gensec - ncalrpc.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 107 164 65.2 %
Date: 2024-05-31 13:13:24 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    dcerpc ncalrpc as system operations
       5             : 
       6             :    Copyright (C) 2014      Andreas Schneider <asn@samba.org>
       7             :    Copyright (C) 2014      Stefan Metzmacher <metze@samba.org>
       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 <tevent.h>
      25             : #include "lib/util/tevent_ntstatus.h"
      26             : #include "auth/auth.h"
      27             : #include "auth/gensec/gensec.h"
      28             : #include "auth/gensec/gensec_internal.h"
      29             : #include "librpc/gen_ndr/dcerpc.h"
      30             : #include "lib/param/param.h"
      31             : #include "tsocket.h"
      32             : 
      33             : #undef DBGC_CLASS
      34             : #define DBGC_CLASS DBGC_AUTH
      35             : 
      36             : _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx);
      37             : 
      38             : struct gensec_ncalrpc_state {
      39             :         enum {
      40             :                 GENSEC_NCALRPC_START,
      41             :                 GENSEC_NCALRPC_MORE,
      42             :                 GENSEC_NCALRPC_DONE,
      43             :                 GENSEC_NCALRPC_ERROR,
      44             :         } step;
      45             : 
      46             :         struct auth_user_info_dc *user_info_dc;
      47             : };
      48             : 
      49         576 : static NTSTATUS gensec_ncalrpc_client_start(struct gensec_security *gensec_security)
      50             : {
      51           8 :         struct gensec_ncalrpc_state *state;
      52             : 
      53         576 :         state = talloc_zero(gensec_security,
      54             :                             struct gensec_ncalrpc_state);
      55         576 :         if (state == NULL) {
      56           0 :                 return NT_STATUS_NO_MEMORY;
      57             :         }
      58         576 :         gensec_security->private_data = state;
      59             : 
      60         576 :         state->step = GENSEC_NCALRPC_START;
      61         576 :         return NT_STATUS_OK;
      62             : }
      63             : 
      64         575 : static NTSTATUS gensec_ncalrpc_server_start(struct gensec_security *gensec_security)
      65             : {
      66           8 :         struct gensec_ncalrpc_state *state;
      67             : 
      68         575 :         state = talloc_zero(gensec_security,
      69             :                             struct gensec_ncalrpc_state);
      70         575 :         if (state == NULL) {
      71           0 :                 return NT_STATUS_NO_MEMORY;
      72             :         }
      73         575 :         gensec_security->private_data = state;
      74             : 
      75         575 :         state->step = GENSEC_NCALRPC_START;
      76         575 :         return NT_STATUS_OK;
      77             : }
      78             : 
      79             : struct gensec_ncalrpc_update_state {
      80             :         NTSTATUS status;
      81             :         DATA_BLOB out;
      82             : };
      83             : 
      84             : static NTSTATUS gensec_ncalrpc_update_internal(
      85             :                                 struct gensec_security *gensec_security,
      86             :                                 TALLOC_CTX *mem_ctx,
      87             :                                 const DATA_BLOB in,
      88             :                                 DATA_BLOB *out);
      89             : 
      90        1727 : static struct tevent_req *gensec_ncalrpc_update_send(TALLOC_CTX *mem_ctx,
      91             :                                         struct tevent_context *ev,
      92             :                                         struct gensec_security *gensec_security,
      93             :                                         const DATA_BLOB in)
      94             : {
      95          24 :         struct tevent_req *req;
      96        1727 :         struct gensec_ncalrpc_update_state *state = NULL;
      97          24 :         NTSTATUS status;
      98             : 
      99        1727 :         req = tevent_req_create(mem_ctx, &state,
     100             :                                 struct gensec_ncalrpc_update_state);
     101        1727 :         if (req == NULL) {
     102           0 :                 return NULL;
     103             :         }
     104             : 
     105        1751 :         status = gensec_ncalrpc_update_internal(gensec_security,
     106             :                                                 state, in,
     107        1727 :                                                 &state->out);
     108        1727 :         state->status = status;
     109        1727 :         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     110         576 :                 status = NT_STATUS_OK;
     111             :         }
     112        1727 :         if (tevent_req_nterror(req, status)) {
     113           0 :                 return tevent_req_post(req, ev);
     114             :         }
     115             : 
     116        1727 :         tevent_req_done(req);
     117        1727 :         return tevent_req_post(req, ev);
     118             : }
     119             : 
     120        1727 : static NTSTATUS gensec_ncalrpc_update_internal(
     121             :                                 struct gensec_security *gensec_security,
     122             :                                 TALLOC_CTX *mem_ctx,
     123             :                                 const DATA_BLOB in,
     124             :                                 DATA_BLOB *out)
     125             : {
     126          24 :         struct gensec_ncalrpc_state *state =
     127        1727 :                 talloc_get_type_abort(gensec_security->private_data,
     128             :                 struct gensec_ncalrpc_state);
     129        1727 :         DATA_BLOB magic_req = data_blob_string_const("NCALRPC_AUTH_TOKEN");
     130        1727 :         DATA_BLOB magic_ok = data_blob_string_const("NCALRPC_AUTH_OK");
     131        1727 :         DATA_BLOB magic_fail = data_blob_string_const("NCALRPC_AUTH_FAIL");
     132        1727 :         char *unix_path = NULL;
     133          24 :         int cmp;
     134          24 :         NTSTATUS status;
     135             : 
     136        1727 :         *out = data_blob_null;
     137             : 
     138        1727 :         if (state->step >= GENSEC_NCALRPC_DONE) {
     139           0 :                 return NT_STATUS_INVALID_PARAMETER;
     140             :         }
     141             : 
     142        1727 :         switch (gensec_security->gensec_role) {
     143        1152 :         case GENSEC_CLIENT:
     144        1152 :                 switch (state->step) {
     145         576 :                 case GENSEC_NCALRPC_START:
     146         576 :                         *out = data_blob_dup_talloc(mem_ctx, magic_req);
     147         576 :                         if (out->data == NULL) {
     148           0 :                                 state->step = GENSEC_NCALRPC_ERROR;
     149           0 :                                 return NT_STATUS_NO_MEMORY;
     150             :                         }
     151             : 
     152         576 :                         state->step = GENSEC_NCALRPC_MORE;
     153         576 :                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
     154             : 
     155         576 :                 case GENSEC_NCALRPC_MORE:
     156         576 :                         cmp = data_blob_cmp(&in, &magic_ok);
     157         576 :                         if (cmp != 0) {
     158           0 :                                 state->step = GENSEC_NCALRPC_ERROR;
     159           0 :                                 return NT_STATUS_LOGON_FAILURE;
     160             :                         }
     161             : 
     162         576 :                         state->step = GENSEC_NCALRPC_DONE;
     163         576 :                         return NT_STATUS_OK;
     164             : 
     165           0 :                 case GENSEC_NCALRPC_DONE:
     166             :                 case GENSEC_NCALRPC_ERROR:
     167           0 :                         break;
     168             :                 }
     169             : 
     170           0 :                 state->step = GENSEC_NCALRPC_ERROR;
     171           0 :                 return NT_STATUS_INTERNAL_ERROR;
     172             : 
     173         575 :         case GENSEC_SERVER:
     174         575 :                 if (state->step != GENSEC_NCALRPC_START) {
     175           0 :                         state->step = GENSEC_NCALRPC_ERROR;
     176           0 :                         return NT_STATUS_INTERNAL_ERROR;
     177             :                 }
     178             : 
     179         575 :                 cmp = data_blob_cmp(&in, &magic_req);
     180         575 :                 if (cmp != 0) {
     181           0 :                         state->step = GENSEC_NCALRPC_ERROR;
     182           0 :                         *out = data_blob_dup_talloc(mem_ctx, magic_fail);
     183           0 :                         if (out->data == NULL) {
     184           0 :                                 return NT_STATUS_NO_MEMORY;
     185             :                         }
     186           0 :                         return NT_STATUS_LOGON_FAILURE;
     187             :                 }
     188             : 
     189         575 :                 if (gensec_security->remote_addr == NULL) {
     190           0 :                         state->step = GENSEC_NCALRPC_ERROR;
     191           0 :                         *out = data_blob_dup_talloc(mem_ctx, magic_fail);
     192           0 :                         if (out->data == NULL) {
     193           0 :                                 return NT_STATUS_NO_MEMORY;
     194             :                         }
     195           0 :                         return NT_STATUS_LOGON_FAILURE;
     196             :                 }
     197             : 
     198         575 :                 unix_path = tsocket_address_unix_path(gensec_security->remote_addr,
     199             :                                                       state);
     200         575 :                 if (unix_path == NULL) {
     201           0 :                         state->step = GENSEC_NCALRPC_ERROR;
     202           0 :                         *out = data_blob_dup_talloc(mem_ctx, magic_fail);
     203           0 :                         if (out->data == NULL) {
     204           0 :                                 return NT_STATUS_NO_MEMORY;
     205             :                         }
     206           0 :                         return NT_STATUS_LOGON_FAILURE;
     207             :                 }
     208             : 
     209         575 :                 cmp = strcmp(unix_path, AS_SYSTEM_MAGIC_PATH_TOKEN);
     210         575 :                 TALLOC_FREE(unix_path);
     211         575 :                 if (cmp != 0) {
     212           0 :                         state->step = GENSEC_NCALRPC_ERROR;
     213           0 :                         *out = data_blob_dup_talloc(mem_ctx, magic_fail);
     214           0 :                         if (out->data == NULL) {
     215           0 :                                 return NT_STATUS_NO_MEMORY;
     216             :                         }
     217           0 :                         return NT_STATUS_LOGON_FAILURE;
     218             :                 }
     219             : 
     220         575 :                 status = auth_system_user_info_dc(state,
     221         575 :                                 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
     222             :                                 &state->user_info_dc);
     223         575 :                 if (!NT_STATUS_IS_OK(status)) {
     224           0 :                         state->step = GENSEC_NCALRPC_ERROR;
     225           0 :                         *out = data_blob_dup_talloc(mem_ctx, magic_fail);
     226           0 :                         if (out->data == NULL) {
     227           0 :                                 return NT_STATUS_NO_MEMORY;
     228             :                         }
     229           0 :                         return status;
     230             :                 }
     231             : 
     232         575 :                 *out = data_blob_dup_talloc(mem_ctx, magic_ok);
     233         575 :                 if (out->data == NULL) {
     234           0 :                         state->step = GENSEC_NCALRPC_ERROR;
     235           0 :                         return NT_STATUS_NO_MEMORY;
     236             :                 }
     237             : 
     238         575 :                 state->step = GENSEC_NCALRPC_DONE;
     239         575 :                 return NT_STATUS_OK;
     240             :         }
     241             : 
     242           0 :         state->step = GENSEC_NCALRPC_ERROR;
     243           0 :         return NT_STATUS_INTERNAL_ERROR;
     244             : }
     245             : 
     246        1727 : static NTSTATUS gensec_ncalrpc_update_recv(struct tevent_req *req,
     247             :                                            TALLOC_CTX *out_mem_ctx,
     248             :                                            DATA_BLOB *out)
     249             : {
     250          24 :         struct gensec_ncalrpc_update_state *state =
     251        1727 :                 tevent_req_data(req,
     252             :                 struct gensec_ncalrpc_update_state);
     253          24 :         NTSTATUS status;
     254             : 
     255        1727 :         *out = data_blob_null;
     256             : 
     257        1727 :         if (tevent_req_is_nterror(req, &status)) {
     258           0 :                 tevent_req_received(req);
     259           0 :                 return status;
     260             :         }
     261             : 
     262        1727 :         status = state->status;
     263        1727 :         talloc_steal(out_mem_ctx, state->out.data);
     264        1727 :         *out = state->out;
     265        1727 :         tevent_req_received(req);
     266        1727 :         return status;
     267             : }
     268             : 
     269         575 : static NTSTATUS gensec_ncalrpc_session_info(struct gensec_security *gensec_security,
     270             :                                             TALLOC_CTX *mem_ctx,
     271             :                                             struct auth_session_info **psession_info)
     272             : {
     273           8 :         struct gensec_ncalrpc_state *state =
     274         575 :                 talloc_get_type_abort(gensec_security->private_data,
     275             :                 struct gensec_ncalrpc_state);
     276         575 :         struct auth4_context *auth_ctx = gensec_security->auth_context;
     277         575 :         struct auth_session_info *session_info = NULL;
     278         575 :         uint32_t session_info_flags = 0;
     279           8 :         NTSTATUS status;
     280             : 
     281         575 :         if (gensec_security->gensec_role != GENSEC_SERVER) {
     282           0 :                 return NT_STATUS_INVALID_PARAMETER;
     283             :         }
     284             : 
     285         575 :         if (state->step != GENSEC_NCALRPC_DONE) {
     286           0 :                 return NT_STATUS_INVALID_PARAMETER;
     287             :         }
     288             : 
     289         575 :         if (auth_ctx == NULL) {
     290           0 :                 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
     291           0 :                 return NT_STATUS_INTERNAL_ERROR;
     292             :         }
     293             : 
     294         575 :         if (auth_ctx->generate_session_info == NULL) {
     295           0 :                 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
     296           0 :                 return NT_STATUS_INTERNAL_ERROR;
     297             :         }
     298             : 
     299         575 :         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
     300           0 :                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
     301             :         }
     302             : 
     303         575 :         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
     304             : 
     305         575 :         status = auth_ctx->generate_session_info(
     306             :                                 auth_ctx,
     307             :                                 mem_ctx,
     308         567 :                                 state->user_info_dc,
     309         575 :                                 state->user_info_dc->info->account_name,
     310             :                                 session_info_flags,
     311             :                                 &session_info);
     312         575 :         if (!NT_STATUS_IS_OK(status)) {
     313           0 :                 return status;
     314             :         }
     315             : 
     316         575 :         *psession_info = session_info;
     317         575 :         return NT_STATUS_OK;
     318             : }
     319             : 
     320             : /* We have no features */
     321        2651 : static bool gensec_ncalrpc_have_feature(struct gensec_security *gensec_security,
     322             :                                  uint32_t feature)
     323             : {
     324        2651 :         if (feature & GENSEC_FEATURE_DCE_STYLE) {
     325           0 :                 return true;
     326             :         }
     327             : 
     328        2613 :         return false;
     329             : }
     330             : 
     331             : static const struct gensec_security_ops gensec_ncalrpc_security_ops = {
     332             :         .name           = "ncalrpc_as_system",
     333             :         .auth_type      = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
     334             :         .client_start   = gensec_ncalrpc_client_start,
     335             :         .server_start   = gensec_ncalrpc_server_start,
     336             :         .update_send    = gensec_ncalrpc_update_send,
     337             :         .update_recv    = gensec_ncalrpc_update_recv,
     338             :         .session_info   = gensec_ncalrpc_session_info,
     339             :         .have_feature   = gensec_ncalrpc_have_feature,
     340             :         .enabled        = true,
     341             :         .priority       = GENSEC_EXTERNAL,
     342             : };
     343             : 
     344       53161 : _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx)
     345             : {
     346        1228 :         NTSTATUS status;
     347             : 
     348       53161 :         status = gensec_register(ctx, &gensec_ncalrpc_security_ops);
     349       53161 :         if (!NT_STATUS_IS_OK(status)) {
     350           0 :                 DEBUG(0, ("Failed to register '%s' gensec backend!\n",
     351             :                           gensec_ncalrpc_security_ops.name));
     352           0 :                 return status;
     353             :         }
     354             : 
     355       53161 :         return status;
     356             : }

Generated by: LCOV version 1.14