Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/auth/auth_ntlmssp.c
Line
Count
Source
1
/* 
2
   Unix SMB/Netbios implementation.
3
   Version 3.0
4
   handle NLTMSSP, server side
5
6
   Copyright (C) Andrew Tridgell      2001
7
   Copyright (C) Andrew Bartlett 2001-2005,2011
8
   Copyright (C) Stefan Metzmacher 2005
9
10
   This program is free software; you can redistribute it and/or modify
11
   it under the terms of the GNU General Public License as published by
12
   the Free Software Foundation; either version 3 of the License, or
13
   (at your option) any later version.
14
   
15
   This program is distributed in the hope that it will be useful,
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
   GNU General Public License for more details.
19
   
20
   You should have received a copy of the GNU General Public License
21
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
*/
23
24
#include "includes.h"
25
#include "auth.h"
26
#include "libcli/security/security.h"
27
#include "lib/util/tevent_ntstatus.h"
28
#include "source3/lib/substitute.h"
29
30
NTSTATUS auth3_generate_session_info(struct auth4_context *auth_context,
31
             TALLOC_CTX *mem_ctx,
32
             void *server_returned_info,
33
             const char *original_user_name,
34
             uint32_t session_info_flags,
35
             struct auth_session_info **session_info)
36
0
{
37
0
  struct auth_user_info_dc *user_info = NULL;
38
0
  struct auth_serversupplied_info *server_info = NULL;
39
0
  NTSTATUS nt_status;
40
41
  /*
42
   * This is a hack, some callers...
43
   *
44
   * Some callers pass auth_user_info_dc, the SCHANNEL and
45
   * NCALRPC_AS_SYSTEM gensec modules.
46
   *
47
   * While the rest passes auth3_check_password() returned.
48
   */
49
0
  user_info = talloc_get_type(server_returned_info,
50
0
            struct auth_user_info_dc);
51
0
  if (user_info != NULL) {
52
0
    const struct dom_sid *sid;
53
0
    int cmp;
54
55
    /*
56
     * This should only be called from SCHANNEL or NCALRPC_AS_SYSTEM
57
     */
58
0
    if (user_info->num_sids != 1) {
59
0
      return NT_STATUS_INTERNAL_ERROR;
60
0
    }
61
0
    sid = &user_info->sids[PRIMARY_USER_SID_INDEX].sid;
62
63
0
    cmp = dom_sid_compare(sid, &global_sid_System);
64
0
    if (cmp == 0) {
65
0
      return make_session_info_system(mem_ctx, session_info);
66
0
    }
67
68
0
    cmp = dom_sid_compare(sid, &global_sid_Anonymous);
69
0
    if (cmp == 0) {
70
0
      return make_session_info_anonymous(mem_ctx, session_info);
71
0
    }
72
73
0
    return NT_STATUS_INTERNAL_ERROR;
74
0
  }
75
76
0
  server_info = talloc_get_type_abort(server_returned_info,
77
0
              struct auth_serversupplied_info);
78
0
  nt_status = create_local_token(mem_ctx,
79
0
               server_info,
80
0
               NULL,
81
0
               original_user_name,
82
0
               session_info);
83
0
  if (!NT_STATUS_IS_OK(nt_status)) {
84
0
    DEBUG(10, ("create_local_token failed: %s\n",
85
0
         nt_errstr(nt_status)));
86
0
    return nt_status;
87
0
  }
88
89
0
  return NT_STATUS_OK;
90
0
}
91
92
/**
93
 * Return the challenge as determined by the authentication subsystem 
94
 * @return an 8 byte random challenge
95
 */
96
97
NTSTATUS auth3_get_challenge(struct auth4_context *auth4_context,
98
             uint8_t chal[8])
99
0
{
100
0
  struct auth_context *auth_context = talloc_get_type_abort(auth4_context->private_data,
101
0
                  struct auth_context);
102
0
  auth_get_ntlm_challenge(auth_context, chal);
103
0
  return NT_STATUS_OK;
104
0
}
105
106
/**
107
 * NTLM2 authentication modifies the effective challenge, 
108
 * @param challenge The new challenge value
109
 */
110
NTSTATUS auth3_set_challenge(struct auth4_context *auth4_context, const uint8_t *chal,
111
           const char *challenge_set_by)
