Coverage Report

Created: 2026-02-14 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/param/service.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   service (connection) opening and closing
4
   Copyright (C) Andrew Tridgell 1992-1998
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*/
19
20
#include "includes.h"
21
#include "system/filesys.h"
22
#include "../lib/tsocket/tsocket.h"
23
#include "smbd/smbd.h"
24
#include "smbd/globals.h"
25
#include "../librpc/gen_ndr/netlogon.h"
26
#include "../libcli/security/security.h"
27
#include "printing/pcap.h"
28
#include "printing/printer_list.h"
29
#include "passdb/lookup_sid.h"
30
#include "auth.h"
31
#include "lib/param/loadparm.h"
32
33
static int load_registry_service(const char *servicename)
34
0
{
35
0
  if (!lp_registry_shares()) {
36
0
    return -1;
37
0
  }
38
39
0
  if ((servicename == NULL) || (*servicename == '\0')) {
40
0
    return -1;
41
0
  }
42
43
0
  if (strequal(servicename, GLOBAL_NAME)) {
44
0
    return -2;
45
0
  }
46
47
0
  if (!process_registry_service(servicename)) {
48
0
    return -1;
49
0
  }
50
51
0
  return lp_servicenumber(servicename);
52
0
}
53
54
void load_registry_shares(void)
55
0
{
56
0
  DEBUG(8, ("load_registry_shares()\n"));
57
0
  if (!lp_registry_shares()) {
58
0
    return;
59
0
  }
60
61
0
  process_registry_shares();
62
63
0
  return;
64
0
}
65
66
/****************************************************************************
67
 Add a home service. Returns the new service number or -1 if fail.
68
****************************************************************************/
69
70
int add_home_service(const char *service, const char *username, const char *homedir)
71
0
{
72
0
  int iHomeService;
73
74
0
  if (!service || !homedir || homedir[0] == '\0')
75
0
    return -1;
76
77
0
  if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
78
0
    if ((iHomeService = load_registry_service(HOMES_NAME)) < 0) {
79
0
      return -1;
80
0
    }
81
0
  }
82
83
  /*
84
   * If this is a winbindd provided username, remove
85
   * the domain component before adding the service.
86
   * Log a warning if the "path=" parameter does not
87
   * include any macros.
88
   */
89
90
0
  {
91
0
    const char *p = strchr(service,*lp_winbind_separator());
92
93
    /* We only want the 'user' part of the string */
94
0
    if (p) {
95
0
      service = p + 1;
96
0
    }
97
0
  }
98
99
0
  if (!lp_add_home(service, iHomeService, username, homedir)) {
100
0
    return -1;
101
0
  }
102
103
0
  return lp_servicenumber(service);
104
105
0
}
106
107
/**
108
 * Find a service entry.
109
 *
110
 * @param service is modified (to canonical form??)
111
 **/
