LCOV - code coverage report
Current view: top level - libcli/netlogon - netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 105 159 66.0 %
Date: 2024-02-28 12:06:22 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 "../libcli/netlogon/netlogon.h"
      24             : 
      25        2922 : NTSTATUS push_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
      26             :                                          struct netlogon_samlogon_response *response)
      27             : {
      28          36 :         enum ndr_err_code ndr_err;
      29        2922 :         if (response->ntver == NETLOGON_NT_VERSION_1) {
      30         158 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
      31         158 :                                                &response->data.nt4,
      32             :                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40);
      33        2764 :         } else if (response->ntver & NETLOGON_NT_VERSION_5EX) {
      34        2691 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
      35        2691 :                                                &response->data.nt5_ex,
      36             :                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags);
      37          73 :         } else if (response->ntver & NETLOGON_NT_VERSION_5) {
      38          73 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
      39          73 :                                                &response->data.nt5,
      40             :                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE);
      41             :         } else {
      42           0 :                 DEBUG(0, ("Asked to push unknown netlogon response type 0x%02x\n", response->ntver));
      43           0 :                 return NT_STATUS_INVALID_PARAMETER;
      44             :         }
      45        2922 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      46           0 :                 DEBUG(2,("failed to push netlogon response of type 0x%02x\n",
      47             :                          response->ntver));
      48           0 :                 return ndr_map_error2ntstatus(ndr_err);
      49             :         }
      50        2922 :         return NT_STATUS_OK;
      51             : }
      52             : 
      53        2507 : NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
      54             :                                          struct netlogon_samlogon_response *response)
      55             : {
      56          36 :         uint32_t ntver;
      57          36 :         enum ndr_err_code ndr_err;
      58             : 
      59        2507 :         if (data->length < 8) {
      60           0 :                 return NT_STATUS_BUFFER_TOO_SMALL;
      61             :         }
      62             : 
      63             :         /* lmnttoken */
      64        2507 :         if (SVAL(data->data, data->length - 4) != 0xffff) {
      65           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
      66             :         }
      67             :         /* lm20token */
      68        2507 :         if (SVAL(data->data, data->length - 2) != 0xffff) {
      69           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
      70             :         }
      71             : 
      72        2507 :         ntver = IVAL(data->data, data->length - 8);
      73             : 
      74        2507 :         if (ntver == NETLOGON_NT_VERSION_1) {
      75         145 :                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
      76         145 :                                                    &response->data.nt4,
      77             :                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40);
      78         145 :                 response->ntver = NETLOGON_NT_VERSION_1;
      79         145 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
      80           0 :                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_NT40,
      81             :                                         &response->data.nt4);
      82             :                 }
      83             : 
      84        2362 :         } else if (ntver & NETLOGON_NT_VERSION_5EX) {
      85          36 :                 struct ndr_pull *ndr;
      86        2289 :                 ndr = ndr_pull_init_blob(data, mem_ctx);
      87        2289 :                 if (!ndr) {
      88           0 :                         return NT_STATUS_NO_MEMORY;
      89             :                 }
      90        2289 :                 ndr_err = ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
      91             :                         ndr, NDR_SCALARS|NDR_BUFFERS, &response->data.nt5_ex,
      92             :                         ntver);
      93        2289 :                 if (ndr->offset < ndr->data_size) {
      94           0 :                         TALLOC_FREE(ndr);
      95             :                         /*
      96             :                          * We need to handle a bug in IPA (at least <= 4.1.2).
      97             :                          *
      98             :                          * They include the ip address information without setting
      99             :                          * NETLOGON_NT_VERSION_5EX_WITH_IP, while using
     100             :                          * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX instead of
     101             :                          * ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags.
     102             :                          */
     103           0 :                         ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
     104           0 :                                                    &response->data.nt5,
     105             :                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX);
     106             :                 }
     107        2289 :                 response->ntver = NETLOGON_NT_VERSION_5EX;
     108        2289 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
     109           2 :                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX,
     110             :                                         &response->data.nt5_ex);
     111             :                 }
     112             : 
     113          73 :         } else if (ntver & NETLOGON_NT_VERSION_5) {
     114          73 :                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
     115          73 :                                                    &response->data.nt5,
     116             :                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE);
     117          73 :                 response->ntver = NETLOGON_NT_VERSION_5;
     118          73 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
     119           0 :                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE,
     120             :                                         &response->data.nt5);
     121             :                 }
     122             :         } else {
     123           0 :                 DEBUG(2,("failed to parse netlogon response of type 0x%02x - unknown response type\n",
     124             :                          ntver));
     125           0 :                 dump_data(10, data->data, data->length);
     126           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     127             :         }
     128             : 
     129        2507 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     130           0 :                 DEBUG(2,("failed to parse netlogon response of type 0x%02x\n",
     131             :                          ntver));
     132           0 :                 dump_data(10, data->data, data->length);
     133           0 :                 return ndr_map_error2ntstatus(ndr_err);
     134             :         }
     135             : 
     136        2507 :         return NT_STATUS_OK;
     137             : }
     138             : 
     139        1604 : void map_netlogon_samlogon_response(struct netlogon_samlogon_response *response)
     140             : {
     141          36 :         struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex;
     142        1604 :         switch (response->ntver) {
     143        1333 :         case NETLOGON_NT_VERSION_5EX:
     144        1333 :                 break;
     145          72 :         case NETLOGON_NT_VERSION_5:
     146          72 :                 ZERO_STRUCT(response_5_ex);
     147          72 :                 response_5_ex.command = response->data.nt5.command;
     148          72 :                 response_5_ex.pdc_name = response->data.nt5.pdc_name;
     149          72 :                 response_5_ex.user_name = response->data.nt5.user_name;
     150          72 :                 response_5_ex.domain_name = response->data.nt5.domain_name;
     151          72 :                 response_5_ex.domain_uuid = response->data.nt5.domain_uuid;
     152          72 :                 response_5_ex.forest = response->data.nt5.forest;
     153          72 :                 response_5_ex.dns_domain = response->data.nt5.dns_domain;
     154          72 :                 response_5_ex.pdc_dns_name = response->data.nt5.pdc_dns_name;
     155          72 :                 response_5_ex.sockaddr.pdc_ip = response->data.nt5.pdc_ip;
     156          72 :                 response_5_ex.server_type = response->data.nt5.server_type;
     157          72 :                 response_5_ex.nt_version = response->data.nt5.nt_version;
     158          72 :                 response_5_ex.lmnt_token = response->data.nt5.lmnt_token;
     159          72 :                 response_5_ex.lm20_token = response->data.nt5.lm20_token;
     160          72 :                 response->ntver = NETLOGON_NT_VERSION_5EX;
     161          72 :                 response->data.nt5_ex = response_5_ex;
     162          72 :                 break;
     163             : 
     164         163 :         case NETLOGON_NT_VERSION_1:
     165         163 :                 ZERO_STRUCT(response_5_ex);
     166         163 :                 response_5_ex.command = response->data.nt4.command;
     167         163 :                 response_5_ex.pdc_name = response->data.nt4.pdc_name;
     168         163 :                 response_5_ex.user_name = response->data.nt4.user_name;
     169         163 :                 response_5_ex.domain_name = response->data.nt4.domain_name;
     170         163 :                 response_5_ex.nt_version = response->data.nt4.nt_version;
     171         163 :                 response_5_ex.lmnt_token = response->data.nt4.lmnt_token;
     172         163 :                 response_5_ex.lm20_token = response->data.nt4.lm20_token;
     173         163 :                 response->ntver = NETLOGON_NT_VERSION_5EX;
     174         163 :                 response->data.nt5_ex = response_5_ex;
     175         163 :                 break;
     176             :         }
     177        1604 :         return;
     178             : }
     179             : 
     180          52 : NTSTATUS push_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     181             :                                     struct nbt_netlogon_response *response)
     182             : {
     183           0 :         NTSTATUS status;
     184           0 :         enum ndr_err_code ndr_err;
     185          52 :         switch (response->response_type) {
     186          11 :         case NETLOGON_GET_PDC:
     187          11 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
     188          11 :                                                &response->data.get_pdc,
     189             :                                                (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response_from_pdc);
     190          11 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     191           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     192           0 :                         DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
     193             :                                  (int)data->length, nt_errstr(status)));
     194           0 :                         if (DEBUGLVL(10)) {
     195           0 :                                 (void)file_save("netlogon.dat", data->data, data->length);
     196             :                         }
     197           0 :                         return status;
     198             :                 }
     199          11 :                 status = NT_STATUS_OK;
     200          11 :                 break;
     201          41 :         case NETLOGON_SAMLOGON:
     202          41 :                 status = push_netlogon_samlogon_response(
     203             :                         data, mem_ctx,
     204             :                         &response->data.samlogon);
     205          41 :                 break;
     206           0 :         case NETLOGON_RESPONSE2:
     207           0 :                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
     208           0 :                                                &response->data.response2,
     209             :                                                (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response2);
     210           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     211           0 :                         return ndr_map_error2ntstatus(ndr_err);
     212             :                 }
     213           0 :                 status = NT_STATUS_OK;
     214           0 :                 break;
     215           0 :         default:
     216           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     217           0 :                 break;
     218             :         }
     219             : 
     220          52 :         return status;
     221             : }
     222             : 
     223             : 
     224          36 : NTSTATUS pull_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     225             :                                          struct nbt_netlogon_response *response)
     226             : {
     227           0 :         NTSTATUS status;
     228           0 :         enum netlogon_command command;
     229           0 :         enum ndr_err_code ndr_err;
     230          36 :         if (data->length < 4) {
     231           0 :                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
     232             :         }
     233             : 
     234          36 :         command = SVAL(data->data, 0);
     235             : 
     236          36 :         switch (command) {
     237          11 :         case NETLOGON_RESPONSE_FROM_PDC:
     238          11 :                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
     239          11 :                                                    &response->data.get_pdc,
     240             :                                                    (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response_from_pdc);
     241          11 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     242           0 :                         status = ndr_map_error2ntstatus(ndr_err);
     243           0 :                         DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
     244             :                                  (int)data->length, nt_errstr(status)));
     245           0 :                         if (DEBUGLVL(10)) {
     246           0 :                                 (void)file_save("netlogon.dat", data->data, data->length);
     247             :                         }
     248           0 :                         return status;
     249             :                 }
     250          11 :                 status = NT_STATUS_OK;
     251          11 :                 response->response_type = NETLOGON_GET_PDC;
     252          36 :                 break;
     253           0 :         case LOGON_RESPONSE2:
     254           0 :                 ndr_err = ndr_pull_struct_blob(data, mem_ctx, &response->data.response2,
     255             :                         (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response2);
     256           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     257           0 :                         return ndr_map_error2ntstatus(ndr_err);
     258             :                 }
     259           0 :                 status = NT_STATUS_OK;
     260           0 :                 response->response_type = NETLOGON_RESPONSE2;
     261           0 :                 break;
     262          25 :         case LOGON_SAM_LOGON_RESPONSE:
     263             :         case LOGON_SAM_LOGON_PAUSE_RESPONSE:
     264             :         case LOGON_SAM_LOGON_USER_UNKNOWN:
     265             :         case LOGON_SAM_LOGON_RESPONSE_EX:
     266             :         case LOGON_SAM_LOGON_PAUSE_RESPONSE_EX:
     267             :         case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
     268          25 :                 status = pull_netlogon_samlogon_response(
     269             :                         data, mem_ctx,
     270             :                         &response->data.samlogon);
     271          25 :                 response->response_type = NETLOGON_SAMLOGON;
     272          25 :                 break;
     273             : 
     274             :         /* These levels are queries, not responses */
     275           0 :         case LOGON_PRIMARY_QUERY:
     276             :         case LOGON_REQUEST:
     277             :         case NETLOGON_ANNOUNCE_UAS:
     278             :         case LOGON_SAM_LOGON_REQUEST:
     279             :         default:
     280           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
     281             :         }
     282             : 
     283          36 :         return status;
     284             : 
     285             : }

Generated by: LCOV version 1.14