2 Unix SMB/CIFS implementation.
4 Connect to the SAMR 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 "libcli/security/security.h"
29 #include "librpc/gen_ndr/ndr_samr_c.h"
32 /* Helper to initialize SAMR with a specific auth methods. Verify by opening
35 struct connect_samr_state
{
36 struct composite_context
*ctx
;
38 struct cli_credentials
*creds
;
41 struct dcerpc_pipe
*samr_pipe
;
42 struct policy_handle
*connect_handle
;
43 struct policy_handle
*domain_handle
;
45 struct samr_Connect2 c
;
46 struct samr_OpenDomain o
;
49 static void connect_samr_recv_pipe(struct composite_context
*ctx
);
50 static void connect_samr_recv_anon_bind(struct composite_context
*ctx
);
51 static void connect_samr_recv_auth_bind(struct composite_context
*ctx
);
52 static void connect_samr_recv_conn(struct rpc_request
*req
);
53 static void connect_samr_recv_open(struct rpc_request
*req
);
55 struct composite_context
*wb_connect_sam_send(TALLOC_CTX
*mem_ctx
,
56 struct smbcli_tree
*tree
,
58 struct cli_credentials
*creds
,
59 const struct dom_sid
*domain_sid
)
61 struct composite_context
*result
, *ctx
;
62 struct connect_samr_state
*state
;
64 result
= talloc(mem_ctx
, struct composite_context
);
65 if (result
== NULL
) goto failed
;
66 result
->state
= COMPOSITE_STATE_IN_PROGRESS
;
67 result
->async
.fn
= NULL
;
68 result
->event_ctx
= tree
->session
->transport
->socket
->event
.ctx
;
70 state
= talloc(result
, struct connect_samr_state
);
71 if (state
== NULL
) goto failed
;
73 result
->private_data
= state
;
75 state
->auth_type
= auth_type
;
77 state
->sid
= dom_sid_dup(state
, domain_sid
);
78 if (state
->sid
== NULL
) goto failed
;
80 state
->samr_pipe
= dcerpc_pipe_init(state
, result
->event_ctx
);
81 if (state
->samr_pipe
== NULL
) goto failed
;
83 ctx
= dcerpc_pipe_open_smb_send(state
->samr_pipe
, tree
,
85 ctx
->async
.fn
= connect_samr_recv_pipe
;
86 ctx
->async
.private_data
= state
;
94 static void connect_samr_recv_pipe(struct composite_context
*ctx
)
96 struct connect_samr_state
*state
=
97 talloc_get_type(ctx
->async
.private_data
,
98 struct connect_samr_state
);
100 state
->ctx
->status
= dcerpc_pipe_open_smb_recv(ctx
);
101 if (!composite_is_ok(state
->ctx
)) return;
103 switch (state
->auth_type
) {
104 case DCERPC_AUTH_TYPE_NONE
:
105 ctx
= dcerpc_bind_auth_none_send(state
, state
->samr_pipe
,
107 composite_continue(state
->ctx
, ctx
,
108 connect_samr_recv_anon_bind
, state
);
110 case DCERPC_AUTH_TYPE_NTLMSSP
:
111 case DCERPC_AUTH_TYPE_SCHANNEL
:
114 if (lp_winbind_sealed_pipes()) {
115 auth_type
= DCERPC_AUTH_LEVEL_PRIVACY
;
117 auth_type
= DCERPC_AUTH_LEVEL_INTEGRITY
;
119 if (state
->creds
== NULL
) {
120 composite_error(state
->ctx
, NT_STATUS_INTERNAL_ERROR
);
123 ctx
= dcerpc_bind_auth_send(state
, state
->samr_pipe
,
125 state
->creds
, state
->auth_type
,
128 composite_continue(state
->ctx
, ctx
,
129 connect_samr_recv_auth_bind
, state
);
133 composite_error(state
->ctx
, NT_STATUS_INTERNAL_ERROR
);
137 static void connect_samr_recv_anon_bind(struct composite_context
*ctx
)
139 struct connect_samr_state
*state
=
140 talloc_get_type(ctx
->async
.private_data
,
141 struct connect_samr_state
);
142 struct rpc_request
*req
;
144 state
->ctx
->status
= dcerpc_bind_auth_none_recv(ctx
);
145 if (!composite_is_ok(state
->ctx
)) return;
147 state
->connect_handle
= talloc(state
, struct policy_handle
);
148 if (composite_nomem(state
->connect_handle
, state
->ctx
)) return;
150 state
->c
.in
.system_name
=
151 talloc_asprintf(state
, "\\\\%s",
152 dcerpc_server_name(state
->samr_pipe
));
153 state
->c
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
154 state
->c
.out
.connect_handle
= state
->connect_handle
;
156 req
= dcerpc_samr_Connect2_send(state
->samr_pipe
, state
, &state
->c
);
157 composite_continue_rpc(state
->ctx
, req
, connect_samr_recv_conn
, state
);
160 static void connect_samr_recv_auth_bind(struct composite_context
*ctx
)
162 struct connect_samr_state
*state
=
163 talloc_get_type(ctx
->async
.private_data
,
164 struct connect_samr_state
);
165 struct rpc_request
*req
;
167 state
->ctx
->status
= dcerpc_bind_auth_recv(ctx
);
168 if (!composite_is_ok(state
->ctx
)) return;
170 state
->connect_handle
= talloc(state
, struct policy_handle
);
171 if (composite_nomem(state
->connect_handle
, state
->ctx
)) return;
173 state
->c
.in
.system_name
=
174 talloc_asprintf(state
, "\\\\%s",
175 dcerpc_server_name(state
->samr_pipe
));
176 state
->c
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
177 state
->c
.out
.connect_handle
= state
->connect_handle
;
179 req
= dcerpc_samr_Connect2_send(state
->samr_pipe
, state
, &state
->c
);
180 composite_continue_rpc(state
->ctx
, req
, connect_samr_recv_conn
, state
);
183 static void connect_samr_recv_conn(struct rpc_request
*req
)
185 struct connect_samr_state
*state
=
186 talloc_get_type(req
->async
.private,
187 struct connect_samr_state
);
189 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
190 if (!composite_is_ok(state
->ctx
)) return;
191 state
->ctx
->status
= state
->c
.out
.result
;
192 if (!composite_is_ok(state
->ctx
)) return;
194 state
->domain_handle
= talloc(state
, struct policy_handle
);
195 if (composite_nomem(state
->domain_handle
, state
->ctx
)) return;
197 state
->o
.in
.connect_handle
= state
->connect_handle
;
198 state
->o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
199 state
->o
.in
.sid
= state
->sid
;
200 state
->o
.out
.domain_handle
= state
->domain_handle
;
202 req
= dcerpc_samr_OpenDomain_send(state
->samr_pipe
, state
, &state
->o
);
203 composite_continue_rpc(state
->ctx
, req
,
204 connect_samr_recv_open
, state
);
207 static void connect_samr_recv_open(struct rpc_request
*req
)
209 struct connect_samr_state
*state
=
210 talloc_get_type(req
->async
.private,
211 struct connect_samr_state
);
213 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
214 if (!composite_is_ok(state
->ctx
)) return;
215 state
->ctx
->status
= state
->o
.out
.result
;
216 if (!composite_is_ok(state
->ctx
)) return;
218 composite_done(state
->ctx
);
221 NTSTATUS
wb_connect_sam_recv(struct composite_context
*c
,
223 struct dcerpc_pipe
**samr_pipe
,
224 struct policy_handle
**connect_handle
,
225 struct policy_handle
**domain_handle
)
227 NTSTATUS status
= composite_wait(c
);
228 if (NT_STATUS_IS_OK(status
)) {
229 struct connect_samr_state
*state
=
230 talloc_get_type(c
->private_data
,
231 struct connect_samr_state
);
232 *samr_pipe
= talloc_steal(mem_ctx
, state
->samr_pipe
);
233 *connect_handle
= talloc_steal(mem_ctx
, state
->connect_handle
);
234 *domain_handle
= talloc_steal(mem_ctx
, state
->domain_handle
);
240 NTSTATUS
wb_connect_sam(TALLOC_CTX
*mem_ctx
,
241 struct smbcli_tree
*tree
,
243 struct cli_credentials
*creds
,
244 const struct dom_sid
*domain_sid
,
245 struct dcerpc_pipe
**samr_pipe
,
246 struct policy_handle
**connect_handle
,
247 struct policy_handle
**domain_handle
)
249 struct composite_context
*c
=
250 wb_connect_sam_send(mem_ctx
, tree
, auth_type
, creds
,
252 return wb_connect_sam_recv(c
, mem_ctx
, samr_pipe
, connect_handle
,