112
113
int find_service(TALLOC_CTX *ctx, const char *service_in, char **p_service_out)
114
0
{
115
0
  const struct loadparm_substitution *lp_sub =
116
0
    loadparm_s3_global_substitution();
117
0
  int iService;
118
119
0
  if (!service_in) {
120
0
    return -1;
121
0
  }
122
123
  /* First make a copy. */
124
0
  *p_service_out = talloc_strdup(ctx, service_in);
125
0
  if (!*p_service_out) {
126
0
    return -1;
127
0
  }
128
129
0
  all_string_sub(*p_service_out,"\\","/",0);
130
131
0
  iService = lp_servicenumber(*p_service_out);
132
133
  /*
134
   * check for whether the service is a registry share before
135
   * handling home directories. This is to ensure that
136
   * that in the case service name is identical to a user's
137
   * home directory, the explicit service is preferred.
138
   */
139
0
  if (iService < 0) {
140
0
    iService = load_registry_service(*p_service_out);
141
0
  }
142
143
  /* now handle the special case of a home directory */
144
0
  if (iService < 0) {
145
0
    char *phome_dir = get_user_home_dir(ctx, *p_service_out);
146
147
0
    if(!phome_dir) {
148
      /*
149
       * Try mapping the servicename, it may
150
       * be a Windows to unix mapped user name.
151
       */
152
0
      if(map_username(ctx, *p_service_out, p_service_out)) {
153
0
        if (*p_service_out == NULL) {
154
          /* Out of memory. */
155
0
          return -1;
156
0
        }
157
0
        phome_dir = get_user_home_dir(
158
0
            ctx, *p_service_out);
159
0
      }
160
0
    }
161
162
0
    DEBUG(3,("checking for home directory %s gave %s\n",*p_service_out,
163
0
      phome_dir?phome_dir:"(NULL)"));
164
165
0
    if (!strequal(phome_dir, "/")) {
166
0
      iService = add_home_service(*p_service_out,
167
0
                *p_service_out, /* username */
168
0
                phome_dir);
169
0
    }
170
0
  }
171
172
  /* If we still don't have a service, attempt to add it as a printer. */
173
0
  if (iService < 0) {
174
0
    int iPrinterService;
175
176
0
    if ((iPrinterService = lp_servicenumber(PRINTERS_NAME)) < 0) {
177
0
      iPrinterService = load_registry_service(PRINTERS_NAME);
178
0
    }
179
0
    if (iPrinterService >= 0) {
180
0
      DEBUG(3,("checking whether %s is a valid printer name...\n",
181
0
        *p_service_out));
182
0
      if (printer_list_printername_exists(*p_service_out)) {
183
0
        DEBUG(3,("%s is a valid printer name\n",
184
0
          *p_service_out));
185
0
        DEBUG(3,("adding %s as a printer service\n",
186
0
          *p_service_out));
187
0
        lp_add_printer(*p_service_out, iPrinterService);
188
0
        iService = lp_servicenumber(*p_service_out);
189
0
        if (iService < 0) {
190
0
          DEBUG(0,("failed to add %s as a printer service!\n",
191
0
            *p_service_out));
192
0
        }
193
0
      } else {
194
0
        DEBUG(3,("%s is not a valid printer name\n",
195
0
          *p_service_out));
196
0
      }
197
0
    }
198
0
  }
199
200
  /* Is it a usershare service ? */
201
0
  if (iService < 0 && *lp_usershare_path(talloc_tos(), lp_sub)) {
202
    /* Ensure the name is canonicalized. */
203
0
    if (!strlower_m(*p_service_out)) {
204
0
      goto fail;
205
0
    }
206
0
    iService = load_usershare_service(*p_service_out);
207
0
  }
208
209
  /* just possibly it's a default service? */
210
0
  if (iService < 0) {
211
0
    char *pdefservice = lp_defaultservice(talloc_tos(), lp_sub);
212
0
    if (pdefservice &&
213
0
        *pdefservice &&
214
0
        !strequal(pdefservice, *p_service_out)
215
0
        && !strstr_m(*p_service_out,"..")) {
216
      /*
217
       * We need to do a local copy here as lp_defaultservice()
218
       * returns one of the rotating lp_string buffers that
219
       * could get overwritten by the recursive find_service() call
220
       * below. Fix from Josef Hinteregger <joehtg@joehtg.co.at>.
221
       */
222
0
      char *defservice = talloc_strdup(ctx, pdefservice);
223
224
0
      if (!defservice) {
225
0
        goto fail;
226
0
      }
227
228
      /* Disallow anything except explicit share names. */
229
0
      if (strequal(defservice,HOMES_NAME) ||
230
0
          strequal(defservice, PRINTERS_NAME) ||
231
0
          strequal(defservice, "IPC$")) {
232
0
        TALLOC_FREE(defservice);
233
0
        goto fail;
234
0
      }
235
236
0
      iService = find_service(ctx, defservice, p_service_out);
237
0
      if (!*p_service_out) {
238
0
        TALLOC_FREE(defservice);
239
0
        iService = -1;
240
0
        goto fail;
241
0
      }
242
0
      if (iService >= 0) {
243
0
        all_string_sub(*p_service_out, "_","/",0);
244
0
        iService = lp_add_service(*p_service_out, iService);
245
0
      }
246
0
      TALLOC_FREE(defservice);
247
0
    }
248
0
  }
249
250
0
  if (iService >= 0) {
251
0
    if (!VALID_SNUM(iService)) {
252
0
      DEBUG(0,("Invalid snum %d for %s\n",iService,
253
0
        *p_service_out));
254
0
      iService = -1;
255
0
    }
256
0
  }
257
258
0
  fail:
259
260
0
  if (iService < 0) {
261
0
    DEBUG(3,("find_service() failed to find service %s\n",
262
0
      *p_service_out));
263
0
  }
264
265
0
  return (iService);
266
0
}
267
268
bool lp_allow_local_address(
269
  int snum, const struct tsocket_address *local_address)
270
0
{
271
0
  bool is_inet = tsocket_address_is_inet(local_address, "ip");
272
0
  const char **server_addresses = lp_server_addresses(snum);
273
0
  char *local = NULL;
274
0
  ssize_t i;
275
276
0
  if (!is_inet) {
277
0
    return false;
278
0
  }
279
280
0
  if (server_addresses == NULL) {
281
0
    return true;
282
0
  }
283
284
0
  local = tsocket_address_inet_addr_string(local_address, talloc_tos());
285
0
  if (local == NULL) {
286
0
    return false;
287
0
  }
288
289
0
  for (i=0; server_addresses[i] != NULL; i++) {
290
0
    struct tsocket_address *server_addr = NULL;
291
0
    char *server_addr_string = NULL;
292
0
    bool equal;
293
0
    int ret;
294
295
    /*
296
     * Go through struct tsocket_address to normalize the
297
     * string representation
298
     */
299
300
0
    ret = tsocket_address_inet_from_strings(
301
0
      talloc_tos(),
302
0
      "ip",
303
0
      server_addresses[i],
304
0
      0,
305
0
      &server_addr);
306
0
    if (ret == -1) {
307
0
      DBG_WARNING("tsocket_address_inet_from_strings "
308
0
            "failed for %s: %s, ignoring\n",
309
0
            server_addresses[i],
310
0
            strerror(errno));
311
0
      continue;
312
0
    }
313
314
0
    server_addr_string = tsocket_address_inet_addr_string(
315
0
      server_addr, talloc_tos());
316
0
    TALLOC_FREE(server_addr);
317
0
    if (server_addr_string == NULL) {
318
0
      DBG_ERR("tsocket_address_inet_addr_string failed "
319
0
        "for %s, ignoring\n",
320
0
        server_addresses[i]);
321
0
      continue;
322
0
    }
323
324
0
    equal = strequal(local, server_addr_string);
325
0
    TALLOC_FREE(server_addr_string);
326
327
0
    if (equal) {
328
0
      TALLOC_FREE(local);
329
0
      return true;
330
0
    }
331
0
  }
332
333
0
  TALLOC_FREE(local);
334
  return false;
335
0
}