1 /*
2 Copyright 2017 Skytechnology sp. z o.o.
3
4 This file is part of LizardFS.
5
6 LizardFS is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, version 3.
9
10 LizardFS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with LizardFS. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "context_wrap.h"
20 #include "lzfs_internal.h"
21
22 void lzfs_int_apply_masks(liz_acl_t *lzfs_acl, uint32_t owner);
23
lzfs_int_convert_fsal_acl(const fsal_acl_t * fsal_acl)24 liz_acl_t *lzfs_int_convert_fsal_acl(const fsal_acl_t *fsal_acl) {
25 liz_acl_t *lzfs_acl = NULL;
26
27 if (!fsal_acl || (!fsal_acl->aces && fsal_acl->naces > 0)) {
28 return NULL;
29 }
30
31 int count = 0;
32 for (unsigned i = 0; i < fsal_acl->naces; ++i) {
33 fsal_ace_t *fsal_ace = fsal_acl->aces + i;
34 count += (IS_FSAL_ACE_ALLOW(*fsal_ace) || IS_FSAL_ACE_DENY(*fsal_ace)) ? 1 : 0;
35 }
36
37 lzfs_acl = liz_create_acl();
38 if (!lzfs_acl) {
39 return NULL;
40 }
41
42 for (unsigned i = 0; i < fsal_acl->naces; ++i) {
43 fsal_ace_t *fsal_ace = fsal_acl->aces + i;
44 if (!(IS_FSAL_ACE_ALLOW(*fsal_ace) || IS_FSAL_ACE_DENY(*fsal_ace))) {
45 continue;
46 }
47
48 liz_acl_ace_t ace;
49 ace.flags = fsal_ace->flag & 0xFF;
50 ace.mask = fsal_ace->perm;
51 ace.type = fsal_ace->type;
52 if (IS_FSAL_ACE_GROUP_ID(*fsal_ace)) {
53 ace.id = GET_FSAL_ACE_GROUP(*fsal_ace);
54 } else {
55 ace.id = GET_FSAL_ACE_USER(*fsal_ace);
56 }
57 if (IS_FSAL_ACE_SPECIAL_ID(*fsal_ace)) {
58 ace.flags |= LIZ_ACL_SPECIAL_WHO;
59 switch (GET_FSAL_ACE_USER(*fsal_ace)) {
60 case FSAL_ACE_SPECIAL_OWNER:
61 ace.id = LIZ_ACL_OWNER_SPECIAL_ID;
62 break;
63 case FSAL_ACE_SPECIAL_GROUP:
64 ace.id = LIZ_ACL_GROUP_SPECIAL_ID;
65 break;
66 case FSAL_ACE_SPECIAL_EVERYONE:
67 ace.id = LIZ_ACL_EVERYONE_SPECIAL_ID;
68 break;
69 default:
70 LogFullDebug(COMPONENT_FSAL, "Invalid FSAL ACE special id type (%d)",
71 (int)GET_FSAL_ACE_USER(*fsal_ace));
72 continue;
73 }
74 }
75
76 liz_add_acl_entry(lzfs_acl, &ace);
77 }
78
79 return lzfs_acl;
80 }
81
lzfs_int_convert_lzfs_acl(const liz_acl_t * lzfs_acl)82 fsal_acl_t *lzfs_int_convert_lzfs_acl(const liz_acl_t *lzfs_acl) {
83 fsal_acl_data_t acl_data;
84 fsal_acl_status_t acl_status;
85 fsal_acl_t *fsal_acl = NULL;
86
87 if (!lzfs_acl) {
88 return NULL;
89 }
90
91 acl_data.naces = liz_get_acl_size(lzfs_acl);
92 acl_data.aces = (fsal_ace_t *)nfs4_ace_alloc(acl_data.naces);
93
94 if (!acl_data.aces) {
95 return NULL;
96 }
97
98 for (unsigned i = 0; i < acl_data.naces; ++i) {
99 fsal_ace_t *fsal_ace = acl_data.aces + i;
100 liz_acl_ace_t lzfs_ace;
101
102 int rc = liz_get_acl_entry(lzfs_acl, i, &lzfs_ace);
103 (void)rc;
104 assert(rc == 0);
105
106 fsal_ace->type = lzfs_ace.type;
107 fsal_ace->flag = lzfs_ace.flags & 0xFF;
108 fsal_ace->iflag = (lzfs_ace.flags & LIZ_ACL_SPECIAL_WHO) ? FSAL_ACE_IFLAG_SPECIAL_ID : 0;
109
110 if (IS_FSAL_ACE_GROUP_ID(*fsal_ace)) {
111 fsal_ace->who.gid = lzfs_ace.id;
112 } else {
113 fsal_ace->who.uid = lzfs_ace.id;
114 }
115
116 if (IS_FSAL_ACE_SPECIAL_ID(*fsal_ace)) {
117 switch (lzfs_ace.id) {
118 case LIZ_ACL_OWNER_SPECIAL_ID:
119 fsal_ace->who.uid = FSAL_ACE_SPECIAL_OWNER;
120 break;
121 case LIZ_ACL_GROUP_SPECIAL_ID:
122 fsal_ace->who.uid = FSAL_ACE_SPECIAL_GROUP;
123 break;
124 case LIZ_ACL_EVERYONE_SPECIAL_ID:
125 fsal_ace->who.uid = FSAL_ACE_SPECIAL_EVERYONE;
126 break;
127 default:
128 fsal_ace->who.uid = FSAL_ACE_NORMAL_WHO;
129 LogWarn(COMPONENT_FSAL, "Invalid LizardFS ACE special id type (%u)",
130 (unsigned)lzfs_ace.id);
131 }
132 }
133 }
134
135 fsal_acl = nfs4_acl_new_entry(&acl_data, &acl_status);
136 LogDebug(COMPONENT_FSAL, "fsal acl = %p, fsal_acl_status = %u", fsal_acl, acl_status);
137 return fsal_acl;
138 }
139
lzfs_int_getacl(struct lzfs_fsal_export * lzfs_export,uint32_t inode,uint32_t owner_id,fsal_acl_t ** fsal_acl)140 fsal_status_t lzfs_int_getacl(struct lzfs_fsal_export *lzfs_export, uint32_t inode,
141 uint32_t owner_id, fsal_acl_t **fsal_acl) {
142 if (*fsal_acl) {
143 int acl_status = nfs4_acl_release_entry(*fsal_acl);
144 if (acl_status != NFS_V4_ACL_SUCCESS) {
145 LogCrit(COMPONENT_FSAL, "Failed to release old acl, status=%d", acl_status);
146 }
147 *fsal_acl = NULL;
148 }
149
150 liz_acl_t *acl = NULL;
151 int rc = liz_cred_getacl(lzfs_export->lzfs_instance, op_ctx->creds, inode, &acl);
152 if (rc < 0) {
153 LogFullDebug(COMPONENT_FSAL, "getacl status=%s export=%" PRIu16 " inode=%" PRIu32,
154 liz_error_string(liz_last_err()), lzfs_export->export.export_id, inode);
155 return lzfs_fsal_last_err();
156 }
157
158 lzfs_int_apply_masks(acl, owner_id);
159
160 *fsal_acl = lzfs_int_convert_lzfs_acl(acl);
161 liz_destroy_acl(acl);
162
163 if (*fsal_acl == NULL) {
164 LogFullDebug(COMPONENT_FSAL,
165 "Failed to convert lzfs acl to nfs4 acl, export=%" PRIu16 " inode=%" PRIu32,
166 lzfs_export->export.export_id, inode);
167 return fsalstat(ERR_FSAL_FAULT, 0);
168 }
169
170 return fsalstat(ERR_FSAL_NO_ERROR, 0);
171 }
172
lzfs_int_setacl(struct lzfs_fsal_export * lzfs_export,uint32_t inode,const fsal_acl_t * fsal_acl)173 fsal_status_t lzfs_int_setacl(struct lzfs_fsal_export *lzfs_export, uint32_t inode,
174 const fsal_acl_t *fsal_acl) {
175 if (!fsal_acl) {
176 return fsalstat(ERR_FSAL_NO_ERROR, 0);
177 }
178
179 liz_acl_t *lzfs_acl = lzfs_int_convert_fsal_acl(fsal_acl);
180 if (!lzfs_acl) {
181 LogFullDebug(COMPONENT_FSAL, "failed to convert acl");
182 return fsalstat(ERR_FSAL_FAULT, 0);
183 }
184 int rc = liz_cred_setacl(lzfs_export->lzfs_instance, op_ctx->creds, inode, lzfs_acl);
185 liz_destroy_acl(lzfs_acl);
186
187 if (rc < 0) {
188 LogFullDebug(COMPONENT_FSAL, "setacl returned %s (%d)", liz_error_string(liz_last_err()),
189 (int)liz_last_err());
190 return lzfs_fsal_last_err();
191 }
192
193 return fsalstat(ERR_FSAL_NO_ERROR, 0);
194 }
195