Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/auth/auth_winbind.c
Line
Count
Source
1
/* 
2
   Unix SMB/CIFS implementation.
3
4
   Winbind authentication mechanism
5
6
   Copyright (C) Tim Potter 2000
7
   Copyright (C) Andrew Bartlett 2001 - 2002
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
#include "nsswitch/libwbclient/wbclient.h"
27
28
#undef DBGC_CLASS
29
0
#define DBGC_CLASS DBGC_AUTH
30
31
/* Authenticate a user with a challenge/response */
32
33
static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
34
               void *my_private_data, 
35
               TALLOC_CTX *mem_ctx,
36
               const struct auth_usersupplied_info *user_info,
37
               struct auth_serversupplied_info **server_info)
38
0
{
39
0
  NTSTATUS nt_status;
40
0
  wbcErr wbc_status;
41
0
  struct wbcAuthUserParams params;
42
0
  struct wbcAuthUserInfo *info = NULL;
43
0
  struct wbcAuthErrorInfo *err = NULL;
44
45
0
  ZERO_STRUCT(params);
46
47
0
  if (!user_info) {
48
0
    return NT_STATUS_INVALID_PARAMETER;
49
0
  }
50
51
0
  DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name));
52
53
0
  if (!auth_context) {
54
0
    DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", 
55
0
       user_info->mapped.account_name));
56
0
    return NT_STATUS_INVALID_PARAMETER;
57
0
  }   
58
59
0
  if (strequal(user_info->mapped.domain_name, get_global_sam_name())) {
60
0
    DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n",
61
0
      user_info->mapped.domain_name));
62
0
    return NT_STATUS_NOT_IMPLEMENTED;
63
0
  }
64
65
  /* Send off request */
66
0
  params.account_name = user_info->client.account_name;
67
  /*
68
   * We need to send the domain name from the client to the DC. With
69
   * NTLMv2 the domain name is part of the hashed second challenge,
70
   * if we change the domain name, the DC will fail to verify the
71
   * challenge cause we changed the domain name, this is like a
72
   * man in the middle attack.
73
   */
74
0
  params.domain_name  = user_info->client.domain_name;
75
0
  params.workstation_name = user_info->workstation_name;
76
77
0
  params.flags    = 0;
78
0
  params.parameter_control= user_info->logon_parameters;
79
80
0
  params.level    = WBC_AUTH_USER_LEVEL_RESPONSE;
81
82
0
  memcpy(params.password.response.challenge,
83
0
         auth_context->challenge.data,
84
0
         sizeof(params.password.response.challenge));
85
86
0
  if (user_info->password.response.nt.length != 0) {
87
0
    params.password.response.nt_length =
88
0
      user_info->password.response.nt.length;
89
0
    params.password.response.nt_data =
90
0
      user_info->password.response.nt.data;
91
0
  }
92
0
  if (user_info->password.response.lanman.length != 0) {
93
0
    params.password.response.lm_length =
94
0
      user_info->password.response.lanman.length;
95
0
    params.password.response.lm_data =
96
0
      user_info->password.response.lanman.data;
97
0
  }
98
99
0
  if (auth_context->for_netlogon) {
100
0
    params.flags |= WBC_AUTH_PARAM_FLAGS_FOR_NETLOGON;
101
0
  }
102
103
  /* we are contacting the privileged pipe */
104
0
  become_root();
105
0
  wbc_status = wbcAuthenticateUserEx(&params, &info, &err);
106
0
  unbecome_root();
107
108
0
  if (!WBC_ERROR_IS_OK(wbc_status)) {
109
0
    DEBUG(10,("check_winbind_security: wbcAuthenticateUserEx failed: %s\n",
110
0
      wbcErrorString(wbc_status)));
111
0
  }
112
113
0
  if (wbc_status == WBC_ERR_NO_MEMORY) {
114
0
    return NT_STATUS_NO_MEMORY;
115
0
  }
116
117
0
  if (wbc_status == WBC_ERR_WINBIND_NOT_AVAILABLE) {
118
0
    struct pdb_trusted_domain **domains = NULL;
119
0
    uint32_t num_domains = 0;
120
0
    NTSTATUS status;
121
122
0
    if (lp_server_role() == ROLE_DOMAIN_MEMBER) {
123
0
      status = NT_STATUS_NO_LOGON_SERVERS;
124
0
      DBG_ERR("winbindd not running - "
125
0
        "but required as domain member: %s\n",
126
0
        nt_errstr(status));
127
0
      return status;
128
0
    }
129
130
0
    status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
131
0
    if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) {
132
0
      DBG_DEBUG("pdb_enum_trusted_domains() not implemented "
133
0
          "for this passdb backend\n");
134
0
      return status;
135
0
    } else if (!NT_STATUS_IS_OK(status)) {
136
0
      DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
137
0
        nt_errstr(status));
138
0
      return status;
139
0
    }
140
0
    TALLOC_FREE(domains);
141
142
0
    if (num_domains == 0) {
143
0
      DBG_DEBUG("winbindd not running - ignoring without "
144
0
          "trusted domains\n");
145
0
      return NT_STATUS_NOT_IMPLEMENTED;
146
0
    }
147
148
0
    status = NT_STATUS_NO_LOGON_SERVERS;
149
0
    DBG_ERR("winbindd not running - "
150
0
      "but required as DC with trusts: %s\n",
151
0
      nt_errstr(status));
152
0
    return status;
153
0
  }
154
155
0
  if (wbc_status == WBC_ERR_AUTH_ERROR) {
156
0
    nt_status = NT_STATUS(err->nt_status);
157
158
0
    if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
159
0
        (err->authoritative == 0)) {
160
      /*
161
       * Trigger a fallback to local SAM
162
       */
163
0
      nt_status = NT_STATUS_NOT_IMPLEMENTED;
164
0
    }
165
166
0
    wbcFreeMemory(err);
167
0
    return nt_status;
168
0
  }
169
170
0
  if (!WBC_ERROR_IS_OK(wbc_status)) {
171
0
    return NT_STATUS_LOGON_FAILURE;
172
0
  }
173
174
0
  nt_status = make_server_info_wbcAuthUserInfo(mem_ctx,
175
0
                 user_info->client.account_name,
176
0
                 user_info->mapped.domain_name,
177
0
                 info, server_info);
178
0
  wbcFreeMemory(info);
179
0
  if (!NT_STATUS_IS_OK(nt_status)) {
180
0
    return nt_status;
181
0
  }
182
183
0
  (*server_info)->nss_token |= user_info->was_mapped;
184
185
0
        return nt_status;
186
0
}
187
188
/* module initialisation */
189
static NTSTATUS auth_init_winbind(
190
  struct auth_context *auth_context,
191
  const char *param,
192
  struct auth_methods **auth_method)
193
0
{
194
0
  struct auth_methods *result;
195
196
0
  result = talloc_zero(auth_context, struct auth_methods);
197
0
  if (result == NULL) {
198
0
    return NT_STATUS_NO_MEMORY;
199
0
  }
200
0
  result->name = "winbind";
201
0
  result->auth = check_winbind_security;
202
203
0
  *auth_method = result;
204
0
  return NT_STATUS_OK;
205
0
}
206
207
NTSTATUS auth_winbind_init(TALLOC_CTX *mem_ctx)
208
0
{
209
0
  return smb_register_auth(AUTH_INTERFACE_VERSION, "winbind", auth_init_winbind);
210
0
}