libcli/cldap: make use of samba_tevent_context_init()
[Samba/gebeck_regimport.git] / source4 / winbind / wb_sam_logon.c
blobe940082791e5ddf405ff51af38342d4cd5ea5d19
1 /*
2 Unix SMB/CIFS implementation.
4 Do a netr_LogonSamLogon to a remote DC
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
8 Copyright (C) Stefan Metzmacher 2006
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.
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.
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/>.
24 #include "includes.h"
25 #include <tevent.h>
26 #include "../lib/util/tevent_ntstatus.h"
27 #include "libcli/composite/composite.h"
28 #include "winbind/wb_server.h"
29 #include "smbd/service_task.h"
30 #include "auth/credentials/credentials.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "librpc/gen_ndr/ndr_netlogon_c.h"
33 #include "librpc/gen_ndr/winbind.h"
35 struct wb_sam_logon_state {
36 struct tevent_context *ev;
38 struct winbind_SamLogon *req;
40 struct wbsrv_domain *domain;
41 struct tevent_queue_entry *queue_entry;
42 struct netlogon_creds_CredentialState *creds_state;
43 struct netr_Authenticator auth1, auth2;
45 TALLOC_CTX *r_mem_ctx;
46 struct netr_LogonSamLogon r;
49 static void wb_sam_logon_recv_domain(struct composite_context *ctx);
50 static void wb_sam_logon_queue_trigger(struct tevent_req *req, void *priv);
51 static void wb_sam_logon_recv_samlogon(struct tevent_req *subreq);
54 Find the connection to the DC (or find an existing connection)
56 struct tevent_req *wb_sam_logon_send(TALLOC_CTX *mem_ctx,
57 struct tevent_context *ev,
58 struct wbsrv_service *service,
59 struct winbind_SamLogon *_req)
61 struct tevent_req *req;
62 struct wb_sam_logon_state *state;
63 struct composite_context *csubreq;
65 req = tevent_req_create(mem_ctx, &state,
66 struct wb_sam_logon_state);
67 if (req == NULL) {
68 return NULL;
70 state->ev = ev;
71 state->req = _req;
73 csubreq = wb_sid2domain_send(state, service, service->primary_sid);
74 if (tevent_req_nomem(csubreq, req)) {
75 return tevent_req_post(req, ev);
77 csubreq->async.fn = wb_sam_logon_recv_domain;
78 csubreq->async.private_data = req;
80 return req;
84 Having finished making the connection to the DC
85 Send of a SamLogon request to authenticate a user.
87 static void wb_sam_logon_recv_domain(struct composite_context *csubreq)
89 struct tevent_req *req =
90 talloc_get_type_abort(csubreq->async.private_data,
91 struct tevent_req);
92 struct wb_sam_logon_state *state =
93 tevent_req_data(req,
94 struct wb_sam_logon_state);
95 NTSTATUS status;
96 struct tevent_queue_entry *e;
98 status = wb_sid2domain_recv(csubreq, &state->domain);
99 if (tevent_req_nterror(req, status)) {
100 return;
104 * Because of the netlogon_creds behavior we have to
105 * queue the netr_LogonSamLogon() calls
107 e = tevent_queue_add_entry(state->domain->netlogon_queue,
108 state->ev,
109 req,
110 wb_sam_logon_queue_trigger,
111 NULL);
112 state->queue_entry = e;
115 static void wb_sam_logon_queue_trigger(struct tevent_req *req, void *priv)
117 struct wb_sam_logon_state *state =
118 tevent_req_data(req,
119 struct wb_sam_logon_state);
120 struct wbsrv_domain *domain = state->domain;
121 struct tevent_req *subreq;
123 state->creds_state = cli_credentials_get_netlogon_creds(domain->libnet_ctx->cred);
124 netlogon_creds_client_authenticator(state->creds_state, &state->auth1);
126 state->r.in.server_name = talloc_asprintf(state, "\\\\%s",
127 dcerpc_server_name(domain->netlogon_pipe));
128 if (tevent_req_nomem(state->r.in.server_name, req)) {
129 return;
132 state->r.in.computer_name = cli_credentials_get_workstation(domain->libnet_ctx->cred);
133 state->r.in.credential = &state->auth1;
134 state->r.in.return_authenticator = &state->auth2;
135 state->r.in.logon_level = state->req->in.logon_level;
136 state->r.in.logon = &state->req->in.logon;
137 state->r.in.validation_level = state->req->in.validation_level;
138 state->r.out.return_authenticator = NULL;
139 state->r.out.validation = talloc(state, union netr_Validation);
140 if (tevent_req_nomem(state->r.out.validation, req)) {
141 return;
143 state->r.out.authoritative = talloc(state, uint8_t);
144 if (tevent_req_nomem(state->r.out.authoritative, req)) {
145 return;
149 * use a new talloc context for the LogonSamLogon call
150 * because then we can just to a talloc_steal on this context
151 * in the final _recv() function to give the caller all the content of
152 * the state->r.out.validation
154 state->r_mem_ctx = talloc_new(state);
155 if (tevent_req_nomem(state->r_mem_ctx, req)) {
156 return;
159 subreq = dcerpc_netr_LogonSamLogon_r_send(state,
160 state->ev,
161 domain->netlogon_pipe->binding_handle,
162 &state->r);
163 if (tevent_req_nomem(subreq, req)) {
164 return;
166 tevent_req_set_callback(subreq, wb_sam_logon_recv_samlogon, req);
170 NTLM Authentication
172 Check the SamLogon reply and decrypt the session keys
174 static void wb_sam_logon_recv_samlogon(struct tevent_req *subreq)
176 struct tevent_req *req =
177 tevent_req_callback_data(subreq,
178 struct tevent_req);
179 struct wb_sam_logon_state *state =
180 tevent_req_data(req,
181 struct wb_sam_logon_state);
182 NTSTATUS status;
183 bool ok;
185 status = dcerpc_netr_LogonSamLogon_r_recv(subreq, state->r_mem_ctx);
186 TALLOC_FREE(subreq);
187 if (tevent_req_nterror(req, status)) {
188 return;
191 if (tevent_req_nterror(req, state->r.out.result)) {
192 return;
195 if (state->r.out.return_authenticator == NULL) {
196 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
197 return;
200 ok = netlogon_creds_client_check(state->creds_state,
201 &state->r.out.return_authenticator->cred);
202 if (!ok) {
203 DEBUG(0, ("Credentials check failed!\n"));
204 tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED);
205 return;
208 /* Decrypt the session keys before we reform the info3, so the
209 * person on the other end of winbindd pipe doesn't have to.
210 * They won't have the encryption key anyway */
211 netlogon_creds_decrypt_samlogon_validation(state->creds_state,
212 state->r.in.validation_level,
213 state->r.out.validation);
216 * we do not need the netlogon_creds lock anymore
218 TALLOC_FREE(state->queue_entry);
220 tevent_req_done(req);
223 NTSTATUS wb_sam_logon_recv(struct tevent_req *req,
224 TALLOC_CTX *mem_ctx,
225 struct winbind_SamLogon *_req)
227 struct wb_sam_logon_state *state =
228 tevent_req_data(req,
229 struct wb_sam_logon_state);
230 NTSTATUS status;
232 if (tevent_req_is_nterror(req, &status)) {
233 tevent_req_received(req);
234 return status;
237 talloc_steal(mem_ctx, state->r_mem_ctx);
238 _req->out.validation = *state->r.out.validation;
239 _req->out.authoritative = 1;
241 tevent_req_received(req);
242 return NT_STATUS_OK;