Line data Source code
1 : /*
2 : SSSD
3 :
4 : NSS Responder Interface for ID-SID mappings
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2013 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include <stdlib.h>
26 : #include <errno.h>
27 : #include <nss.h>
28 :
29 : #include "sss_client/sss_cli.h"
30 : #include "sss_client/idmap/sss_nss_idmap.h"
31 : #include "util/strtonum.h"
32 :
33 : #define DATA_START (3 * sizeof(uint32_t))
34 : union input {
35 : const char *str;
36 : uint32_t id;
37 : };
38 :
39 : struct output {
40 : enum sss_id_type type;
41 : union {
42 : char *str;
43 : uint32_t id;
44 : struct sss_nss_kv *kv_list;
45 : } d;
46 : };
47 :
48 0 : int nss_status_to_errno(enum nss_status nret) {
49 0 : switch (nret) {
50 : case NSS_STATUS_TRYAGAIN:
51 0 : return EAGAIN;
52 : case NSS_STATUS_SUCCESS:
53 0 : return EOK;
54 : case NSS_STATUS_UNAVAIL:
55 : default:
56 0 : return ENOENT;
57 : }
58 :
59 : return EINVAL;
60 : }
61 :
62 1 : void sss_nss_free_kv(struct sss_nss_kv *kv_list)
63 : {
64 : size_t c;
65 :
66 1 : if (kv_list != NULL) {
67 2 : for (c = 0; kv_list[c].key != NULL; c++) {
68 1 : free(kv_list[c].key);
69 1 : free(kv_list[c].value);
70 : }
71 1 : free(kv_list);
72 : }
73 1 : }
74 :
75 1 : static int buf_to_kv_list(uint8_t *buf, size_t buf_len,
76 : struct sss_nss_kv **kv_list)
77 : {
78 : size_t c;
79 1 : size_t count = 0;
80 : struct sss_nss_kv *list;
81 : uint8_t *p;
82 : int ret;
83 :
84 11 : for (c = 0; c < buf_len; c++) {
85 10 : if (buf[c] == '\0') {
86 2 : count++;
87 : }
88 : }
89 :
90 1 : if ((count % 2) != 0) {
91 0 : return EINVAL;
92 : }
93 1 : count /= 2;
94 :
95 1 : list = calloc((count + 1), sizeof(struct sss_nss_kv));
96 1 : if (list == NULL) {
97 0 : return ENOMEM;
98 : }
99 :
100 1 : p = buf;
101 2 : for (c = 0; c < count; c++) {
102 1 : list[c].key = strdup((char *) p);
103 1 : if (list[c].key == NULL) {
104 0 : ret = ENOMEM;
105 0 : goto done;
106 : }
107 :
108 1 : p = memchr(p, '\0', buf_len - (p - buf));
109 1 : if (p == NULL) {
110 0 : ret = EINVAL;
111 0 : goto done;
112 : }
113 1 : p++;
114 :
115 1 : list[c].value = strdup((char *) p);
116 1 : if (list[c].value == NULL) {
117 0 : ret = ENOMEM;
118 0 : goto done;
119 : }
120 :
121 1 : p = memchr(p, '\0', buf_len - (p - buf));
122 1 : if (p == NULL) {
123 0 : ret = EINVAL;
124 0 : goto done;
125 : }
126 1 : p++;
127 : }
128 :
129 1 : *kv_list = list;
130 :
131 1 : ret = EOK;
132 :
133 : done:
134 1 : if (ret != EOK) {
135 0 : sss_nss_free_kv(list);
136 : }
137 :
138 1 : return ret;
139 : }
140 :
141 5 : static int sss_nss_getyyybyxxx(union input inp, enum sss_cli_command cmd ,
142 : struct output *out)
143 : {
144 : int ret;
145 : size_t inp_len;
146 : struct sss_cli_req_data rd;
147 5 : uint8_t *repbuf = NULL;
148 : size_t replen;
149 : int errnop;
150 : enum nss_status nret;
151 : uint32_t num_results;
152 5 : char *str = NULL;
153 : size_t data_len;
154 : uint32_t c;
155 : struct sss_nss_kv *kv_list;
156 :
157 5 : switch (cmd) {
158 : case SSS_NSS_GETSIDBYNAME:
159 : case SSS_NSS_GETNAMEBYSID:
160 : case SSS_NSS_GETIDBYSID:
161 : case SSS_NSS_GETORIGBYNAME:
162 : case SSS_NSS_GETNAMEBYCERT:
163 5 : ret = sss_strnlen(inp.str, 2048, &inp_len);
164 5 : if (ret != EOK) {
165 0 : return EINVAL;
166 : }
167 :
168 5 : rd.len = inp_len + 1;
169 5 : rd.data = inp.str;
170 :
171 5 : break;
172 : case SSS_NSS_GETSIDBYID:
173 0 : rd.len = sizeof(uint32_t);
174 0 : rd.data = &inp.id;
175 :
176 0 : break;
177 : default:
178 0 : return EINVAL;
179 : }
180 :
181 5 : sss_nss_lock();
182 :
183 5 : nret = sss_nss_make_request(cmd, &rd, &repbuf, &replen, &errnop);
184 5 : if (nret != NSS_STATUS_SUCCESS) {
185 0 : ret = nss_status_to_errno(nret);
186 0 : goto done;
187 : }
188 :
189 5 : if (replen < 8) {
190 0 : ret = EBADMSG;
191 0 : goto done;
192 : }
193 :
194 5 : SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
195 5 : if (num_results == 0) {
196 0 : ret = ENOENT;
197 0 : goto done;
198 5 : } else if (num_results > 1) {
199 0 : ret = EBADMSG;
200 0 : goto done;
201 : }
202 :
203 : /* Skip first two 32 bit values (number of results and
204 : * reserved padding) */
205 5 : SAFEALIGN_COPY_UINT32(&out->type, repbuf + 2 * sizeof(uint32_t), NULL);
206 :
207 5 : data_len = replen - DATA_START;
208 :
209 5 : switch(cmd) {
210 : case SSS_NSS_GETSIDBYID:
211 : case SSS_NSS_GETSIDBYNAME:
212 : case SSS_NSS_GETNAMEBYSID:
213 : case SSS_NSS_GETNAMEBYCERT:
214 4 : if (data_len <= 1 || repbuf[replen - 1] != '\0') {
215 0 : ret = EBADMSG;
216 0 : goto done;
217 : }
218 :
219 4 : str = malloc(sizeof(char) * data_len);
220 4 : if (str == NULL) {
221 0 : ret = ENOMEM;
222 0 : goto done;
223 : }
224 :
225 4 : strncpy(str, (char *) repbuf + DATA_START, data_len);
226 :
227 4 : out->d.str = str;
228 :
229 4 : break;
230 : case SSS_NSS_GETIDBYSID:
231 0 : if (data_len != sizeof(uint32_t)) {
232 0 : ret = EBADMSG;
233 0 : goto done;
234 : }
235 :
236 0 : SAFEALIGN_COPY_UINT32(&c, repbuf + DATA_START, NULL);
237 0 : out->d.id = c;
238 :
239 0 : break;
240 : case SSS_NSS_GETORIGBYNAME:
241 1 : ret = buf_to_kv_list(repbuf + DATA_START, data_len, &kv_list);
242 1 : if (ret != EOK) {
243 0 : goto done;
244 : }
245 :
246 1 : out->d.kv_list = kv_list;
247 :
248 1 : break;
249 : default:
250 0 : ret = EINVAL;
251 0 : goto done;
252 : }
253 :
254 5 : ret = EOK;
255 :
256 : done:
257 5 : sss_nss_unlock();
258 5 : free(repbuf);
259 5 : if (ret != EOK) {
260 0 : free(str);
261 : }
262 :
263 5 : return ret;
264 : }
265 :
266 7 : int sss_nss_getsidbyname(const char *fq_name, char **sid,
267 : enum sss_id_type *type)
268 : {
269 : int ret;
270 : union input inp;
271 : struct output out;
272 :
273 7 : if (sid == NULL || fq_name == NULL || *fq_name == '\0') {
274 3 : return EINVAL;
275 : }
276 :
277 4 : inp.str = fq_name;
278 :
279 4 : ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYNAME, &out);
280 4 : if (ret == EOK) {
281 4 : *sid = out.d.str;
282 4 : *type = out.type;
283 : }
284 :
285 4 : return ret;
286 : }
287 :
288 0 : int sss_nss_getsidbyid(uint32_t id, char **sid, enum sss_id_type *type)
289 : {
290 : int ret;
291 : union input inp;
292 : struct output out;
293 :
294 0 : if (sid == NULL) {
295 0 : return EINVAL;
296 : }
297 :
298 0 : inp.id = id;
299 :
300 0 : ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETSIDBYID, &out);
301 0 : if (ret == EOK) {
302 0 : *sid = out.d.str;
303 0 : *type = out.type;
304 : }
305 :
306 0 : return ret;
307 : }
308 :
309 0 : int sss_nss_getnamebysid(const char *sid, char **fq_name,
310 : enum sss_id_type *type)
311 : {
312 : int ret;
313 : union input inp;
314 : struct output out;
315 :
316 0 : if (fq_name == NULL || sid == NULL || *sid == '\0') {
317 0 : return EINVAL;
318 : }
319 :
320 0 : inp.str = sid;
321 :
322 0 : ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETNAMEBYSID, &out);
323 0 : if (ret == EOK) {
324 0 : *fq_name = out.d.str;
325 0 : *type = out.type;
326 : }
327 :
328 0 : return ret;
329 : }
330 :
331 0 : int sss_nss_getidbysid(const char *sid, uint32_t *id, enum sss_id_type *id_type)
332 : {
333 : int ret;
334 : union input inp;
335 : struct output out;
336 :
337 0 : if (id == NULL || id_type == NULL || sid == NULL || *sid == '\0') {
338 0 : return EINVAL;
339 : }
340 :
341 0 : inp.str = sid;
342 :
343 0 : ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETIDBYSID, &out);
344 0 : if (ret == EOK) {
345 0 : *id = out.d.id;
346 0 : *id_type = out.type;
347 : }
348 :
349 0 : return ret;
350 : }
351 :
352 1 : int sss_nss_getorigbyname(const char *fq_name, struct sss_nss_kv **kv_list,
353 : enum sss_id_type *type)
354 : {
355 : int ret;
356 : union input inp;
357 : struct output out;
358 :
359 1 : if (kv_list == NULL || fq_name == NULL || *fq_name == '\0') {
360 0 : return EINVAL;
361 : }
362 :
363 1 : inp.str = fq_name;
364 :
365 1 : ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETORIGBYNAME, &out);
366 1 : if (ret == EOK) {
367 1 : *kv_list = out.d.kv_list;
368 1 : *type = out.type;
369 : }
370 :
371 1 : return ret;
372 : }
373 :
374 0 : int sss_nss_getnamebycert(const char *cert, char **fq_name,
375 : enum sss_id_type *type)
376 : {
377 : int ret;
378 : union input inp;
379 : struct output out;
380 :
381 0 : if (fq_name == NULL || cert == NULL || *cert == '\0') {
382 0 : return EINVAL;
383 : }
384 :
385 0 : inp.str = cert;
386 :
387 0 : ret = sss_nss_getyyybyxxx(inp, SSS_NSS_GETNAMEBYCERT, &out);
388 0 : if (ret == EOK) {
389 0 : *fq_name = out.d.str;
390 0 : *type = out.type;
391 : }
392 :
393 0 : return ret;
394 : }
|