root/libcli/netlogon.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. push_netlogon_samlogon_response
  2. pull_netlogon_samlogon_response
  3. map_netlogon_samlogon_response
  4. push_nbt_netlogon_response
  5. pull_nbt_netlogon_response

   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.h"
  24 
  25 #undef DEBUG
  26 #define DEBUG(x, y)
  27 #undef DEBUGLVL
  28 #define DEBUGLVL(x) false
  29 #undef DEBUGLEVEL
  30 #define DEBUGLEVEL 0
  31 
  32 NTSTATUS push_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  33                                          struct smb_iconv_convenience *iconv_convenience,
  34                                          struct netlogon_samlogon_response *response)
  35 {
  36         enum ndr_err_code ndr_err;
  37         if (response->ntver == NETLOGON_NT_VERSION_1) {
  38                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
  39                                                iconv_convenience,
  40                                                &response->data.nt4,
  41                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_NT40);
  42         } else if (response->ntver & NETLOGON_NT_VERSION_5EX) {
  43                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
  44                                                iconv_convenience,
  45                                                &response->data.nt5_ex,
  46                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags);
  47         } else if (response->ntver & NETLOGON_NT_VERSION_5) {
  48                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
  49                                                iconv_convenience,
  50                                                &response->data.nt5,
  51                                                (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE);
  52         } else {
  53                 DEBUG(0, ("Asked to push unknown netlogon response type 0x%02x\n", response->ntver));
  54                 return NT_STATUS_INVALID_PARAMETER;
  55         }
  56         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
  57                 DEBUG(2,("failed to push netlogon response of type 0x%02x\n",
  58                          response->ntver));
  59                 return ndr_map_error2ntstatus(ndr_err);
  60         }
  61         return NT_STATUS_OK;
  62 }
  63 
  64 NTSTATUS pull_netlogon_samlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
  65                                          struct smb_iconv_convenience *iconv_convenience,
  66                                          struct netlogon_samlogon_response *response)
  67 {
  68         uint32_t ntver;
  69         enum ndr_err_code ndr_err;
  70 
  71         if (data->length < 8) {
  72                 return NT_STATUS_BUFFER_TOO_SMALL;
  73         }
  74 
  75         /* lmnttoken */
  76         if (SVAL(data->data, data->length - 4) != 0xffff) {
  77                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
  78         }
  79         /* lm20token */
  80         if (SVAL(data->data, data->length - 2) != 0xffff) {
  81                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
  82         }
  83 
  84         ntver = IVAL(data->data, data->length - 8);
  85 
  86         if (ntver == NETLOGON_NT_VERSION_1) {
  87                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
  88                                                    iconv_convenience,
  89                                                    &response->data.nt4,
  90                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_NT40);
  91                 response->ntver = NETLOGON_NT_VERSION_1;
  92                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
  93                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_NT40,
  94                                         &response->data.nt4);
  95                 }
  96 
  97         } else if (ntver & NETLOGON_NT_VERSION_5EX) {
  98                 struct ndr_pull *ndr;
  99                 ndr = ndr_pull_init_blob(data, mem_ctx, iconv_convenience);
 100                 if (!ndr) {
 101                         return NT_STATUS_NO_MEMORY;
 102                 }
 103                 ndr_err = ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX_with_flags(
 104                         ndr, NDR_SCALARS|NDR_BUFFERS, &response->data.nt5_ex,
 105                         ntver);
 106                 if (ndr->offset < ndr->data_size) {
 107                         ndr_err = ndr_pull_error(ndr, NDR_ERR_UNREAD_BYTES,
 108                                                  "not all bytes consumed ofs[%u] size[%u]",
 109                                                  ndr->offset, ndr->data_size);
 110                 }
 111                 response->ntver = NETLOGON_NT_VERSION_5EX;
 112                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
 113                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE_EX,
 114                                         &response->data.nt5_ex);
 115                 }
 116 
 117         } else if (ntver & NETLOGON_NT_VERSION_5) {
 118                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
 119                                                    iconv_convenience,
 120                                                    &response->data.nt5,
 121                                                    (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE);
 122                 response->ntver = NETLOGON_NT_VERSION_5;
 123                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && DEBUGLEVEL >= 10) {
 124                         NDR_PRINT_DEBUG(NETLOGON_SAM_LOGON_RESPONSE,
 125                                         &response->data.nt5);
 126                 }
 127         } else {
 128                 DEBUG(2,("failed to parse netlogon response of type 0x%02x - unknown response type\n",
 129                          ntver));
 130                 dump_data(10, data->data, data->length);
 131                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
 132         }
 133 
 134         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 135                 DEBUG(2,("failed to parse netlogon response of type 0x%02x\n",
 136                          ntver));
 137                 dump_data(10, data->data, data->length);
 138                 return ndr_map_error2ntstatus(ndr_err);
 139         }
 140 
 141         return NT_STATUS_OK;
 142 }
 143 
 144 void map_netlogon_samlogon_response(struct netlogon_samlogon_response *response)
     /* [<][>][^][v][top][bottom][index][help] */
 145 {
 146         struct NETLOGON_SAM_LOGON_RESPONSE_EX response_5_ex;
 147         switch (response->ntver) {
 148         case NETLOGON_NT_VERSION_5EX:
 149                 break;
 150         case NETLOGON_NT_VERSION_5:
 151                 ZERO_STRUCT(response_5_ex);
 152                 response_5_ex.command = response->data.nt5.command;
 153                 response_5_ex.pdc_name = response->data.nt5.pdc_name;
 154                 response_5_ex.user_name = response->data.nt5.user_name;
 155                 response_5_ex.domain = response->data.nt5.domain_name;
 156                 response_5_ex.domain_uuid = response->data.nt5.domain_uuid;
 157                 response_5_ex.forest = response->data.nt5.forest;
 158                 response_5_ex.dns_domain = response->data.nt5.dns_domain;
 159                 response_5_ex.pdc_dns_name = response->data.nt5.pdc_dns_name;
 160                 response_5_ex.sockaddr.pdc_ip = response->data.nt5.pdc_ip;
 161                 response_5_ex.server_type = response->data.nt5.server_type;
 162                 response_5_ex.nt_version = response->data.nt5.nt_version;
 163                 response_5_ex.lmnt_token = response->data.nt5.lmnt_token;
 164                 response_5_ex.lm20_token = response->data.nt5.lm20_token;
 165                 response->ntver = NETLOGON_NT_VERSION_5EX;
 166                 response->data.nt5_ex = response_5_ex;
 167                 break;
 168 
 169         case NETLOGON_NT_VERSION_1:
 170                 ZERO_STRUCT(response_5_ex);
 171                 response_5_ex.command = response->data.nt4.command;
 172                 response_5_ex.pdc_name = response->data.nt4.server;
 173                 response_5_ex.user_name = response->data.nt4.user_name;
 174                 response_5_ex.domain = response->data.nt4.domain;
 175                 response_5_ex.nt_version = response->data.nt4.nt_version;
 176                 response_5_ex.lmnt_token = response->data.nt4.lmnt_token;
 177                 response_5_ex.lm20_token = response->data.nt4.lm20_token;
 178                 response->ntver = NETLOGON_NT_VERSION_5EX;
 179                 response->data.nt5_ex = response_5_ex;
 180                 break;
 181         }
 182         return;
 183 }
 184 
 185 NTSTATUS push_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 186                                     struct smb_iconv_convenience *iconv_convenience,
 187                                     struct nbt_netlogon_response *response)
 188 {
 189         NTSTATUS status = NT_STATUS_INVALID_NETWORK_RESPONSE;
 190         enum ndr_err_code ndr_err;
 191         switch (response->response_type) {
 192         case NETLOGON_GET_PDC:
 193                 ndr_err = ndr_push_struct_blob(data, mem_ctx,
 194                                                iconv_convenience,
 195                                                &response->data.get_pdc,
 196                                                (ndr_push_flags_fn_t)ndr_push_nbt_netlogon_response_from_pdc);
 197                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 198                         status = ndr_map_error2ntstatus(ndr_err);
 199                         DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
 200                                  (int)data->length, nt_errstr(status)));
 201                         if (DEBUGLVL(10)) {
 202                                 file_save("netlogon.dat", data->data, data->length);
 203                         }
 204                         return status;
 205                 }
 206                 status = NT_STATUS_OK;
 207                 break;
 208         case NETLOGON_SAMLOGON:
 209                 status = push_netlogon_samlogon_response(
 210                         data, mem_ctx, iconv_convenience,
 211                         &response->data.samlogon);
 212                 break;
 213         }
 214         return status;
 215 }
 216 
 217 
 218 NTSTATUS pull_nbt_netlogon_response(DATA_BLOB *data, TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 219                                          struct smb_iconv_convenience *iconv_convenience,
 220                                          struct nbt_netlogon_response *response)
 221 {
 222         NTSTATUS status = NT_STATUS_INVALID_NETWORK_RESPONSE;
 223         enum netlogon_command command;
 224         enum ndr_err_code ndr_err;
 225         if (data->length < 4) {
 226                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
 227         }
 228 
 229         command = SVAL(data->data, 0);
 230 
 231         switch (command) {
 232         case NETLOGON_RESPONSE_FROM_PDC:
 233                 ndr_err = ndr_pull_struct_blob_all(data, mem_ctx,
 234                                                    iconv_convenience,
 235                                                    &response->data.get_pdc,
 236                                                    (ndr_pull_flags_fn_t)ndr_pull_nbt_netlogon_response_from_pdc);
 237                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 238                         status = ndr_map_error2ntstatus(ndr_err);
 239                         DEBUG(0,("Failed to parse netlogon packet of length %d: %s\n",
 240                                  (int)data->length, nt_errstr(status)));
 241                         if (DEBUGLVL(10)) {
 242                                 file_save("netlogon.dat", data->data, data->length);
 243                         }
 244                         return status;
 245                 }
 246                 status = NT_STATUS_OK;
 247                 response->response_type = NETLOGON_GET_PDC;
 248                 break;
 249         case LOGON_SAM_LOGON_RESPONSE:
 250         case LOGON_SAM_LOGON_PAUSE_RESPONSE:
 251         case LOGON_SAM_LOGON_USER_UNKNOWN:
 252         case LOGON_SAM_LOGON_RESPONSE_EX:
 253         case LOGON_SAM_LOGON_PAUSE_RESPONSE_EX:
 254         case LOGON_SAM_LOGON_USER_UNKNOWN_EX:
 255                 status = pull_netlogon_samlogon_response(
 256                         data, mem_ctx, iconv_convenience,
 257                         &response->data.samlogon);
 258                 response->response_type = NETLOGON_SAMLOGON;
 259                 break;
 260 
 261         /* These levels are queries, not responses */
 262         case LOGON_PRIMARY_QUERY:
 263         case NETLOGON_ANNOUNCE_UAS:
 264         case LOGON_SAM_LOGON_REQUEST:
 265                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
 266         }
 267 
 268         return status;
 269 
 270 }

/* [<][>][^][v][top][bottom][index][help] */