Coverage Report

Created: 2026-09-03 07:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/auth/auth_sam.c
Line
Count
Source
1
/*
2
   Unix SMB/CIFS implementation.
3
   Password and authentication handling
4
   Copyright (C) Andrew Tridgell              1992-2000
5
   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
6
   Copyright (C) Andrew Bartlett              2001-2003
7
   Copyright (C) Gerald Carter                2003
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 "auth.h"
25
#include "passdb.h"
26
27
#undef DBGC_CLASS
28
0
#define DBGC_CLASS DBGC_AUTH
29
30
static NTSTATUS auth_sam_ignoredomain_auth(const struct auth_context *auth_context,
31
             void *my_private_data,
32
             TALLOC_CTX *mem_ctx,
33
             const struct auth_usersupplied_info *user_info,
34
             struct auth_serversupplied_info **server_info)
35
0
{
36
0
  if (!user_info || !auth_context) {
37
0
    return NT_STATUS_UNSUCCESSFUL;
38
0
  }
39
40
0
  if (user_info->mapped.account_name == NULL ||
41
0
      user_info->mapped.account_name[0] == '\0')
42
0
  {
43
0
    return NT_STATUS_NOT_IMPLEMENTED;
44
0
  }
45
46
0
  DBG_DEBUG("Check auth for: [%s]\\[%s]\n",
47
0
      user_info->mapped.domain_name,
48
0
      user_info->mapped.account_name);
49
50
0
  return check_sam_security(&auth_context->challenge, mem_ctx,
51
0
          user_info, server_info);
52
0
}
53
54
/* module initialisation */
55
static NTSTATUS auth_init_sam_ignoredomain(
56
  struct auth_context *auth_context,
57
  const char *param,
58
  struct auth_methods **auth_method)
59
0
{
60
0
  struct auth_methods *result;
61
62
0
  result = talloc_zero(auth_context, struct auth_methods);
63
0
  if (result == NULL) {
64
0
    return NT_STATUS_NO_MEMORY;
65
0
  }
66
0
  result->auth = auth_sam_ignoredomain_auth;
67
0
  result->name = "sam_ignoredomain";
68
69
0
        *auth_method = result;
70
0
  return NT_STATUS_OK;
71
0
}
72
73
74
/****************************************************************************
75
Check SAM security (above) but with a few extra checks.
76
****************************************************************************/
77
78
static NTSTATUS auth_samstrict_auth(const struct auth_context *auth_context,
79
            void *my_private_data,
80
            TALLOC_CTX *mem_ctx,
81
            const struct auth_usersupplied_info *user_info,
82
            struct auth_serversupplied_info **server_info)
