LCOV - code coverage report
Current view: top level - libcli/netlogon - netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 105 159 66.0 %
Date: 2024-04-21 15:09:00 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    CLDAP server structures
       5             : 
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/util/util_file.h"
      24             : #include "../libcli/netlogon/netlogon.h"
      25             : 
      26        3006 : NTSTATUS push_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
      27             :                                          struct netlogon_samlogon_response *response)
      28             : {
      29          36 :         enum ndr_err_code ndr_err;
      30        3006 :         if (response->ntver == NETLOGON_NT_VERSION_1) {
      31         164 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
      32         164 :                                                &response->data.nt4,
      33             :                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40);
      34        2842 :         } else if (response->ntver & NETLOGON_NT_VERSION_5EX) {
      35        2769 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
      36        2769 :                                                &response->data.nt5_ex,
      37             :                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags);
      38          73 :         } else if (response->ntver & NETLOGON_NT_VERSION_5) {
      39          73 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
      40          73 :                                                &response->data.nt5,
      41             :                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE);
      42             :         } else {
      43           0 :                 DEBUG(0, ("Asked to push unknown netlogon response type 0x%02x\n", response->ntver));
      44           0 :                 return NT_STATUS_INVALID_PARAMETER;
      45             :         }
      46        3006 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      47           0 :                 DEBUG(2,("failed to push netlogon response of type 0x%02x\n",
      48             :                          response->ntver));
      49           0 :                 return ndr_map_error2ntstatus(ndr_err);
      50             :         }
      51        3006 :         return NT_STATUS_OK;
      52             : }
      53             : 
      54        2581 : NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
      55             :                                          struct netlogon_samlogon_response *response)
      56             : {
      57          36 :         uint32_t ntver;
      58          36 :         enum ndr_err_code ndr_err;
      59             : 
      60        2581 :         if (data->length < 8) {
      61           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
      62             :         }
      63             : 
      64             :         /* lmnttoken */
      65        2581 :         if (SVAL(data->data, data->length - 4) != 0xffff) {
      66           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
      67             :         }
      68             :         /* lm20token */
      69        2581 :         if (SVAL(data->data, data->length - 2) != 0xffff) {
      70           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
      71             :         }
      72             : 
      73        2581 :         ntver = IVAL(data->data, data->length - 8);
      74             : 
      75        2581 :         if (ntver == NETLOGON_NT_VERSION_1) {
      76         147 :                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
      77         147 :                                                    &response->data.nt4,
      78             :                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40);
      79         147 :                 response->ntver = NETLOGON_NT_VERSION_1;
      80         147 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
      81           0 :                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_NT40,
      82             :                                         &response->data.nt4);
      83             :                 }
      84             : 
      85        2434 :         } else if (ntver & NETLOGON_NT_VERSION_5EX) {
      86          36 :                 struct ndr_pull *ndr;
      87        2361 :                 ndr = ndr_pull_init_blob(data, mem_ctx);
      88        2361 :                 if (!ndr) {
      89           0 :                         return NT_STATUS_NO_MEMORY;
      90             :                 }
      91        2361 :                 ndr_err = ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
      92             :                         ndr, NDR_SCALARS|NDR_BUFFERS, &response->data.nt5_ex,
      93             :                         ntver);
      94        2361 :                 if (ndr->offset < ndr->data_size) {
      95           0 :                         TALLOC_FREE(ndr);
      96             :                         /*
      97             :                          * We need to handle a bug in IPA (at least <= 4.1.2).
      98             :                          *
      99             :                          * They include the ip address information without setting
     100             :                          * NETLOGON_NT_VERSION_5EX_WITH_IP, while using
     101             :                          * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX instead of
     102             :                          * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags.
     103             :                          */
     104           0 :                         ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
     105           0 :                                                    &response->data.nt5,
     106             :                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX);
     107             :                 }
     108        2361 :                 response->ntver = NETLOGON_NT_VERSION_5EX;
     109        2361 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
     110           2 :                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX,
     111             :                                         &response->data.nt5_ex);
     112             :                 }
     113             : 
     114          73 :         } else if (ntver & NETLOGON_NT_VERSION_5) {
     115          73 :                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
     116          73 :                                                    &response->data.nt5,
     117             :                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE);
     118          73 :                 response->ntver = NETLOGON_NT_VERSION_5;
     119          73 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
     120           0 :                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE,
     121             :                                         &response->data.nt5);
     122             :                 }
     123             :         } else {
     124           0 :                 DEBUG(2,("failed to parse netlogon response of type 0x%02x - unknown response type\n",
     125             :                          ntver));
     126           0 :                 dump_data(10, data->data, data->length);
     127           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     128             :         }
     129             : 
     130        2581 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     131           0 :                 DEBUG(2,("failed to parse netlogon response of type 0x%02x\n",
     132             :                          ntver));
     133           0 :                 dump_data(10, data->data, data->length);
     134           0 :                 return ndr_map_error2ntstatus(ndr_err);
     135             :         }
     136             : 
     137        2581 :         return NT_STATUS_OK;
     138             : }
     139             : 
     140        1606 : void map_netlogon_samlogon_response(struct netlogon_samlogon_response *response)
     141             : {
     142          36 :         struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex;
     143        1606 :         switch (response->ntver) {
     144        1333 :         case NETLOGON_NT_VERSION_5EX:
     145        1333 :                 break;
     146          72 :         case NETLOGON_NT_VERSION_5:
     147          72 :                 ZERO_STRUCT(response_5_ex);
     148          72 :                 response_5_ex.command = response->data.nt5.command;
     149          72 :                 response_5_ex.pdc_name = response->data.nt5.pdc_name;
     150          72 :                 response_5_ex.user_name = response->data.nt5.user_name;
     151          72 :                 response_5_ex.domain_name = response->data.nt5.domain_name;
     152          72 :                 response_5_ex.domain_uuid = response->data.nt5.domain_uuid;
     153          72 :                 response_5_ex.forest = response->data.nt5.forest;
     154          72 :                 response_5_ex.dns_domain = response->data.nt5.dns_domain;
     155          72 :                 response_5_ex.pdc_dns_name = response->data.nt5.pdc_dns_name;
     156          72 :                 response_5_ex.sockaddr.pdc_ip = response->data.nt5.pdc_ip;
     157          72 :                 response_5_ex.server_type = response->data.nt5.server_type;
     158          72 :                 response_5_ex.nt_version = response->data.nt5.nt_version;
     159          72 :                 response_5_ex.lmnt_token = response->data.nt5.lmnt_token;
     160          72 :                 response_5_ex.lm20_token = response->data.nt5.lm20_token;
     161          72 :                 response->ntver = NETLOGON_NT_VERSION_5EX;
     162          72 :                 response->data.nt5_ex = response_5_ex;
     163          72 :                 break;
     164             : 
     165         165 :         case NETLOGON_NT_VERSION_1:
     166         165 :                 ZERO_STRUCT(response_5_ex);
     167         165 :                 response_5_ex.command = response->data.nt4.command;
     168         165 :                 response_5_ex.pdc_name = response->data.nt4.pdc_name;
     169         165 :                 response_5_ex.user_name = response->data.nt4.user_name;
     170         165 :                 response_5_ex.domain_name = response->data.nt4.domain_name;
     171         165 :                 response_5_ex.nt_version = response->data.nt4.nt_version;
     172         165 :                 response_5_ex.lmnt_token = response->data.nt4.lmnt_token;
     173         165 :                 response_5_ex.lm20_token = response->data.nt4.lm20_token;
     174         165 :                 response->ntver = NETLOGON_NT_VERSION_5EX;
     175         165 :                 response->data.nt5_ex = response_5_ex;
     176         165 :                 break;
     177             :         }
     178        1606 :         return;
     179             : }
     180             : 
     181          73 : NTSTATUS push_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     182             :                                     struct nbt_netlogon_response *response)
     183             : {
     184           0 :         NTSTATUS status;
     185           0 :         enum ndr_err_code ndr_err;
     186          73 :         switch (response->response_type) {
     187          15 :         case NETLOGON_GET_PDC:
     188          15 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
     189          15 :                                                &response->data.get_pdc,
     190             :                                                (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response_from_pdc);
     191          15 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     192           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     193           0 :                         DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
     194             :                                  (int)data->length, nt_errstr(status)));
     195           0 :                         if (DEBUGLVL(10)) {
     196           0 :                                 (void)file_save("netlogon.dat", data->data, data->length);
     197             :                         }
     198           0 :                         return status;
     199             :                 }
     200          15 :                 status = NT_STATUS_OK;
     201          15 :                 break;
     202          58 :         case NETLOGON_SAMLOGON:
     203          58 :                 status = push_netlogon_samlogon_response(
     204             :                         data, mem_ctx,
     205             :                         &response->data.samlogon);
     206          58 :                 break;
     207           0 :         case NETLOGON_RESPONSE2:
     208           0 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
     209           0 :                                                &response->data.response2,
     210             :                                                (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response2);
     211           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     212           0 :                         return ndr_map_error2ntstatus(ndr_err);
     213             :                 }
     214           0 :                 status = NT_STATUS_OK;
     215           0 :                 break;
     216           0 :         default:
     217           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     218           0 :                 break;
     219             :         }
     220             : 
     221          73 :         return status;
     222             : }
     223             : 
     224             : 
     225          42 : NTSTATUS pull_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     226             :                                          struct nbt_netlogon_response *response)
     227             : {
     228           0 :         NTSTATUS status;
     229           0 :         enum netlogon_command command;
     230           0 :         enum ndr_err_code ndr_err;
     231          42 :         if (data->length < 4) {
     232           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     233             :         }
     234             : 
     235          42 :         command = SVAL(data->data, 0);
     236             : 
     237          42 :         switch (command) {
     238          15 :         case NETLOGON_RESPONSE_FROM_PDC:
     239          15 :                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
     240          15 :                                                    &response->data.get_pdc,
     241             :                                                    (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response_from_pdc);
     242          15 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     243           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     244           0 :                         DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
     245             :                                  (int)data->length, nt_errstr(status)));
     246           0 :                         if (DEBUGLVL(10)) {
     247           0 :                                 (void)file_save("netlogon.dat", data->data, data->length);
     248             :                         }
     249           0 :                         return status;
     250             :                 }
     251          15 :                 status = NT_STATUS_OK;
     252          15 :                 response->response_type = NETLOGON_GET_PDC;
     253          42 :                 break;
     254           0 :         case LOGON_RESPONSE2:
     255           0 :                 ndr_err = ndr_pull_struct_blob(data, mem_ctx, &response->data.response2,
     256             :                         (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response2);
     257           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     258           0 :                         return ndr_map_error2ntstatus(ndr_err);
     259             :                 }
     260           0 :                 status = NT_STATUS_OK;
     261           0 :                 response->response_type = NETLOGON_RESPONSE2;
     262           0 :                 break;
     263          27 :         case LOGON_SAM_LOGON_RESPONSE:
     264             :         case LOGON_SAM_LOGON_PAUSE_RESPONSE:
     265             :         case LOGON_SAM_LOGON_USER_UNKNOWN:
     266             :         case LOGON_SAM_LOGON_RESPONSE_EX:
     267             :         case LOGON_SAM_LOGON_PAUSE_RESPONSE_EX:
     268             :         case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
     269          27 :                 status = pull_netlogon_samlogon_response(
     270             :                         data, mem_ctx,
     271             :                         &response->data.samlogon);
     272          27 :                 response->response_type = NETLOGON_SAMLOGON;
     273          27 :                 break;
     274             : 
     275             :         /* These levels are queries, not responses */
     276           0 :         case LOGON_PRIMARY_QUERY:
     277             :         case LOGON_REQUEST:
     278             :         case NETLOGON_ANNOUNCE_UAS:
     279             :         case LOGON_SAM_LOGON_REQUEST:
     280             :         default:
     281           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     282             :         }
     283             : 
     284          42 :         return status;
     285             : 
     286             : }

Generated by: LCOV version 1.14