Line data Source code
1 : /*
2 : Authors:
3 : Benjamin Franzke <benjaminfranzke@googlemail.com>
4 :
5 : Copyright (C) 2013 Benjamin Franzke
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 : /* TODO: Support of [all] samba's Unix SIDs:
22 : * Users: S-1-22-1-%UID
23 : * Groups: S-1-22-2-%GID
24 : */
25 :
26 : #include <stdio.h>
27 : #include <stdlib.h>
28 : #include <errno.h>
29 : #include <string.h>
30 : #include <limits.h>
31 : #include <stdarg.h>
32 :
33 : #include <cifsidmap.h>
34 :
35 : #include "lib/idmap/sss_idmap.h"
36 : #include "sss_client/idmap/sss_nss_idmap.h"
37 :
38 : #ifdef DEBUG
39 : #include <syslog.h>
40 : #define debug(str, ...) \
41 : syslog(0, "%s: " str "\n", \
42 : __FUNCTION__, ##__VA_ARGS__)
43 : #else
44 : #define debug(...) do { } while(0)
45 : #endif
46 :
47 : struct sssd_ctx {
48 : struct sss_idmap_ctx *idmap;
49 : const char **errmsg;
50 : };
51 :
52 : #define ctx_set_error(ctx, error) \
53 : do { \
54 : *ctx->errmsg = error; \
55 : debug("%s", error ? error : ""); \
56 : } while (0);
57 :
58 : int cifs_idmap_init_plugin(void **handle, const char **errmsg)
59 : {
60 : struct sssd_ctx *ctx;
61 : enum idmap_error_code err;
62 :
63 0 : if (handle == NULL || errmsg == NULL)
64 0 : return EINVAL;
65 :
66 0 : ctx = malloc(sizeof *ctx);
67 0 : if (!ctx) {
68 0 : *errmsg = "Failed to allocate context";
69 0 : return -1;
70 : }
71 0 : ctx->errmsg = errmsg;
72 0 : ctx_set_error(ctx, NULL);
73 :
74 0 : err = sss_idmap_init(NULL, NULL, NULL, &ctx->idmap);
75 0 : if (err != IDMAP_SUCCESS) {
76 0 : ctx_set_error(ctx, idmap_error_string(err));
77 0 : free(ctx);
78 0 : return -1;
79 : }
80 :
81 0 : *handle = ctx;
82 0 : return 0;
83 : }
84 :
85 : void cifs_idmap_exit_plugin(void *handle)
86 : {
87 0 : struct sssd_ctx *ctx = handle;
88 :
89 : debug("exit");
90 :
91 0 : if (ctx == NULL)
92 0 : return;
93 :
94 0 : sss_idmap_free(ctx->idmap);
95 :
96 0 : free(ctx);
97 : }
98 :
99 :
100 : /* Test with `getcifsacl file` on client. */
101 : int cifs_idmap_sid_to_str(void *handle, const struct cifs_sid *csid,
102 : char **name)
103 : {
104 0 : struct sssd_ctx *ctx = handle;
105 : enum idmap_error_code iderr;
106 : char *sid;
107 : enum sss_id_type id_type;
108 : int err;
109 :
110 0 : iderr = sss_idmap_bin_sid_to_sid(ctx->idmap, (const uint8_t *) csid,
111 : sizeof(*csid), &sid);
112 0 : if (iderr != IDMAP_SUCCESS) {
113 0 : ctx_set_error(ctx, idmap_error_string(iderr));
114 0 : *name = NULL;
115 0 : return -1;
116 : }
117 :
118 : debug("sid: %s", sid);
119 :
120 0 : err = sss_nss_getnamebysid(sid, name, &id_type);
121 0 : if (err != 0) {
122 0 : ctx_set_error(ctx, strerror(err));
123 0 : *name = NULL;
124 0 : return -err;
125 : }
126 :
127 : /* FIXME: Map Samba Unix SIDs? (sid->id and use getpwuid)? */
128 :
129 : debug("name: %s", *name);
130 :
131 0 : return 0;
132 : }
133 :
134 0 : static int sid_to_cifs_sid(struct sssd_ctx *ctx, const char *sid,
135 : struct cifs_sid *csid)
136 : {
137 0 : uint8_t *bsid = NULL;
138 : enum idmap_error_code err;
139 : size_t length;
140 :
141 0 : err = sss_idmap_sid_to_bin_sid(ctx->idmap,
142 : sid, &bsid, &length);
143 0 : if (err != IDMAP_SUCCESS) {
144 0 : ctx_set_error(ctx, idmap_error_string(err));
145 0 : return -1;
146 : }
147 0 : if (length > sizeof(struct cifs_sid)) {
148 0 : ctx_set_error(ctx, "too large sid length");
149 0 : free(bsid);
150 0 : return -1;
151 : }
152 :
153 0 : memcpy(csid, bsid, length);
154 0 : sss_idmap_free_bin_sid(ctx->idmap, bsid);
155 :
156 0 : return 0;
157 : }
158 :
159 : /* Test with setcifsacl -a */
160 : int cifs_idmap_str_to_sid(void *handle, const char *name,
161 : struct cifs_sid *csid)
162 : {
163 0 : struct sssd_ctx *ctx = handle;
164 : int err;
165 : enum sss_id_type id_type;
166 0 : char *sid = NULL;
167 0 : int success = 0;
168 :
169 : debug("%s", name);
170 :
171 0 : err = sss_nss_getsidbyname(name, &sid, &id_type);
172 0 : if (err != 0) {
173 : /* Might be a raw string representation of SID,
174 : * try converting that before returning an error. */
175 0 : if (sid_to_cifs_sid(ctx, name, csid) == 0)
176 0 : return 0;
177 :
178 0 : ctx_set_error(ctx, strerror(err));
179 0 : return -err;
180 : }
181 :
182 0 : if (sid_to_cifs_sid(ctx, sid, csid) != 0)
183 0 : success = -1;
184 :
185 0 : free(sid);
186 :
187 0 : return success;
188 : }
189 :
190 0 : static int samba_unix_sid_to_id(const char *sid, struct cifs_uxid *cuxid)
191 : {
192 : id_t id;
193 : uint8_t type;
194 :
195 0 : if (sscanf(sid, "S-1-22-%hhu-%u", &type, &id) != 2)
196 0 : return -1;
197 :
198 0 : switch (type) {
199 : case 1:
200 0 : cuxid->type = CIFS_UXID_TYPE_UID;
201 0 : cuxid->id.uid = id;
202 0 : break;
203 : case 2:
204 0 : cuxid->type = CIFS_UXID_TYPE_GID;
205 0 : cuxid->id.gid = id;
206 0 : break;
207 : default:
208 0 : cuxid->type = CIFS_UXID_TYPE_UNKNOWN;
209 0 : return -1;
210 : }
211 :
212 0 : return 0;
213 : }
214 :
215 0 : static int sss_sid_to_id(struct sssd_ctx *ctx, const char *sid,
216 : struct cifs_uxid *cuxid)
217 : {
218 : int err;
219 : enum sss_id_type id_type;
220 :
221 0 : err = sss_nss_getidbysid(sid, (uint32_t *)&cuxid->id.uid, &id_type);
222 0 : if (err != 0) {
223 0 : ctx_set_error(ctx, strerror(err));
224 0 : return -1;
225 : }
226 :
227 0 : switch (id_type) {
228 : case SSS_ID_TYPE_UID:
229 0 : cuxid->type = CIFS_UXID_TYPE_UID;
230 0 : break;
231 : case SSS_ID_TYPE_GID:
232 0 : cuxid->type = CIFS_UXID_TYPE_GID;
233 0 : break;
234 : case SSS_ID_TYPE_BOTH:
235 0 : cuxid->type = CIFS_UXID_TYPE_BOTH;
236 0 : break;
237 : case SSS_ID_TYPE_NOT_SPECIFIED:
238 : default:
239 0 : return -1;
240 : }
241 :
242 0 : return 0;
243 : }
244 :
245 : /**
246 : * cifs_idmap_sids_to_ids - convert struct cifs_sids to struct cifs_uxids
247 : * usecase: mount.cifs -o sec=krb5,multiuser,cifsacl,nounix
248 : * test: ls -n on mounted share
249 : */
250 : int cifs_idmap_sids_to_ids(void *handle, const struct cifs_sid *csid,
251 : const size_t num, struct cifs_uxid *cuxid)
252 : {
253 0 : struct sssd_ctx *ctx = handle;
254 : enum idmap_error_code err;
255 0 : int success = -1;
256 : size_t i;
257 : char *sid;
258 :
259 : debug("num: %zd", num);
260 :
261 0 : if (num > UINT_MAX) {
262 0 : ctx_set_error(ctx, "num is too large.");
263 0 : return EINVAL;
264 : }
265 :
266 0 : for (i = 0; i < num; ++i) {
267 0 : err = sss_idmap_bin_sid_to_sid(ctx->idmap, (const uint8_t *) &csid[i],
268 : sizeof(csid[i]), &sid);
269 0 : if (err != IDMAP_SUCCESS) {
270 0 : ctx_set_error(ctx, idmap_error_string(err));
271 0 : continue;
272 : }
273 :
274 0 : cuxid[i].type = CIFS_UXID_TYPE_UNKNOWN;
275 :
276 0 : if (sss_sid_to_id(ctx, sid, &cuxid[i]) == 0 ||
277 0 : samba_unix_sid_to_id(sid, &cuxid[i]) == 0) {
278 :
279 : debug("setting uid of %s to %d", sid, cuxid[i].id.uid);
280 0 : success = 0;
281 : }
282 :
283 0 : free(sid);
284 : }
285 :
286 0 : return success;
287 : }
288 :
289 :
290 : int cifs_idmap_ids_to_sids(void *handle, const struct cifs_uxid *cuxid,
291 : const size_t num, struct cifs_sid *csid)
292 : {
293 0 : struct sssd_ctx *ctx = handle;
294 0 : int err, success = -1;
295 : char *sid;
296 : enum sss_id_type id_type;
297 : size_t i;
298 :
299 : debug("num ids: %zd", num);
300 :
301 0 : if (num > UINT_MAX) {
302 0 : ctx_set_error(ctx, "num is too large.");
303 0 : return EINVAL;
304 : }
305 :
306 0 : for (i = 0; i < num; ++i) {
307 0 : err = sss_nss_getsidbyid((uint32_t)cuxid[i].id.uid, &sid, &id_type);
308 0 : if (err != 0) {
309 0 : ctx_set_error(ctx, strerror(err));
310 0 : csid[i].revision = 0;
311 : /* FIXME: would it be safe to map *any* uid/gids unknown by sssd to
312 : * SAMBA's UNIX SIDs? */
313 0 : continue;
314 : }
315 :
316 0 : if (sid_to_cifs_sid(ctx, sid, csid) == 0)
317 0 : success = 0;
318 : else
319 0 : csid[i].revision = 0;
320 0 : free(sid);
321 : }
322 :
323 0 : return success;
324 : }
|