s3: Add winbindd_lookupsids
[ira/wip.git] / source3 / winbindd / winbindd_lookupsids.c
1 /*
2    Unix SMB/CIFS implementation.
3    async implementation of WINBINDD_LOOKUPSIDS
4    Copyright (C) Volker Lendecke 2011
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "winbindd.h"
22 #include "../libcli/security/security.h"
23
24 struct winbindd_lookupsids_state {
25         struct dom_sid *sids;
26         uint32_t num_sids;
27         struct lsa_RefDomainList *domains;
28         struct lsa_TransNameArray *names;
29 };
30
31 static void winbindd_lookupsids_done(struct tevent_req *subreq);
32
33 struct tevent_req *winbindd_lookupsids_send(TALLOC_CTX *mem_ctx,
34                                             struct tevent_context *ev,
35                                            struct winbindd_cli_state *cli,
36                                            struct winbindd_request *request)
37 {
38         struct tevent_req *req, *subreq;
39         struct winbindd_lookupsids_state *state;
40
41         req = tevent_req_create(mem_ctx, &state,
42                                 struct winbindd_lookupsids_state);
43         if (req == NULL) {
44                 return NULL;
45         }
46
47         DEBUG(3, ("lookupsids\n"));
48
49         if (request->extra_len == 0) {
50                 tevent_req_done(req);
51                 return tevent_req_post(req, ev);
52         }
53         if (request->extra_data.data[request->extra_len-1] != '\0') {
54                 DEBUG(10, ("Got invalid sids list\n"));
55                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
56                 return tevent_req_post(req, ev);
57         }
58         if (!parse_sidlist(state, request->extra_data.data,
59                            &state->sids, &state->num_sids)) {
60                 DEBUG(10, ("parse_sidlist failed\n"));
61                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
62                 return tevent_req_post(req, ev);
63         }
64         subreq = wb_lookupsids_send(state, ev, state->sids, state->num_sids);
65         if (tevent_req_nomem(subreq, req)) {
66                 return tevent_req_post(req, ev);
67         }
68         tevent_req_set_callback(subreq, winbindd_lookupsids_done, req);
69         return req;
70 }
71
72 static void winbindd_lookupsids_done(struct tevent_req *subreq)
73 {
74         struct tevent_req *req = tevent_req_callback_data(
75                 subreq, struct tevent_req);
76         struct winbindd_lookupsids_state *state = tevent_req_data(
77                 req, struct winbindd_lookupsids_state);
78         NTSTATUS status;
79
80         status = wb_lookupsids_recv(subreq, state, &state->domains,
81                                     &state->names);
82         TALLOC_FREE(subreq);
83         if (!NT_STATUS_IS_OK(status)) {
84                 tevent_req_nterror(req, status);
85                 return;
86         }
87         tevent_req_done(req);
88 }
89
90 NTSTATUS winbindd_lookupsids_recv(struct tevent_req *req,
91                                   struct winbindd_response *response)
92 {
93         struct winbindd_lookupsids_state *state = tevent_req_data(
94                 req, struct winbindd_lookupsids_state);
95         NTSTATUS status;
96         char *result;
97         uint32_t i;
98
99         if (tevent_req_is_nterror(req, &status)) {
100                 DEBUG(5, ("wb_lookupsids failed: %s\n", nt_errstr(status)));
101                 return status;
102         }
103
104         result = talloc_asprintf(response, "%d\n", (int)state->domains->count);
105         if (result == NULL) {
106                 return NT_STATUS_NO_MEMORY;
107         }
108
109         for (i=0; i<state->domains->count; i++) {
110                 fstring sid_str;
111
112                 result = talloc_asprintf_append_buffer(
113                         result, "%s %s\n",
114                         sid_to_fstring(sid_str,
115                                        state->domains->domains[i].sid),
116                         state->domains->domains[i].name.string);
117                 if (result == NULL) {
118                         return NT_STATUS_NO_MEMORY;
119                 }
120         }
121
122         result = talloc_asprintf_append_buffer(
123                 result, "%d\n", (int)state->names->count);
124         if (result == NULL) {
125                 return NT_STATUS_NO_MEMORY;
126         }
127
128         for (i=0; i<state->names->count; i++) {
129                 struct lsa_TranslatedName *name;
130
131                 name = &state->names->names[i];
132
133                 result = talloc_asprintf_append_buffer(
134                         result, "%d %d %s\n",
135                         (int)name->sid_index, (int)name->sid_type,
136                         name->name.string);
137                 if (result == NULL) {
138                         return NT_STATUS_NO_MEMORY;
139                 }
140         }
141
142         response->extra_data.data = result;
143         response->length += talloc_get_size(result);
144         return NT_STATUS_OK;
145 }