aboutsummaryrefslogtreecommitdiff
path: root/src/pam-freerdp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pam-freerdp.c')
-rw-r--r--src/pam-freerdp.c196
1 files changed, 5 insertions, 191 deletions
diff --git a/src/pam-freerdp.c b/src/pam-freerdp.c
index fbfe182..8979e6e 100644
--- a/src/pam-freerdp.c
+++ b/src/pam-freerdp.c
@@ -34,11 +34,9 @@
#include <security/pam_modutil.h>
#include <security/pam_appl.h>
+#include "pam-freerdp-children.h"
#include "auth-check-path.h"
-#define PAM_TYPE_DOMAIN 1234
-#define ALL_GOOD_SIGNAL "Ar, ready to authenticate cap'n"
-
static int unpriveleged_kill (struct passwd * pwdent);
static char * global_domain = NULL;
@@ -236,44 +234,7 @@ pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv)
pid_t pid;
switch (pid = fork()) {
case 0: { /* child */
- dup2(stdinpipe[0], 0);
-
- char * args[5];
-
- args[0] = (char *)auth_check_path;
- args[1] = rhost;
- args[2] = ruser;
- args[3] = rdomain;
- args[4] = NULL;
-
- struct passwd * pwdent = getpwnam(username);
- if (pwdent == NULL) {
- _exit(EXIT_FAILURE);
- }
-
- /* Setting groups, but allowing EPERM as if we're not 100% root
- we might not be able to do this */
- if (setgroups(1, &pwdent->pw_gid) != 0 && errno != EPERM) {
- _exit(EXIT_FAILURE);
- }
-
- if (setgid(pwdent->pw_gid) < 0 || setuid(pwdent->pw_uid) < 0 ||
- setegid(pwdent->pw_gid) < 0 || seteuid(pwdent->pw_uid) < 0) {
- _exit(EXIT_FAILURE);
- }
-
- if (clearenv() != 0) {
- _exit(EXIT_FAILURE);
- }
-
- if (chdir(pwdent->pw_dir) != 0) {
- _exit(EXIT_FAILURE);
- }
-
- setenv("HOME", pwdent->pw_dir, 1);
-
- execvp(args[0], args);
- _exit(EXIT_FAILURE);
+ pam_sm_authenticate_helper (stdinpipe, username, rhost, ruser, rdomain);
break;
}
case -1: { /* fork'n error! */
@@ -304,153 +265,7 @@ done:
return retval;
}
-static int
-session_socket_handler (struct passwd * pwdent, int readypipe, const char * ruser, const char * rhost, const char * rdomain, const char * password)
-{
- /* Socket stuff */
- int socketfd = 0;
- struct sockaddr_un socket_addr;
-
- /* Connected user */
- socklen_t connected_addr_size;
- int connectfd = 0;
- struct sockaddr_un connected_addr;
-
- /* Our buffer */
- char * buffer = NULL;
- int buffer_len = 0;
- int buffer_fill = 0;
-
- /* Track write out */
- int writedata = 0;
-
- /* Track ready writing */
- int readywrite = 0;
-
- /* Setting groups, but allowing EPERM as if we're not 100% root
- we might not be able to do this */
- if (setgroups(1, &pwdent->pw_gid) != 0 && errno != EPERM) {
- _exit(EXIT_FAILURE);
- }
-
- if (setgid(pwdent->pw_gid) < 0 || setuid(pwdent->pw_uid) < 0 ||
- setegid(pwdent->pw_gid) < 0 || seteuid(pwdent->pw_uid) < 0) {
- /* Don't need to clean up yet */
- return EXIT_FAILURE;
- }
-
- if (clearenv() != 0) {
- /* Don't need to clean up yet */
- return EXIT_FAILURE;
- }
-
- if (chdir(pwdent->pw_dir) != 0) {
- /* Don't need to clean up yet */
- return EXIT_FAILURE;
- }
-
- if (rdomain[0] == '\0') {
- rdomain = ".";
- }
-
- /* Build this up as a buffer so we can just write it and see that
- very, very clearly */
- buffer_len += strlen(ruser) + 1; /* Add one for the space */
- buffer_len += strlen(rhost) + 1; /* Add one for the space */
- buffer_len += strlen(rdomain) + 1; /* Add one for the space */
- buffer_len += strlen(password) + 1; /* Add one for the NULL */
-
- if (buffer_len < 5) {
- /* Don't need to clean up yet */
- return EXIT_FAILURE;
- }
-
- buffer = malloc(buffer_len);
-
- if (buffer == NULL) {
- /* Don't need to clean up yet */
- return EXIT_FAILURE;
- }
-
- /* Lock the buffer before writing */
- if (mlock(buffer, buffer_len) != 0) {
- /* We can't lock, we go home */
- goto cleanup;
- }
-
- buffer_fill = snprintf(buffer, buffer_len, "%s %s %s %s", ruser, password, rdomain, rhost);
- if (buffer_fill > buffer_len) {
- /* This really shouldn't happen, but if for some reason we have an
- difference between they way that the lengths are calculated we want
- to catch that. */
- goto cleanup;
- }
-
- /* Make our socket and bind it */
- socketfd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (socketfd < 0) {
- goto cleanup;
- }
- memset(&socket_addr, 0, sizeof(struct sockaddr_un));
- socket_addr.sun_family = AF_UNIX;
- strncpy(socket_addr.sun_path, pwdent->pw_dir, sizeof(socket_addr.sun_path) - 1);
- strncpy(socket_addr.sun_path + strlen(pwdent->pw_dir), "/.freerdp-socket", (sizeof(socket_addr.sun_path) - strlen(pwdent->pw_dir)) - 1);
-
- /* We bind the socket before forking so that we ensure that
- there isn't a race condition to get to it. Things will block
- otherwise. */
- if (bind(socketfd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_un)) < 0) {
- goto cleanup;
- }
-
- /* Set the socket file permissions to be 600 and the user and group
- to be the guest user. NOTE: This won't protect on BSD */
- if (chmod(socket_addr.sun_path, S_IRUSR | S_IWUSR) != 0 ||
- chown(socket_addr.sun_path, pwdent->pw_uid, pwdent->pw_gid) != 0) {
- goto cleanup;
- }
-
- if (listen(socketfd, 1) < 0) {
- goto cleanup;
- }
-
- readywrite = write(readypipe, ALL_GOOD_SIGNAL, strlen(ALL_GOOD_SIGNAL) + 1);
- if (readywrite != strlen(ALL_GOOD_SIGNAL) + 1) {
- goto cleanup;
- }
-
- connected_addr_size = sizeof(struct sockaddr_un);
- connectfd = accept(socketfd, (struct sockaddr *)&connected_addr, &connected_addr_size);
- if (connectfd < 0) {
- goto cleanup;
- }
-
- writedata = write(connectfd, buffer, buffer_len);
-
-cleanup:
- if (socketfd != 0) {
- close(socketfd);
- }
- if (connectfd != 0) {
- close(connectfd);
- }
-
- if (buffer != NULL) {
- memset(buffer, 0, buffer_len);
- munlock(buffer, buffer_len);
- free(buffer);
- buffer = NULL;
- }
-
- /* This should be only true on the write, so we can use this to check
- out as writedata is init to 0 */
- if (writedata == buffer_len) {
- return 0;
- }
-
- return EXIT_FAILURE;
-}
pid_t session_pid = 0;
/* Open Session. Here we need to fork a little process so that we can
@@ -492,12 +307,11 @@ pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, const char ** argv
pid_t pid = fork();
if (pid == 0) {
- int retval = 0;
-
- retval = session_socket_handler(pwdent, sessionready[1], ruser, rhost, rdomain, password);
+
+ int ret = session_socket_handler(pwdent, sessionready[1], ruser, rhost, rdomain, password);
close(sessionready[1]);
- _exit(retval);
+ _exit(ret);
} else if (pid < 0) {
close(sessionready[0]);
close(sessionready[1]);