112
0
{
113
0
  struct auth_context *auth_context = talloc_get_type_abort(auth4_context->private_data,
114
0
                  struct auth_context);
115
0
  bool ok;
116
117
0
  ok = auth3_context_set_challenge(auth_context, chal, challenge_set_by);
118
0
  if (!ok) {
119
    /*
120
     * This can only fail for ENOMEM
121
     */
122
0
    return NT_STATUS_NO_MEMORY;
123
0
  }
124
125
0
  DEBUG(5, ("auth_context challenge set by %s\n", auth_context->challenge_set_by));
126
0
  DEBUG(5, ("challenge is: \n"));
127
0
  dump_data(5, auth_context->challenge.data, auth_context->challenge.length);
128
0
  return NT_STATUS_OK;
129
0
}
130
131
/**
132
 * Check the password on an NTLMSSP login.  
133
 *
134
 * Return the session keys used on the connection.
135
 */
136
137
struct auth3_check_password_state {
138
  uint8_t authoritative;
139
  void *server_info;
140
  DATA_BLOB nt_session_key;
141
  DATA_BLOB lm_session_key;
142
};
143
144
struct tevent_req *auth3_check_password_send(
145
  TALLOC_CTX *mem_ctx,
146
  struct tevent_context *ev,
147
  struct auth4_context *auth4_context,
148
  const struct auth_usersupplied_info *user_info)
