s3-registry: Check return code of push_reg_sz().
[kai/samba.git] / source3 / winbindd / winbindd_sids_to_xids.c
1 /*
2    Unix SMB/CIFS implementation.
3    async implementation of WINBINDD_SIDS_TO_XIDS
4    Copyright (C) Volker Lendecke 2011
5    Copyright (C) Michael Adam 2012
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "winbindd.h"
23 #include "../libcli/security/security.h"
24
25
26 struct winbindd_sids_to_xids_state {
27         struct tevent_context *ev;
28         struct dom_sid *sids;
29         uint32_t num_sids;
30         struct unixid *xids;
31 };
32
33 static void winbindd_sids_to_xids_done(struct tevent_req *subreq);
34
35 struct tevent_req *winbindd_sids_to_xids_send(TALLOC_CTX *mem_ctx,
36                                               struct tevent_context *ev,
37                                               struct winbindd_cli_state *cli,
38                                               struct winbindd_request *request)
39 {
40         struct tevent_req *req, *subreq;
41         struct winbindd_sids_to_xids_state *state;
42
43         req = tevent_req_create(mem_ctx, &state,
44                                 struct winbindd_sids_to_xids_state);
45         if (req == NULL) {
46                 return NULL;
47         }
48         state->ev = ev;
49
50         DEBUG(3, ("sids_to_xids\n"));
51
52         if (request->extra_len == 0) {
53                 tevent_req_done(req);
54                 return tevent_req_post(req, ev);
55         }
56         if (request->extra_data.data[request->extra_len-1] != '\0') {
57                 DEBUG(10, ("Got invalid sids list\n"));
58                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
59                 return tevent_req_post(req, ev);
60         }
61         if (!parse_sidlist(state, request->extra_data.data,
62                            &state->sids, &state->num_sids)) {
63                 DEBUG(10, ("parse_sidlist failed\n"));
64                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
65                 return tevent_req_post(req, ev);
66         }
67
68         DEBUG(10, ("num_sids: %d\n", (int)state->num_sids));
69
70         subreq = wb_sids2xids_send(state, ev, state->sids, state->num_sids);
71         if (tevent_req_nomem(subreq, req)) {
72                 return tevent_req_post(req, ev);
73         }
74
75         tevent_req_set_callback(subreq, winbindd_sids_to_xids_done, req);
76         return req;
77 }
78
79 static void winbindd_sids_to_xids_done(struct tevent_req *subreq)
80 {
81         struct tevent_req *req = tevent_req_callback_data(
82                 subreq, struct tevent_req);
83         struct winbindd_sids_to_xids_state *state = tevent_req_data(
84                 req, struct winbindd_sids_to_xids_state);
85         NTSTATUS status;
86
87         state->xids = talloc_zero_array(state, struct unixid, state->num_sids);
88         if (tevent_req_nomem(state->xids, req)) {
89                 return;
90         }
91
92         status = wb_sids2xids_recv(subreq, state->xids);
93         TALLOC_FREE(subreq);
94         if (tevent_req_nterror(req, status)) {
95                 return;
96         }
97         tevent_req_done(req);
98 }
99
100 NTSTATUS winbindd_sids_to_xids_recv(struct tevent_req *req,
101                                     struct winbindd_response *response)
102 {
103         struct winbindd_sids_to_xids_state *state = tevent_req_data(
104                 req, struct winbindd_sids_to_xids_state);
105         NTSTATUS status;
106         char *result = NULL;
107         uint32_t i;
108
109         if (tevent_req_is_nterror(req, &status)) {
110                 DEBUG(5, ("Could not convert sids: %s\n", nt_errstr(status)));
111                 return status;
112         }
113
114         result = talloc_strdup(response, "");
115         if (result == NULL) {
116                 return NT_STATUS_NO_MEMORY;
117         }
118
119         for (i=0; i<state->num_sids; i++) {
120                 char type = '\0';
121                 bool found = true;
122                 struct unixid xid;
123
124                 xid = state->xids[i];
125
126                 switch (xid.type) {
127                 case ID_TYPE_UID:
128                         type = 'U';
129                         break;
130                 case ID_TYPE_GID:
131                         type = 'G';
132                         break;
133                 case ID_TYPE_BOTH:
134                         type = 'B';
135                         break;
136                 default:
137                         found = false;
138                         break;
139                 }
140
141                 if (xid.id == UINT32_MAX) {
142                         found = false;
143                 }
144
145                 if (found) {
146                         result = talloc_asprintf_append_buffer(
147                                 result, "%c%lu\n", type,
148                                 (unsigned long)xid.id);
149                 } else {
150                         result = talloc_asprintf_append_buffer(result, "\n");
151                 }
152                 if (result == NULL) {
153                         return NT_STATUS_NO_MEMORY;
154                 }
155         }
156
157         response->extra_data.data = result;
158         response->length += talloc_get_size(result);
159
160         return NT_STATUS_OK;
161 }