Line data Source code
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 : 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 <tevent.h>
26 : #include "../lib/util/tevent_ntstatus.h"
27 : #include "auth/auth.h"
28 : #include "auth/ntlm/auth_proto.h"
29 : #include "librpc/gen_ndr/ndr_winbind_c.h"
30 : #include "lib/messaging/irpc.h"
31 : #include "param/param.h"
32 : #include "nsswitch/libwbclient/wbclient.h"
33 : #include "auth/auth_sam_reply.h"
34 : #include "libcli/security/security.h"
35 : #include "dsdb/samdb/samdb.h"
36 : #include "auth/auth_sam.h"
37 :
38 : #undef DBGC_CLASS
39 : #define DBGC_CLASS DBGC_AUTH
40 :
41 : _PUBLIC_ NTSTATUS auth4_winbind_init(TALLOC_CTX *);
42 :
43 1586 : static NTSTATUS winbind_want_check(struct auth_method_context *ctx,
44 : TALLOC_CTX *mem_ctx,
45 : const struct auth_usersupplied_info *user_info)
46 : {
47 1586 : if (!user_info->mapped.account_name || !*user_info->mapped.account_name) {
48 14 : return NT_STATUS_NOT_IMPLEMENTED;
49 : }
50 :
51 : /* TODO: maybe limit the user scope to remote users only */
52 1572 : return NT_STATUS_OK;
53 : }
54 :
55 : struct winbind_check_password_state {
56 : struct auth_method_context *ctx;
57 : const struct auth_usersupplied_info *user_info;
58 : struct winbind_SamLogon req;
59 : struct auth_user_info_dc *user_info_dc;
60 : bool authoritative;
61 : };
62 :
63 : static void winbind_check_password_done(struct tevent_req *subreq);
64 :
65 : /*
66 : Authenticate a user with a challenge/response
67 : using IRPC to the winbind task
68 : */
69 1572 : static struct tevent_req *winbind_check_password_send(TALLOC_CTX *mem_ctx,
70 : struct tevent_context *ev,
71 : struct auth_method_context *ctx,
72 : const struct auth_usersupplied_info *user_info)
73 : {
74 1572 : struct tevent_req *req = NULL;
75 1572 : struct winbind_check_password_state *state = NULL;
76 6 : NTSTATUS status;
77 6 : struct dcerpc_binding_handle *irpc_handle;
78 6 : const struct auth_usersupplied_info *user_info_new;
79 6 : struct netr_IdentityInfo *identity_info;
80 6 : struct imessaging_context *msg_ctx;
81 1572 : struct tevent_req *subreq = NULL;
82 :
83 1572 : req = tevent_req_create(mem_ctx, &state,
84 : struct winbind_check_password_state);
85 1572 : if (req == NULL) {
86 0 : return NULL;
87 : }
88 1572 : state->ctx = ctx;
89 1572 : state->user_info = user_info;
90 1572 : state->authoritative = true;
91 :
92 1572 : msg_ctx = imessaging_client_init(state, ctx->auth_ctx->lp_ctx, ev);
93 1572 : if (msg_ctx == NULL) {
94 0 : DEBUG(1, ("imessaging_init failed\n"));
95 0 : tevent_req_nterror(req, NT_STATUS_INVALID_SERVER_STATE);
96 0 : return tevent_req_post(req, ev);
97 : }
98 :
99 1572 : irpc_handle = irpc_binding_handle_by_name(state, msg_ctx,
100 : "winbind_server",
101 : &ndr_table_winbind);
102 1572 : if (irpc_handle == NULL) {
103 0 : DEBUG(0, ("Winbind authentication for [%s]\\[%s] failed, "
104 : "no winbind_server running!\n",
105 : user_info->client.domain_name, user_info->client.account_name));
106 0 : tevent_req_nterror(req, NT_STATUS_NO_LOGON_SERVERS);
107 0 : return tevent_req_post(req, ev);
108 : }
109 :
110 : /*
111 : * 120 seconds should be enough even for trusted domains.
112 : *
113 : * Currently winbindd has a much lower limit.
114 : * And tests with Windows RODCs show that it
115 : * returns NO_LOGON_SERVERS after 90-100 seconds
116 : * if it can't reach any RWDC.
117 : */
118 1572 : dcerpc_binding_handle_set_timeout(irpc_handle, 120);
119 :
120 1572 : if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) {
121 0 : struct netr_PasswordInfo *password_info;
122 :
123 120 : status = encrypt_user_info(state, ctx->auth_ctx, AUTH_PASSWORD_HASH,
124 : user_info, &user_info_new);
125 120 : if (tevent_req_nterror(req, status)) {
126 0 : return tevent_req_post(req, ev);
127 : }
128 120 : user_info = user_info_new;
129 :
130 120 : password_info = talloc_zero(state, struct netr_PasswordInfo);
131 120 : if (tevent_req_nomem(password_info, req)) {
132 0 : return tevent_req_post(req, ev);
133 : }
134 :
135 120 : password_info->lmpassword = *user_info->password.hash.lanman;
136 120 : password_info->ntpassword = *user_info->password.hash.nt;
137 :
138 120 : identity_info = &password_info->identity_info;
139 120 : state->req.in.logon_level = 1;
140 120 : state->req.in.logon.password= password_info;
141 : } else {
142 6 : struct netr_NetworkInfo *network_info;
143 6 : uint8_t chal[8];
144 :
145 1452 : status = encrypt_user_info(state, ctx->auth_ctx, AUTH_PASSWORD_RESPONSE,
146 : user_info, &user_info_new);
147 1452 : if (tevent_req_nterror(req, status)) {
148 0 : return tevent_req_post(req, ev);
149 : }
150 1452 : user_info = user_info_new;
151 :
152 1452 : network_info = talloc_zero(state, struct netr_NetworkInfo);
153 1452 : if (tevent_req_nomem(network_info, req)) {
154 0 : return tevent_req_post(req, ev);
155 : }
156 :
157 1452 : status = auth_get_challenge(ctx->auth_ctx, chal);
158 1452 : if (tevent_req_nterror(req, status)) {
159 0 : return tevent_req_post(req, ev);
160 : }
161 :
162 1452 : memcpy(network_info->challenge, chal, sizeof(network_info->challenge));
163 :
164 1452 : network_info->nt.length = user_info->password.response.nt.length;
165 1452 : network_info->nt.data = user_info->password.response.nt.data;
166 :
167 1452 : network_info->lm.length = user_info->password.response.lanman.length;
168 1452 : network_info->lm.data = user_info->password.response.lanman.data;
169 :
170 1452 : identity_info = &network_info->identity_info;
171 1452 : state->req.in.logon_level = 2;
172 1452 : state->req.in.logon.network = network_info;
173 : }
174 :
175 1572 : identity_info->domain_name.string = user_info->client.domain_name;
176 1572 : identity_info->parameter_control = user_info->logon_parameters; /* see MSV1_0_* */
177 1572 : identity_info->logon_id = user_info->logon_id;
178 1572 : identity_info->account_name.string = user_info->client.account_name;
179 1572 : identity_info->workstation.string = user_info->workstation_name;
180 :
181 1572 : state->req.in.validation_level = 6;
182 :
183 1572 : subreq = dcerpc_winbind_SamLogon_r_send(state, ev, irpc_handle,
184 1566 : &state->req);
185 1572 : if (tevent_req_nomem(subreq, req)) {
186 0 : return tevent_req_post(req, ev);
187 : }
188 1572 : tevent_req_set_callback(subreq,
189 : winbind_check_password_done,
190 : req);
191 :
192 1572 : return req;
193 : }
194 :
195 1572 : static void winbind_check_password_done(struct tevent_req *subreq)
196 : {
197 6 : struct tevent_req *req =
198 1572 : tevent_req_callback_data(subreq,
199 : struct tevent_req);
200 6 : struct winbind_check_password_state *state =
201 1572 : tevent_req_data(req,
202 : struct winbind_check_password_state);
203 1572 : struct auth_method_context *ctx = state->ctx;
204 1572 : const struct auth_usersupplied_info *user_info = state->user_info;
205 1572 : struct ldb_dn *domain_dn = NULL;
206 1572 : const char *nt4_domain = NULL;
207 1572 : const char *nt4_account = NULL;
208 1572 : struct ldb_message *msg = NULL;
209 6 : NTSTATUS status;
210 :
211 1572 : status = dcerpc_winbind_SamLogon_r_recv(subreq, state);
212 1572 : if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
213 0 : status = NT_STATUS_NO_LOGON_SERVERS;
214 : }
215 1572 : TALLOC_FREE(subreq);
216 1572 : if (tevent_req_nterror(req, status)) {
217 1284 : return;
218 : }
219 :
220 1570 : status = state->req.out.result;
221 1570 : if (!NT_STATUS_IS_OK(status)) {
222 1282 : if (!state->req.out.authoritative) {
223 1213 : state->authoritative = false;
224 : }
225 1282 : tevent_req_nterror(req, status);
226 1282 : return;
227 : }
228 :
229 288 : status = make_user_info_dc_netlogon_validation(state,
230 288 : user_info->client.account_name,
231 288 : state->req.in.validation_level,
232 288 : &state->req.out.validation,
233 : true, /* This user was authenticated */
234 : &state->user_info_dc);
235 288 : if (tevent_req_nterror(req, status)) {
236 0 : return;
237 : }
238 :
239 288 : nt4_domain = state->user_info_dc->info->domain_name;
240 288 : nt4_account = state->user_info_dc->info->account_name;
241 :
242 288 : if (lpcfg_is_mydomain(ctx->auth_ctx->lp_ctx, nt4_domain)) {
243 123 : domain_dn = ldb_get_default_basedn(ctx->auth_ctx->sam_ctx);
244 : }
245 :
246 288 : if (domain_dn != NULL) {
247 : /*
248 : * At best, reset the badPwdCount to 0 if the account exists.
249 : * This means that lockouts happen at a badPwdCount earlier than
250 : * normal, but makes it more fault tolerant.
251 : */
252 123 : status = authsam_search_account(state, ctx->auth_ctx->sam_ctx,
253 : nt4_account, domain_dn, &msg);
254 123 : if (NT_STATUS_IS_OK(status)) {
255 123 : status = authsam_logon_success_accounting(
256 123 : ctx->auth_ctx->sam_ctx, msg,
257 : domain_dn,
258 123 : user_info->flags & USER_INFO_INTERACTIVE_LOGON,
259 : NULL, NULL);
260 123 : if (tevent_req_nterror(req, status)) {
261 0 : return;
262 : }
263 : }
264 : }
265 :
266 : /*
267 : * We need to expand group memberships within our local domain,
268 : * as the token might be generated by a trusted domain, unless we're
269 : * an RODC.
270 : */
271 288 : status = authsam_update_user_info_dc(state->user_info_dc,
272 288 : ctx->auth_ctx->sam_ctx,
273 : state->user_info_dc);
274 288 : if (tevent_req_nterror(req, status)) {
275 0 : return;
276 : }
277 :
278 288 : tevent_req_done(req);
279 : }
280 :
281 1572 : static NTSTATUS winbind_check_password_recv(struct tevent_req *req,
282 : TALLOC_CTX *mem_ctx,
283 : struct auth_user_info_dc **user_info_dc,
284 : const struct authn_audit_info **client_audit_info,
285 : const struct authn_audit_info **server_audit_info,
286 : bool *pauthoritative)
287 : {
288 6 : struct winbind_check_password_state *state =
289 1572 : tevent_req_data(req,
290 : struct winbind_check_password_state);
291 1572 : NTSTATUS status = NT_STATUS_OK;
292 :
293 1572 : *pauthoritative = state->authoritative;
294 1572 : *client_audit_info = NULL;
295 1572 : *server_audit_info = NULL;
296 :
297 1572 : if (tevent_req_is_nterror(req, &status)) {
298 1284 : tevent_req_received(req);
299 1284 : return status;
300 : }
301 :
302 288 : *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
303 :
304 288 : tevent_req_received(req);
305 288 : return NT_STATUS_OK;
306 : }
307 :
308 : static const struct auth_operations winbind_ops = {
309 : .name = "winbind",
310 : .want_check = winbind_want_check,
311 : .check_password_send = winbind_check_password_send,
312 : .check_password_recv = winbind_check_password_recv
313 : };
314 :
315 9681 : _PUBLIC_ NTSTATUS auth4_winbind_init(TALLOC_CTX *ctx)
316 : {
317 837 : NTSTATUS ret;
318 :
319 9681 : ret = auth_register(ctx, &winbind_ops);
320 9681 : if (!NT_STATUS_IS_OK(ret)) {
321 0 : DEBUG(0,("Failed to register 'winbind' auth backend!\n"));
322 0 : return ret;
323 : }
324 :
325 9681 : return NT_STATUS_OK;
326 : }
|