src/server/daemon/vfs.c

changeset 63
66442f81f823
parent 59
ab25c0a231d0
child 66
74babc0082b7
equal deleted inserted replaced
62:c47e081b6c0f 63:66442f81f823
31 #include <unistd.h> 31 #include <unistd.h>
32 #include <sys/types.h> 32 #include <sys/types.h>
33 33
34 #include "../util/pool.h" 34 #include "../util/pool.h"
35 #include "../ucx/map.h" 35 #include "../ucx/map.h"
36 #include "acl.h"
36 #include "vfs.h" 37 #include "vfs.h"
37 38
38 static UcxMap *vfs_map; 39 static UcxMap *vfs_map;
39 40
40 static VFS_IO sys_file_io = { 41 static VFS_IO sys_file_io = {
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);
122 sys_set_error_status(ctx); 129 sys_set_error_status(ctx);
123 } 130 }
124 return NULL; 131 return NULL;
125 } 132 }
126 133
134 // if a file system acl is active, we set the owner for newly created files
135 if(((oflags & O_CREAT) == O_CREAT) && sysacl.user_uid != -1) {
136 if(fchown(fd, sysacl.user_uid, sysacl.user_gid)) {
137 perror("vfs_open: fchown");
138 close(fd);
139 return NULL;
140 }
141 }
142
143
127 VFSFile *file = pool ? 144 VFSFile *file = pool ?
128 pool_malloc(pool, sizeof(VFSFile)) : malloc(sizeof(VFSFile)); 145 pool_malloc(pool, sizeof(VFSFile)) : malloc(sizeof(VFSFile));
129 if(!file) { 146 if(!file) {
130 close(fd); 147 close(fd);
131 return NULL; 148 return NULL;
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

mercurial