87 #include "zfs_deleg.h" |
87 #include "zfs_deleg.h" |
88 |
88 |
89 /* |
89 /* |
90 * Validate that user is allowed to delegate specified permissions. |
90 * Validate that user is allowed to delegate specified permissions. |
91 * |
91 * |
92 * In order to delegate "create" you must have create" |
92 * In order to delegate "create" you must have "create" |
93 * and "allow". |
93 * and "allow". |
94 */ |
94 */ |
95 int |
95 int |
96 dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr) |
96 dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr) |
97 { |
97 { |
98 nvpair_t *whopair = NULL; |
98 nvpair_t *whopair = NULL; |
99 int error = 0; |
99 int error; |
100 |
100 |
101 if ((error = dsl_deleg_access(ddname, |
101 if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0) |
102 ZFS_DELEG_PERM_ALLOW, cr)) != 0) |
|
103 return (error); |
102 return (error); |
104 |
103 |
105 while (whopair = nvlist_next_nvpair(nvp, whopair)) { |
104 while (whopair = nvlist_next_nvpair(nvp, whopair)) { |
106 nvlist_t *perms; |
105 nvlist_t *perms; |
107 nvpair_t *permpair = NULL; |
106 nvpair_t *permpair = NULL; |
130 int |
128 int |
131 dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr) |
129 dsl_deleg_can_unallow(char *ddname, nvlist_t *nvp, cred_t *cr) |
132 { |
130 { |
133 nvpair_t *whopair = NULL; |
131 nvpair_t *whopair = NULL; |
134 int error; |
132 int error; |
135 |
133 char idstr[32]; |
136 if ((error = dsl_deleg_access(ddname, |
134 |
137 ZFS_DELEG_PERM_ALLOW, cr)) != 0) |
135 if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0) |
138 return (error); |
136 return (error); |
|
137 |
|
138 (void) snprintf(idstr, sizeof (idstr), "%lld", |
|
139 (longlong_t)crgetuid(cr)); |
139 |
140 |
140 while (whopair = nvlist_next_nvpair(nvp, whopair)) { |
141 while (whopair = nvlist_next_nvpair(nvp, whopair)) { |
141 zfs_deleg_who_type_t type = nvpair_name(whopair)[0]; |
142 zfs_deleg_who_type_t type = nvpair_name(whopair)[0]; |
142 char idstr[32]; |
|
143 |
143 |
144 if (type != ZFS_DELEG_USER && |
144 if (type != ZFS_DELEG_USER && |
145 type != ZFS_DELEG_USER_SETS) |
145 type != ZFS_DELEG_USER_SETS) |
146 return (EPERM); |
146 return (EPERM); |
147 |
147 |
148 (void) snprintf(idstr, sizeof (idstr), "%lld", |
|
149 (longlong_t)crgetuid(cr)); |
|
150 if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0) |
148 if (strcmp(idstr, &nvpair_name(whopair)[3]) != 0) |
151 return (EPERM); |
149 return (EPERM); |
152 |
|
153 continue; |
|
154 } |
150 } |
155 return (0); |
151 return (0); |
156 } |
152 } |
157 |
153 |
158 typedef struct { |
154 typedef struct { |
199 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) { |
196 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) { |
200 /* |
197 /* |
201 * If object doesn't exist and we are removing |
198 * If object doesn't exist and we are removing |
202 * it, then just continue to next item in nvlist |
199 * it, then just continue to next item in nvlist |
203 */ |
200 */ |
204 if (pa->p_unset == 1) |
201 if (pa->p_unset) |
205 continue; |
202 continue; |
206 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, |
203 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, |
207 DMU_OT_NONE, 0, tx); |
204 DMU_OT_NONE, 0, tx); |
208 VERIFY(zap_update(mos, zapobj, |
205 VERIFY(zap_update(mos, zapobj, |
209 whokey, 8, 1, &jumpobj, tx) == 0); |
206 whokey, 8, 1, &jumpobj, tx) == 0); |
406 |
403 |
407 /* |
404 /* |
408 * check a specified user/group for a requested permission |
405 * check a specified user/group for a requested permission |
409 */ |
406 */ |
410 static int |
407 static int |
411 dsl_check_user_access(objset_t *os, uint64_t zapobj, const char *perm, |
408 dsl_check_user_access(objset_t *mos, uint64_t zapobj, const char *perm, |
412 int checkflag, cred_t *cr) |
409 int checkflag, cred_t *cr) |
413 { |
410 { |
414 const gid_t *gids; |
411 const gid_t *gids; |
415 int ngids; |
412 int ngids; |
416 int i; |
413 int i; |
417 uint64_t id; |
414 uint64_t id; |
418 |
415 |
419 /* check for user */ |
416 /* check for user */ |
420 id = crgetuid(cr); |
417 id = crgetuid(cr); |
421 if (dsl_check_access(os, zapobj, |
418 if (dsl_check_access(mos, zapobj, |
422 ZFS_DELEG_USER, checkflag, &id, perm) == 0) |
419 ZFS_DELEG_USER, checkflag, &id, perm) == 0) |
423 return (0); |
420 return (0); |
424 |
421 |
425 /* check for users primary group */ |
422 /* check for users primary group */ |
426 id = crgetgid(cr); |
423 id = crgetgid(cr); |
427 if (dsl_check_access(os, zapobj, |
424 if (dsl_check_access(mos, zapobj, |
428 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0) |
425 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0) |
429 return (0); |
426 return (0); |
430 |
427 |
431 /* check for everyone entry */ |
428 /* check for everyone entry */ |
432 id = -1; |
429 id = -1; |
433 if (dsl_check_access(os, zapobj, |
430 if (dsl_check_access(mos, zapobj, |
434 ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0) |
431 ZFS_DELEG_EVERYONE, checkflag, &id, perm) == 0) |
435 return (0); |
432 return (0); |
436 |
433 |
437 /* check each supplemental group user is a member of */ |
434 /* check each supplemental group user is a member of */ |
438 ngids = crgetngroups(cr); |
435 ngids = crgetngroups(cr); |
439 gids = crgetgroups(cr); |
436 gids = crgetgroups(cr); |
440 for (i = 0; i != ngids; i++) { |
437 for (i = 0; i != ngids; i++) { |
441 id = gids[i]; |
438 id = gids[i]; |
442 if (dsl_check_access(os, zapobj, |
439 if (dsl_check_access(mos, zapobj, |
443 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0) |
440 ZFS_DELEG_GROUP, checkflag, &id, perm) == 0) |
444 return (0); |
441 return (0); |
445 } |
442 } |
446 |
443 |
447 return (EPERM); |
444 return (EPERM); |
579 |
576 |
580 if (dsl_prop_get_ds_locked(dd, |
577 if (dsl_prop_get_ds_locked(dd, |
581 zfs_prop_to_name(ZFS_PROP_ZONED), |
578 zfs_prop_to_name(ZFS_PROP_ZONED), |
582 8, 1, &zoned, NULL) != 0) |
579 8, 1, &zoned, NULL) != 0) |
583 break; |
580 break; |
584 |
|
585 /* |
|
586 * if zoned property isn't set then break |
|
587 * out and return EPERM. |
|
588 */ |
|
589 if (!zoned) |
581 if (!zoned) |
590 break; |
582 break; |
591 } |
583 } |
592 zapobj = dd->dd_phys->dd_deleg_zapobj; |
584 zapobj = dd->dd_phys->dd_deleg_zapobj; |
593 |
585 |
594 if (zapobj == 0) |
586 if (zapobj == 0) |
595 continue; |
587 continue; |
596 |
588 |
597 dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr); |
589 dsl_load_user_sets(mos, zapobj, &permsets, checkflag, cr); |
598 setnode = avl_first(&permsets); |
|
599 again: |
590 again: |
600 expanded = B_FALSE; |
591 expanded = B_FALSE; |
601 for (setnode = avl_first(&permsets); setnode; |
592 for (setnode = avl_first(&permsets); setnode; |
602 setnode = AVL_NEXT(&permsets, setnode)) { |
593 setnode = AVL_NEXT(&permsets, setnode)) { |
603 |
|
604 if (setnode->p_matched == B_TRUE) |
594 if (setnode->p_matched == B_TRUE) |
605 continue; |
595 continue; |
606 |
596 |
607 /* See if this set directly grants this permission */ |
597 /* See if this set directly grants this permission */ |
608 error = dsl_check_access(mos, zapobj, |
598 error = dsl_check_access(mos, zapobj, |
634 success: |
624 success: |
635 rw_exit(&dp->dp_config_rwlock); |
625 rw_exit(&dp->dp_config_rwlock); |
636 dsl_dir_close(startdd, FTAG); |
626 dsl_dir_close(startdd, FTAG); |
637 |
627 |
638 cookie = NULL; |
628 cookie = NULL; |
639 while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL) { |
629 while ((setnode = avl_destroy_nodes(&permsets, &cookie)) != NULL) |
640 /* These sets were used but never defined! */ |
|
641 kmem_free(setnode, sizeof (perm_set_t)); |
630 kmem_free(setnode, sizeof (perm_set_t)); |
642 } |
|
643 |
631 |
644 return (error); |
632 return (error); |
645 } |
633 } |
646 |
634 |
647 /* |
635 /* |
648 * Other routines. |
636 * Other routines. |
649 */ |
637 */ |
650 |
638 |
651 static void |
639 static void |
652 copy_create_perms(objset_t *mos, uint64_t pzapobj, dsl_dir_t *dd, |
640 copy_create_perms(dsl_dir_t *dd, uint64_t pzapobj, |
653 boolean_t dosets, uint64_t uid, dmu_tx_t *tx) |
641 boolean_t dosets, uint64_t uid, dmu_tx_t *tx) |
654 { |
642 { |
655 int error; |
643 objset_t *mos = dd->dd_pool->dp_meta_objset; |
656 uint64_t jumpobj, pjumpobj; |
644 uint64_t jumpobj, pjumpobj; |
657 uint64_t zero = 0; |
|
658 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; |
645 uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; |
659 zap_cursor_t zc; |
646 zap_cursor_t zc; |
660 zap_attribute_t za; |
647 zap_attribute_t za; |
661 char whokey[ZFS_MAX_DELEG_NAME]; |
648 char whokey[ZFS_MAX_DELEG_NAME]; |
662 |
649 |
663 zfs_deleg_whokey(whokey, |
650 zfs_deleg_whokey(whokey, |
664 dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE, |
651 dosets ? ZFS_DELEG_CREATE_SETS : ZFS_DELEG_CREATE, |
665 ZFS_DELEG_LOCAL, NULL); |
652 ZFS_DELEG_LOCAL, NULL); |
666 error = zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj); |
653 if (zap_lookup(mos, pzapobj, whokey, 8, 1, &pjumpobj) != 0) |
667 if (error != 0) |
|
668 return; |
654 return; |
669 |
|
670 zfs_deleg_whokey(whokey, |
|
671 dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER, |
|
672 ZFS_DELEG_LOCAL, &uid); |
|
673 |
655 |
674 if (zapobj == 0) { |
656 if (zapobj == 0) { |
675 dmu_buf_will_dirty(dd->dd_dbuf, tx); |
657 dmu_buf_will_dirty(dd->dd_dbuf, tx); |
676 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos, |
658 zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos, |
677 DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); |
659 DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); |
678 } |
660 } |
679 |
661 |
|
662 zfs_deleg_whokey(whokey, |
|
663 dosets ? ZFS_DELEG_USER_SETS : ZFS_DELEG_USER, |
|
664 ZFS_DELEG_LOCAL, &uid); |
680 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) { |
665 if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == ENOENT) { |
681 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); |
666 jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); |
682 VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0); |
667 VERIFY(zap_add(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0); |
683 } |
668 } |
684 |
669 |
685 for (zap_cursor_init(&zc, mos, pjumpobj); |
670 for (zap_cursor_init(&zc, mos, pjumpobj); |
686 zap_cursor_retrieve(&zc, &za) == 0; |
671 zap_cursor_retrieve(&zc, &za) == 0; |
687 zap_cursor_advance(&zc)) { |
672 zap_cursor_advance(&zc)) { |
|
673 uint64_t zero = 0; |
688 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1); |
674 ASSERT(za.za_integer_length == 8 && za.za_num_integers == 1); |
689 |
675 |
690 VERIFY(zap_update(mos, jumpobj, za.za_name, |
676 VERIFY(zap_update(mos, jumpobj, za.za_name, |
691 8, 1, &zero, tx) == 0); |
677 8, 1, &zero, tx) == 0); |
692 } |
678 } |
698 */ |
684 */ |
699 void |
685 void |
700 dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr) |
686 dsl_deleg_set_create_perms(dsl_dir_t *sdd, dmu_tx_t *tx, cred_t *cr) |
701 { |
687 { |
702 dsl_dir_t *dd; |
688 dsl_dir_t *dd; |
703 objset_t *mos = sdd->dd_pool->dp_meta_objset; |
689 uint64_t uid = crgetuid(cr); |
704 |
690 |
705 if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) < |
691 if (spa_version(dmu_objset_spa(sdd->dd_pool->dp_meta_objset)) < |
706 ZFS_VERSION_DELEGATED_PERMS) |
692 ZFS_VERSION_DELEGATED_PERMS) |
707 return; |
693 return; |
708 |
694 |
709 for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) { |
695 for (dd = sdd->dd_parent; dd != NULL; dd = dd->dd_parent) { |
710 uint64_t pobj = dd->dd_phys->dd_deleg_zapobj; |
696 uint64_t pzapobj = dd->dd_phys->dd_deleg_zapobj; |
711 |
697 |
712 if (pobj == 0) |
698 if (pzapobj == 0) |
713 continue; |
699 continue; |
714 |
700 |
715 copy_create_perms(mos, pobj, sdd, B_FALSE, crgetuid(cr), tx); |
701 copy_create_perms(sdd, pzapobj, B_FALSE, uid, tx); |
716 copy_create_perms(mos, pobj, sdd, B_TRUE, crgetuid(cr), tx); |
702 copy_create_perms(sdd, pzapobj, B_TRUE, uid, tx); |
717 } |
703 } |
718 } |
704 } |
719 |
705 |
720 int |
706 int |
721 dsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx) |
707 dsl_deleg_destroy(objset_t *mos, uint64_t zapobj, dmu_tx_t *tx) |