149
0
{
150
0
  struct tevent_req *req = NULL;
151
0
  struct auth3_check_password_state *state = NULL;
152
0
  struct auth_context *auth_context = talloc_get_type_abort(
153
0
    auth4_context->private_data, struct auth_context);
154
0
  struct auth_usersupplied_info *mapped_user_info = NULL;
155
0
  struct auth_serversupplied_info *server_info = NULL;
156
0
  char *sanitized_username = NULL;
157
0
  NTSTATUS nt_status;
158
0
  bool username_was_mapped;
159
160
0
  req = tevent_req_create(
161
0
    mem_ctx, &state, struct auth3_check_password_state);
162
0
  if (req == NULL) {
163
0
    return NULL;
164
0
  }
165
166
  /*
167
   * Be authoritative by default.
168
   */
169
0
  state->authoritative = 1;
170
171
  /* The client has given us its machine name (which we only get over NBT transport).
172
     We need to possibly reload smb.conf if smb.conf includes depend on the machine name. */
173
174
0
  set_remote_machine_name(user_info->workstation_name, True);
175
176
0
  nt_status = make_user_info_map(talloc_tos(),
177
0
                                       &mapped_user_info,
178
0
               user_info->client.account_name,
179
0
               user_info->client.domain_name,
180
0
               user_info->workstation_name,
181
0
               user_info->remote_host,
182
0
               user_info->local_host,
183
0
               user_info->service_description,
184
0
                                 user_info->password.response.lanman.data ? &user_info->password.response.lanman : NULL,
185
0
                                 user_info->password.response.nt.data ? &user_info->password.response.nt : NULL,
186
0
               NULL, NULL, user_info->password.plaintext,
187
0
               AUTH_PASSWORD_RESPONSE);
188
189
0
  if (tevent_req_nterror(req, nt_status)) {
190
0
    return tevent_req_post(req, ev);
191
0
  }
192
193
0
  mapped_user_info->logon_parameters = user_info->logon_parameters;
194
195
0
  mapped_user_info->flags = user_info->flags;
196
197
0
  sanitized_username = talloc_alpha_strcpy(
198
0
    state,
199
0
    user_info->client.account_name,
200
0
    SAFE_NETBIOS_CHARS "$");
201
0
  if (sanitized_username == NULL) {
202
0
    tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
203
0
    return tevent_req_post(req, ev);
204
0
  }
205
206
0
  nt_status = auth_check_ntlm_password(state,
207
0
               auth_context,
208
0
               mapped_user_info,
209
0
               &server_info,
210
0
               &state->authoritative);
211
212
0
  if (!NT_STATUS_IS_OK(nt_status)) {
213
0
    DBG_INFO("Checking NTLMSSP password for %s\\%s failed: "
214
0
       "%s, authoritative=%"PRIu8"\n",
215
0
       user_info->client.domain_name,
216
0
       user_info->client.account_name,
217
0
       nt_errstr(nt_status),
218
0
       state->authoritative);
219
0
  }
220
221
0
  username_was_mapped = mapped_user_info->was_mapped;
222
223
0
  TALLOC_FREE(mapped_user_info);
224
225
0
  if (!NT_STATUS_IS_OK(nt_status)) {
226
0
    nt_status = do_map_to_guest_server_info(
227
0
      state,
228
0
      nt_status,
229
0
      user_info->client.account_name,
230
0
      user_info->client.domain_name,
231
0
      &server_info);
232
0
    if (!tevent_req_nterror(req, nt_status)) {
233
0
      state->authoritative = 1;
234
235
      /* setup the string used by %U */
236
0
      set_current_user_info(
237
0
        sanitized_username,
238
0
        server_info->unix_name,
239
0
        server_info->info3->base.logon_domain.string);
240
241
0
      lp_load_with_shares(get_dyn_CONFIGFILE());
242
243
0
      tevent_req_done(req);
244
0
    }
245
0
    state->server_info = server_info;
246
0
    return tevent_req_post(req, ev);
247
0
  }
248
249
0
  server_info->nss_token |= username_was_mapped;
250
251
  /* setup the string used by %U */
252
0
  set_current_user_info(sanitized_username,
253
0
            server_info->unix_name,
254
0
            server_info->info3->base.logon_domain.string);
255
256
0
  lp_load_with_shares(get_dyn_CONFIGFILE());
257
258
  /* Clear out the session keys, and pass them to the caller.
259
   * They will not be used in this form again - instead the
260
   * NTLMSSP code will decide on the final correct session key,
261
   * and supply it to create_local_token() */
262
263
0
  DBG_DEBUG("Got NT session key of length %zu\n",
264
0
      server_info->session_key.length);
265
0
  state->nt_session_key = (DATA_BLOB) {
266
0
    .data = talloc_move(
267
0
      state, &server_info->session_key.data),
268
0
    .length = server_info->session_key.length,
269
0
  };
270
0
  server_info->session_key = data_blob_null;
271
272
0
  DBG_DEBUG("Got LM session key of length %zu\n",
273
0
      server_info->lm_session_key.length);
274
0
  state->lm_session_key = (DATA_BLOB) {
275
0
    .data = talloc_move(
276
0
      state, &server_info->lm_session_key.data),
277
0
    .length = server_info->lm_session_key.length,
278
0
  };
279
0
  server_info->lm_session_key = data_blob_null;
280
281
0
  state->server_info = server_info;
282
283
0
  tevent_req_done(req);
284
0
  return tevent_req_post(req, ev);
285
0
}
286
287
NTSTATUS auth3_check_password_recv(struct tevent_req *req,
288
           TALLOC_CTX *mem_ctx,
289
           uint8_t *pauthoritative,
290
           void **server_returned_info,
291
           DATA_BLOB *nt_session_key,
292
           DATA_BLOB *lm_session_key)
293
0
{
294
0
  struct auth3_check_password_state *state = tevent_req_data(
295
0
    req, struct auth3_check_password_state);
296
0
  NTSTATUS status;
297
298
0
  if (pauthoritative != NULL) {
299
0
    *pauthoritative = state->authoritative;
300
0
  }
301
302
0
  if (tevent_req_is_nterror(req, &status)) {
303
0
    return status;
304
0
  }
305
306
0
  if (server_returned_info != NULL) {
307
0
    *server_returned_info = talloc_move(
308
0
      mem_ctx, &state->server_info);
309
0
  }
310
0
  if (nt_session_key != NULL) {
311
0
    *nt_session_key = (DATA_BLOB) {
312
0
      .data = talloc_move(
313
0
        mem_ctx, &state->nt_session_key.data),
314
0
      .length = state->nt_session_key.length,
315
0
    };
316
0
  }
317
0
  if (lm_session_key != NULL) {
318
0
    *lm_session_key = (DATA_BLOB) {
319
0
      .data = talloc_move(
320
0
        mem_ctx, &state->lm_session_key.data),
321
0
      .length = state->lm_session_key.length,
322
0
    };
323
0
  }
324
325
0
  return NT_STATUS_OK;
326
0
}