The branch, build-main has been updated via b17e449c99af738d4cbc8c5d177a1b6943f601d7 (commit) from 343ae349c3645c8ad6f80215ceaf685a5b975cc7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: src/pam-freerdp-children.c | 231 ++++++++++++++++++++ .../pam-freerdp-children.h | 45 +--- 2 files changed, 240 insertions(+), 36 deletions(-) create mode 100644 src/pam-freerdp-children.c copy tests/test-freerdp-auth.c => src/pam-freerdp-children.h (56%) The diff of changes is: diff --git a/src/pam-freerdp-children.c b/src/pam-freerdp-children.c new file mode 100644 index 0000000..ea29c14 --- /dev/null +++ b/src/pam-freerdp-children.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2012 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Author: Ted Gould <ted@canonical.com> + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/un.h> +#include <pwd.h> +#include <grp.h> +#include <errno.h> + +#include <security/pam_modules.h> +#include <security/pam_modutil.h> +#include <security/pam_appl.h> + +#include "pam-freerdp-children.h" +#include "auth-check-path.h" + +void +pam_sm_authenticate_helper (int *stdinpipe, const char* username, const char* rhost, const char* ruser, const char* rdomain) +{ + + dup2(stdinpipe[0], 0); + + char * args[5]; + + args[0] = (char *)auth_check_path; + args[1] = (char *)rhost; + args[2] = (char *)ruser; + args[3] = (char *)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(0); +} + +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) { + _exit (0); + } + + _exit(EXIT_FAILURE); +} + diff --git a/tests/test-freerdp-auth.c b/src/pam-freerdp-children.h similarity index 56% copy from tests/test-freerdp-auth.c copy to src/pam-freerdp-children.h index a83885e..cb36312 100644 --- a/tests/test-freerdp-auth.c +++ b/src/pam-freerdp-children.h @@ -16,42 +16,15 @@ * Author: Ted Gould <ted@canonical.com> */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> +#ifndef _PAM_FREERDP_CHILDREN_H_ +#define _PAM_FREERDP_CHILDREN_H_ -int -main (int argc, char * argv[]) -{ - char password[512]; - if (argc != 4) { - printf("Not enough params"); - return -1; - } - - if (scanf("%511s", password) != 1) { - return -1; - } - - /* Check username */ - if (strcmp(argv[2], "ruser")) { - return -1; - } +#define PAM_TYPE_DOMAIN 1234 +#define ALL_GOOD_SIGNAL "Ar, ready to authenticate cap'n" - /* Check password */ - if (strcmp(password, "password")) { - return -1; - } +void +pam_sm_authenticate_helper (int *stdinpipe, const char* username, const char* rhost, const char* ruser, const char* rdomain); - /* Check domain */ - if (strcmp(argv[3], "domain")) { - return -1; - } - - /* Check hostname */ - if (strcmp(argv[1], "rhost")) { - return -1; - } - - return 0; -} +int +session_socket_handler (struct passwd * pwdent, int readypipe, const char * ruser, const char * rhost, const char * rdomain, const char * password); +#endif //_PAM_FREERDP_CHILDREN_H_ hooks/post-receive -- libpam-x2go.git (Remote login session via X2Go (PAM module)) This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "libpam-x2go.git" (Remote login session via X2Go (PAM module)).