105 pool = NULL; |
106 pool = NULL; |
106 access_mask = acl_oflag2mask(oflags); |
107 access_mask = acl_oflag2mask(oflags); |
107 } |
108 } |
108 |
109 |
109 // check ACLs |
110 // check ACLs |
110 uid_t uid; // uid and gid will be initialized by sys_acl_check |
111 SysACL sysacl; |
111 gid_t gid; |
112 if(sys_acl_check(ctx, access_mask, &sysacl)) { |
112 if(sys_acl_check(ctx, access_mask, &uid, &gid)) { |
113 return NULL; |
113 return NULL; |
114 } |
|
115 |
|
116 if(sysacl.acl) { |
|
117 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) { |
|
118 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user); |
|
119 return NULL; |
|
120 } |
114 } |
121 } |
115 |
122 |
116 // open file |
123 // open file |
117 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
124 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; |
118 int fd = open(path, oflags, mode); |
125 int fd = open(path, oflags, mode); |
174 rq = NULL; |
191 rq = NULL; |
175 access_mask = ACL_READ_ATTRIBUTES; |
192 access_mask = ACL_READ_ATTRIBUTES; |
176 } |
193 } |
177 |
194 |
178 // check ACLs |
195 // check ACLs |
179 uid_t uid; // uid and gid will be initialized by sys_acl_check |
196 SysACL sysacl; |
180 gid_t gid; |
197 if(sys_acl_check(ctx, access_mask, &sysacl)) { |
181 if(sys_acl_check(ctx, access_mask, &uid, &gid)) { |
198 return -1; |
182 return -1; |
199 } |
|
200 |
|
201 if(sysacl.acl) { |
|
202 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) { |
|
203 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user); |
|
204 return -1; |
|
205 } |
183 } |
206 } |
184 |
207 |
185 // stat |
208 // stat |
186 if(stat(path, buf)) { |
209 if(stat(path, buf)) { |
187 if(ctx) { |
210 if(ctx) { |
254 pool = NULL; |
277 pool = NULL; |
255 access_mask = ACL_LIST; |
278 access_mask = ACL_LIST; |
256 } |
279 } |
257 |
280 |
258 // check ACLs |
281 // check ACLs |
259 uid_t uid; // uid and gid will be initialized by sys_acl_check |
282 SysACL sysacl; |
260 gid_t gid; |
283 if(sys_acl_check(ctx, access_mask, &sysacl)) { |
261 if(sys_acl_check(ctx, access_mask, &uid, &gid)) { |
284 return NULL; |
262 return NULL; |
285 } |
|
286 |
|
287 if(sysacl.acl) { |
|
288 if(!fs_acl_check(&sysacl, ctx->user, path, access_mask)) { |
|
289 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user); |
|
290 return NULL; |
|
291 } |
263 } |
292 } |
264 |
293 |
265 // open file |
294 // open file |
266 int sys_fd = open(path, O_RDONLY); |
295 int sys_fd = open(path, O_RDONLY); |
267 if(sys_fd == -1) { |
296 if(sys_fd == -1) { |
313 |
342 |
314 int vfs_mkdir(VFSContext *ctx, char *path) { |
343 int vfs_mkdir(VFSContext *ctx, char *path) { |
315 if(ctx && ctx->vfs) { |
344 if(ctx && ctx->vfs) { |
316 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE); |
345 return vfs_path_op(ctx, path, ctx->vfs->mkdir, ACL_ADD_FILE); |
317 } else { |
346 } else { |
318 return vfs_path_op(ctx, path, sys_mkdir, ACL_ADD_FILE); |
347 return sys_path_op(ctx, path, sys_mkdir, ACL_ADD_FILE); |
319 } |
348 } |
320 } |
349 } |
321 |
350 |
322 int vfs_unlink(VFSContext *ctx, char *path) { |
351 int vfs_unlink(VFSContext *ctx, char *path) { |
323 if(ctx && ctx->vfs) { |
352 if(ctx && ctx->vfs) { |
324 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE); |
353 return vfs_path_op(ctx, path, ctx->vfs->unlink, ACL_DELETE); |
325 } else { |
354 } else { |
326 return vfs_path_op(ctx, path, sys_unlink, ACL_DELETE); |
355 return sys_path_op(ctx, path, sys_unlink, ACL_DELETE); |
327 } |
356 } |
328 } |
357 } |
329 |
358 |
330 |
359 |
331 // private |
360 // private |
332 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) { |
361 int vfs_path_op(VFSContext *ctx, char *path, vfs_op_f op, uint32_t access) { |
333 Session *sn; |
362 Session *sn; |
334 Request *rq; |
363 Request *rq; |
335 uint32_t access_mask; |
364 |
336 |
365 uint32_t access_mask = ctx->aclreqaccess; |
|
366 access_mask |= access; |
|
367 if(!ctx->pool) { |
|
368 // TODO: log warning |
|
369 // broken VFSContext |
|
370 return -1; |
|
371 } |
|
372 |
|
373 // ctx->aclreqaccess should be the complete access mask |
|
374 uint32_t m = ctx->aclreqaccess; // save original access mask |
|
375 ctx->aclreqaccess = access_mask; // set mask for vfs function call |
|
376 int ret = op(ctx, path); |
|
377 ctx->aclreqaccess = m; // restore original access mask |
|
378 return ret; |
|
379 } |
|
380 |
|
381 int sys_path_op(VFSContext *ctx, char *path, sys_op_f op, uint32_t access) { |
337 if(ctx) { |
382 if(ctx) { |
338 access_mask = ctx->aclreqaccess; |
383 access |= ctx->aclreqaccess; |
339 access_mask |= access; |
|
340 if(!ctx->pool) { |
|
341 // TODO: log warning |
|
342 // broken VFSContext |
|
343 } |
|
344 if(ctx->vfs) { |
|
345 // ctx->aclreqaccess should be the complete access mask |
|
346 uint32_t m = ctx->aclreqaccess; // save original access mask |
|
347 ctx->aclreqaccess = access_mask; // set mask for vfs->fstat call |
|
348 int ret = op(ctx, path); |
|
349 ctx->aclreqaccess = m; // restore original access mask |
|
350 return ret; |
|
351 } |
|
352 } else { |
|
353 sn = NULL; |
|
354 rq = NULL; |
|
355 access_mask = access; |
|
356 } |
384 } |
357 |
385 |
358 // check ACLs |
386 // check ACLs |
359 uid_t uid; // uid and gid will be initialized by sys_acl_check |
387 SysACL sysacl; |
360 gid_t gid; |
388 if(sys_acl_check(ctx, access, &sysacl)) { |
361 if(sys_acl_check(ctx, access_mask, &uid, &gid)) { |
389 return -1; |
362 return -1; |
390 } |
|
391 |
|
392 if(sysacl.acl) { |
|
393 if(!fs_acl_check(&sysacl, ctx->user, path, access)) { |
|
394 acl_set_error_status(ctx->sn, ctx->rq, sysacl.acl, ctx->user); |
|
395 return -1; |
|
396 } |
363 } |
397 } |
364 |
398 |
365 // do path operation |
399 // do path operation |
366 if(op(ctx, path)) { |
400 if(op(ctx, path, &sysacl)) { |
367 // error |
401 // error |
368 if(ctx) { |
402 if(ctx) { |
369 ctx->vfs_errno = errno; |
403 ctx->vfs_errno = errno; |
370 sys_set_error_status(ctx); |
404 sys_set_error_status(ctx); |
371 } |
405 } |
373 } |
407 } |
374 |
408 |
375 return 0; |
409 return 0; |
376 } |
410 } |
377 |
411 |
378 int sys_acl_check(VFSContext *ctx, uint32_t acm, uid_t *uid, gid_t *gid) { |
412 int sys_acl_check(VFSContext *ctx, uint32_t access_mask, SysACL *sysacl) { |
379 /* |
|
380 * we don't allow remote root access, so a uid of 0 means that |
|
381 * no file system acl check is needed |
|
382 */ |
|
383 *uid = 0; |
|
384 *gid = 0; |
|
385 if(!ctx) { |
413 if(!ctx) { |
|
414 if(sysacl) { |
|
415 sysacl->acl = NULL; |
|
416 } |
386 return 0; |
417 return 0; |
387 } |
418 } |
388 |
419 |
389 ACLListHandle *acllist = ctx->acllist; |
420 ACLListHandle *acllist = ctx->acllist; |
390 if(acllist) { |
421 if(acllist) { |
391 ACLListElm *elm = acllist->listhead; |
422 ACLList *acl = acl_evallist( |
392 while(elm) { |
423 acllist, |
393 ACLList *acl = elm->acl; |
424 ctx->user, |
394 if(acl->isextern) { |
425 access_mask, |
395 // TODO |
426 &sysacl->acl); |
396 } else if(!acl->check(acl, ctx->user, acm)) { |
427 |
397 // access denied |
428 if(acl) { |
398 if(ctx->sn && ctx->rq) { |
429 acl_set_error_status(ctx->sn, ctx->rq, acl, ctx->user); |
399 acl_set_error_status(ctx->sn, ctx->rq, acl, ctx->user); |
430 return 1; |
400 } |
|
401 return 1; |
|
402 } |
|
403 elm = elm->next; |
|
404 } |
431 } |
405 } |
432 } |
406 |
433 |
407 return 0; |
434 return 0; |
408 } |
435 } |
450 |
477 |
451 void sys_dir_close(VFS_DIR dir) { |
478 void sys_dir_close(VFS_DIR dir) { |
452 closedir(dir->data); |
479 closedir(dir->data); |
453 } |
480 } |
454 |
481 |
455 int sys_mkdir(VFSContext *ctx, char *path) { |
482 int sys_mkdir(VFSContext *ctx, char *path, SysACL *sysacl) { |
456 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |
483 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; |
457 return mkdir(path, mode); |
484 int ret = mkdir(path, mode); |
458 } |
485 if(ret == 0) { |
459 |
486 if(sysacl->user_uid != -1) { |
460 int sys_unlink(VFSContext *ctx, char *path) { |
487 if(chown(path, sysacl->user_uid, sysacl->user_gid)) { |
|
488 // TODO: error |
|
489 } |
|
490 } |
|
491 } |
|
492 return ret; |
|
493 } |
|
494 |
|
495 int sys_unlink(VFSContext *ctx, char *path, SysACL *sysacl) { |
461 return unlink(path); |
496 return unlink(path); |
462 } |
497 } |
463 |
498 |
464 /* public file api */ |
499 /* public file api */ |
465 |
500 |