int main(int argc, char *argv[]) { if (argc != 2) { helpAndLeave(argv[0], EXIT_FAILURE); } if (effective_access(argv[1], W_OK) == 0) { printf("You have permission to write!\n"); } else { printf("No permission to write!\n"); } return EXIT_SUCCESS; }
/* * Check per accout or global hush-login setting. * * Hushed mode is enabled: * * a) if global (e.g. /etc/hushlogins) hush file exists: * 1) for ALL ACCOUNTS if the file is empty * 2) for the current user if the username or shell are found in the file * * b) if ~/.hushlogin file exists * * The ~/.hushlogin is ignored if the global hush file exists. * * The HUSHLOGIN_FILE login.def variable overwrites the default hush filename. * * Note that shadow-utils login(1) does not support "a1)". The "a1)" is * necessary if you want to use PAM for "Last login" message. * * -- Karel Zak <*****@*****.**> (26-Aug-2011) * * * Per-account check requires some explanation: As root we may not be able to * read the directory of the user if it is on an NFS mounted filesystem. We * temporarily set our effective uid to the user-uid making sure that we keep * root privs. in the real uid. * * A portable solution would require a fork(), but we rely on Linux having the * BSD setreuid() */ static int get_hushlogin_status(struct passwd *pwd) { const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL }; const char *file; char buf[BUFSIZ]; int i; file = getlogindefs_str("HUSHLOGIN_FILE", NULL); if (file) { if (!*file) return 0; /* empty HUSHLOGIN_FILE defined */ files[0] = file; files[1] = NULL; } for (i = 0; files[i]; i++) { int ok = 0; file = files[i]; /* Global hush-file*/ if (*file == '/') { struct stat st; FILE *f; if (stat(file, &st) != 0) continue; /* file does not exist */ if (st.st_size == 0) return 1; /* for all accounts */ f = fopen(file, "r"); if (!f) continue; /* ignore errors... */ while (ok == 0 && fgets(buf, sizeof(buf), f)) { buf[strlen(buf) - 1] = '\0'; ok = !strcmp(buf, *buf == '/' ? pwd->pw_shell : pwd->pw_name); } fclose(f); if (ok) return 1; /* found username/shell */ return 0; /* ignore per-account files */ } /* Per-account setting */ if (strlen(pwd->pw_dir) + sizeof(file) + 2 > sizeof(buf)) continue; else { uid_t ruid = getuid(); gid_t egid = getegid(); sprintf(buf, "%s/%s", pwd->pw_dir, file); setregid(-1, pwd->pw_gid); setreuid(0, pwd->pw_uid); ok = effective_access(buf, O_RDONLY) == 0; setuid(0); /* setreuid doesn't do it alone! */ setreuid(ruid, 0); setregid(-1, egid); if (ok) return 1; /* enabled by user */ } } return 0; }