r13924: Split more prototypes out of include/proto.h + initial work on header
[kai/samba-autobuild/.git] / source4 / winbind / wb_connect_sam.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Connect to the SAMR pipe, given an smbcli_tree and possibly some
5    credentials. Try ntlmssp, schannel and anon in that order.
6
7    Copyright (C) Volker Lendecke 2005
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "libcli/composite/composite.h"
26
27 #include "libcli/raw/libcliraw.h"
28 #include "libcli/security/proto.h"
29 #include "librpc/gen_ndr/ndr_samr.h"
30
31
32 /* Helper to initialize SAMR with a specific auth methods. Verify by opening
33  * the SAM handle */
34
35 struct connect_samr_state {
36         struct composite_context *ctx;
37         uint8_t auth_type;
38         struct cli_credentials *creds;
39         struct dom_sid *sid;
40
41         struct dcerpc_pipe *samr_pipe;
42         struct policy_handle *connect_handle;
43         struct policy_handle *domain_handle;
44
45         struct samr_Connect2 c;
46         struct samr_OpenDomain o;
47 };
48
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);
54
55 struct composite_context *wb_connect_sam_send(TALLOC_CTX *mem_ctx,
56                                               struct smbcli_tree *tree,
57                                               uint8_t auth_type,
58                                               struct cli_credentials *creds,
59                                               const struct dom_sid *domain_sid)
60 {
61         struct composite_context *result, *ctx;
62         struct connect_samr_state *state;
63
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;
69
70         state = talloc(result, struct connect_samr_state);
71         if (state == NULL) goto failed;
72         state->ctx = result;
73         result->private_data = state;
74
75         state->auth_type = auth_type;
76         state->creds = creds;
77         state->sid = dom_sid_dup(state, domain_sid);
78         if (state->sid == NULL) goto failed;
79
80         state->samr_pipe = dcerpc_pipe_init(state, result->event_ctx);
81         if (state->samr_pipe == NULL) goto failed;
82
83         ctx = dcerpc_pipe_open_smb_send(state->samr_pipe->conn, tree,
84                                         "\\samr");
85         ctx->async.fn = connect_samr_recv_pipe;
86         ctx->async.private_data = state;
87         return result;
88         
89  failed:
90         talloc_free(result);
91         return NULL;
92 }
93
94 static void connect_samr_recv_pipe(struct composite_context *ctx)
95 {
96         struct connect_samr_state *state =
97                 talloc_get_type(ctx->async.private_data,
98                                 struct connect_samr_state);
99
100         state->ctx->status = dcerpc_pipe_open_smb_recv(ctx);
101         if (!composite_is_ok(state->ctx)) return;
102
103         switch (state->auth_type) {
104         case DCERPC_AUTH_TYPE_NONE:
105                 ctx = dcerpc_bind_auth_none_send(state, state->samr_pipe,
106                                                  &dcerpc_table_samr);
107                 composite_continue(state->ctx, ctx,
108                                    connect_samr_recv_anon_bind, state);
109                 break;
110         case DCERPC_AUTH_TYPE_NTLMSSP:
111         case DCERPC_AUTH_TYPE_SCHANNEL:
112         {
113                 uint8_t auth_type;
114                 if (lp_winbind_sealed_pipes()) {
115                         auth_type = DCERPC_AUTH_LEVEL_PRIVACY;
116                 } else {
117                         auth_type = DCERPC_AUTH_LEVEL_INTEGRITY;
118                 }
119                 if (state->creds == NULL) {
120                         composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
121                         return;
122                 }
123                 ctx = dcerpc_bind_auth_send(state, state->samr_pipe,
124                                             &dcerpc_table_samr,
125                                             state->creds, state->auth_type,
126                                             auth_type,
127                                             NULL);
128                 composite_continue(state->ctx, ctx,
129                                    connect_samr_recv_auth_bind, state);
130                 break;
131         }
132         default:
133                 composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
134         }
135 }
136
137 static void connect_samr_recv_anon_bind(struct composite_context *ctx)
138 {
139         struct connect_samr_state *state =
140                 talloc_get_type(ctx->async.private_data,
141                                 struct connect_samr_state);
142         struct rpc_request *req;
143
144         state->ctx->status = dcerpc_bind_auth_none_recv(ctx);
145         if (!composite_is_ok(state->ctx)) return;
146                         
147         state->connect_handle = talloc(state, struct policy_handle);
148         if (composite_nomem(state->connect_handle, state->ctx)) return;
149
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;
155
156         req = dcerpc_samr_Connect2_send(state->samr_pipe, state, &state->c);
157         composite_continue_rpc(state->ctx, req, connect_samr_recv_conn, state);
158 }
159
160 static void connect_samr_recv_auth_bind(struct composite_context *ctx)
161 {
162         struct connect_samr_state *state =
163                 talloc_get_type(ctx->async.private_data,
164                                 struct connect_samr_state);
165         struct rpc_request *req;
166
167         state->ctx->status = dcerpc_bind_auth_recv(ctx);
168         if (!composite_is_ok(state->ctx)) return;
169                         
170         state->connect_handle = talloc(state, struct policy_handle);
171         if (composite_nomem(state->connect_handle, state->ctx)) return;
172
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;
178
179         req = dcerpc_samr_Connect2_send(state->samr_pipe, state, &state->c);
180         composite_continue_rpc(state->ctx, req, connect_samr_recv_conn, state);
181 }
182
183 static void connect_samr_recv_conn(struct rpc_request *req)
184 {
185         struct connect_samr_state *state =
186                 talloc_get_type(req->async.private,
187                                 struct connect_samr_state);
188
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;
193
194         state->domain_handle = talloc(state, struct policy_handle);
195         if (composite_nomem(state->domain_handle, state->ctx)) return;
196
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;
201
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);
205 }
206
207 static void connect_samr_recv_open(struct rpc_request *req)
208 {
209         struct connect_samr_state *state =
210                 talloc_get_type(req->async.private,
211                                 struct connect_samr_state);
212
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;
217
218         composite_done(state->ctx);
219 }
220
221 NTSTATUS wb_connect_sam_recv(struct composite_context *c,
222                              TALLOC_CTX *mem_ctx,
223                              struct dcerpc_pipe **samr_pipe,
224                              struct policy_handle **connect_handle,
225                              struct policy_handle **domain_handle)
226 {
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);
235         }
236         talloc_free(c);
237         return status;
238 }
239
240 NTSTATUS wb_connect_sam(TALLOC_CTX *mem_ctx,
241                         struct smbcli_tree *tree,
242                         uint8_t auth_type,
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)
248 {
249         struct composite_context *c =
250                 wb_connect_sam_send(mem_ctx, tree, auth_type, creds,
251                                     domain_sid);
252         return wb_connect_sam_recv(c, mem_ctx, samr_pipe, connect_handle,
253                                    domain_handle);
254 }