#include "config.h" #define __USE_MISC #define _SVID_SOURCE #define _DEFAULT_SOURCE #include #include #include #include #include #include #include #ifdef HAVE_ALLOCA_H #include #endif #if defined(__OpenBSD__) static int _check_auth(uid_t uid, const char *guess) { struct passwd *pwent; pwent = getpwuid_shadow(uid); if (!pwent) return -1; if (!pwent->pw_passwd) return -1; return crypt_checkpass(guess, pwent->pw_passwd); } #elif defined(__FreeBSD__) #include static int _check_auth(uid_t uid, const char *pw) { struct passwd *pwent = getpwuid(uid); if (!pwent) return -1; if (!pwent->pw_passwd) return -1; if (!strcmp(crypt(pw, pwent->pw_passwd), pwent->pw_passwd)) return 0; return -1; } #elif defined(HAVE_PAM) # include typedef struct { const char *user; const char *pw; } Authinfo; static int _conv_cb(int num, const struct pam_message **msg, struct pam_response **resp, void *data) { Authinfo *ai = data; int replies; struct pam_response *reply = NULL; reply = malloc(sizeof(struct pam_response) * num); if (!reply) return PAM_CONV_ERR; for (replies = 0; replies < num; replies++) { switch (msg[replies]->msg_style) { case PAM_PROMPT_ECHO_ON: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = strdup(ai->user); break; case PAM_PROMPT_ECHO_OFF: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = strdup(ai->pw); break; case PAM_ERROR_MSG: case PAM_TEXT_INFO: reply[replies].resp_retcode = PAM_SUCCESS; reply[replies].resp = NULL; break; default: free(reply); return PAM_CONV_ERR; } } *resp = reply; return PAM_SUCCESS; } static int _check_auth(uid_t uid, const char *pw) { Authinfo ai; struct passwd *pwent; const char *user; const char *prof; const char *host; struct stat st; pam_handle_t *handle; int pamerr; struct pam_conv conv; pwent = getpwuid(uid); if (!pwent) return -1; user = pwent->pw_name; if (!user) return -1; host = "localhost"; prof = "login"; if (!stat("/etc/pam.d/enlightenment", &st)) prof = "enlightenment"; else if (!stat("/etc/pam.d/xscreensaver", &st)) prof = "xscreensaver"; else if (!stat("/etc/pam.d/kscreensaver", &st)) prof = "kscreensaver"; else if (!stat("/etc/pam.d/system-auth", &st)) prof = "system-auth"; else if (!stat("/etc/pam.d/system", &st)) prof = "system"; else if (!stat("/etc/pam.d/xdm", &st)) prof = "xdm"; else if (!stat("/etc/pam.d/gdm", &st)) prof = "gdm"; else if (!stat("/etc/pam.d/kdm", &st)) prof = "kdm"; ai.user = user; ai.pw = pw; conv.conv = _conv_cb; conv.appdata_ptr = &ai; if (pam_start(prof, user, &conv, &handle) != PAM_SUCCESS) return -1; if (pam_set_item(handle, PAM_USER, user) != PAM_SUCCESS) return -1; if (pam_set_item(handle, PAM_RHOST, host) != PAM_SUCCESS) return -1; pamerr = pam_authenticate(handle, 0); pam_end(handle, pamerr); if (pamerr != PAM_SUCCESS) return -1; return 0; } #else static int _check_auth(uid_t uid, const char *pw) { return -1; } #endif int main(int argc, char **argv) { ssize_t rd; uid_t id; char pw[4096], *p; if (argc != 1) { int i; for (i = 1; i < argc; i++) fprintf(stderr, "Unknown option %s\n", argv[i]); fprintf(stderr, "This is an internal tool for Enlightenment\n"); goto err; } // get uid who ran this id = getuid(); // read passwd from stdin rd = read(0, pw, sizeof(pw) - 1); if (rd < 0) { fprintf(stderr, "Error. Can't read passwd on stdin\n"); goto err; } pw[rd] = 0; for (p = pw; *p; p++) { if ((*p == '\r') || (*p == '\n')) { *p = 0; break; } } // If we are setuid root then try become root - we can work without though // if pam etc. can work without being root if (setuid(0) != 0) fprintf(stderr, "Warning. Can't become user root. If password auth requires root then this will fail\n"); if (setgid(0) != 0) fprintf(stderr, "Warning. Can't become group root. If password auth requires root then this will fail\n"); if (_check_auth(id, pw) == 0) return 0; err: fprintf(stderr, "Password auth fail\n"); return -1; }