Merge 2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 as Samba-4.0alpha16
[amitay/samba.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 (tevent_req_nterror(req, status)) {
84                 return;
85         }
86         tevent_req_done(req);
87 }
88
89 NTSTATUS winbindd_lookupsids_recv(struct tevent_req *req,
90                                   struct winbindd_response *response)
91 {
92         struct winbindd_lookupsids_state *state = tevent_req_data(
93                 req, struct winbindd_lookupsids_state);
94         NTSTATUS status;
95         char *result;
96         uint32_t i;
97
98         if (tevent_req_is_nterror(req, &status)) {
99                 DEBUG(5, ("wb_lookupsids failed: %s\n", nt_errstr(status)));
100                 return status;
101         }
102
103         result = talloc_asprintf(response, "%d\n", (int)state->domains->count);
104         if (result == NULL) {
105                 return NT_STATUS_NO_MEMORY;
106         }
107
108         for (i=0; i<state->domains->count; i++) {
109                 fstring sid_str;
110
111                 result = talloc_asprintf_append_buffer(
112                         result, "%s %s\n",
113                         sid_to_fstring(sid_str,
114                                        state->domains->domains[i].sid),
115                         state->domains->domains[i].name.string);
116                 if (result == NULL) {
117                         return NT_STATUS_NO_MEMORY;
118                 }
119         }
120
121         result = talloc_asprintf_append_buffer(
122                 result, "%d\n", (int)state->names->count);
123         if (result == NULL) {
124                 return NT_STATUS_NO_MEMORY;
125         }
126
127         for (i=0; i<state->names->count; i++) {
128                 struct lsa_TranslatedName *name;
129
130                 name = &state->names->names[i];
131
132                 result = talloc_asprintf_append_buffer(
133                         result, "%d %d %s\n",
134                         (int)name->sid_index, (int)name->sid_type,
135                         name->name.string);
136                 if (result == NULL) {
137                         return NT_STATUS_NO_MEMORY;
138                 }
139         }
140
141         response->extra_data.data = result;
142         response->length += talloc_get_size(result);
143         return NT_STATUS_OK;
144 }