Print this page
NEX-16818 Add fksmbcl development tool
NEX-17264 SMB client test tp_smbutil_013 fails after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
and: (fix ref leaks)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/common/smbclnt/smbfs_ntacl.c
+++ new/usr/src/common/smbclnt/smbfs_ntacl.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 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
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 /*
23 23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
24 25 */
25 26
26 27 /*
27 28 * ACL conversion support for smbfs
28 29 * (To/from NT/ZFS-style ACLs.)
29 30 */
30 31
31 32 #include <sys/types.h>
32 33 #include <sys/errno.h>
33 34 #include <sys/acl.h>
34 35 #include <sys/byteorder.h>
35 36
36 -#ifdef _KERNEL
37 +#if defined(_KERNEL) || defined(_FAKE_KERNEL)
37 38
38 39 #include <sys/cred.h>
39 40 #include <sys/cmn_err.h>
40 41 #include <sys/kmem.h>
41 42 #include <sys/sunddi.h>
42 43 #include <sys/vnode.h>
43 44 #include <sys/vfs.h>
44 45
45 -#include <sys/kidmap.h>
46 -
47 46 #else /* _KERNEL */
48 47
49 48 #include <stdio.h>
50 49 #include <stdlib.h>
51 50 #include <strings.h>
52 51
53 -#include <idmap.h>
52 +#endif /* _KERNEL */
54 53
54 +#ifdef _KERNEL
55 +#include <sys/kidmap.h>
56 +#else /* _KERNEL */
57 +#include <idmap.h>
55 58 #endif /* _KERNEL */
56 59
57 60 #include <netsmb/mchain.h>
58 61 #include <netsmb/smb.h>
59 62 #include "smbfs_ntacl.h"
60 63
61 64 #define NT_SD_REVISION 1
62 65 #define NT_ACL_REVISION 2
63 66
64 -#ifdef _KERNEL
67 +#if defined(_KERNEL) || defined(_FAKE_KERNEL)
65 68 #define MALLOC(size) kmem_alloc(size, KM_SLEEP)
66 69 #define FREESZ(p, sz) kmem_free(p, sz)
67 70 #else /* _KERNEL */
68 71 #define MALLOC(size) malloc(size)
69 72 /*
70 73 * Define FREESZ() as inline function so the compiler will not
71 74 * trigger variable set but not used warning for sz in calling function.
72 75 */
73 76 /* ARGSUSED */
74 77 static inline void
75 78 FREESZ(void *p, size_t sz __unused)
76 79 {
77 80 free(p);
78 81 }
79 82 #endif /* _KERNEL */
80 83
81 84 #define ERRCHK(expr) if ((error = expr) != 0) goto errout
82 85
83 86 /*
84 87 * Security IDentifier (SID)
85 88 */
86 89 static void
87 90 ifree_sid(i_ntsid_t *sid)
88 91 {
89 92 size_t sz;
90 93
91 94 if (sid == NULL)
92 95 return;
93 96
94 97 sz = I_SID_SIZE(sid->sid_subauthcount);
95 98 FREESZ(sid, sz);
96 99 }
97 100
98 101 static int
99 102 md_get_sid(mdchain_t *mdp, i_ntsid_t **sidp)
100 103 {
101 104 i_ntsid_t *sid = NULL;
102 105 uint8_t revision, subauthcount;
103 106 uint32_t *subauthp;
104 107 size_t sidsz;
105 108 int error, i;
106 109
107 110 if ((error = md_get_uint8(mdp, &revision)) != 0)
108 111 return (error);
109 112 if ((error = md_get_uint8(mdp, &subauthcount)) != 0)
110 113 return (error);
111 114
112 115 sidsz = I_SID_SIZE(subauthcount);
113 116
114 117 if ((sid = MALLOC(sidsz)) == NULL)
115 118 return (ENOMEM);
116 119
117 120 bzero(sid, sidsz);
118 121 sid->sid_revision = revision;
119 122 sid->sid_subauthcount = subauthcount;
120 123 ERRCHK(md_get_mem(mdp, sid->sid_authority, 6, MB_MSYSTEM));
121 124
122 125 subauthp = &sid->sid_subauthvec[0];
123 126 for (i = 0; i < subauthcount; i++) {
124 127 ERRCHK(md_get_uint32le(mdp, subauthp));
125 128 subauthp++;
126 129 }
127 130
128 131 /* Success! */
129 132 *sidp = sid;
130 133 return (0);
131 134
132 135 errout:
133 136 ifree_sid(sid);
134 137 return (error);
135 138 }
136 139
137 140 static int
138 141 mb_put_sid(mbchain_t *mbp, i_ntsid_t *sid)
139 142 {
140 143 uint32_t *subauthp;
141 144 int error, i;
142 145
143 146 if (sid == NULL)
144 147 return (EINVAL);
145 148
146 149 ERRCHK(mb_put_uint8(mbp, sid->sid_revision));
147 150 ERRCHK(mb_put_uint8(mbp, sid->sid_subauthcount));
148 151 ERRCHK(mb_put_mem(mbp, sid->sid_authority, 6, MB_MSYSTEM));
149 152
150 153 subauthp = &sid->sid_subauthvec[0];
151 154 for (i = 0; i < sid->sid_subauthcount; i++) {
152 155 ERRCHK(mb_put_uint32le(mbp, *subauthp));
153 156 subauthp++;
154 157 }
155 158
156 159 /* Success! */
157 160 return (0);
158 161
159 162 errout:
160 163 return (error);
161 164 }
162 165
163 166
164 167 /*
165 168 * Access Control Entry (ACE)
166 169 */
167 170 static void
168 171 ifree_ace(i_ntace_t *ace)
169 172 {
170 173
171 174 if (ace == NULL)
172 175 return;
173 176
174 177 switch (ace->ace_hdr.ace_type) {
175 178 case ACCESS_ALLOWED_ACE_TYPE:
176 179 case ACCESS_DENIED_ACE_TYPE:
177 180 case SYSTEM_AUDIT_ACE_TYPE:
178 181 case SYSTEM_ALARM_ACE_TYPE:
179 182 ifree_sid(ace->ace_v2.ace_sid);
180 183 FREESZ(ace, sizeof (i_ntace_v2_t));
181 184 break;
182 185 /* other types todo */
183 186 default:
184 187 break;
185 188 }
186 189 }
187 190
188 191 static int
189 192 md_get_ace(mdchain_t *mdp, i_ntace_t **acep)
190 193 {
191 194 mdchain_t tmp_md;
192 195 i_ntace_hdr_t ace_hdr;
193 196 i_ntace_t *ace = NULL;
194 197 uint16_t alloc_size;
195 198 int error;
196 199
197 200 /*
198 201 * The ACE is realy variable length,
199 202 * with format determined by the type.
200 203 *
201 204 * There may also be padding after it, so
202 205 * decode it using a copy of the mdchain,
203 206 * and then consume the specified length.
204 207 */
205 208 tmp_md = *mdp;
206 209
207 210 /* Fixed-size ACE header */
208 211 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_type));
209 212 ERRCHK(md_get_uint8(&tmp_md, &ace_hdr.ace_flags));
210 213 ERRCHK(md_get_uint16le(&tmp_md, &ace_hdr.ace_size));
211 214
212 215 switch (ace_hdr.ace_type) {
213 216 case ACCESS_ALLOWED_ACE_TYPE:
214 217 case ACCESS_DENIED_ACE_TYPE:
215 218 case SYSTEM_AUDIT_ACE_TYPE:
216 219 case SYSTEM_ALARM_ACE_TYPE:
217 220 alloc_size = sizeof (i_ntace_v2_t);
218 221 if ((ace = MALLOC(alloc_size)) == NULL)
219 222 return (ENOMEM);
220 223 bzero(ace, alloc_size);
221 224 /* ACE header */
222 225 ace->ace_hdr.ace_type = ace_hdr.ace_type;
223 226 ace->ace_hdr.ace_flags = ace_hdr.ace_flags;
224 227 ace->ace_hdr.ace_size = alloc_size;
225 228 /* Type-specific data. */
226 229 ERRCHK(md_get_uint32le(&tmp_md, &ace->ace_v2.ace_rights));
227 230 ERRCHK(md_get_sid(&tmp_md, &ace->ace_v2.ace_sid));
228 231 break;
229 232
230 233 /* other types todo */
231 234 default:
232 235 error = EIO;
233 236 goto errout;
234 237 }
235 238
236 239 /* Now actually consume ace_hdr.ace_size */
237 240 ERRCHK(md_get_mem(mdp, NULL, ace_hdr.ace_size, MB_MSYSTEM));
238 241
239 242 /* Success! */
240 243 *acep = ace;
241 244 return (0);
242 245
243 246 errout:
244 247 ifree_ace(ace);
245 248 return (error);
246 249 }
247 250
248 251 static int
249 252 mb_put_ace(mbchain_t *mbp, i_ntace_t *ace)
250 253 {
251 254 int cnt0, error;
252 255 uint16_t ace_len, *ace_len_p;
253 256
254 257 if (ace == NULL)
255 258 return (EINVAL);
256 259
257 260 cnt0 = mbp->mb_count;
258 261
259 262 /*
260 263 * Put the (fixed-size) ACE header
261 264 * Will fill in the length later.
262 265 */
263 266 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_type));
264 267 ERRCHK(mb_put_uint8(mbp, ace->ace_hdr.ace_flags));
265 268 ace_len_p = mb_reserve(mbp, sizeof (*ace_len_p));
266 269 if (ace_len_p == NULL) {
267 270 error = ENOMEM;
268 271 goto errout;
269 272 }
270 273
271 274 switch (ace->ace_hdr.ace_type) {
272 275 case ACCESS_ALLOWED_ACE_TYPE:
273 276 case ACCESS_DENIED_ACE_TYPE:
274 277 case SYSTEM_AUDIT_ACE_TYPE:
275 278 case SYSTEM_ALARM_ACE_TYPE:
276 279 /* Put type-specific data. */
277 280 ERRCHK(mb_put_uint32le(mbp, ace->ace_v2.ace_rights));
278 281 ERRCHK(mb_put_sid(mbp, ace->ace_v2.ace_sid));
279 282 break;
280 283
281 284 /* other types todo */
282 285 default:
283 286 error = EIO;
284 287 goto errout;
285 288 }
286 289
287 290 /* Fill in the (OtW) ACE length. */
288 291 ace_len = mbp->mb_count - cnt0;
289 292 *ace_len_p = htoles(ace_len);
290 293
291 294 /* Success! */
292 295 return (0);
293 296
294 297 errout:
295 298 return (error);
296 299 }
297 300
298 301
299 302 /*
300 303 * Access Control List (ACL)
301 304 */
302 305
303 306 /* Not an OTW structure, so size can be at our convenience. */
304 307 #define I_ACL_SIZE(cnt) (sizeof (i_ntacl_t) + (cnt) * sizeof (void *))
305 308
306 309 static void
307 310 ifree_acl(i_ntacl_t *acl)
308 311 {
309 312 i_ntace_t **acep;
310 313 size_t sz;
311 314 int i;
312 315
313 316 if (acl == NULL)
314 317 return;
315 318
316 319 acep = &acl->acl_acevec[0];
317 320 for (i = 0; i < acl->acl_acecount; i++) {
318 321 ifree_ace(*acep);
319 322 acep++;
320 323 }
321 324 sz = I_ACL_SIZE(acl->acl_acecount);
322 325 FREESZ(acl, sz);
323 326 }
324 327
325 328 static int
326 329 md_get_acl(mdchain_t *mdp, i_ntacl_t **aclp)
327 330 {
328 331 i_ntacl_t *acl = NULL;
329 332 i_ntace_t **acep;
330 333 uint8_t revision;
331 334 uint16_t acl_len, acecount;
332 335 size_t aclsz;
333 336 int i, error;
334 337
335 338 if ((error = md_get_uint8(mdp, &revision)) != 0)
336 339 return (error);
337 340 if ((error = md_get_uint8(mdp, NULL)) != 0) /* pad1 */
338 341 return (error);
339 342 if ((error = md_get_uint16le(mdp, &acl_len)) != 0)
340 343 return (error);
341 344 if ((error = md_get_uint16le(mdp, &acecount)) != 0)
342 345 return (error);
343 346 if ((error = md_get_uint16le(mdp, NULL)) != 0) /* pad2 */
344 347 return (error);
345 348
346 349 aclsz = I_ACL_SIZE(acecount);
347 350 if ((acl = MALLOC(aclsz)) == NULL)
348 351 return (ENOMEM);
349 352 bzero(acl, aclsz);
350 353 acl->acl_revision = revision;
351 354 acl->acl_acecount = acecount;
352 355
353 356 acep = &acl->acl_acevec[0];
354 357 for (i = 0; i < acl->acl_acecount; i++) {
355 358 ERRCHK(md_get_ace(mdp, acep));
356 359 acep++;
357 360 }
358 361 /*
359 362 * There may be more data here, but
360 363 * the caller takes care of that.
361 364 */
362 365
363 366 /* Success! */
364 367 *aclp = acl;
365 368 return (0);
366 369
367 370 errout:
368 371 ifree_acl(acl);
369 372 return (error);
370 373 }
371 374
372 375 static int
373 376 mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl)
374 377 {
375 378 i_ntace_t **acep;
376 379 uint16_t acl_len, *acl_len_p;
377 380 int i, cnt0, error;
378 381
379 382 cnt0 = mbp->mb_count;
380 383
381 384 ERRCHK(mb_put_uint8(mbp, acl->acl_revision));
382 385 ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */
383 386 acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p));
384 387 if (acl_len_p == NULL) {
385 388 error = ENOMEM;
386 389 goto errout;
387 390 }
388 391 ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount));
389 392 ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */
390 393
391 394 acep = &acl->acl_acevec[0];
392 395 for (i = 0; i < acl->acl_acecount; i++) {
393 396 ERRCHK(mb_put_ace(mbp, *acep));
394 397 acep++;
395 398 }
396 399
397 400 /* Fill in acl_len_p */
398 401 acl_len = mbp->mb_count - cnt0;
399 402 *acl_len_p = htoles(acl_len);
400 403
401 404 /* Success! */
402 405 return (0);
403 406
404 407 errout:
405 408 return (error);
406 409 }
407 410
408 411
409 412 /*
410 413 * Security Descriptor
411 414 */
412 415 void
413 416 smbfs_acl_free_sd(i_ntsd_t *sd)
414 417 {
415 418
416 419 if (sd == NULL)
417 420 return;
418 421
419 422 ifree_sid(sd->sd_owner);
420 423 ifree_sid(sd->sd_group);
421 424 ifree_acl(sd->sd_sacl);
422 425 ifree_acl(sd->sd_dacl);
423 426
424 427 FREESZ(sd, sizeof (*sd));
425 428 }
426 429
427 430 /*
428 431 * Import a raw SD (mb chain) into "internal" form.
429 432 * (like "absolute" form per. NT docs)
430 433 * Returns allocated data in sdp
431 434 *
432 435 * Note: does NOT consume all the mdp data, so the
433 436 * caller has to take care of that if necessary.
434 437 */
435 438 int
436 439 md_get_ntsd(mdchain_t *mdp, i_ntsd_t **sdp)
437 440 {
438 441 i_ntsd_t *sd = NULL;
439 442 mdchain_t top_md, tmp_md;
440 443 uint32_t owneroff, groupoff, sacloff, dacloff;
441 444 int error;
442 445
443 446 if ((sd = MALLOC(sizeof (*sd))) == NULL)
444 447 return (ENOMEM);
445 448 bzero(sd, sizeof (*sd));
446 449
447 450 /*
448 451 * Offsets below are relative to this point,
449 452 * so save the mdp state for use below.
450 453 */
451 454 top_md = *mdp;
452 455
453 456 ERRCHK(md_get_uint8(mdp, &sd->sd_revision));
454 457 ERRCHK(md_get_uint8(mdp, &sd->sd_rmctl));
455 458 ERRCHK(md_get_uint16le(mdp, &sd->sd_flags));
456 459 ERRCHK(md_get_uint32le(mdp, &owneroff));
457 460 ERRCHK(md_get_uint32le(mdp, &groupoff));
458 461 ERRCHK(md_get_uint32le(mdp, &sacloff));
459 462 ERRCHK(md_get_uint32le(mdp, &dacloff));
460 463
461 464 /*
462 465 * The SD is "self-relative" on the wire,
463 466 * but not after this decodes it.
464 467 */
465 468 sd->sd_flags &= ~SD_SELF_RELATIVE;
466 469
467 470 /*
468 471 * For each section make a temporary copy of the
469 472 * top_md state, advance to the given offset, and
470 473 * pass that to the lower md_get_xxx functions.
471 474 * These could be marshalled in any order, but
472 475 * are normally found in the order shown here.
473 476 */
474 477 if (sacloff) {
475 478 tmp_md = top_md;
476 479 md_get_mem(&tmp_md, NULL, sacloff, MB_MSYSTEM);
477 480 ERRCHK(md_get_acl(&tmp_md, &sd->sd_sacl));
478 481 }
479 482 if (dacloff) {
480 483 tmp_md = top_md;
481 484 md_get_mem(&tmp_md, NULL, dacloff, MB_MSYSTEM);
482 485 ERRCHK(md_get_acl(&tmp_md, &sd->sd_dacl));
483 486 }
484 487 if (owneroff) {
485 488 tmp_md = top_md;
486 489 md_get_mem(&tmp_md, NULL, owneroff, MB_MSYSTEM);
487 490 ERRCHK(md_get_sid(&tmp_md, &sd->sd_owner));
488 491 }
489 492 if (groupoff) {
490 493 tmp_md = top_md;
491 494 md_get_mem(&tmp_md, NULL, groupoff, MB_MSYSTEM);
492 495 ERRCHK(md_get_sid(&tmp_md, &sd->sd_group));
493 496 }
494 497
495 498 /* Success! */
496 499 *sdp = sd;
497 500 return (0);
498 501
499 502 errout:
500 503 smbfs_acl_free_sd(sd);
501 504 return (error);
502 505 }
503 506
504 507 /*
505 508 * Export an "internal" SD into an raw SD (mb chain).
506 509 * (a.k.a "self-relative" form per. NT docs)
507 510 * Returns allocated mbchain in mbp.
508 511 */
509 512 int
510 513 mb_put_ntsd(mbchain_t *mbp, i_ntsd_t *sd)
511 514 {
512 515 uint32_t *owneroffp, *groupoffp, *sacloffp, *dacloffp;
513 516 uint32_t owneroff, groupoff, sacloff, dacloff;
514 517 uint16_t flags;
515 518 int cnt0, error;
516 519
517 520 cnt0 = mbp->mb_count;
518 521 owneroff = groupoff = sacloff = dacloff = 0;
519 522
520 523 /* The SD is "self-relative" on the wire. */
521 524 flags = sd->sd_flags | SD_SELF_RELATIVE;
522 525
523 526 ERRCHK(mb_put_uint8(mbp, sd->sd_revision));
524 527 ERRCHK(mb_put_uint8(mbp, sd->sd_rmctl));
525 528 ERRCHK(mb_put_uint16le(mbp, flags));
526 529
527 530 owneroffp = mb_reserve(mbp, sizeof (*owneroffp));
528 531 groupoffp = mb_reserve(mbp, sizeof (*groupoffp));
529 532 sacloffp = mb_reserve(mbp, sizeof (*sacloffp));
530 533 dacloffp = mb_reserve(mbp, sizeof (*dacloffp));
531 534 if (owneroffp == NULL || groupoffp == NULL ||
532 535 sacloffp == NULL || dacloffp == NULL) {
533 536 error = ENOMEM;
534 537 goto errout;
535 538 }
536 539
537 540 /*
538 541 * These could be marshalled in any order, but
539 542 * are normally found in the order shown here.
540 543 */
541 544 if (sd->sd_sacl) {
542 545 sacloff = mbp->mb_count - cnt0;
543 546 ERRCHK(mb_put_acl(mbp, sd->sd_sacl));
544 547 }
545 548 if (sd->sd_dacl) {
546 549 dacloff = mbp->mb_count - cnt0;
547 550 ERRCHK(mb_put_acl(mbp, sd->sd_dacl));
548 551 }
549 552 if (sd->sd_owner) {
550 553 owneroff = mbp->mb_count - cnt0;
551 554 ERRCHK(mb_put_sid(mbp, sd->sd_owner));
552 555 }
553 556 if (sd->sd_group) {
554 557 groupoff = mbp->mb_count - cnt0;
555 558 ERRCHK(mb_put_sid(mbp, sd->sd_group));
556 559 }
557 560
558 561 /* Fill in the offsets */
559 562 *owneroffp = htolel(owneroff);
560 563 *groupoffp = htolel(groupoff);
561 564 *sacloffp = htolel(sacloff);
562 565 *dacloffp = htolel(dacloff);
563 566
564 567 /* Success! */
565 568 return (0);
566 569
567 570 errout:
568 571 return (error);
569 572 }
570 573
571 574 /*
572 575 * ================================================================
573 576 * Support for ACL fetch, including conversions
574 577 * from Windows ACLs to NFSv4-style ACLs.
575 578 * ================================================================
576 579 */
577 580
578 581 #define GENERIC_RIGHTS_MASK \
579 582 (GENERIC_RIGHT_READ_ACCESS | GENERIC_RIGHT_WRITE_ACCESS |\
580 583 GENERIC_RIGHT_EXECUTE_ACCESS | GENERIC_RIGHT_ALL_ACCESS)
581 584
582 585 /*
583 586 * Table for converting NT GENERIC_RIGHT_... to specific rights
584 587 * appropriate for objects of type file.
585 588 */
586 589 struct gen2fsr {
587 590 uint32_t gf_generic;
588 591 uint32_t gf_specific;
589 592 };
590 593 static const struct gen2fsr
591 594 smbfs_gen2fsr[] = {
592 595 {
593 596 GENERIC_RIGHT_READ_ACCESS,
594 597 STD_RIGHT_SYNCHRONIZE_ACCESS |
595 598 STD_RIGHT_READ_CONTROL_ACCESS |
596 599 SA_RIGHT_FILE_READ_ATTRIBUTES |
597 600 SA_RIGHT_FILE_READ_EA |
598 601 SA_RIGHT_FILE_READ_DATA },
599 602 {
600 603 GENERIC_RIGHT_WRITE_ACCESS,
601 604 STD_RIGHT_SYNCHRONIZE_ACCESS |
602 605 STD_RIGHT_READ_CONTROL_ACCESS |
603 606 SA_RIGHT_FILE_WRITE_ATTRIBUTES |
604 607 SA_RIGHT_FILE_WRITE_EA |
605 608 SA_RIGHT_FILE_APPEND_DATA |
606 609 SA_RIGHT_FILE_WRITE_DATA },
607 610 {
608 611 GENERIC_RIGHT_EXECUTE_ACCESS,
609 612 STD_RIGHT_SYNCHRONIZE_ACCESS |
610 613 STD_RIGHT_READ_CONTROL_ACCESS |
611 614 SA_RIGHT_FILE_READ_ATTRIBUTES |
612 615 SA_RIGHT_FILE_EXECUTE },
613 616 {
614 617 GENERIC_RIGHT_ALL_ACCESS,
615 618 STD_RIGHT_SYNCHRONIZE_ACCESS |
616 619 STD_RIGHT_WRITE_OWNER_ACCESS |
617 620 STD_RIGHT_WRITE_DAC_ACCESS |
618 621 STD_RIGHT_READ_CONTROL_ACCESS |
619 622 STD_RIGHT_DELETE_ACCESS |
620 623 SA_RIGHT_FILE_ALL_ACCESS },
621 624 { 0, 0 }
622 625 };
623 626
624 627 /*
625 628 * Table for translating ZFS ACE flags to NT ACE flags.
626 629 * The low four bits are the same, but not others.
627 630 */
628 631 struct zaf2naf {
629 632 uint16_t za_flag;
630 633 uint8_t na_flag;
631 634 };
632 635 static const struct zaf2naf
633 636 smbfs_zaf2naf[] = {
634 637 { ACE_FILE_INHERIT_ACE, OBJECT_INHERIT_ACE_FLAG },
635 638 { ACE_DIRECTORY_INHERIT_ACE, CONTAINER_INHERIT_ACE_FLAG },
636 639 { ACE_NO_PROPAGATE_INHERIT_ACE, NO_PROPAGATE_INHERIT_ACE_FLAG },
637 640 { ACE_INHERIT_ONLY_ACE, INHERIT_ONLY_ACE_FLAG },
638 641 { ACE_INHERITED_ACE, INHERITED_ACE_FLAG },
639 642 { ACE_SUCCESSFUL_ACCESS_ACE_FLAG, SUCCESSFUL_ACCESS_ACE_FLAG },
640 643 { ACE_FAILED_ACCESS_ACE_FLAG, FAILED_ACCESS_ACE_FLAG },
641 644 { 0, 0 }
642 645 };
643 646
644 647 /*
645 648 * Convert an NT SID to a string. Optionally return the
646 649 * last sub-authority (or "relative ID" -- RID) in *ridp
647 650 * and truncate the output string after the domain part.
648 651 * If ridp==NULL, the output string is the whole SID,
649 652 * including both the domain and RID.
650 653 *
651 654 * Return length written, or -1 on error.
652 655 */
653 656 int
654 657 smbfs_sid2str(i_ntsid_t *sid,
655 658 char *obuf, size_t osz, uint32_t *ridp)
656 659 {
657 660 char *s = obuf;
658 661 uint64_t auth = 0;
659 662 uint_t i, n;
660 663 uint32_t subs, *ip;
661 664
662 665 n = snprintf(s, osz, "S-%u", sid->sid_revision);
663 666 if (n > osz)
664 667 return (-1);
665 668 s += n; osz -= n;
666 669
667 670 for (i = 0; i < 6; i++)
668 671 auth = (auth << 8) | sid->sid_authority[i];
669 672 n = snprintf(s, osz, "-%llu", (u_longlong_t)auth);
670 673 if (n > osz)
671 674 return (-1);
672 675 s += n; osz -= n;
673 676
674 677 subs = sid->sid_subauthcount;
675 678 if (subs < 1 || subs > 15)
676 679 return (-1);
677 680 if (ridp)
678 681 subs--;
679 682
680 683 ip = &sid->sid_subauthvec[0];
681 684 for (; subs; subs--, ip++) {
682 685 n = snprintf(s, osz, "-%u", *ip);
683 686 if (n > osz)
684 687 return (-1);
685 688 s += n; osz -= n;
686 689 }
687 690 if (ridp)
688 691 *ridp = *ip;
689 692
690 693 /* LINTED E_PTRDIFF_OVERFLOW */
691 694 return (s - obuf);
692 695 }
693 696
694 697 /*
695 698 * Our interface to the idmap service.
696 699 *
697 700 * The idmap API is _almost_ the same between
698 701 * kernel and user-level. But not quite...
699 702 * Hope this improves readability below.
700 703 */
701 704 #ifdef _KERNEL
702 705
703 706 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
704 707 kidmap_batch_getuidbysid(GH, SPP, RID, UIDP, SP)
705 708
706 709 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
707 710 kidmap_batch_getgidbysid(GH, SPP, RID, GIDP, SP)
708 711
709 712 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
710 713 kidmap_batch_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP)
711 714
712 715 #define I_getmappings kidmap_get_mappings
713 716
714 717 #else /* _KERNEL */
715 718
716 719 #define I_getuidbysid(GH, SPP, RID, UIDP, SP) \
717 720 idmap_get_uidbysid(GH, SPP, RID, 0, UIDP, SP)
718 721
719 722 #define I_getgidbysid(GH, SPP, RID, GIDP, SP) \
720 723 idmap_get_gidbysid(GH, SPP, RID, 0, GIDP, SP)
721 724
722 725 #define I_getpidbysid(GH, SPP, RID, PIDP, ISUP, SP) \
723 726 idmap_get_pidbysid(GH, SPP, RID, 0, PIDP, ISUP, SP)
724 727
725 728 #define I_getmappings idmap_get_mappings
726 729
727 730 #endif /* _KERNEL */
728 731
729 732
730 733 /*
731 734 * The idmap request types, chosen so they also
732 735 * match the values returned in mi_isuser.
733 736 */
734 737 #define IDM_TYPE_ANY -1
735 738 #define IDM_TYPE_GROUP 0
736 739 #define IDM_TYPE_USER 1
737 740
738 741 /*
739 742 * A sentinel value for mi_isuser (below) to indicate
740 743 * that the SID is the well-known "Everyone" (S-1-1-0).
741 744 * The idmap library only uses -1, 0, 1, so this value
742 745 * is arbitrary but must not overlap w/ idmap values.
743 746 * XXX: Could use a way for idmap to tell us when
744 747 * it recognizes this well-known SID.
745 748 */
746 749 #define IDM_EVERYONE 11
747 750
748 751 struct mapinfo2uid {
749 752 uid_t mi_uid; /* or gid, or pid */
750 753 int mi_isuser; /* IDM_TYPE */
751 754 idmap_stat mi_status;
752 755 };
753 756
754 757 /*
755 758 * Build an idmap request. Cleanup is
756 759 * handled by the caller (error or not)
757 760 */
758 761 static int
759 762 mkrq_idmap_sid2ux(
760 763 idmap_get_handle_t *idmap_gh,
761 764 struct mapinfo2uid *mip,
762 765 i_ntsid_t *sid,
763 766 int req_type)
764 767 {
765 768 char strbuf[256];
766 769 char *sid_prefix;
767 770 uint32_t rid;
768 771 idmap_stat idms;
769 772
770 773 if (smbfs_sid2str(sid, strbuf, sizeof (strbuf), &rid) < 0)
771 774 return (EINVAL);
772 775 sid_prefix = strbuf;
773 776
774 777 /*
775 778 * Give the "Everyone" group special treatment.
776 779 */
777 780 if (strcmp(sid_prefix, "S-1-1") == 0 && rid == 0) {
778 781 /* This is "Everyone" */
779 782 mip->mi_uid = (uid_t)-1;
780 783 mip->mi_isuser = IDM_EVERYONE;
781 784 mip->mi_status = 0;
782 785 return (0);
783 786 }
784 787
785 788 switch (req_type) {
786 789
787 790 case IDM_TYPE_USER:
788 791 mip->mi_isuser = req_type;
789 792 idms = I_getuidbysid(idmap_gh, sid_prefix, rid,
790 793 &mip->mi_uid, &mip->mi_status);
791 794 break;
792 795
793 796 case IDM_TYPE_GROUP:
794 797 mip->mi_isuser = req_type;
795 798 idms = I_getgidbysid(idmap_gh, sid_prefix, rid,
796 799 &mip->mi_uid, &mip->mi_status);
797 800 break;
798 801
799 802 case IDM_TYPE_ANY:
800 803 idms = I_getpidbysid(idmap_gh, sid_prefix, rid,
801 804 &mip->mi_uid, &mip->mi_isuser, &mip->mi_status);
802 805 break;
803 806
804 807 default:
805 808 idms = IDMAP_ERR_OTHER;
806 809 break;
807 810 }
808 811
809 812 if (idms != IDMAP_SUCCESS)
810 813 return (EINVAL);
811 814
812 815 return (0);
813 816 }
814 817
815 818 /*
816 819 * Convert an NT ACE to a ZFS ACE.
817 820 * ACE type was already validated.
818 821 */
819 822 static void
820 823 ntace2zace(ace_t *zacep, i_ntace_t *ntace, struct mapinfo2uid *mip)
821 824 {
822 825 const struct zaf2naf *znaf;
823 826 uid_t zwho;
824 827 uint32_t zamask;
825 828 uint16_t zflags;
826 829
827 830 /*
828 831 * Set the "ID type" flags in the ZFS ace flags.
829 832 */
830 833 zflags = 0;
831 834 switch (mip->mi_isuser) {
832 835 case IDM_EVERYONE:
833 836 zflags = ACE_EVERYONE;
834 837 zwho = (uid_t)-1;
835 838 break;
836 839
837 840 case IDM_TYPE_GROUP: /* it's a GID */
838 841 zflags = ACE_IDENTIFIER_GROUP;
839 842 zwho = mip->mi_uid;
840 843 break;
841 844
842 845 default:
843 846 case IDM_TYPE_USER: /* it's a UID */
844 847 zflags = 0;
845 848 zwho = mip->mi_uid;
846 849 break;
847 850 }
848 851
849 852 /*
850 853 * Translate NT ACE flags to ZFS ACE flags.
851 854 */
852 855 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
853 856 if (ntace->ace_hdr.ace_flags & znaf->na_flag)
854 857 zflags |= znaf->za_flag;
855 858
856 859 /*
857 860 * The "normal" access mask bits are the same, but
858 861 * if the ACE has any GENERIC_RIGHT_... convert those
859 862 * to specific rights. GENERIC bits are rarely seen,
860 863 * but reportedly can happen with inherit-only ACEs.
861 864 */
862 865 zamask = ntace->ace_v2.ace_rights & ACE_ALL_PERMS;
863 866 if (ntace->ace_v2.ace_rights & GENERIC_RIGHTS_MASK) {
864 867 const struct gen2fsr *gf;
865 868 for (gf = smbfs_gen2fsr; gf->gf_generic; gf++)
866 869 if (ntace->ace_v2.ace_rights & gf->gf_generic)
867 870 zamask |= gf->gf_specific;
868 871 }
869 872
870 873 /*
871 874 * Fill in the ZFS-style ACE
872 875 */
873 876 zacep->a_who = zwho;
874 877 zacep->a_access_mask = zamask;
875 878 zacep->a_flags = zflags;
876 879 zacep->a_type = ntace->ace_hdr.ace_type;
877 880 }
878 881
879 882 /*
|
↓ open down ↓ |
805 lines elided |
↑ open up ↑ |
880 883 * Convert an internal SD to a ZFS-style ACL.
881 884 * Note optional args: vsa/acl, uidp, gidp.
882 885 *
883 886 * This makes two passes over the SD, the first building a
884 887 * "batch" request for idmap with results in mapinfo, the
885 888 * second building a ZFS-style ACL using the idmap results.
886 889 */
887 890 int
888 891 smbfs_acl_sd2zfs(
889 892 i_ntsd_t *sd,
890 -#ifdef _KERNEL
893 +#if defined(_KERNEL) || defined(_FAKE_KERNEL)
891 894 vsecattr_t *acl_info,
892 895 #else /* _KERNEL */
893 896 acl_t *acl_info,
894 897 #endif /* _KERNEL */
895 898 uid_t *uidp, gid_t *gidp)
896 899 {
897 900 struct mapinfo2uid *mip, *mapinfo = NULL;
898 901 int error, i, mapcnt, zacecnt, zacl_size;
899 902 ace_t *zacep0, *zacep;
900 903 uid_t own_uid = (uid_t)-1;
901 904 gid_t own_gid = (gid_t)-1;
902 905 i_ntacl_t *ntacl;
903 906 i_ntace_t **ntacep;
904 907 idmap_get_handle_t *idmap_gh = NULL;
905 908 idmap_stat idms;
906 909
907 910 /*
908 911 * sanity checks
909 912 */
910 913 if (acl_info) {
911 -#ifndef _KERNEL
914 +#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
912 915 if (acl_info->acl_type != ACE_T ||
913 916 acl_info->acl_aclp != NULL ||
914 917 acl_info->acl_entry_size != sizeof (ace_t))
915 918 return (EINVAL);
916 -#endif /* _KERNEL */
919 +#endif /* !_KERNEL */
917 920 if ((sd->sd_flags & SD_DACL_PRESENT) == 0)
918 921 return (EINVAL);
919 922 }
920 923
921 924 /*
922 925 * How many SID mappings will we need?
923 926 */
924 927 mapcnt = 0;
925 928 if (sd->sd_owner)
926 929 mapcnt++;
927 930 if (sd->sd_group)
928 931 mapcnt++;
929 932 if ((sd->sd_flags & SD_SACL_PRESENT) &&
930 933 (sd->sd_sacl != NULL))
931 934 mapcnt += sd->sd_sacl->acl_acecount;
932 935 if ((sd->sd_flags & SD_DACL_PRESENT) &&
933 936 (sd->sd_dacl != NULL))
934 937 mapcnt += sd->sd_dacl->acl_acecount;
935 938 if (mapcnt == 0) {
936 939 /*
937 940 * We have a NULL DACL, SACL, and don't
938 941 * have an owner or group, so there's no
939 942 * idmap work to do. This is very rare,
940 943 * so rather than complicate things below,
941 944 * pretend we need one mapping slot.
942 945 */
943 946 mapcnt = 1;
944 947 }
945 948
946 949 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
947 950 if (mapinfo == NULL) {
948 951 error = ENOMEM;
949 952 goto errout;
950 953 }
951 954 bzero(mapinfo, mapcnt * sizeof (*mapinfo));
952 955
953 956
954 957 /*
955 958 * Get an imap "batch" request handle.
956 959 */
957 960 #ifdef _KERNEL
958 961 idmap_gh = kidmap_get_create(curproc->p_zone);
959 962 #else /* _KERNEL */
960 963 idms = idmap_get_create(&idmap_gh);
961 964 if (idms != IDMAP_SUCCESS) {
962 965 error = ENOTACTIVE;
963 966 goto errout;
964 967 }
965 968 #endif /* _KERNEL */
966 969
967 970 /*
968 971 * Build our request to the idmap deamon,
969 972 * getting Unix IDs for every SID.
970 973 */
971 974 mip = mapinfo;
972 975 if (sd->sd_owner) {
973 976 error = mkrq_idmap_sid2ux(idmap_gh, mip,
974 977 sd->sd_owner, IDM_TYPE_USER);
975 978 if (error)
976 979 goto errout;
977 980 mip++;
978 981 }
979 982 if (sd->sd_group) {
980 983 error = mkrq_idmap_sid2ux(idmap_gh, mip,
981 984 sd->sd_group, IDM_TYPE_GROUP);
982 985 if (error)
983 986 goto errout;
984 987 mip++;
985 988 }
986 989 if ((sd->sd_flags & SD_SACL_PRESENT) &&
987 990 (sd->sd_sacl != NULL)) {
988 991 ntacl = sd->sd_sacl;
989 992 ntacep = &ntacl->acl_acevec[0];
990 993 for (i = 0; i < ntacl->acl_acecount; i++) {
991 994 error = mkrq_idmap_sid2ux(idmap_gh, mip,
992 995 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
993 996 if (error)
994 997 goto errout;
995 998 ntacep++;
996 999 mip++;
997 1000 }
998 1001 }
999 1002 if ((sd->sd_flags & SD_DACL_PRESENT) &&
1000 1003 (sd->sd_dacl != NULL)) {
1001 1004 ntacl = sd->sd_dacl;
1002 1005 ntacep = &ntacl->acl_acevec[0];
1003 1006 for (i = 0; i < ntacl->acl_acecount; i++) {
1004 1007 error = mkrq_idmap_sid2ux(idmap_gh, mip,
1005 1008 (*ntacep)->ace_v2.ace_sid, IDM_TYPE_ANY);
1006 1009 if (error)
1007 1010 goto errout;
1008 1011 ntacep++;
1009 1012 mip++;
1010 1013 }
1011 1014 }
1012 1015
1013 1016 if (mip != mapinfo) {
1014 1017 idms = I_getmappings(idmap_gh);
1015 1018 if (idms != IDMAP_SUCCESS) {
1016 1019 /* creative error choice */
1017 1020 error = EIDRM;
1018 1021 goto errout;
1019 1022 }
1020 1023 }
1021 1024
1022 1025 /*
1023 1026 * With any luck, we now have Unix user/group IDs
1024 1027 * for every Windows SID in the security descriptor.
1025 1028 * The remaining work is just format conversion.
1026 1029 */
1027 1030 mip = mapinfo;
1028 1031 if (sd->sd_owner) {
1029 1032 own_uid = mip->mi_uid;
1030 1033 mip++;
1031 1034 }
1032 1035 if (sd->sd_group) {
1033 1036 own_gid = mip->mi_uid;
1034 1037 mip++;
1035 1038 }
1036 1039
1037 1040 if (uidp)
1038 1041 *uidp = own_uid;
1039 1042 if (gidp)
1040 1043 *gidp = own_gid;
1041 1044
1042 1045 if (acl_info == NULL) {
1043 1046 /* Caller only wanted uid/gid */
1044 1047 goto done;
1045 1048 }
1046 1049
1047 1050 /*
1048 1051 * Build the ZFS-style ACL
1049 1052 * First, allocate the most ZFS ACEs we'll need.
1050 1053 */
1051 1054 zacecnt = 0;
1052 1055 if ((sd->sd_flags & SD_SACL_PRESENT) &&
1053 1056 (sd->sd_sacl != NULL))
1054 1057 zacecnt += sd->sd_sacl->acl_acecount;
1055 1058
1056 1059 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1057 1060 if ((sd->sd_dacl != NULL) &&
1058 1061 (sd->sd_dacl->acl_acecount > 0)) {
1059 1062 zacecnt += sd->sd_dacl->acl_acecount;
1060 1063 } else {
1061 1064 /*
1062 1065 * DACL is NULL or empty. Either way,
1063 1066 * we'll need to add a ZFS ACE below.
1064 1067 */
1065 1068 zacecnt++;
1066 1069 }
1067 1070 zacl_size = zacecnt * sizeof (ace_t);
1068 1071 zacep0 = MALLOC(zacl_size);
1069 1072 if (zacep0 == NULL) {
1070 1073 error = ENOMEM;
1071 1074 goto errout;
1072 1075 }
1073 1076 zacep = zacep0;
1074 1077
1075 1078 if ((sd->sd_flags & SD_SACL_PRESENT) &&
1076 1079 (sd->sd_sacl != NULL)) {
1077 1080 ntacl = sd->sd_sacl;
1078 1081 ntacep = &ntacl->acl_acevec[0];
1079 1082 for (i = 0; i < ntacl->acl_acecount; i++) {
1080 1083 ntace2zace(zacep, *ntacep, mip);
1081 1084 zacep++;
1082 1085 ntacep++;
1083 1086 mip++;
1084 1087 }
1085 1088 }
1086 1089
1087 1090 /* NB, have: (sd->sd_flags & SD_DACL_PRESENT) */
1088 1091 if (sd->sd_dacl != NULL) {
1089 1092 ntacl = sd->sd_dacl;
1090 1093 ntacep = &ntacl->acl_acevec[0];
1091 1094 for (i = 0; i < ntacl->acl_acecount; i++) {
1092 1095 ntace2zace(zacep, *ntacep, mip);
1093 1096 zacep++;
1094 1097 ntacep++;
1095 1098 mip++;
1096 1099 }
1097 1100 }
1098 1101 if (sd->sd_dacl == NULL) {
1099 1102 /*
1100 1103 * The SD has a NULL DACL. That means
1101 1104 * everyone@, full-control
1102 1105 */
1103 1106 zacep->a_who = (uid_t)-1;
1104 1107 zacep->a_access_mask = ACE_ALL_PERMS;
1105 1108 zacep->a_flags = ACE_EVERYONE;
1106 1109 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1107 1110 } else if (sd->sd_dacl->acl_acecount == 0) {
1108 1111 /*
1109 1112 * The SD has an Empty DACL. We need
|
↓ open down ↓ |
183 lines elided |
↑ open up ↑ |
1110 1113 * at least one ACE, so add one giving
1111 1114 * the owner the usual implied access.
1112 1115 */
1113 1116 zacep->a_who = (uid_t)-1;
1114 1117 zacep->a_access_mask = ACE_READ_ATTRIBUTES | \
1115 1118 ACE_READ_ACL | ACE_WRITE_ACL;
1116 1119 zacep->a_flags = ACE_OWNER;
1117 1120 zacep->a_type = ACCESS_ALLOWED_ACE_TYPE;
1118 1121 }
1119 1122
1120 -#ifdef _KERNEL
1123 +#if defined(_KERNEL) || defined(_FAKE_KERNEL)
1121 1124 acl_info->vsa_aclcnt = zacecnt;
1122 1125 acl_info->vsa_aclentp = zacep0;
1123 1126 acl_info->vsa_aclentsz = zacl_size;
1124 1127 #else /* _KERNEL */
1125 1128 acl_info->acl_cnt = zacecnt;
1126 1129 acl_info->acl_aclp = zacep0;
1127 1130 #endif /* _KERNEL */
1128 1131
1129 1132 done:
1130 1133 error = 0;
1131 1134
1132 1135 errout:
1133 1136 if (mapinfo != NULL)
1134 1137 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1135 1138 #ifdef _KERNEL
1136 1139 if (idmap_gh != NULL)
1137 1140 kidmap_get_destroy(idmap_gh);
1138 1141 #else /* _KERNEL */
1139 1142 if (idmap_gh != NULL)
1140 1143 idmap_get_destroy(idmap_gh);
1141 1144 #endif /* _KERNEL */
1142 1145
1143 1146 return (error);
1144 1147 }
1145 1148
1146 1149
1147 1150 /*
1148 1151 * ================================================================
1149 1152 * Support for ACL store, including conversions
1150 1153 * from NFSv4-style ACLs to Windows ACLs.
1151 1154 * ================================================================
1152 1155 */
1153 1156
1154 1157 /*
1155 1158 * Convert a "sid-prefix" string plus RID into an NT SID.
1156 1159 *
1157 1160 * If successful, sets *osid and returns zero,
1158 1161 * otherwise returns an errno value.
1159 1162 */
1160 1163 int
1161 1164 smbfs_str2sid(const char *sid_prefix, uint32_t *ridp, i_ntsid_t **osidp)
1162 1165 {
1163 1166 i_ntsid_t *sid = NULL;
1164 1167 u_longlong_t auth = 0;
1165 1168 ulong_t sa;
1166 1169 uint8_t sacnt;
1167 1170 const char *p;
1168 1171 char *np;
1169 1172 size_t size;
1170 1173 int i;
1171 1174 int err;
1172 1175
1173 1176 if (sid_prefix == NULL)
1174 1177 return (EINVAL);
1175 1178
1176 1179 p = sid_prefix;
1177 1180 if (strncmp(p, "S-1-", 4) != 0)
1178 1181 return (EINVAL);
1179 1182 p += 4;
1180 1183
1181 1184 /* Parse the "authority" */
1182 1185 #ifdef _KERNEL
1183 1186 err = ddi_strtoull(p, &np, 10, &auth);
1184 1187 if (err != 0)
1185 1188 return (err);
1186 1189 #else /* _KERNEL */
1187 1190 auth = strtoull(p, &np, 10);
1188 1191 if (p == np)
1189 1192 return (EINVAL);
1190 1193 #endif /* _KERNEL */
1191 1194
1192 1195 /*
1193 1196 * Count the sub-authorities. Here, np points to
1194 1197 * the "-" before the first sub-authority.
1195 1198 */
1196 1199 sacnt = 0;
1197 1200 for (p = np; *p; p++) {
1198 1201 if (*p == '-')
1199 1202 sacnt++;
1200 1203 }
1201 1204 if (ridp != NULL)
1202 1205 sacnt++;
1203 1206
1204 1207 /* Allocate the internal SID. */
1205 1208 size = I_SID_SIZE(sacnt);
1206 1209 sid = MALLOC(size);
1207 1210 if (sid == NULL)
1208 1211 return (ENOMEM);
1209 1212 bzero(sid, size);
1210 1213
1211 1214 /* Fill it in. */
1212 1215 sid->sid_revision = 1;
1213 1216 sid->sid_subauthcount = sacnt;
1214 1217 for (i = 5; i >= 0; i--) {
1215 1218 sid->sid_authority[i] = auth & 0xFF;
1216 1219 auth = auth >> 8;
1217 1220 }
1218 1221
|
↓ open down ↓ |
88 lines elided |
↑ open up ↑ |
1219 1222 err = EINVAL;
1220 1223 if (ridp != NULL)
1221 1224 sacnt--; /* Last SA not from string */
1222 1225 p = np;
1223 1226 for (i = 0; i < sacnt; i++) {
1224 1227 if (*p != '-') {
1225 1228 err = EINVAL;
1226 1229 goto out;
1227 1230 }
1228 1231 p++;
1229 -#ifdef _KERNEL
1232 +#if defined(_KERNEL) || defined(_FAKE_KERNEL)
1230 1233 err = ddi_strtoul(p, &np, 10, &sa);
1231 1234 if (err != 0)
1232 1235 goto out;
1233 1236 #else /* _KERNEL */
1234 1237 sa = strtoul(p, &np, 10);
1235 1238 if (p == np) {
1236 1239 err = EINVAL;
1237 1240 goto out;
1238 1241 }
1239 1242 #endif /* _KERNEL */
1240 1243 sid->sid_subauthvec[i] = (uint32_t)sa;
1241 1244 p = np;
1242 1245 }
1243 1246 if (*p != '\0')
1244 1247 goto out;
1245 1248 if (ridp != NULL)
1246 1249 sid->sid_subauthvec[i] = *ridp;
1247 1250 err = 0;
1248 1251
1249 1252 out:
1250 1253 if (err)
1251 1254 FREESZ(sid, size);
1252 1255 else
1253 1256 *osidp = sid;
1254 1257
1255 1258 return (err);
1256 1259 }
1257 1260
1258 1261 /*
1259 1262 * The idmap API is _almost_ the same between
1260 1263 * kernel and user-level. But not quite...
1261 1264 * Hope this improves readability below.
1262 1265 */
1263 1266 #ifdef _KERNEL
1264 1267
1265 1268 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1266 1269 kidmap_batch_getsidbyuid(GH, UID, SPP, RP, ST)
1267 1270
1268 1271 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1269 1272 kidmap_batch_getsidbygid(GH, GID, SPP, RP, ST)
1270 1273
1271 1274 #else /* _KERNEL */
1272 1275
1273 1276 #define I_getsidbyuid(GH, UID, SPP, RP, ST) \
1274 1277 idmap_get_sidbyuid(GH, UID, 0, SPP, RP, ST)
1275 1278
1276 1279 #define I_getsidbygid(GH, GID, SPP, RP, ST) \
1277 1280 idmap_get_sidbygid(GH, GID, 0, SPP, RP, ST)
1278 1281
1279 1282 #endif /* _KERNEL */
1280 1283
1281 1284 struct mapinfo2sid {
1282 1285 /* Yet another kernel vs. user difference. */
1283 1286 #ifdef _KERNEL
1284 1287 const char *mi_dsid; /* domain SID */
1285 1288 #else /* _KERNEL */
1286 1289 char *mi_dsid;
1287 1290 #endif /* _KERNEL */
1288 1291 uint32_t mi_rid; /* relative ID */
1289 1292 idmap_stat mi_status;
1290 1293 };
1291 1294
1292 1295 /*
1293 1296 * Build an idmap request. Cleanup is
1294 1297 * handled by the caller (error or not)
1295 1298 */
1296 1299 static int
1297 1300 mkrq_idmap_ux2sid(
1298 1301 idmap_get_handle_t *idmap_gh,
1299 1302 struct mapinfo2sid *mip,
1300 1303 uid_t uid, /* or gid */
1301 1304 int req_type)
1302 1305 {
1303 1306 idmap_stat idms;
1304 1307
1305 1308 switch (req_type) {
1306 1309
1307 1310 case IDM_TYPE_USER:
1308 1311 if (uid == (uid_t)-1)
1309 1312 return (EINVAL);
1310 1313 idms = I_getsidbyuid(idmap_gh, uid,
1311 1314 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1312 1315 break;
1313 1316
1314 1317 case IDM_TYPE_GROUP:
1315 1318 if (uid == (uid_t)-1)
1316 1319 return (EINVAL);
1317 1320 idms = I_getsidbygid(idmap_gh, uid,
1318 1321 &mip->mi_dsid, &mip->mi_rid, &mip->mi_status);
1319 1322 break;
1320 1323
1321 1324 case IDM_EVERYONE:
1322 1325 mip->mi_dsid = "S-1-1";
1323 1326 mip->mi_rid = 0;
1324 1327 mip->mi_status = 0;
1325 1328 idms = IDMAP_SUCCESS;
1326 1329 break;
1327 1330
1328 1331 default:
1329 1332 idms = IDMAP_ERR_OTHER;
1330 1333 break;
1331 1334 }
1332 1335
1333 1336 if (idms != IDMAP_SUCCESS)
1334 1337 return (EINVAL);
1335 1338
1336 1339 return (0);
1337 1340 }
1338 1341
1339 1342 /*
1340 1343 * Convert a ZFS ACE to an NT ACE.
1341 1344 * ACE type was already validated.
1342 1345 */
1343 1346 static int
1344 1347 zace2ntace(i_ntace_t **ntacep, ace_t *zacep, struct mapinfo2sid *mip)
1345 1348 {
1346 1349 const struct zaf2naf *znaf;
1347 1350 uint8_t aflags;
1348 1351 uint16_t alloc_size;
1349 1352 uint32_t rights;
1350 1353 i_ntace_t *ntace = NULL;
1351 1354 i_ntsid_t *sid = NULL;
1352 1355 int error;
1353 1356
1354 1357 if (mip->mi_dsid == NULL || mip->mi_status != 0) {
1355 1358 return (EINVAL);
1356 1359 }
1357 1360
1358 1361 /*
1359 1362 * Translate ZFS ACE flags to NT ACE flags.
1360 1363 */
1361 1364 aflags = 0;
1362 1365 for (znaf = smbfs_zaf2naf; znaf->za_flag; znaf++)
1363 1366 if (zacep->a_flags & znaf->za_flag)
1364 1367 aflags |= znaf->na_flag;
1365 1368
1366 1369 /*
1367 1370 * The access rights bits are OK as-is.
1368 1371 */
1369 1372 rights = zacep->a_access_mask;
1370 1373
1371 1374 /*
1372 1375 * Make sure we can get the SID.
1373 1376 * Note: allocates sid.
1374 1377 */
1375 1378 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid, &sid);
1376 1379 if (error)
1377 1380 return (error);
1378 1381
1379 1382 /*
1380 1383 * Allocate the NT ACE and fill it in.
1381 1384 */
1382 1385 alloc_size = sizeof (i_ntace_v2_t);
1383 1386 if ((ntace = MALLOC(alloc_size)) == NULL) {
1384 1387 ifree_sid(sid);
1385 1388 return (ENOMEM);
1386 1389 }
1387 1390 bzero(ntace, alloc_size);
1388 1391
1389 1392 ntace->ace_hdr.ace_type = zacep->a_type;
1390 1393 ntace->ace_hdr.ace_flags = aflags;
1391 1394 ntace->ace_hdr.ace_size = alloc_size;
1392 1395 ntace->ace_v2.ace_rights = rights;
1393 1396 ntace->ace_v2.ace_sid = sid;
1394 1397
1395 1398 *ntacep = ntace;
1396 1399 return (0);
1397 1400 }
1398 1401
1399 1402 /*
1400 1403 * Convert a ZFS-style ACL to an internal SD.
1401 1404 * Set owner/group too if selector indicates.
|
↓ open down ↓ |
162 lines elided |
↑ open up ↑ |
1402 1405 * Always need to pass uid+gid, either the new
1403 1406 * (when setting them) or existing, so that any
1404 1407 * owner@ or group@ ACEs can be translated.
1405 1408 *
1406 1409 * This makes two passes over the ZFS ACL. The first builds a
1407 1410 * "batch" request for idmap with results in mapinfo, and the
1408 1411 * second builds the NT SD using the idmap SID results.
1409 1412 */
1410 1413 int
1411 1414 smbfs_acl_zfs2sd(
1412 -#ifdef _KERNEL
1415 +#if defined(_KERNEL) || defined(_FAKE_KERNEL)
1413 1416 vsecattr_t *acl_info,
1414 1417 #else /* _KERNEL */
1415 1418 acl_t *acl_info,
1416 1419 #endif /* _KERNEL */
1417 1420 uid_t own_uid,
1418 1421 gid_t own_gid,
1419 1422 uint32_t selector,
1420 1423 i_ntsd_t **sdp)
1421 1424 {
1422 1425 struct mapinfo2sid *mip, *mip_acl, *mapinfo = NULL;
1423 1426 int aclsz, error, i, mapcnt;
1424 1427 int dacl_acecnt = 0;
1425 1428 int sacl_acecnt = 0;
1426 1429 int zacecnt = 0;
1427 1430 ace_t *zacevec = NULL;
1428 1431 ace_t *zacep;
1429 1432 i_ntsd_t *sd = NULL;
1430 1433 i_ntacl_t *acl = NULL;
1431 1434 i_ntace_t **acep = NULL;
1432 1435 idmap_get_handle_t *idmap_gh = NULL;
1433 1436 idmap_stat idms;
1434 1437
1435 1438 /*
1436 1439 * First, get all the UID+GID to SID mappings.
1437 1440 * How many? Also sanity checks.
1438 1441 */
1439 1442 mapcnt = 0;
1440 1443 if (selector & OWNER_SECURITY_INFORMATION) {
1441 1444 if (own_uid == (uid_t)-1)
1442 1445 return (EINVAL);
1443 1446 mapcnt++;
1444 1447 }
1445 1448 if (selector & GROUP_SECURITY_INFORMATION) {
1446 1449 if (own_gid == (gid_t)-1)
1447 1450 return (EINVAL);
|
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
1448 1451 mapcnt++;
1449 1452 }
1450 1453 if (selector & (DACL_SECURITY_INFORMATION |
1451 1454 SACL_SECURITY_INFORMATION)) {
1452 1455 if (acl_info == NULL)
1453 1456 return (EINVAL);
1454 1457 if (own_uid == (uid_t)-1)
1455 1458 return (EINVAL);
1456 1459 if (own_gid == (gid_t)-1)
1457 1460 return (EINVAL);
1458 -#ifdef _KERNEL
1461 +#if defined(_KERNEL) || defined(_FAKE_KERNEL)
1459 1462 if ((acl_info->vsa_mask & VSA_ACE) == 0)
1460 1463 return (EINVAL);
1461 1464 zacecnt = acl_info->vsa_aclcnt;
1462 1465 zacevec = acl_info->vsa_aclentp;
1463 1466 #else /* _KERNEL */
1464 1467 if (acl_info->acl_type != ACE_T ||
1465 1468 acl_info->acl_entry_size != sizeof (ace_t))
1466 1469 return (EINVAL);
1467 1470 zacecnt = acl_info->acl_cnt;
1468 1471 zacevec = acl_info->acl_aclp;
1469 1472 #endif /* _KERNEL */
1470 1473 if (zacecnt == 0 || zacevec == NULL)
1471 1474 return (EINVAL);
1472 1475 mapcnt += zacecnt;
1473 1476 }
1474 1477 if (mapcnt == 0)
1475 1478 return (EINVAL);
1476 1479 mapinfo = MALLOC(mapcnt * sizeof (*mapinfo));
1477 1480 if (mapinfo == NULL)
1478 1481 return (ENOMEM);
1479 1482 bzero(mapinfo, mapcnt * sizeof (*mapinfo));
1480 1483 /* no more returns until errout */
1481 1484
1482 1485 /*
1483 1486 * Get an imap "batch" request handle.
1484 1487 */
1485 1488 #ifdef _KERNEL
1486 1489 idmap_gh = kidmap_get_create(curproc->p_zone);
1487 1490 #else /* _KERNEL */
1488 1491 idms = idmap_get_create(&idmap_gh);
1489 1492 if (idms != IDMAP_SUCCESS) {
1490 1493 error = ENOTACTIVE;
1491 1494 goto errout;
1492 1495 }
1493 1496 #endif /* _KERNEL */
1494 1497
1495 1498 /*
1496 1499 * Build our request to the idmap deamon,
1497 1500 * getting SIDs for every Unix UID/GID.
1498 1501 * Also count DACL and SACL ACEs here.
1499 1502 */
1500 1503 mip = mapinfo;
1501 1504 if (selector & OWNER_SECURITY_INFORMATION) {
1502 1505 error = mkrq_idmap_ux2sid(idmap_gh, mip,
1503 1506 own_uid, IDM_TYPE_USER);
1504 1507 if (error)
1505 1508 goto errout;
1506 1509 mip++;
1507 1510 }
1508 1511 if (selector & GROUP_SECURITY_INFORMATION) {
1509 1512 error = mkrq_idmap_ux2sid(idmap_gh, mip,
1510 1513 own_gid, IDM_TYPE_GROUP);
1511 1514 if (error)
1512 1515 goto errout;
1513 1516 mip++;
1514 1517 }
1515 1518 if (selector & (DACL_SECURITY_INFORMATION |
1516 1519 SACL_SECURITY_INFORMATION)) {
1517 1520 int rqtype;
1518 1521 uid_t uid;
1519 1522
1520 1523 zacep = zacevec;
1521 1524 for (i = 0; i < zacecnt; i++) {
1522 1525
1523 1526 switch (zacep->a_type) {
1524 1527 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1525 1528 case ACE_ACCESS_DENIED_ACE_TYPE:
1526 1529 dacl_acecnt++;
1527 1530 break;
1528 1531 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1529 1532 case ACE_SYSTEM_ALARM_ACE_TYPE:
1530 1533 sacl_acecnt++;
1531 1534 break;
1532 1535 /* other types todo */
1533 1536 }
1534 1537
1535 1538 if (zacep->a_flags & ACE_EVERYONE) {
1536 1539 rqtype = IDM_EVERYONE;
1537 1540 uid = (uid_t)-1;
1538 1541 } else if (zacep->a_flags & ACE_GROUP) {
1539 1542 /* owning group (a_who = -1) */
1540 1543 rqtype = IDM_TYPE_GROUP;
1541 1544 uid = (uid_t)own_gid;
1542 1545 } else if (zacep->a_flags & ACE_OWNER) {
1543 1546 /* owning user (a_who = -1) */
1544 1547 rqtype = IDM_TYPE_USER;
1545 1548 uid = (uid_t)own_uid;
1546 1549 } else if (zacep->a_flags & ACE_IDENTIFIER_GROUP) {
1547 1550 /* regular group */
1548 1551 rqtype = IDM_TYPE_GROUP;
1549 1552 uid = zacep->a_who;
1550 1553 } else {
1551 1554 rqtype = IDM_TYPE_USER;
1552 1555 uid = zacep->a_who;
1553 1556 }
1554 1557
1555 1558 error = mkrq_idmap_ux2sid(idmap_gh, mip, uid, rqtype);
1556 1559 if (error)
1557 1560 goto errout;
1558 1561 zacep++;
1559 1562 mip++;
1560 1563 }
1561 1564 }
1562 1565
1563 1566 idms = I_getmappings(idmap_gh);
1564 1567 if (idms != IDMAP_SUCCESS) {
1565 1568 /* creative error choice */
1566 1569 error = EIDRM;
1567 1570 goto errout;
1568 1571 }
1569 1572
1570 1573 /*
1571 1574 * With any luck, we now have a Windows SID for
1572 1575 * every Unix UID or GID in the NFS/ZFS ACL.
1573 1576 * The remaining work is just format conversion,
1574 1577 * memory allocation, etc.
1575 1578 */
1576 1579 if ((sd = MALLOC(sizeof (*sd))) == NULL) {
1577 1580 error = ENOMEM;
1578 1581 goto errout;
1579 1582 }
1580 1583 bzero(sd, sizeof (*sd));
1581 1584 sd->sd_revision = NT_SD_REVISION;
1582 1585
1583 1586 mip = mapinfo;
1584 1587 if (selector & OWNER_SECURITY_INFORMATION) {
1585 1588 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1586 1589 &sd->sd_owner);
1587 1590 mip++;
1588 1591 }
1589 1592 if (selector & GROUP_SECURITY_INFORMATION) {
1590 1593 error = smbfs_str2sid(mip->mi_dsid, &mip->mi_rid,
1591 1594 &sd->sd_group);
1592 1595 mip++;
1593 1596 }
1594 1597
1595 1598 /*
1596 1599 * If setting both DACL and SACL, we will
1597 1600 * make two passes starting here in mapinfo.
1598 1601 */
1599 1602 mip_acl = mip;
1600 1603
1601 1604 if (selector & DACL_SECURITY_INFORMATION) {
1602 1605 /*
1603 1606 * Caller wants to set the DACL.
1604 1607 */
1605 1608 aclsz = I_ACL_SIZE(dacl_acecnt);
1606 1609 if ((acl = MALLOC(aclsz)) == NULL) {
1607 1610 error = ENOMEM;
1608 1611 goto errout;
1609 1612 }
1610 1613 bzero(acl, aclsz);
1611 1614
1612 1615 acl->acl_revision = NT_ACL_REVISION;
1613 1616 acl->acl_acecount = (uint16_t)dacl_acecnt;
1614 1617 acep = &acl->acl_acevec[0];
1615 1618
1616 1619 /* 1st pass - scan for DACL ACE types. */
1617 1620 mip = mip_acl;
1618 1621 zacep = zacevec;
1619 1622 for (i = 0; i < zacecnt; i++) {
1620 1623
1621 1624 switch (zacep->a_type) {
1622 1625 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1623 1626 case ACE_ACCESS_DENIED_ACE_TYPE:
1624 1627 error = zace2ntace(acep, zacep, mip);
1625 1628 if (error != 0)
1626 1629 goto errout;
1627 1630 acep++;
1628 1631 break;
1629 1632
1630 1633 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1631 1634 case ACE_SYSTEM_ALARM_ACE_TYPE:
1632 1635 break;
1633 1636 /* other types todo */
1634 1637 }
1635 1638 zacep++;
1636 1639 mip++;
1637 1640 }
1638 1641 sd->sd_dacl = acl;
1639 1642 acl = NULL;
1640 1643 sd->sd_flags |= SD_DACL_PRESENT;
1641 1644 }
1642 1645
1643 1646 if (selector & SACL_SECURITY_INFORMATION) {
1644 1647 /*
1645 1648 * Caller wants to set the SACL.
1646 1649 */
1647 1650 aclsz = I_ACL_SIZE(sacl_acecnt);
1648 1651 if ((acl = MALLOC(aclsz)) == NULL) {
1649 1652 error = ENOMEM;
1650 1653 goto errout;
1651 1654 }
1652 1655 bzero(acl, aclsz);
1653 1656
1654 1657 acl->acl_revision = NT_ACL_REVISION;
1655 1658 acl->acl_acecount = (uint16_t)sacl_acecnt;
1656 1659 acep = &acl->acl_acevec[0];
1657 1660
1658 1661 /* 2nd pass - scan for SACL ACE types. */
1659 1662 mip = mip_acl;
1660 1663 zacep = zacevec;
1661 1664 for (i = 0; i < zacecnt; i++) {
1662 1665
1663 1666 switch (zacep->a_type) {
1664 1667 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1665 1668 case ACE_ACCESS_DENIED_ACE_TYPE:
1666 1669 break;
1667 1670
1668 1671 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1669 1672 case ACE_SYSTEM_ALARM_ACE_TYPE:
1670 1673 error = zace2ntace(acep, zacep, mip);
1671 1674 if (error != 0)
1672 1675 goto errout;
1673 1676 acep++;
1674 1677 break;
1675 1678 /* other types todo */
1676 1679 }
1677 1680 zacep++;
1678 1681 mip++;
1679 1682 }
1680 1683 sd->sd_sacl = acl;
1681 1684 acl = NULL;
1682 1685 sd->sd_flags |= SD_SACL_PRESENT;
1683 1686 }
1684 1687
1685 1688 *sdp = sd;
1686 1689 error = 0;
1687 1690
1688 1691 errout:
1689 1692 if (error != 0) {
1690 1693 if (acl != NULL)
1691 1694 ifree_acl(acl);
1692 1695 if (sd != NULL)
1693 1696 smbfs_acl_free_sd(sd);
1694 1697 }
1695 1698 if (mapinfo != NULL)
1696 1699 FREESZ(mapinfo, mapcnt * sizeof (*mapinfo));
1697 1700 #ifdef _KERNEL
1698 1701 if (idmap_gh != NULL)
1699 1702 kidmap_get_destroy(idmap_gh);
1700 1703 #else /* _KERNEL */
1701 1704 if (idmap_gh != NULL)
1702 1705 idmap_get_destroy(idmap_gh);
1703 1706 #endif /* _KERNEL */
1704 1707
1705 1708 return (error);
1706 1709 }
|
↓ open down ↓ |
238 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX