LCOV - code coverage report
Current view: top level - source4/nbt_server/dgram - netlogon.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 87 124 70.2 %
Date: 2021-09-23 10:06:22 Functions: 4 6 66.7 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    NBT datagram netlogon server
       5             : 
       6             :    Copyright (C) Andrew Tridgell        2005
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2008
       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 "nbt_server/nbt_server.h"
      25             : #include "lib/socket/socket.h"
      26             : #include <ldb.h>
      27             : #include "dsdb/samdb/samdb.h"
      28             : #include "auth/auth.h"
      29             : #include "param/param.h"
      30             : #include "samba/service_task.h"
      31             : #include "dsdb/samdb/ldb_modules/util.h"
      32             : #include "libcli/security/security.h"
      33             : #include "nbt_server/dgram/proto.h"
      34             : #include "libds/common/roles.h"
      35             : 
      36             : /*
      37             :   reply to a GETDC request
      38             :  */
      39           9 : static NTSTATUS nbtd_netlogon_getdc(struct nbtd_server *nbtsrv,
      40             :                                     struct nbt_name *dst_name,
      41             :                                     struct nbt_netlogon_packet *netlogon,
      42             :                                     TALLOC_CTX *mem_ctx,
      43             :                                     struct nbt_netlogon_response **presponse,
      44             :                                     char **preply_mailslot)
      45             : {
      46             :         struct nbt_netlogon_response_from_pdc *pdc;
      47             :         struct ldb_context *samctx;
      48           9 :         struct nbt_netlogon_response *response = NULL;
      49           9 :         char *reply_mailslot = NULL;
      50             : 
      51             :         /* only answer getdc requests on the PDC or LOGON names */
      52          15 :         if ((dst_name->type != NBT_NAME_PDC) &&
      53           9 :             (dst_name->type != NBT_NAME_LOGON)) {
      54           0 :                 return NT_STATUS_NOT_SUPPORTED;
      55             :         }
      56             : 
      57           9 :         samctx = nbtsrv->sam_ctx;
      58             : 
      59           9 :         if (lpcfg_server_role(nbtsrv->task->lp_ctx) != ROLE_ACTIVE_DIRECTORY_DC
      60           9 :             || !samdb_is_pdc(samctx)) {
      61           0 :                 DEBUG(2, ("Not a PDC, so not processing LOGON_PRIMARY_QUERY\n"));
      62           0 :                 return NT_STATUS_NOT_SUPPORTED;
      63             :         }
      64             : 
      65           9 :         if (strcasecmp_m(dst_name->name,
      66           9 :                          lpcfg_workgroup(nbtsrv->task->lp_ctx)) != 0) {
      67           0 :                 DBG_INFO("GetDC requested for a domain %s that we don't "
      68             :                          "host\n", dst_name->name);
      69           0 :                 return NT_STATUS_NOT_SUPPORTED;
      70             :         }
      71             : 
      72           9 :         reply_mailslot = talloc_strdup(
      73             :                 mem_ctx, netlogon->req.pdc.mailslot_name);
      74           9 :         if (reply_mailslot == NULL) {
      75           0 :                 goto nomem;
      76             :         }
      77             : 
      78             :         /* setup a GETDC reply */
      79           9 :         response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
      80           9 :         if (response == NULL) {
      81           0 :                 goto nomem;
      82             :         }
      83           9 :         response->response_type = NETLOGON_GET_PDC;
      84           9 :         pdc = &response->data.get_pdc;
      85             : 
      86           9 :         pdc->command = NETLOGON_RESPONSE_FROM_PDC;
      87             : 
      88           9 :         pdc->pdc_name = talloc_strdup(
      89           9 :                 response, lpcfg_netbios_name(nbtsrv->task->lp_ctx));
      90           9 :         if (pdc->pdc_name == NULL) {
      91           0 :                 goto nomem;
      92             :         }
      93             : 
      94           9 :         pdc->unicode_pdc_name = pdc->pdc_name;
      95             : 
      96           9 :         pdc->domain_name = talloc_strdup(
      97           9 :                 response, lpcfg_workgroup(nbtsrv->task->lp_ctx));
      98           9 :         if (pdc->domain_name == NULL) {
      99           0 :                 goto nomem;
     100             :         }
     101             : 
     102           9 :         pdc->nt_version       = 1;
     103           9 :         pdc->lmnt_token       = 0xFFFF;
     104           9 :         pdc->lm20_token       = 0xFFFF;
     105             : 
     106           9 :         *presponse = response;
     107           9 :         *preply_mailslot = reply_mailslot;
     108           9 :         return NT_STATUS_OK;
     109             : 
     110           0 : nomem:
     111           0 :         TALLOC_FREE(response);
     112           0 :         TALLOC_FREE(reply_mailslot);
     113           0 :         return NT_STATUS_NO_MEMORY;
     114             : }
     115             : 
     116             : /*
     117             :   reply to a ADS style GETDC request
     118             :  */
     119          21 : static NTSTATUS nbtd_netlogon_samlogon(
     120             :         struct nbtd_server *nbtsrv,
     121             :         struct nbt_name *dst_name,
     122             :         const struct socket_address *src,
     123             :         struct nbt_netlogon_packet *netlogon,
     124             :         TALLOC_CTX *mem_ctx,
     125             :         struct nbt_netlogon_response **presponse,
     126             :         char **preply_mailslot)
     127             : {
     128             :         struct ldb_context *samctx;
     129          21 :         struct dom_sid *sid = NULL;
     130          21 :         struct nbt_netlogon_response *response = NULL;
     131          21 :         char *reply_mailslot = NULL;
     132             :         NTSTATUS status;
     133             : 
     134             :         /* only answer getdc requests on the PDC or LOGON names */
     135          35 :         if ((dst_name->type != NBT_NAME_PDC) &&
     136          21 :             (dst_name->type != NBT_NAME_LOGON)) {
     137           0 :                 return NT_STATUS_NOT_SUPPORTED;
     138             :         }
     139             : 
     140          21 :         samctx = nbtsrv->sam_ctx;
     141             : 
     142          21 :         if (netlogon->req.logon.sid_size != 0) {
     143          12 :                 sid = &netlogon->req.logon.sid;
     144             :         }
     145             : 
     146          21 :         reply_mailslot = talloc_strdup(
     147             :                 mem_ctx, netlogon->req.logon.mailslot_name);
     148          21 :         if (reply_mailslot == NULL) {
     149           0 :                 return NT_STATUS_NO_MEMORY;
     150             :         }
     151             : 
     152          21 :         response = talloc_zero(mem_ctx, struct nbt_netlogon_response);
     153          21 :         if (response == NULL) {
     154           0 :                 TALLOC_FREE(reply_mailslot);
     155           0 :                 return NT_STATUS_NO_MEMORY;
     156             :         }
     157          21 :         response->response_type = NETLOGON_SAMLOGON;
     158             : 
     159          49 :         status = fill_netlogon_samlogon_response(
     160             :                 samctx, response, NULL, dst_name->name, sid, NULL,
     161             :                 netlogon->req.logon.user_name,
     162          21 :                 netlogon->req.logon.acct_control, src->addr,
     163          21 :                 netlogon->req.logon.nt_version, nbtsrv->task->lp_ctx,
     164             :                 &response->data.samlogon, false);
     165          21 :         if (!NT_STATUS_IS_OK(status)) {
     166             :                 struct dom_sid_buf buf;
     167             : 
     168           0 :                 DBG_NOTICE("NBT netlogon query failed domain=%s sid=%s "
     169             :                            "version=%d - %s\n",
     170             :                            dst_name->name,
     171             :                            dom_sid_str_buf(sid, &buf),
     172             :                            netlogon->req.logon.nt_version,
     173             :                            nt_errstr(status));
     174           0 :                 TALLOC_FREE(reply_mailslot);
     175           0 :                 TALLOC_FREE(response);
     176           0 :                 return status;
     177             :         }
     178             : 
     179          21 :         *presponse = response;
     180          21 :         *preply_mailslot = reply_mailslot;
     181          21 :         return NT_STATUS_OK;
     182             : }
     183             : 
     184          30 : static NTSTATUS nbtd_mailslot_netlogon_reply(
     185             :         struct nbtd_interface *iface,
     186             :         struct nbt_dgram_packet *packet,
     187             :         struct socket_address *src,
     188             :         TALLOC_CTX *mem_ctx,
     189             :         struct nbt_netlogon_response **presponse,
     190             :         char **preply_mailslot)
     191             : {
     192             :         struct nbt_netlogon_packet *netlogon;
     193          30 :         struct nbt_name *dst_name = &packet->data.msg.dest_name;
     194          30 :         struct nbt_netlogon_response *response = NULL;
     195             :         struct nbtd_iface_name *iname;
     196          30 :         char *reply_mailslot = NULL;
     197             :         NTSTATUS status;
     198             : 
     199             :         /*
     200             :           see if the we are listening on the destination netbios name
     201             :         */
     202          30 :         iname = nbtd_find_iname(iface, dst_name, 0);
     203          30 :         if (iname == NULL) {
     204           0 :                 return NT_STATUS_BAD_NETWORK_NAME;
     205             :         }
     206             : 
     207          30 :         netlogon = talloc(mem_ctx, struct nbt_netlogon_packet);
     208          30 :         if (netlogon == NULL) {
     209           0 :                 return NT_STATUS_NO_MEMORY;
     210             :         }
     211             : 
     212          30 :         status = dgram_mailslot_netlogon_parse_request(netlogon, packet,
     213             :                                                        netlogon);
     214          30 :         if (!NT_STATUS_IS_OK(status)) {
     215           0 :                 goto failed;
     216             :         }
     217             : 
     218          30 :         switch (netlogon->command) {
     219           9 :         case LOGON_PRIMARY_QUERY:
     220           9 :                 status = nbtd_netlogon_getdc(
     221             :                         iface->nbtsrv, &packet->data.msg.dest_name,
     222             :                         netlogon, mem_ctx, &response, &reply_mailslot);
     223           9 :                 break;
     224          21 :         case LOGON_SAM_LOGON_REQUEST:
     225          21 :                 status = nbtd_netlogon_samlogon(
     226             :                         iface->nbtsrv, &packet->data.msg.dest_name, src,
     227             :                         netlogon, mem_ctx, &response, &reply_mailslot);
     228          21 :                 break;
     229           0 :         default:
     230           0 :                 DEBUG(2,("unknown netlogon op %d from %s:%d\n",
     231             :                          netlogon->command, src->addr, src->port));
     232           0 :                 NDR_PRINT_DEBUG(nbt_netlogon_packet, netlogon);
     233           0 :                 status = NT_STATUS_NOT_SUPPORTED;
     234           0 :                 break;
     235             :         }
     236             : 
     237          30 :         if (!NT_STATUS_IS_OK(status)) {
     238           0 :                 DBG_DEBUG("Calculating reply failed: %s\n",
     239             :                           nt_errstr(status));
     240           0 :                 goto failed;
     241             :         }
     242             : 
     243          30 :         *presponse = response;
     244          30 :         *preply_mailslot = reply_mailslot;
     245          30 :         return NT_STATUS_OK;
     246             : 
     247           0 : failed:
     248           0 :         TALLOC_FREE(reply_mailslot);
     249           0 :         TALLOC_FREE(netlogon);
     250           0 :         return status;
     251             : }
     252             : 
     253             : /*
     254             :   handle incoming netlogon mailslot requests
     255             : */
     256          30 : void nbtd_mailslot_netlogon_handler(struct dgram_mailslot_handler *dgmslot,
     257             :                                     struct nbt_dgram_packet *packet,
     258             :                                     struct socket_address *src)
     259             : {
     260          30 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     261          20 :         struct nbtd_interface *iface =
     262          30 :                 talloc_get_type(dgmslot->private_data, struct nbtd_interface);
     263          30 :         struct nbtd_interface *reply_iface = nbtd_find_reply_iface(
     264          30 :                 iface, src->addr, false);
     265          30 :         struct nbt_netlogon_response *response = NULL;
     266          30 :         char *reply_mailslot = NULL;
     267             : 
     268          30 :         if (reply_iface->ip_address == NULL) {
     269           0 :                 DBG_WARNING("Could not obtain own IP address for datagram "
     270             :                             "socket\n");
     271           0 :                 return;
     272             :         }
     273             : 
     274          30 :         status = nbtd_mailslot_netlogon_reply(
     275             :                 iface, packet, src, dgmslot, &response, &reply_mailslot);
     276             : 
     277          30 :         if (NT_STATUS_IS_OK(status)) {
     278          50 :                 dgram_mailslot_netlogon_reply(
     279             :                         reply_iface->dgmsock, packet,
     280          30 :                         lpcfg_netbios_name(iface->nbtsrv->task->lp_ctx),
     281             :                         reply_mailslot, response);
     282             :         }
     283             : 
     284          30 :         TALLOC_FREE(response);
     285          30 :         TALLOC_FREE(reply_mailslot);
     286             : }

Generated by: LCOV version 1.13