Print this page
13026 SMB and NFS use the global zone's IDMAP when they shouldn't
Change-Id: I3b5f7bc68bb77764aa7cb59a48dd1740a8387ccf
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_idmap.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_idmap.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2020 Nexenta by DDN, Inc. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * SMB server interface to idmap
28 28 * (smb_idmap_get..., smb_idmap_batch_...)
29 29 *
30 30 * There are three implementations of this interface.
31 31 * This is the kernel version of these routines. See also:
32 32 * $SRC/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c
33 33 * $SRC/lib/smbsrv/libsmb/common/smb_idmap.c
34 34 *
35 35 * There are enough differences (relative to the code size)
36 36 * that it's more trouble than it's worth to merge them.
37 37 *
38 38 * This one differs from the others in that it:
39 39 * calls kernel (kidmap_...) interfaces
40 40 * returned domain SIDs are shared, not strdup'ed
41 41 */
42 42
43 43 /*
44 44 * SMB ID mapping
45 45 *
46 46 * Solaris ID mapping service (aka Winchester) works with domain SIDs
47 47 * and RIDs where domain SIDs are in string format. CIFS service works
48 48 * with binary SIDs understandable by CIFS clients. A layer of SMB ID
49 49 * mapping functions are implemeted to hide the SID conversion details
50 50 * and also hide the handling of array of batch mapping requests.
51 51 */
52 52
53 53 #include <sys/param.h>
54 54 #include <sys/types.h>
55 55 #include <sys/tzfile.h>
56 56 #include <sys/atomic.h>
57 57 #include <sys/kidmap.h>
58 58 #include <sys/time.h>
59 59 #include <sys/spl.h>
60 60 #include <sys/random.h>
61 61 #include <smbsrv/smb_kproto.h>
62 62 #include <smbsrv/smb_fsops.h>
63 63 #include <smbsrv/smbinfo.h>
64 64 #include <smbsrv/smb_xdr.h>
65 65 #include <smbsrv/smb_vops.h>
66 66 #include <smbsrv/smb_idmap.h>
67 67
68 68 #include <sys/sid.h>
69 69 #include <sys/priv_names.h>
70 70
71 71 static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
72 72
73 73 /*
74 74 * smb_idmap_getsid
75 75 *
|
↓ open down ↓ |
42 lines elided |
↑ open up ↑ |
76 76 * Maps the given Solaris ID to a Windows SID using the
77 77 * simple mapping API.
78 78 */
79 79 idmap_stat
80 80 smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
81 81 {
82 82 smb_idmap_t sim;
83 83
84 84 switch (idtype) {
85 85 case SMB_IDMAP_USER:
86 - sim.sim_stat = kidmap_getsidbyuid(global_zone, id,
86 + sim.sim_stat = kidmap_getsidbyuid(curzone, id,
87 87 (const char **)&sim.sim_domsid, &sim.sim_rid);
88 88 break;
89 89
90 90 case SMB_IDMAP_GROUP:
91 - sim.sim_stat = kidmap_getsidbygid(global_zone, id,
91 + sim.sim_stat = kidmap_getsidbygid(curzone, id,
92 92 (const char **)&sim.sim_domsid, &sim.sim_rid);
93 93 break;
94 94
95 95 case SMB_IDMAP_EVERYONE:
96 96 /* Everyone S-1-1-0 */
97 97 sim.sim_domsid = "S-1-1";
98 98 sim.sim_rid = 0;
99 99 sim.sim_stat = IDMAP_SUCCESS;
100 100 break;
101 101
102 102 default:
103 103 ASSERT(0);
104 104 return (IDMAP_ERR_ARG);
105 105 }
106 106
107 107 /*
108 108 * IDMAP_ERR_NOTFOUND is an advisory error
109 109 * and idmap will generate a local sid.
110 110 */
111 111 if (sim.sim_stat == IDMAP_ERR_NOTFOUND &&
112 112 sim.sim_domsid != NULL)
113 113 sim.sim_stat = IDMAP_SUCCESS;
114 114
115 115 if (sim.sim_stat != IDMAP_SUCCESS)
116 116 return (sim.sim_stat);
117 117
118 118 if (sim.sim_domsid == NULL)
119 119 return (IDMAP_ERR_NOMAPPING);
120 120
121 121 sim.sim_sid = smb_sid_fromstr(sim.sim_domsid);
122 122 if (sim.sim_sid == NULL)
123 123 return (IDMAP_ERR_INTERNAL);
124 124
125 125 *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid);
126 126 smb_sid_free(sim.sim_sid);
127 127 if (*sid == NULL)
128 128 sim.sim_stat = IDMAP_ERR_INTERNAL;
129 129
130 130 return (sim.sim_stat);
131 131 }
132 132
133 133 /*
134 134 * smb_idmap_getid
135 135 *
136 136 * Maps the given Windows SID to a Unix ID using the
137 137 * simple mapping API.
138 138 */
139 139 idmap_stat
140 140 smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype)
141 141 {
142 142 smb_idmap_t sim;
|
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
143 143 char sidstr[SMB_SID_STRSZ];
144 144
145 145 smb_sid_tostr(sid, sidstr);
146 146 if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0)
147 147 return (IDMAP_ERR_SID);
148 148 sim.sim_domsid = sidstr;
149 149 sim.sim_id = id;
150 150
151 151 switch (*idtype) {
152 152 case SMB_IDMAP_USER:
153 - sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid,
153 + sim.sim_stat = kidmap_getuidbysid(curzone, sim.sim_domsid,
154 154 sim.sim_rid, sim.sim_id);
155 155 break;
156 156
157 157 case SMB_IDMAP_GROUP:
158 - sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid,
158 + sim.sim_stat = kidmap_getgidbysid(curzone, sim.sim_domsid,
159 159 sim.sim_rid, sim.sim_id);
160 160 break;
161 161
162 162 case SMB_IDMAP_UNKNOWN:
163 - sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid,
163 + sim.sim_stat = kidmap_getpidbysid(curzone, sim.sim_domsid,
164 164 sim.sim_rid, sim.sim_id, &sim.sim_idtype);
165 165 break;
166 166
167 167 default:
168 168 ASSERT(0);
169 169 return (IDMAP_ERR_ARG);
170 170 }
171 171
172 172 *idtype = sim.sim_idtype;
173 173
174 174 return (sim.sim_stat);
175 175 }
176 176
177 177 /*
178 178 * smb_idmap_batch_create
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
179 179 *
180 180 * Creates and initializes the context for batch ID mapping.
181 181 */
182 182 idmap_stat
183 183 smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
184 184 {
185 185 ASSERT(sib != NULL);
186 186
187 187 bzero(sib, sizeof (smb_idmap_batch_t));
188 188
189 - sib->sib_idmaph = kidmap_get_create(global_zone);
189 + sib->sib_idmaph = kidmap_get_create(curzone);
190 190
191 191 sib->sib_flags = flags;
192 192 sib->sib_nmap = nmap;
193 193 sib->sib_size = nmap * sizeof (smb_idmap_t);
194 194 sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
195 195
196 196 return (IDMAP_SUCCESS);
197 197 }
198 198
199 199 /*
200 200 * smb_idmap_batch_destroy
201 201 *
202 202 * Frees the batch ID mapping context.
203 203 * If ID mapping is Solaris -> Windows it frees memories
204 204 * allocated for binary SIDs.
205 205 */
206 206 void
207 207 smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
208 208 {
209 209 char *domsid;
210 210 int i;
211 211
212 212 ASSERT(sib != NULL);
213 213 ASSERT(sib->sib_maps != NULL);
214 214
215 215 if (sib->sib_idmaph) {
216 216 kidmap_get_destroy(sib->sib_idmaph);
217 217 sib->sib_idmaph = NULL;
218 218 }
219 219
220 220 if (sib->sib_flags & SMB_IDMAP_ID2SID) {
221 221 /*
222 222 * SIDs are allocated only when mapping
223 223 * UID/GID to SIDs
224 224 */
225 225 for (i = 0; i < sib->sib_nmap; i++)
226 226 smb_sid_free(sib->sib_maps[i].sim_sid);
227 227 } else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
228 228 /*
229 229 * SID prefixes are allocated only when mapping
230 230 * SIDs to UID/GID
231 231 */
232 232 for (i = 0; i < sib->sib_nmap; i++) {
233 233 domsid = sib->sib_maps[i].sim_domsid;
234 234 if (domsid)
235 235 smb_mem_free(domsid);
236 236 }
237 237 }
238 238
239 239 if (sib->sib_size && sib->sib_maps) {
240 240 kmem_free(sib->sib_maps, sib->sib_size);
241 241 sib->sib_maps = NULL;
242 242 }
243 243 }
244 244
245 245 /*
246 246 * smb_idmap_batch_getid
247 247 *
248 248 * Queue a request to map the given SID to a UID or GID.
249 249 *
250 250 * sim->sim_id should point to variable that's supposed to
251 251 * hold the returned UID/GID. This needs to be setup by caller
252 252 * of this function.
253 253 *
254 254 * If requested ID type is known, it's passed as 'idtype',
255 255 * if it's unknown it'll be returned in sim->sim_idtype.
256 256 */
257 257 idmap_stat
258 258 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
259 259 smb_sid_t *sid, int idtype)
260 260 {
261 261 char strsid[SMB_SID_STRSZ];
262 262 idmap_stat idm_stat;
263 263
264 264 ASSERT(idmaph != NULL);
265 265 ASSERT(sim != NULL);
266 266 ASSERT(sid != NULL);
267 267
268 268 smb_sid_tostr(sid, strsid);
269 269 if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
270 270 return (IDMAP_ERR_SID);
271 271 /* Note: Free sim_domsid in smb_idmap_batch_destroy */
272 272 sim->sim_domsid = smb_mem_strdup(strsid);
273 273 sim->sim_idtype = idtype;
274 274
275 275 switch (idtype) {
276 276 case SMB_IDMAP_USER:
277 277 idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
278 278 sim->sim_rid, sim->sim_id, &sim->sim_stat);
279 279 break;
280 280
281 281 case SMB_IDMAP_GROUP:
282 282 idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid,
283 283 sim->sim_rid, sim->sim_id, &sim->sim_stat);
284 284 break;
285 285
286 286 case SMB_IDMAP_UNKNOWN:
287 287 idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid,
288 288 sim->sim_rid, sim->sim_id, &sim->sim_idtype,
289 289 &sim->sim_stat);
290 290 break;
291 291
292 292 default:
293 293 ASSERT(0);
294 294 return (IDMAP_ERR_ARG);
295 295 }
296 296
297 297 return (idm_stat);
298 298 }
299 299
300 300 /*
301 301 * smb_idmap_batch_getsid
302 302 *
303 303 * Queue a request to map the given UID/GID to a SID.
304 304 *
305 305 * sim->sim_domsid and sim->sim_rid will contain the mapping
306 306 * result upon successful process of the batched request.
307 307 * Stash the type for error reporting (caller saves the ID).
308 308 */
309 309 idmap_stat
310 310 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
311 311 uid_t id, int idtype)
312 312 {
313 313 idmap_stat idm_stat;
314 314
315 315 sim->sim_idtype = idtype;
316 316 switch (idtype) {
317 317 case SMB_IDMAP_USER:
318 318 idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
319 319 (const char **)&sim->sim_domsid, &sim->sim_rid,
320 320 &sim->sim_stat);
321 321 break;
322 322
323 323 case SMB_IDMAP_GROUP:
324 324 idm_stat = kidmap_batch_getsidbygid(idmaph, id,
325 325 (const char **)&sim->sim_domsid, &sim->sim_rid,
326 326 &sim->sim_stat);
327 327 break;
328 328
329 329 case SMB_IDMAP_OWNERAT:
330 330 /* Current Owner S-1-5-32-766 */
331 331 sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
332 332 sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
333 333 sim->sim_stat = IDMAP_SUCCESS;
334 334 idm_stat = IDMAP_SUCCESS;
335 335 break;
336 336
337 337 case SMB_IDMAP_GROUPAT:
338 338 /* Current Group S-1-5-32-767 */
339 339 sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
340 340 sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
341 341 sim->sim_stat = IDMAP_SUCCESS;
342 342 idm_stat = IDMAP_SUCCESS;
343 343 break;
344 344
345 345 case SMB_IDMAP_EVERYONE:
346 346 /* Everyone S-1-1-0 */
347 347 sim->sim_domsid = NT_WORLD_AUTH_SIDSTR;
348 348 sim->sim_rid = 0;
349 349 sim->sim_stat = IDMAP_SUCCESS;
350 350 idm_stat = IDMAP_SUCCESS;
351 351 break;
352 352
353 353 default:
354 354 ASSERT(0);
355 355 return (IDMAP_ERR_ARG);
356 356 }
357 357
358 358 return (idm_stat);
359 359 }
360 360
361 361 static void
362 362 smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim)
363 363 {
364 364
365 365 if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) {
366 366 /*
367 367 * Note: The ID and type we asked idmap to map
368 368 * were saved in *sim_id and sim_idtype.
369 369 */
370 370 uint_t id = (sim->sim_id == NULL) ?
371 371 0 : (uint_t)*sim->sim_id;
372 372 cmn_err(CE_WARN, "Can't get SID for "
373 373 "ID=%u type=%d, status=%d",
374 374 id, sim->sim_idtype, sim->sim_stat);
375 375 }
376 376
377 377 if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) {
378 378 cmn_err(CE_WARN, "Can't get ID for SID %s-%u, status=%d",
379 379 sim->sim_domsid, sim->sim_rid, sim->sim_stat);
380 380 }
381 381 }
382 382
383 383 /*
384 384 * smb_idmap_batch_getmappings
385 385 *
386 386 * trigger ID mapping service to get the mappings for queued
387 387 * requests.
388 388 *
389 389 * Checks the result of all the queued requests.
390 390 * If this is a Solaris -> Windows mapping it generates
391 391 * binary SIDs from returned (domsid, rid) pairs.
392 392 */
393 393 idmap_stat
394 394 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
395 395 {
396 396 idmap_stat idm_stat = IDMAP_SUCCESS;
397 397 smb_idmap_t *sim;
398 398 int i;
399 399
400 400 idm_stat = kidmap_get_mappings(sib->sib_idmaph);
401 401 if (idm_stat != IDMAP_SUCCESS)
402 402 return (idm_stat);
403 403
404 404 /*
405 405 * Check the status for all the queued requests
406 406 */
407 407 for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
408 408 if (sim->sim_stat != IDMAP_SUCCESS) {
409 409 smb_idmap_bgm_report(sib, sim);
410 410 if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) {
411 411 return (sim->sim_stat);
412 412 }
413 413 }
414 414 }
415 415
416 416 if (smb_idmap_batch_binsid(sib) != 0)
417 417 idm_stat = IDMAP_ERR_OTHER;
418 418
419 419 return (idm_stat);
420 420 }
421 421
422 422 /*
423 423 * smb_idmap_batch_binsid
424 424 *
425 425 * Convert sidrids to binary sids
426 426 *
427 427 * Returns 0 if successful and non-zero upon failure.
428 428 */
429 429 static int
430 430 smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
431 431 {
432 432 smb_sid_t *sid;
433 433 smb_idmap_t *sim;
434 434 int i;
435 435
436 436 if (sib->sib_flags & SMB_IDMAP_SID2ID)
437 437 /* This operation is not required */
438 438 return (0);
439 439
440 440 sim = sib->sib_maps;
441 441 for (i = 0; i < sib->sib_nmap; sim++, i++) {
442 442 ASSERT(sim->sim_domsid != NULL);
443 443 if (sim->sim_domsid == NULL)
444 444 return (1);
445 445
446 446 if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
447 447 return (1);
448 448
449 449 sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
450 450 smb_sid_free(sid);
451 451 }
452 452
453 453 return (0);
454 454 }
|
↓ open down ↓ |
255 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX