diff --git a/pam/pam.c b/pam/pam.c index 7892b57..7940cc6 100644 --- a/pam/pam.c +++ b/pam/pam.c @@ -1,11 +1,11 @@ #include #include #include +#include #include #include -// debug -#include -#include +#include +#include #ifdef sun #define PAM_CONST @@ -13,6 +13,7 @@ #define PAM_CONST const #endif #define MAXBUF 1024 + // source from: github.com/google/google-authenticator-libpam static int converse(pam_handle_t *pamh, int nargs, PAM_CONST struct pam_message **message, struct pam_response **response) @@ -51,28 +52,33 @@ static char *request_pass(pam_handle_t *pamh, int echocode, PAM_CONST char *prom return ret; } -int exec_cmd(pam_handle_t *pamh, char *cmd, char *arg, char *res) +int exec_cmd(char *user_env, char *from_env, char *argv[]) +{ + char *envp[] = {user_env, from_env, NULL}; + pid_t pid = fork(); + if (pid == -1) { + return PAM_AUTHINFO_UNAVAIL; + } else if (pid == 0) { + execve(argv[0], argv, envp); + exit(-1); + } else { + int status; + if (wait(&status) == -1) { + return PAM_AUTHINFO_UNAVAIL; + } else if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return PAM_SUCCESS; + } + } + return PAM_AUTHINFO_UNAVAIL; +} + +int popen_cmd(char *user_env, char *from_env, char *cmd, char *arg, char *res) { - const char *user; - const void *void_from = NULL; - const char *from; FILE *fp; char *c; - char user_env[MAXBUF], host_env[MAXBUF]; char buf[MAXBUF]; - if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL || *user == '\0') { - return PAM_USER_UNKNOWN; - } - sprintf(user_env, "USER=%s", user); putenv(user_env); - - if (pam_get_item(pamh, PAM_RHOST, &void_from) != PAM_SUCCESS) { - return PAM_ABORT; - } - - from = void_from; - sprintf(host_env, "SSH_CONNECTION=%s", from); - putenv(host_env); + putenv(from_env); if (arg != NULL) { c = malloc(strlen(cmd) + strlen(arg) + 2); @@ -106,9 +112,23 @@ int exec_cmd(pam_handle_t *pamh, char *cmd, char *arg, char *res) int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { - char buf[MAXBUF], res[MAXBUF]; - int ret = exec_cmd(pamh, "/usr/bin/google-web-oauth", "-only-url", res); + char res[MAXBUF]; + const char *user; + const char *from; + char user_env[MAXBUF], from_env[MAXBUF]; + + if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || user == NULL || *user == '\0') { + return PAM_USER_UNKNOWN; + } + + if (pam_get_item(pamh, PAM_RHOST, (void *)&from) != PAM_SUCCESS) { + return PAM_ABORT; + } + + sprintf(user_env, "USER=%s", user); + sprintf(from_env, "SSH_CONNECTION=%s", from); + int ret = popen_cmd(user_env, from_env, "/usr/bin/google-web-oauth", "-only-url", res); if (ret != 0) { return PAM_AUTHINFO_UNAVAIL; } @@ -119,9 +139,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar return PAM_AUTHINFO_UNAVAIL; } - sprintf(buf, "-code %s", code); - ret = exec_cmd(pamh, "/usr/bin/google-web-oauth", buf, res); - if (ret != 0) { + char *arg[] = {"/usr/bin/google-web-oauth", "-code", code, NULL}; + ret = exec_cmd(user_env, from_env, arg); + if (ret != PAM_SUCCESS) { goto err; }