83
0
{
84
0
  const char *effective_domain = NULL;
85
0
  bool is_local_name, is_my_domain;
86
87
0
  if (!user_info || !auth_context) {
88
0
    return NT_STATUS_LOGON_FAILURE;
89
0
  }
90
0
  effective_domain = user_info->mapped.domain_name;
91
92
0
  if (user_info->mapped.account_name == NULL ||
93
0
      user_info->mapped.account_name[0] == '\0')
94
0
  {
95
0
    return NT_STATUS_NOT_IMPLEMENTED;
96
0
  }
97
98
0
  if (lp_server_role() == ROLE_DOMAIN_MEMBER) {
99
0
    const char *p = NULL;
100
101
0
    p = strchr_m(user_info->mapped.account_name, '@');
102
0
    if (p != NULL) {
103
      /*
104
       * This needs to go to the DC,
105
       * even if @ is the last character
106
       */
107
0
      return NT_STATUS_NOT_IMPLEMENTED;
108
0
    }
109
0
  }
110
111
0
  if (effective_domain == NULL) {
112
0
    effective_domain = "";
113
0
  }
114
115
0
  DBG_DEBUG("Check auth for: [%s]\\[%s]\n",
116
0
      effective_domain,
117
0
      user_info->mapped.account_name);
118
119
120
0
  if (strequal(effective_domain, "") || strequal(effective_domain, ".")) {
121
    /*
122
     * An empty domain name or '.' should be handled
123
     * as the local SAM name.
124
     */
125
0
    effective_domain = lp_netbios_name();
126
0
  }
127
128
0
  is_local_name = is_myname(effective_domain);
129
0
  is_my_domain  = strequal(effective_domain, lp_workgroup());
130
131
  /* check whether or not we service this domain/workgroup name */
132
133
0
  switch ( lp_server_role() ) {
134
0
    case ROLE_STANDALONE:
135
0
    case ROLE_DOMAIN_MEMBER:
136
0
      if ( !is_local_name ) {
137
0
        DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n",
138
0
          effective_domain, (lp_server_role() == ROLE_DOMAIN_MEMBER
139
0
          ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
140
0
        return NT_STATUS_NOT_IMPLEMENTED;
141
0
      }
142
143
0
      break;
144
0
    case ROLE_DOMAIN_PDC:
145
0
    case ROLE_DOMAIN_BDC:
146
0
    case ROLE_IPA_DC:
147
0
      if (!is_local_name && !is_my_domain) {
148
             /* If we are running on a DC that has PASSDB module with domain
149
        * information, check if DNS forest name is matching the domain
150
        * name. This is the case of IPA domain controller when
151
        * trusted AD DCs attempt to authenticate IPA users using
152
        * the forest root domain (which is the only domain in IPA).
153
        */
154
0
        struct pdb_domain_info *dom_info = NULL;
155
156
0
        dom_info = pdb_get_domain_info(mem_ctx);
157
0
        if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) {
158
0
          is_my_domain = strequal(user_info->mapped.domain_name,
159
0
                dom_info->dns_forest);
160
0
        }
161
162
0
        TALLOC_FREE(dom_info);
163
0
        if (!is_my_domain) {
164
0
          DEBUG(6,("check_samstrict_security: %s is not one "
165
0
             "of my local names or domain name (DC)\n",
166
0
             effective_domain));
167
0
          return NT_STATUS_NOT_IMPLEMENTED;
168
0
        }
169
0
      }
170
171
0
      break;
172
0
    default: /* name is ok */
173
0
      break;
174
0
  }
175
176
0
  return check_sam_security(&auth_context->challenge, mem_ctx,
177
0
          user_info, server_info);
178
0
}
179
180
/* module initialisation */
181
static NTSTATUS auth_init_sam(
182
  struct auth_context *auth_context,
183
  const char *param,
184
  struct auth_methods **auth_method)
185
0
{
186
0
  struct auth_methods *result;
187
188
0
  if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
189
0
      && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
190
0
    DEBUG(0, ("server role = 'active directory domain controller' not compatible with running the auth_sam module. \n"));
191
0
    DEBUGADD(0, ("You should not set 'auth methods' when running the AD DC.\n"));
192
0
    exit(1);
193
0
  }
194
195
0
  result = talloc_zero(auth_context, struct auth_methods);
196
0
  if (result == NULL) {
197
0
    return NT_STATUS_NO_MEMORY;
198
0
  }
199
0
  result->auth = auth_samstrict_auth;
200
0
  result->name = "sam";
201
0
  *auth_method = result;
202
0
  return NT_STATUS_OK;
203
0
}
204
205
static NTSTATUS auth_sam_netlogon3_auth(const struct auth_context *auth_context,
206
          void *my_private_data,
207
          TALLOC_CTX *mem_ctx,
208
          const struct auth_usersupplied_info *user_info,
209
          struct auth_serversupplied_info **server_info)
