/* nfs client & server acl query tool */ #include #include #include #include #include #include usage() { printf("Usage: checkfacl {user|group}:{ID|username}:{rwx} file\n"); } help() { printf("checkfacl -- query access rights present in posix acl\n\n"); usage(); printf("This tool is used to verify that a user/group has the expected access rights. \n"); printf("The main purpose is to confirm that posix acls are consistent on both the NFS\n"); printf("client and server.\n"); } struct entry_t { int type; //user or group int ID; char name[10]; char permset[4]; char filename[40]; }; query(entry) struct entry_t * entry; { int index=0; acl_t ACL = acl_get_file(entry->filename, ACL_TYPE_ACCESS); if(ACL==NULL) { fprintf(stderr,"checkfacl: error retrieving acl for %s\n",entry->filename); exit(-1); } acl_entry_t acl_entry; acl_tag_t tag; acl_permset_t perms; if(acl_get_entry(ACL,ACL_FIRST_ENTRY,&acl_entry)!=1) { fprintf(stderr,"checkfacl: error reading acl entry\n"); exit(-1); } int IDFOUND=0; int checkOther=0; uid_t * ID; do{ if(acl_get_tag_type(acl_entry,&tag)!=0) { fprintf(stderr,"checkfacl: error getting entry tag type\n"); exit(-1); } if((tag == ACL_USER && entry->type == 1) || (tag == ACL_GROUP && entry->type==2)) { ID = (uid_t*)acl_get_qualifier(acl_entry); } else if( tag==ACL_USER_OBJ && entry->type==1) { struct stat fstat; stat(entry->filename, &fstat); ID = &fstat.st_uid; } else if( tag==ACL_GROUP_OBJ && entry->type==2) { struct stat fstat; stat(entry->filename, &fstat); ID = &fstat.st_gid; } else if(tag==ACL_OTHER) { if(!IDFOUND) printf("ID %s(%d) not present in acl for file %s\n\n", entry->name,entry->ID, entry->filename); checkOther=1; } else continue; if(entry->ID == *ID || checkOther==1) { if(!checkOther) IDFOUND=1; int error = acl_get_permset(acl_entry,&perms); if(error!=0) { printf("acl_get_permset failure\n"); exit(-1); } while(entry->permset[index] != '\0'){ char c = entry->permset[index++]; switch(c) { case 'r': if(acl_get_perm(perms,ACL_READ)) { if(checkOther) printf("OTHER perms grant %s(%d) READ access\n", entry->name, entry->ID); else printf("%s(%d) has READ access\n", entry->name, entry->ID); } else printf("%s(%d) DOES NOT have READ access\n", entry->name, entry->ID); break; case 'w': if(acl_get_perm(perms,ACL_WRITE)) { if(checkOther) printf("OTHER perms grant %s(%d) WRITE access\n", entry->name, entry->ID); else printf("%s(%d) has WRITE access\n", entry->name, entry->ID); } else printf("%s(%d) DOES NOT have WRITE access\n", entry->name, entry->ID); break; case 'x': if(acl_get_perm(perms,ACL_EXECUTE)) { if(checkOther) printf("OTHER perms grant %s(%d) EXECUTE access\n", entry->name, entry->ID); else printf("%s(%d) has EXECUTE access\n", entry->name, entry->ID); } else printf("%s(%d) DOES NOT have EXECUTE access\n", entry->name, entry->ID); break; default: printf("checkfacl: invalid permission entry\n"); return -1; break; } } break; } }while(acl_get_entry(ACL,ACL_NEXT_ENTRY,&acl_entry)==1); acl_free(ACL); return 0; } ParseCommand(argc, argv,entry) int argc; char **argv; struct entry_t * entry; { entry->filename[0]='\0'; entry->permset[0]='\0'; char type[5]; char ID[10]; if(strcmp(argv[1],"-help")) sscanf(argv[1],"%[^0123456789:]%*c%[^:]%*c%s",type,ID,&entry->permset); else { help(); exit(1); } if(type[0]=='u') { entry->type=1; } else if(type[0]=='g') entry->type=2; else { printf("checkfacl: invalid entry type\n"); return -1; } struct passwd * st; if(ID[0] > 47 && ID[0]< 58) { /*ID is in int form*/ sscanf(ID,"%d",&entry->ID); st = getpwuid(entry->ID); sscanf(st->pw_name,"%s",entry->name); } else { /*user name given*/ sscanf(ID,"%s",entry->name); st = getpwnam(ID); if(st) entry->ID = st->pw_uid; else { printf("checkfacl: Invalid username\n"); return -1; } } // printf("%s:%d:%s\n",type,entry->ID,entry->permset); //for debugging only! //printf("entry->type = %d\n",entry->type); if(strcmp(argv[2],"-help")) sscanf(argv[2],"%s",entry->filename); else { help(); exit(1); } return 0; } int main(argc, argv) int argc; char **argv; { /*MENU *checkfacl -acl aclquery -file filename -help print help menu *checkfacl u:user:perm filename *checkfacl g:group:perm filename *checkfacl -help */ int error=0; if(argc==1) goto usage; else if(argc == 2) { if(strcmp(argv[1],"-help")) goto usage; else help(); goto end; } struct entry_t entry; error = ParseCommand(argc,argv,&entry); if(error!=0) goto usage; error = query(&entry); if(error!=0) goto usage; goto end; usage: usage(); end: return 0; }