From b7e10405b3fce70267bff420466d17d1731dc0d1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 17 Aug 2012 12:29:10 -0500 Subject: Trying to get the values that we should know well --- src/pam-freerdp.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/pam-freerdp.c b/src/pam-freerdp.c index 539cd0d..1858baf 100644 --- a/src/pam-freerdp.c +++ b/src/pam-freerdp.c @@ -1,3 +1,5 @@ +#include + #include #include @@ -6,6 +8,35 @@ PAM_EXTERN int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) { + const char * username = NULL; + const char * password = NULL; + const char * ruser = NULL; + const char * rhost = NULL; + //const char * rdomain = NULL; + + if (pam_get_item(pamh, PAM_USER, (const void **)&username) != PAM_SUCCESS || username == NULL) { + /* If we don't have a local username then bah, we don't want + to deal with this and we're going to fail. This means that + the pam-local-account failed. + + NOTE: We're not using pam_get_user() here because we don't want + to prompt, we want to only work in the case where the username is + built for us. */ + return PAM_AUTH_ERR; + } + + if (pam_get_item(pamh, PAM_RUSER, (const void **)&ruser) != PAM_SUCCESS || ruser == NULL) { + return PAM_AUTH_ERR; + } + + if (pam_get_item(pamh, PAM_RHOST, (const void **)&rhost) != PAM_SUCCESS || rhost == NULL) { + return PAM_AUTH_ERR; + } + + if (pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password) != PAM_SUCCESS || password == NULL) { + return PAM_AUTH_ERR; + } + return PAM_IGNORE; } -- cgit v1.2.3 From d08f8135be6a78615cb8fe85ba6426cc319d5f9f Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 17 Aug 2012 13:27:48 -0500 Subject: Restructured so we can get all the items with prompts --- src/pam-freerdp.c | 107 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 81 insertions(+), 26 deletions(-) diff --git a/src/pam-freerdp.c b/src/pam-freerdp.c index 1858baf..399b84c 100644 --- a/src/pam-freerdp.c +++ b/src/pam-freerdp.c @@ -1,43 +1,98 @@ #include +#include #include #include +#include -/* Authenticate. We need to make sure we have a user account, that - there are remote accounts and then verify them with FreeRDP */ -PAM_EXTERN int -pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) +#define PAM_TYPE_DOMAIN 1234 + +/* Either grab a value or prompt for it */ +static char * +get_item (pam_handle_t * pamh, int type) { - const char * username = NULL; - const char * password = NULL; - const char * ruser = NULL; - const char * rhost = NULL; - //const char * rdomain = NULL; - - if (pam_get_item(pamh, PAM_USER, (const void **)&username) != PAM_SUCCESS || username == NULL) { - /* If we don't have a local username then bah, we don't want - to deal with this and we're going to fail. This means that - the pam-local-account failed. - - NOTE: We're not using pam_get_user() here because we don't want - to prompt, we want to only work in the case where the username is - built for us. */ - return PAM_AUTH_ERR; + /* Check to see if we just have the value. If we do, great + let's dup it some we're consitently allocating memory */ + if (type != PAM_TYPE_DOMAIN) { + char * value; + if (pam_get_item(pamh, type, (const void **)&value) == PAM_SUCCESS) { + return strdup(value); + } } + /* Now we need to prompt */ - if (pam_get_item(pamh, PAM_RUSER, (const void **)&ruser) != PAM_SUCCESS || ruser == NULL) { - return PAM_AUTH_ERR; + /* Build up the message we're prompting for */ + struct pam_message message[1]; + message[0].msg_style = PAM_PROMPT_ECHO_ON; + + switch (type) { + case PAM_USER: + message[0].msg = "login:"; + break; + case PAM_RUSER: + message[0].msg = "remote login:"; + break; + case PAM_RHOST: + message[0].msg = "remote host:"; + break; + case PAM_AUTHTOK: + message[0].msg = "password:"; + message[0].msg_style = PAM_PROMPT_ECHO_OFF; + break; + case PAM_TYPE_DOMAIN: + message[0].msg = "remote domain:"; + break; + default: + return NULL; } - if (pam_get_item(pamh, PAM_RHOST, (const void **)&rhost) != PAM_SUCCESS || rhost == NULL) { - return PAM_AUTH_ERR; + struct pam_conv conv; + if (pam_get_item(pamh, PAM_CONV, (const void **)&conv) != PAM_SUCCESS) { + return NULL; } - if (pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password) != PAM_SUCCESS || password == NULL) { - return PAM_AUTH_ERR; + struct pam_response * responses = NULL; + if (conv.conv(1, (const struct pam_message **)&message, &responses, conv.appdata_ptr) != PAM_SUCCESS) { + return NULL; } - return PAM_IGNORE; + char * retval = responses->resp; + free(responses); + return retval; +} + +#define GET_ITEM(val, type) \ + if ((val = get_item(pamh, type)) == NULL) { \ + retval = PAM_AUTH_ERR; \ + goto done; \ + } + +/* Authenticate. We need to make sure we have a user account, that + there are remote accounts and then verify them with FreeRDP */ +PAM_EXTERN int +pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + char * username = NULL; + char * password = NULL; + char * ruser = NULL; + char * rhost = NULL; + char * rdomain = NULL; + int retval = PAM_IGNORE; + + GET_ITEM(username, PAM_USER); + GET_ITEM(ruser, PAM_RUSER); + GET_ITEM(rhost, PAM_RHOST); + GET_ITEM(rdomain, PAM_TYPE_DOMAIN); + GET_ITEM(password, PAM_AUTHTOK); + +done: + if (username != NULL) { free(username); } + if (password != NULL) { free(password); } + if (ruser != NULL) { free(ruser); } + if (rhost != NULL) { free(rhost); } + if (rdomain != NULL) { free(rdomain); } + + return retval; } /* Open Session. Here we need to fork a little process so that we can -- cgit v1.2.3 From 453e570ea9b890eee61ef3aca99e5601cb0a0a3c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 17 Aug 2012 13:28:55 -0500 Subject: match the string by pam-remotelogin --- src/pam-freerdp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pam-freerdp.c b/src/pam-freerdp.c index 399b84c..259219a 100644 --- a/src/pam-freerdp.c +++ b/src/pam-freerdp.c @@ -40,7 +40,7 @@ get_item (pam_handle_t * pamh, int type) message[0].msg_style = PAM_PROMPT_ECHO_OFF; break; case PAM_TYPE_DOMAIN: - message[0].msg = "remote domain:"; + message[0].msg = "domain:"; break; default: return NULL; -- cgit v1.2.3 From 86984a06c0841c7f973337581a9134f1cf0ad3f2 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 17 Aug 2012 14:21:45 -0500 Subject: Let's call it! --- src/pam-freerdp.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/pam-freerdp.c b/src/pam-freerdp.c index 259219a..edf9eca 100644 --- a/src/pam-freerdp.c +++ b/src/pam-freerdp.c @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -67,6 +69,9 @@ get_item (pam_handle_t * pamh, int type) goto done; \ } +/* TODO: Make this a build thing */ +#define XFREERDP "/usr/bin/xfreerdp" + /* Authenticate. We need to make sure we have a user account, that there are remote accounts and then verify them with FreeRDP */ PAM_EXTERN int @@ -79,12 +84,59 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) char * rdomain = NULL; int retval = PAM_IGNORE; + /* Get all the values, or prompt for them, or return with + an auth error */ GET_ITEM(username, PAM_USER); GET_ITEM(ruser, PAM_RUSER); GET_ITEM(rhost, PAM_RHOST); GET_ITEM(rdomain, PAM_TYPE_DOMAIN); GET_ITEM(password, PAM_AUTHTOK); + /* At this point we should have the values, let's check the auth */ + pid_t pid; + switch (pid = fork()) { + case 0: { /* child */ + char * args[13]; + args[0] = XFREERDP; + args[1] = "--plugin"; + args[2] = "rdpsnd.so"; + args[3] = "--no-nla"; + args[4] = "-f"; + args[5] = "--ignore-certificate"; /* TODO: Change when we set the home directory properly */ + + /* TODO: Use stdin */ + args[6] = "-u"; + args[7] = ruser; + args[8] = "-p"; + args[9] = password; + args[10] = "-d"; + args[11] = rdomain; + + args[12] = NULL; + + /* TODO: Drop privs */ + /* TODO: Home directory environment to user's home */ + execvp(args[0], args); + _exit(EXIT_FAILURE); + break; + } + case -1: { /* fork'n error! */ + retval = PAM_SYSTEM_ERR; + break; + } + default: { + int forkret = 0; + if (waitpid(pid, &forkret, 0) < 0) { + retval = PAM_SYSTEM_ERR; + } else if (forkret == 0) { + retval = PAM_SUCCESS; + } else { + retval = PAM_AUTH_ERR; + } + } + } + + /* Free Memory and return our status */ done: if (username != NULL) { free(username); } if (password != NULL) { free(password); } -- cgit v1.2.3