LCOV - code coverage report
Current view: top level - source4/cldap_server - cldap_server.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 68 102 66.7 %
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 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        2503 : static void cldapd_request_handler(struct cldap_socket *cldap,
      45             :                                    void *private_data,
      46             :                                    struct cldap_incoming *in)
      47             : {
      48        2503 :         struct cldapd_server *cldapd = talloc_get_type(private_data,
      49             :                                        struct cldapd_server);
      50          36 :         struct ldap_SearchRequest *search;
      51             : 
      52        2503 :         if (in->ldap_msg->type == LDAP_TAG_AbandonRequest) {
      53           0 :                 DEBUG(10,("Got (and ignoring) CLDAP AbandonRequest from %s.\n",
      54             :                           tsocket_address_string(in->src, in)));
      55           0 :                 talloc_free(in);
      56           0 :                 return;
      57             :         }
      58             : 
      59        2503 :         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        2503 :         search = &in->ldap_msg->r.SearchRequest;
      70             : 
      71        2503 :         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        2503 :         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        2503 :         cldapd_rootdse_request(cldap, cldapd, in,
      92        2503 :                                in->ldap_msg->messageid,
      93             :                                search, in->src);
      94        2503 :         talloc_free(in);
      95             : }
      96             : 
      97             : 
      98             : /*
      99             :   start listening on the given address
     100             : */
     101         236 : static NTSTATUS cldapd_add_socket(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
     102             :                                   const char *address)
     103             : {
     104           8 :         struct cldap_socket *cldapsock;
     105           8 :         struct tsocket_address *socket_address;
     106           8 :         NTSTATUS status;
     107           8 :         int ret;
     108             : 
     109         236 :         ret = tsocket_address_inet_from_strings(cldapd,
     110             :                                                 "ip",
     111             :                                                 address,
     112             :                                                 lpcfg_cldap_port(lp_ctx),
     113             :                                                 &socket_address);
     114         236 :         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         236 :         status = cldap_socket_init(cldapd,
     124             :                                    socket_address,
     125             :                                    NULL,
     126             :                                    &cldapsock);
     127         236 :         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         236 :         talloc_free(socket_address);
     135             : 
     136         236 :         cldap_set_incoming_handler(cldapsock, cldapd->task->event_ctx,
     137             :                                    cldapd_request_handler, cldapd);
     138             : 
     139         236 :         return NT_STATUS_OK;
     140             : }
     141             : 
     142             : /*
     143             :   setup our listening sockets on the configured network interfaces
     144             : */
     145          59 : static NTSTATUS cldapd_startup_interfaces(struct cldapd_server *cldapd, struct loadparm_context *lp_ctx,
     146             :                                           struct interface *ifaces)
     147             : {
     148           2 :         int i, num_interfaces;
     149          59 :         TALLOC_CTX *tmp_ctx = talloc_new(cldapd);
     150           2 :         NTSTATUS status;
     151             : 
     152          59 :         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          59 :         if (!lpcfg_bind_interfaces_only(lp_ctx)) {
     157          59 :                 size_t num_binds = 0;
     158          59 :                 char **wcard = iface_list_wildcard(cldapd);
     159          59 :                 NT_STATUS_HAVE_NO_MEMORY(wcard);
     160         177 :                 for (i=0; wcard[i]; i++) {
     161         118 :                         status = cldapd_add_socket(cldapd, lp_ctx, wcard[i]);
     162         118 :                         if (NT_STATUS_IS_OK(status)) {
     163         118 :                                 num_binds++;
     164             :                         }
     165             :                 }
     166          59 :                 talloc_free(wcard);
     167          59 :                 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         177 :         for (i=0; i<num_interfaces; i++) {
     175         118 :                 const char *address = talloc_strdup(tmp_ctx, iface_list_n_ip(ifaces, i));
     176         118 :                 status = cldapd_add_socket(cldapd, lp_ctx, address);
     177         118 :                 NT_STATUS_NOT_OK_RETURN(status);
     178             :         }
     179             : 
     180          59 :         talloc_free(tmp_ctx);
     181             : 
     182          59 :         return NT_STATUS_OK;
     183             : }
     184             : 
     185             : /*
     186             :   startup the cldapd task
     187             : */
     188          65 : static NTSTATUS cldapd_task_init(struct task_server *task)
     189             : {
     190           2 :         struct cldapd_server *cldapd;
     191           2 :         NTSTATUS status;
     192           2 :         struct interface *ifaces;
     193             :         
     194          65 :         load_interface_list(task, task->lp_ctx, &ifaces);
     195             : 
     196          65 :         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          65 :         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          57 :         case ROLE_ACTIVE_DIRECTORY_DC:
     211             :                 /* Yes, we want an CLDAP server */
     212          57 :                 break;
     213             :         }
     214             : 
     215          59 :         task_server_set_title(task, "task[cldapd]");
     216             : 
     217          59 :         cldapd = talloc(task, struct cldapd_server);
     218          59 :         if (cldapd == NULL) {
     219           0 :                 task_server_terminate(task, "cldapd: out of memory", true);
     220           0 :                 return NT_STATUS_NO_MEMORY;
     221             :         }
     222             : 
     223          59 :         cldapd->task = task;
     224          59 :         cldapd->samctx = samdb_connect(cldapd,
     225             :                                        task->event_ctx,
     226             :                                        task->lp_ctx,
     227             :                                        system_session(task->lp_ctx),
     228             :                                        NULL,
     229             :                                        0);
     230          59 :         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          59 :         status = cldapd_startup_interfaces(cldapd, task->lp_ctx, ifaces);
     237          59 :         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          59 :         irpc_add_name(task->msg_ctx, "cldap_server");
     243             : 
     244          59 :         return NT_STATUS_OK;
     245             : }
     246             : 
     247             : 
     248             : /*
     249             :   register ourselves as a available server
     250             : */
     251          66 : NTSTATUS server_service_cldapd_init(TALLOC_CTX *ctx)
     252             : {
     253           3 :         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          66 :         return register_server_service(ctx, "cldap", &details);
     260             : }

Generated by: LCOV version 1.14