2 Unix SMB/CIFS implementation.
4 Connect to the LSA pipe, given an smbcli_tree and possibly some
5 credentials. Try ntlmssp, schannel and anon in that order.
7 Copyright (C) Volker Lendecke 2005
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 2 of the License, or
12 (at your option) any later version.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "libcli/composite/composite.h"
27 #include "libcli/raw/libcliraw.h"
28 #include "librpc/gen_ndr/ndr_lsa_c.h"
30 /* Helper to initialize LSA with a specific auth methods. Verify by opening
33 struct init_lsa_state
{
34 struct composite_context
*ctx
;
35 struct dcerpc_pipe
*lsa_pipe
;
38 struct cli_credentials
*creds
;
40 struct lsa_ObjectAttribute objectattr
;
41 struct lsa_OpenPolicy2 openpolicy
;
42 struct policy_handle
*handle
;
45 static void init_lsa_recv_pipe(struct composite_context
*ctx
);
46 static void init_lsa_recv_anon_bind(struct composite_context
*ctx
);
47 static void init_lsa_recv_auth_bind(struct composite_context
*ctx
);
48 static void init_lsa_recv_openpol(struct rpc_request
*req
);
50 struct composite_context
*wb_init_lsa_send(TALLOC_CTX
*mem_ctx
,
51 struct smbcli_tree
*tree
,
53 struct cli_credentials
*creds
)
55 struct composite_context
*result
, *ctx
;
56 struct init_lsa_state
*state
;
58 result
= talloc(mem_ctx
, struct composite_context
);
59 if (result
== NULL
) goto failed
;
60 result
->state
= COMPOSITE_STATE_IN_PROGRESS
;
61 result
->async
.fn
= NULL
;
62 result
->event_ctx
= tree
->session
->transport
->socket
->event
.ctx
;
64 state
= talloc(result
, struct init_lsa_state
);
65 if (state
== NULL
) goto failed
;
67 result
->private_data
= state
;
69 state
->auth_type
= auth_type
;
72 state
->lsa_pipe
= dcerpc_pipe_init(state
, result
->event_ctx
);
73 if (state
->lsa_pipe
== NULL
) goto failed
;
75 ctx
= dcerpc_pipe_open_smb_send(state
->lsa_pipe
->conn
, tree
,
77 ctx
->async
.fn
= init_lsa_recv_pipe
;
78 ctx
->async
.private_data
= state
;
86 static void init_lsa_recv_pipe(struct composite_context
*ctx
)
88 struct init_lsa_state
*state
=
89 talloc_get_type(ctx
->async
.private_data
,
90 struct init_lsa_state
);
92 state
->ctx
->status
= dcerpc_pipe_open_smb_recv(ctx
);
93 if (!composite_is_ok(state
->ctx
)) return;
95 switch (state
->auth_type
) {
96 case DCERPC_AUTH_TYPE_NONE
:
97 ctx
= dcerpc_bind_auth_none_send(state
, state
->lsa_pipe
,
98 &dcerpc_table_lsarpc
);
99 composite_continue(state
->ctx
, ctx
, init_lsa_recv_anon_bind
,
102 case DCERPC_AUTH_TYPE_NTLMSSP
:
103 case DCERPC_AUTH_TYPE_SCHANNEL
:
106 if (lp_winbind_sealed_pipes()) {
107 auth_type
= DCERPC_AUTH_LEVEL_PRIVACY
;
109 auth_type
= DCERPC_AUTH_LEVEL_INTEGRITY
;
111 if (state
->creds
== NULL
) {
112 composite_error(state
->ctx
, NT_STATUS_INTERNAL_ERROR
);
115 ctx
= dcerpc_bind_auth_send(state
, state
->lsa_pipe
,
116 &dcerpc_table_lsarpc
,
117 state
->creds
, state
->auth_type
,
120 composite_continue(state
->ctx
, ctx
, init_lsa_recv_auth_bind
,
125 composite_error(state
->ctx
, NT_STATUS_INTERNAL_ERROR
);
129 static void init_lsa_recv_anon_bind(struct composite_context
*ctx
)
131 struct init_lsa_state
*state
=
132 talloc_get_type(ctx
->async
.private_data
,
133 struct init_lsa_state
);
134 struct rpc_request
*req
;
136 state
->ctx
->status
= dcerpc_bind_auth_none_recv(ctx
);
137 if (!composite_is_ok(state
->ctx
)) return;
139 state
->handle
= talloc(state
, struct policy_handle
);
140 if (composite_nomem(state
->handle
, state
->ctx
)) return;
142 state
->openpolicy
.in
.system_name
=
143 talloc_asprintf(state
, "\\\\%s",
144 dcerpc_server_name(state
->lsa_pipe
));
145 ZERO_STRUCT(state
->objectattr
);
146 state
->openpolicy
.in
.attr
= &state
->objectattr
;
147 state
->openpolicy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
148 state
->openpolicy
.out
.handle
= state
->handle
;
150 req
= dcerpc_lsa_OpenPolicy2_send(state
->lsa_pipe
, state
,
152 composite_continue_rpc(state
->ctx
, req
, init_lsa_recv_openpol
, state
);
155 static void init_lsa_recv_auth_bind(struct composite_context
*ctx
)
157 struct init_lsa_state
*state
=
158 talloc_get_type(ctx
->async
.private_data
,
159 struct init_lsa_state
);
160 struct rpc_request
*req
;
162 state
->ctx
->status
= dcerpc_bind_auth_recv(ctx
);
163 if (!composite_is_ok(state
->ctx
)) return;
165 state
->handle
= talloc(state
, struct policy_handle
);
166 if (composite_nomem(state
->handle
, state
->ctx
)) return;
168 state
->openpolicy
.in
.system_name
=
169 talloc_asprintf(state
, "\\\\%s",
170 dcerpc_server_name(state
->lsa_pipe
));
171 ZERO_STRUCT(state
->objectattr
);
172 state
->openpolicy
.in
.attr
= &state
->objectattr
;
173 state
->openpolicy
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
174 state
->openpolicy
.out
.handle
= state
->handle
;
176 req
= dcerpc_lsa_OpenPolicy2_send(state
->lsa_pipe
, state
,
178 composite_continue_rpc(state
->ctx
, req
, init_lsa_recv_openpol
, state
);
181 static void init_lsa_recv_openpol(struct rpc_request
*req
)
183 struct init_lsa_state
*state
=
184 talloc_get_type(req
->async
.private,
185 struct init_lsa_state
);
187 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
188 if (!composite_is_ok(state
->ctx
)) return;
189 state
->ctx
->status
= state
->openpolicy
.out
.result
;
190 if (!composite_is_ok(state
->ctx
)) return;
192 composite_done(state
->ctx
);
195 NTSTATUS
wb_init_lsa_recv(struct composite_context
*c
,
197 struct dcerpc_pipe
**lsa_pipe
,
198 struct policy_handle
**lsa_policy
)
200 NTSTATUS status
= composite_wait(c
);
201 if (NT_STATUS_IS_OK(status
)) {
202 struct init_lsa_state
*state
=
203 talloc_get_type(c
->private_data
,
204 struct init_lsa_state
);
205 *lsa_pipe
= talloc_steal(mem_ctx
, state
->lsa_pipe
);
206 *lsa_policy
= talloc_steal(mem_ctx
, state
->handle
);
214 * Connect to LSA using the credentials, try NTLMSSP and SCHANNEL using the
215 * given credentials. If both fail or no credentials are available, fall back
216 * to an anonymous bind.
219 struct connect_lsa_state
{
220 struct composite_context
*ctx
;
221 struct smbcli_tree
*tree
;
222 struct cli_credentials
*credentials
;
225 struct dcerpc_pipe
*lsa_pipe
;
226 struct policy_handle
*lsa_policy
;
229 static void connect_lsa_recv_ntlmssp(struct composite_context
*ctx
);
230 static void connect_lsa_recv_schannel(struct composite_context
*ctx
);
231 static void connect_lsa_recv_anon(struct composite_context
*ctx
);
233 struct composite_context
*wb_connect_lsa_send(TALLOC_CTX
*mem_ctx
,
234 struct smbcli_tree
*tree
,
235 struct cli_credentials
*credentials
)
237 struct composite_context
*result
, *ctx
;
238 struct connect_lsa_state
*state
;
240 result
= talloc(mem_ctx
, struct composite_context
);
241 if (result
== NULL
) goto failed
;
242 result
->state
= COMPOSITE_STATE_IN_PROGRESS
;
243 result
->async
.fn
= NULL
;
244 result
->event_ctx
= tree
->session
->transport
->socket
->event
.ctx
;
246 state
= talloc(result
, struct connect_lsa_state
);
247 if (state
== NULL
) goto failed
;
249 result
->private_data
= state
;
252 state
->credentials
= credentials
;
254 if (credentials
== NULL
) {
255 ctx
= wb_init_lsa_send(state
, tree
, DCERPC_AUTH_TYPE_NONE
,
257 if (ctx
== NULL
) goto failed
;
258 ctx
->async
.fn
= connect_lsa_recv_anon
;
259 ctx
->async
.private_data
= state
;
263 ctx
= wb_init_lsa_send(state
, tree
, DCERPC_AUTH_TYPE_NTLMSSP
,
265 if (ctx
== NULL
) goto failed
;
266 ctx
->async
.fn
= connect_lsa_recv_ntlmssp
;
267 ctx
->async
.private_data
= state
;
275 static void connect_lsa_recv_ntlmssp(struct composite_context
*ctx
)
277 struct connect_lsa_state
*state
=
278 talloc_get_type(ctx
->async
.private_data
,
279 struct connect_lsa_state
);
281 state
->ctx
->status
= wb_init_lsa_recv(ctx
, state
, &state
->lsa_pipe
,
284 if (NT_STATUS_IS_OK(state
->ctx
->status
)) {
285 state
->auth_type
= DCERPC_AUTH_TYPE_NTLMSSP
;
286 composite_done(state
->ctx
);
290 ctx
= wb_init_lsa_send(state
, state
->tree
, DCERPC_AUTH_TYPE_SCHANNEL
,
292 composite_continue(state
->ctx
, ctx
,
293 connect_lsa_recv_schannel
, state
);
296 static void connect_lsa_recv_schannel(struct composite_context
*ctx
)
298 struct connect_lsa_state
*state
=
299 talloc_get_type(ctx
->async
.private_data
,
300 struct connect_lsa_state
);
302 state
->ctx
->status
= wb_init_lsa_recv(ctx
, state
, &state
->lsa_pipe
,
305 if (NT_STATUS_IS_OK(state
->ctx
->status
)) {
306 state
->auth_type
= DCERPC_AUTH_TYPE_SCHANNEL
;
307 composite_done(state
->ctx
);
311 ctx
= wb_init_lsa_send(state
, state
->tree
, DCERPC_AUTH_TYPE_NONE
,
313 composite_continue(state
->ctx
, ctx
,
314 connect_lsa_recv_anon
, state
);
317 static void connect_lsa_recv_anon(struct composite_context
*ctx
)
319 struct connect_lsa_state
*state
=
320 talloc_get_type(ctx
->async
.private_data
,
321 struct connect_lsa_state
);
323 state
->ctx
->status
= wb_init_lsa_recv(ctx
, state
, &state
->lsa_pipe
,
325 if (!composite_is_ok(state
->ctx
)) return;
327 state
->auth_type
= DCERPC_AUTH_TYPE_NONE
;
328 composite_done(state
->ctx
);
331 NTSTATUS
wb_connect_lsa_recv(struct composite_context
*c
,
334 struct dcerpc_pipe
**lsa_pipe
,
335 struct policy_handle
**lsa_policy
)
337 NTSTATUS status
= composite_wait(c
);
338 if (NT_STATUS_IS_OK(status
)) {
339 struct connect_lsa_state
*state
=
340 talloc_get_type(c
->private_data
,
341 struct connect_lsa_state
);
342 *auth_type
= state
->auth_type
;
343 *lsa_pipe
= talloc_steal(mem_ctx
, state
->lsa_pipe
);
344 *lsa_policy
= talloc_steal(mem_ctx
, state
->lsa_policy
);
350 NTSTATUS
wb_connect_lsa(TALLOC_CTX
*mem_ctx
,
351 struct smbcli_tree
*tree
,
352 struct cli_credentials
*credentials
,
354 struct dcerpc_pipe
**lsa_pipe
,
355 struct policy_handle
**lsa_policy
)
357 struct composite_context
*c
;
358 c
= wb_connect_lsa_send(mem_ctx
, tree
, credentials
);
359 return wb_connect_lsa_recv(c
, mem_ctx
, auth_type
, lsa_pipe
,