210
0
{
211
0
  const char *effective_domain = NULL;
212
0
  bool is_my_domain;
213
214
0
  if (!user_info || !auth_context) {
215
0
    return NT_STATUS_LOGON_FAILURE;
216
0
  }
217
0
  effective_domain = user_info->mapped.domain_name;
218
219
0
  if (user_info->mapped.account_name == NULL ||
220
0
      user_info->mapped.account_name[0] == '\0')
221
0
  {
222
0
    return NT_STATUS_NOT_IMPLEMENTED;
223
0
  }
224
225
0
  if (effective_domain == NULL) {
226
0
    effective_domain = "";
227
0
  }
228
229
0
  DBG_DEBUG("Check auth for: [%s]\\[%s]\n",
230
0
      effective_domain,
231
0
      user_info->mapped.account_name);
232
233
  /* check whether or not we service this domain/workgroup name */
234
235
0
  switch (lp_server_role()) {
236
0
  case ROLE_DOMAIN_PDC:
237
0
  case ROLE_DOMAIN_BDC:
238
0
  case ROLE_IPA_DC:
239
0
    break;
240
0
  default:
241
0
    DBG_ERR("Invalid server role\n");
242
0
    return NT_STATUS_INVALID_SERVER_STATE;
243
0
  }
244
245
0
  if (strequal(effective_domain, "") || strequal(effective_domain, ".")) {
246
    /*
247
     * An empty domain name or '.' should be handled
248
     * as the local SAM name.
249
     */
250
0
    effective_domain = lp_workgroup();
251
0
  }
252
253
0
  is_my_domain = strequal(user_info->mapped.domain_name, lp_workgroup());
254
0
  if (!is_my_domain) {
255
         /* If we are running on a DC that has PASSDB module with domain
256
    * information, check if DNS forest name is matching the domain
257
    * name. This is the case of IPA domain controller when
258
    * trusted AD DCs attempt to authenticate IPA users using
259
    * the forest root domain (which is the only domain in IPA).
260
    */
261
0
    struct pdb_domain_info *dom_info = NULL;
262
0
    dom_info = pdb_get_domain_info(mem_ctx);
263
264
0
    if ((dom_info != NULL) && (dom_info->dns_forest != NULL)) {
265
0
      is_my_domain = strequal(user_info->mapped.domain_name,
266
0
            dom_info->dns_forest);
267
0
    }
268
269
0
    TALLOC_FREE(dom_info);
270
0
  }
271
272
0
  if (!is_my_domain) {
273
0
    DBG_INFO("%s is not our domain name (DC for %s)\n",
274
0
       effective_domain, lp_workgroup());
275
0
    return NT_STATUS_NOT_IMPLEMENTED;
276
0
  }
277
278
0
  return check_sam_security(&auth_context->challenge, mem_ctx,
279
0
          user_info, server_info);
280
0
}
281
282
/* module initialisation */
283
static NTSTATUS auth_init_sam_netlogon3(
284
  struct auth_context *auth_context,
285
  const char *param,
286
  struct auth_methods **auth_method)
287
0
{
288
0
  struct auth_methods *result;
289
290
0
  if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC
291
0
      && !lp_parm_bool(-1, "server role check", "inhibit", false)) {
292
0
    DEBUG(0, ("server role = 'active directory domain controller' "
293
0
        "not compatible with running the auth_sam module.\n"));
294
0
    DEBUGADD(0, ("You should not set 'auth methods' when "
295
0
           "running the AD DC.\n"));
296
0
    exit(1);
297
0
  }
298
299
0
  result = talloc_zero(auth_context, struct auth_methods);
300
0
  if (result == NULL) {
301
0
    return NT_STATUS_NO_MEMORY;
302
0
  }
303
0
  result->auth = auth_sam_netlogon3_auth;
304
0
  result->name = "sam_netlogon3";
305
0
  *auth_method = result;
306
0
  return NT_STATUS_OK;
307
0
}
308
309
NTSTATUS auth_sam_init(TALLOC_CTX *mem_ctx)
310
0
{
311
0
  smb_register_auth(AUTH_INTERFACE_VERSION, "sam", auth_init_sam);
312
0
  smb_register_auth(AUTH_INTERFACE_VERSION, "sam_ignoredomain", auth_init_sam_ignoredomain);
313
0
  smb_register_auth(AUTH_INTERFACE_VERSION, "sam_netlogon3", auth_init_sam_netlogon3);
314
0
  return NT_STATUS_OK;
315
0
}