aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pam-freerdp.c107
1 files 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 <stdlib.h>
+#include <string.h>
#include <security/pam_modules.h>
#include <security/pam_modutil.h>
+#include <security/pam_appl.h>
-/* 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