2 Unix SMB/CIFS implementation.
4 Async helpers for blocking functions
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Gerald Carter 2006
9 The helpers always consist of three functions:
11 * A request setup function that takes the necessary parameters together
12 with a continuation function that is to be called upon completion
14 * A private continuation function that is internal only. This is to be
15 called by the lower-level functions in do_async(). Its only task is to
16 properly call the continuation function named above.
18 * A worker function that is called inside the appropriate child process.
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 3 of the License, or
23 (at your option) any later version.
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with this program. If not, see <http://www.gnu.org/licenses/>.
38 #define DBGC_CLASS DBGC_WINBIND
40 struct do_async_state
{
42 struct winbindd_request request
;
43 struct winbindd_response response
;
44 void (*cont
)(TALLOC_CTX
*mem_ctx
,
46 struct winbindd_response
*response
,
47 void *c
, void *private_data
);
48 void *c
, *private_data
;
51 static void do_async_recv(void *private_data
, bool success
)
53 struct do_async_state
*state
=
54 talloc_get_type_abort(private_data
, struct do_async_state
);
56 state
->cont(state
->mem_ctx
, success
, &state
->response
,
57 state
->c
, state
->private_data
);
60 void do_async(TALLOC_CTX
*mem_ctx
, struct winbindd_child
*child
,
61 const struct winbindd_request
*request
,
62 void (*cont
)(TALLOC_CTX
*mem_ctx
, bool success
,
63 struct winbindd_response
*response
,
64 void *c
, void *private_data
),
65 void *c
, void *private_data
)
67 struct do_async_state
*state
;
69 state
= TALLOC_ZERO_P(mem_ctx
, struct do_async_state
);
71 DEBUG(0, ("talloc failed\n"));
72 cont(mem_ctx
, False
, NULL
, c
, private_data
);
76 state
->mem_ctx
= mem_ctx
;
77 state
->request
= *request
;
78 state
->request
.length
= sizeof(state
->request
);
81 state
->private_data
= private_data
;
83 async_request(mem_ctx
, child
, &state
->request
,
84 &state
->response
, do_async_recv
, state
);
87 static void do_async_domain(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
88 const struct winbindd_request
*request
,
89 void (*cont
)(TALLOC_CTX
*mem_ctx
, bool success
,
90 struct winbindd_response
*response
,
91 void *c
, void *private_data
),
92 void *c
, void *private_data
)
94 struct do_async_state
*state
;
96 state
= TALLOC_ZERO_P(mem_ctx
, struct do_async_state
);
98 DEBUG(0, ("talloc failed\n"));
99 cont(mem_ctx
, False
, NULL
, c
, private_data
);
103 state
->mem_ctx
= mem_ctx
;
104 state
->request
= *request
;
105 state
->request
.length
= sizeof(state
->request
);
108 state
->private_data
= private_data
;
110 async_domain_request(mem_ctx
, domain
, &state
->request
,
111 &state
->response
, do_async_recv
, state
);
114 enum winbindd_result
winbindd_dual_lookupsid(struct winbindd_domain
*domain
,
115 struct winbindd_cli_state
*state
)
117 enum lsa_SidType type
;
122 /* Ensure null termination */
123 state
->request
->data
.sid
[sizeof(state
->request
->data
.sid
)-1]='\0';
125 DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state
->pid
,
126 state
->request
->data
.sid
));
128 /* Lookup sid from PDC using lsa_lookup_sids() */
130 if (!string_to_sid(&sid
, state
->request
->data
.sid
)) {
131 DEBUG(5, ("%s not a SID\n", state
->request
->data
.sid
));
132 return WINBINDD_ERROR
;
137 if (!winbindd_lookup_name_by_sid(state
->mem_ctx
, domain
, &sid
,
138 &dom_name
, &name
, &type
))
140 TALLOC_FREE(dom_name
);
142 return WINBINDD_ERROR
;
145 fstrcpy(state
->response
->data
.name
.dom_name
, dom_name
);
146 fstrcpy(state
->response
->data
.name
.name
, name
);
147 state
->response
->data
.name
.type
= type
;
149 TALLOC_FREE(dom_name
);
154 enum winbindd_result
winbindd_dual_lookupname(struct winbindd_domain
*domain
,
155 struct winbindd_cli_state
*state
)
157 enum lsa_SidType type
;
158 char *name_domain
, *name_user
;
162 /* Ensure null termination */
163 state
->request
->data
.name
.dom_name
[sizeof(state
->request
->data
.name
.dom_name
)-1]='\0';
165 /* Ensure null termination */
166 state
->request
->data
.name
.name
[sizeof(state
->request
->data
.name
.name
)-1]='\0';
168 /* cope with the name being a fully qualified name */
169 p
= strstr(state
->request
->data
.name
.name
, lp_winbind_separator());
172 name_domain
= state
->request
->data
.name
.name
;
175 name_domain
= state
->request
->data
.name
.dom_name
;
176 name_user
= state
->request
->data
.name
.name
;
179 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state
->pid
,
180 name_domain
, lp_winbind_separator(), name_user
));
182 /* Lookup name from DC using lsa_lookup_names() */
183 if (!winbindd_lookup_sid_by_name(state
->mem_ctx
, state
->request
->original_cmd
, domain
, name_domain
,
184 name_user
, &sid
, &type
)) {
185 return WINBINDD_ERROR
;
188 sid_to_fstring(state
->response
->data
.sid
.sid
, &sid
);
189 state
->response
->data
.sid
.type
= type
;
194 bool print_sidlist(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sids
,
195 size_t num_sids
, char **result
, ssize_t
*len
)
202 for (i
=0; i
<num_sids
; i
++) {
204 sprintf_append(mem_ctx
, result
, len
, &buflen
,
205 "%s\n", sid_to_fstring(tmp
, &sids
[i
]));
208 if ((num_sids
!= 0) && (*result
== NULL
)) {
215 bool parse_sidlist(TALLOC_CTX
*mem_ctx
, const char *sidstr
,
216 DOM_SID
**sids
, size_t *num_sids
)
224 while (p
[0] != '\0') {
230 DEBUG(0, ("Got invalid sidstr: %s\n", p
));
233 sidlen
= PTR_DIFF(q
, p
);
234 if (sidlen
>= sizeof(tmp
)-1) {
237 memcpy(tmp
, p
, sidlen
);
240 if (!string_to_sid(&sid
, tmp
)) {
241 DEBUG(0, ("Could not parse sid %s\n", p
));
244 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx
, &sid
, sids
,
254 static void getsidaliases_recv(TALLOC_CTX
*mem_ctx
, bool success
,
255 struct winbindd_response
*response
,
256 void *c
, void *private_data
)
258 void (*cont
)(void *priv
, bool succ
,
259 DOM_SID
*aliases
, size_t num_aliases
) =
260 (void (*)(void *, bool, DOM_SID
*, size_t))c
;
262 DOM_SID
*sids
= NULL
;
266 DEBUG(5, ("Could not trigger getsidaliases\n"));
267 cont(private_data
, success
, NULL
, 0);
271 if (response
->result
!= WINBINDD_OK
) {
272 DEBUG(5, ("getsidaliases returned an error\n"));
273 cont(private_data
, False
, NULL
, 0);
277 aliases_str
= (char *)response
->extra_data
.data
;
279 if (aliases_str
== NULL
) {
280 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
281 cont(private_data
, True
, NULL
, 0);
285 if (!parse_sidlist(mem_ctx
, aliases_str
, &sids
, &num_sids
)) {
286 DEBUG(0, ("Could not parse sids\n"));
287 cont(private_data
, False
, NULL
, 0);
291 cont(private_data
, True
, sids
, num_sids
);
294 void winbindd_getsidaliases_async(struct winbindd_domain
*domain
,
296 const DOM_SID
*sids
, size_t num_sids
,
297 void (*cont
)(void *private_data
,
299 const DOM_SID
*aliases
,
303 struct winbindd_request request
;
308 cont(private_data
, True
, NULL
, 0);
312 if (!print_sidlist(mem_ctx
, sids
, num_sids
, &sidstr
, &len
)) {
313 cont(private_data
, False
, NULL
, 0);
317 ZERO_STRUCT(request
);
318 request
.cmd
= WINBINDD_DUAL_GETSIDALIASES
;
319 request
.extra_len
= len
;
320 request
.extra_data
.data
= sidstr
;
322 do_async_domain(mem_ctx
, domain
, &request
, getsidaliases_recv
,
323 (void *)cont
, private_data
);
326 static void query_user_recv(TALLOC_CTX
*mem_ctx
, bool success
,
327 struct winbindd_response
*response
,
328 void *c
, void *private_data
)
330 void (*cont
)(void *priv
, bool succ
, const char *acct_name
,
331 const char *full_name
, const char *homedir
,
332 const char *shell
, uint32 gid
, uint32 group_rid
) =
333 (void (*)(void *, bool, const char *, const char *,
334 const char *, const char *, uint32
, uint32
))c
;
337 DEBUG(5, ("Could not trigger query_user\n"));
338 cont(private_data
, False
, NULL
, NULL
, NULL
, NULL
, -1, -1);
342 if (response
->result
!= WINBINDD_OK
) {
343 DEBUG(5, ("query_user returned an error\n"));
344 cont(private_data
, False
, NULL
, NULL
, NULL
, NULL
, -1, -1);
348 cont(private_data
, True
, response
->data
.user_info
.acct_name
,
349 response
->data
.user_info
.full_name
,
350 response
->data
.user_info
.homedir
,
351 response
->data
.user_info
.shell
,
352 response
->data
.user_info
.primary_gid
,
353 response
->data
.user_info
.group_rid
);
356 void query_user_async(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
358 void (*cont
)(void *private_data
, bool success
,
359 const char *acct_name
,
360 const char *full_name
,
367 struct winbindd_request request
;
368 ZERO_STRUCT(request
);
369 request
.cmd
= WINBINDD_DUAL_USERINFO
;
370 sid_to_fstring(request
.data
.sid
, sid
);
371 do_async_domain(mem_ctx
, domain
, &request
, query_user_recv
,
372 (void *)cont
, private_data
);
375 enum winbindd_result
winbindd_dual_ping(struct winbindd_domain
*domain
,
376 struct winbindd_cli_state
*state
)