LCOV - code coverage report
Current view: top level - source4/cldap_server - cldap_server.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 57 91 62.6 %
Date: 2024-06-13 04:01:37 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    CLDAP server task
       5             : 
       6             :    Copyright (C) Andrew Tridgell        2005
       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 <talloc.h>
      24             : #include "lib/messaging/irpc.h"
      25             : #include "samba/service_task.h"
      26             : #include "samba/service.h"
      27             : #include "cldap_server/cldap_server.h"
      28             : #include "system/network.h"
      29             : #include "lib/socket/netif.h"
      30             : #include <ldb.h>
      31             : #include <ldb_errors.h>
      32             : #include "dsdb/samdb/samdb.h"
      33             : #include "ldb_wrap.h"
      34             : #include "auth/auth.h"
      35             : #include "param/param.h"
      36             : #include "../lib/tsocket/tsocket.h"
      37             : #include "libds/common/roles.h"
      38             : 
      39             : NTSTATUS server_service_cldapd_init(TALLOC_CTX *);
      40             : 
      41             : /*
      42             :   handle incoming cldap requests
      43             : */
      44        1260 : static void cldapd_request_handler(struct cldap_socket *cldap,
      45             :                                    void *private_data,
      46             :                                    struct cldap_incoming *in)
      47             : {
      48        1260 :         struct cldapd_server *cldapd = talloc_get_type(private_data,
      49             :                                        struct cldapd_server);
      50             :         struct ldap_SearchRequest *search;
      51             : 
      52        1260 :         if (in->ldap_msg->type == LDAP_TAG_AbandonRequest) {
      53           0 :                 DEBUG(10,("Got (and ignoring) CLDAP AbandonRequest from %s.",
      54             :                           tsocket_address_string(in->src, in)));
      55           0 :                 talloc_free(in);
      56           0 :                 return;
      57             :         }
      58             : 
      59        1260 :         if (in->ldap_msg->type != LDAP_TAG_SearchRequest) {
      60           0 :                 DEBUG(0,("Invalid CLDAP request type %d from %s\n",
      61             :                          in->ldap_msg->type,
      62             :                          tsocket_address_string(in->src, in)));
      63           0 :                 cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
      64             :                                   LDAP_OPERATIONS_ERROR, "Invalid CLDAP request");
      65           0 :                 talloc_free(in);
      66           0 :                 return;
      67             :         }
      68             : 
      69        1260 :         search = &in->ldap_msg->r.SearchRequest;
      70             : 
      71        1260 :         if (strcmp("", search->basedn) != 0) {
      72           0 :                 DEBUG(0,("Invalid CLDAP basedn '%s' from %s\n",
      73             :                          search->basedn,
      74             :                          tsocket_address_string(in->src, in)));
      75           0 :                 cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
      76             :                                   LDAP_OPERATIONS_ERROR, "Invalid CLDAP basedn");
      77           0 :                 talloc_free(in);
      78           0 :                 return;
      79             :         }
      80             : 
      81        1260 :         if (search->scope != LDAP_SEARCH_SCOPE_BASE) {
      82           0 :                 DEBUG(0,("Invalid CLDAP scope %d from %s\n",
      83             :                          search->scope,
      84             :                          tsocket_address_string(in->src, in)));
      85           0 :                 cldap_error_reply(cldap, in->ldap_msg->messageid, in->src,
      86             :                                   LDAP_OPERATIONS_ERROR, "Invalid CLDAP scope");
      87           0 :                 talloc_free(in);
      88           0 :                 return;
      89             :         }
      90             : 
      91        2330 :         cldapd_rootdse_request(cldap, cldapd, in,
      92        1260 :                                in->ldap_msg->messageid,
      93             :                                search, in->src);
      94        1260 :         talloc_free(in);
      95             : }
      96             : 
      97             : 
      98             : /*
      99             :   start listening on the given address
     100             : */
     101         188 : static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
     102             :                                   const char *address)
     103             : {
     104             :         struct cldap_socket *cldapsock;
     105             :         struct tsocket_address *socket_address;
     106             :         NTSTATUS status;
     107             :         int ret;
     108             : 
     109         188 :         ret = tsocket_address_inet_from_strings(cldapd,
     110             :                                                 "ip",
     111             :                                                 address,
     112             :                                                 lpcfg_cldap_port(lp_ctx),
     113             :                                                 &socket_address);
     114         188 :         if (ret != 0) {
     115           0 :                 status = map_nt_error_from_unix_common(errno);
     116           0 :                 DEBUG(0,("invalid address %s:%d - %s:%s\n",
     117             :                          address, lpcfg_cldap_port(lp_ctx),
     118             :                          gai_strerror(ret), nt_errstr(status)));
     119           0 :                 return status;
     120             :         }
     121             : 
     122             :         /* listen for unicasts on the CLDAP port (389) */
     123         188 :         status = cldap_socket_init(cldapd,
     124             :                                    socket_address,
     125             :                                    NULL,
     126             :                                    &cldapsock);
     127         188 :         if (!NT_STATUS_IS_OK(status)) {
     128           0 :                 DEBUG(0,("Failed to bind to %s - %s\n", 
     129             :                          tsocket_address_string(socket_address, socket_address),
     130             :                          nt_errstr(status)));
     131           0 :                 talloc_free(socket_address);
     132           0 :                 return status;
     133             :         }
     134         188 :         talloc_free(socket_address);
     135             : 
     136         188 :         cldap_set_incoming_handler(cldapsock, cldapd->task->event_ctx,
     137             :                                    cldapd_request_handler, cldapd);
     138             : 
     139         188 :         return NT_STATUS_OK;
     140             : }
     141             : 
     142             : /*
     143             :   setup our listening sockets on the configured network interfaces
     144             : */
     145          47 : static NTSTATUS cldapd_startup_interfaces(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
     146             :                                           struct interface *ifaces)
     147             : {
     148             :         int i, num_interfaces;
     149          47 :         TALLOC_CTX *tmp_ctx = talloc_new(cldapd);
     150             :         NTSTATUS status;
     151             : 
     152          47 :         num_interfaces = iface_list_count(ifaces);
     153             : 
     154             :         /* if we are allowing incoming packets from any address, then
     155             :            we need to bind to the wildcard address */
     156          47 :         if (!lpcfg_bind_interfaces_only(lp_ctx)) {
     157          47 :                 size_t num_binds = 0;
     158          47 :                 char **wcard = iface_list_wildcard(cldapd);
     159          47 :                 NT_STATUS_HAVE_NO_MEMORY(wcard);
     160         141 :                 for (i=0; wcard[i]; i++) {
     161          94 :                         status = cldapd_add_socket(cldapd, lp_ctx, wcard[i]);
     162          94 :                         if (NT_STATUS_IS_OK(status)) {
     163          94 :                                 num_binds++;
     164             :                         }
     165             :                 }
     166          47 :                 talloc_free(wcard);
     167          47 :                 if (num_binds == 0) {
     168           0 :                         return NT_STATUS_INVALID_PARAMETER_MIX;
     169             :                 }
     170             :         }
     171             : 
     172             :         /* now we have to also listen on the specific interfaces,
     173             :            so that replies always come from the right IP */
     174         141 :         for (i=0; i<num_interfaces; i++) {
     175          94 :                 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
     176          94 :                 status = cldapd_add_socket(cldapd, lp_ctx, address);
     177          94 :                 NT_STATUS_NOT_OK_RETURN(status);
     178             :         }
     179             : 
     180          47 :         talloc_free(tmp_ctx);
     181             : 
     182          47 :         return NT_STATUS_OK;
     183             : }
     184             : 
     185             : /*
     186             :   startup the cldapd task
     187             : */
     188          53 : static NTSTATUS cldapd_task_init(struct task_server *task)
     189             : {
     190             :         struct cldapd_server *cldapd;
     191             :         NTSTATUS status;
     192             :         struct interface *ifaces;
     193             :         
     194          53 :         load_interface_list(task, task->lp_ctx, &ifaces);
     195             : 
     196          53 :         if (iface_list_count(ifaces) == 0) {
     197           0 :                 task_server_terminate(task, "cldapd: no network interfaces configured", false);
     198           0 :                 return NT_STATUS_UNSUCCESSFUL;
     199             :         }
     200             : 
     201          53 :         switch (lpcfg_server_role(task->lp_ctx)) {
     202           0 :         case ROLE_STANDALONE:
     203           0 :                 task_server_terminate(task, "cldap_server: no CLDAP server required in standalone configuration", 
     204             :                                       false);
     205           0 :                 return NT_STATUS_INVALID_DOMAIN_ROLE;
     206           6 :         case ROLE_DOMAIN_MEMBER:
     207           6 :                 task_server_terminate(task, "cldap_server: no CLDAP server required in member server configuration",
     208             :                                       false);
     209           0 :                 return NT_STATUS_INVALID_DOMAIN_ROLE;
     210          47 :         case ROLE_ACTIVE_DIRECTORY_DC:
     211             :                 /* Yes, we want an CLDAP server */
     212          47 :                 break;
     213             :         }
     214             : 
     215          47 :         task_server_set_title(task, "task[cldapd]");
     216             : 
     217          47 :         cldapd = talloc(task, struct cldapd_server);
     218          47 :         if (cldapd == NULL) {
     219           0 :                 task_server_terminate(task, "cldapd: out of memory", true);
     220           0 :                 return NT_STATUS_NO_MEMORY;
     221             :         }
     222             : 
     223          47 :         cldapd->task = task;
     224          47 :         cldapd->samctx = samdb_connect(cldapd,
     225             :                                        task->event_ctx,
     226             :                                        task->lp_ctx,
     227             :                                        system_session(task->lp_ctx),
     228             :                                        NULL,
     229             :                                        0);
     230          47 :         if (cldapd->samctx == NULL) {
     231           0 :                 task_server_terminate(task, "cldapd failed to open samdb", true);
     232           0 :                 return NT_STATUS_UNSUCCESSFUL;
     233             :         }
     234             : 
     235             :         /* start listening on the configured network interfaces */
     236          47 :         status = cldapd_startup_interfaces(cldapd, task->lp_ctx, ifaces);
     237          47 :         if (!NT_STATUS_IS_OK(status)) {
     238           0 :                 task_server_terminate(task, "cldapd failed to setup interfaces", true);
     239           0 :                 return status;
     240             :         }
     241             : 
     242          47 :         irpc_add_name(task->msg_ctx, "cldap_server");
     243             : 
     244          47 :         return NT_STATUS_OK;
     245             : }
     246             : 
     247             : 
     248             : /*
     249             :   register ourselves as a available server
     250             : */
     251          53 : NTSTATUS server_service_cldapd_init(TALLOC_CTX *ctx)
     252             : {
     253             :         static const struct service_details details = {
     254             :                 .inhibit_fork_on_accept = true,
     255             :                 .inhibit_pre_fork = true,
     256             :                 .task_init = cldapd_task_init,
     257             :                 .post_fork = NULL
     258             :         };
     259          53 :         return register_server_service(ctx, "cldap", &details);
     260             : }

Generated by: LCOV version 1.13