diff -up Linux-PAM-1.1.3/modules/pam_console/pam_console.c.abstract Linux-PAM-1.1.3/modules/pam_console/pam_console.c --- Linux-PAM-1.1.3/modules/pam_console/pam_console.c.abstract 2008-12-16 13:37:52.000000000 +0100 +++ Linux-PAM-1.1.3/modules/pam_console/pam_console.c 2010-11-01 17:01:55.000000000 +0100 @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include #include @@ -136,6 +138,32 @@ check_one_console_name(const char *name, } static int +try_xsocket(const char *path, size_t len) { + int fd; + union { + struct sockaddr sa; + struct sockaddr_un su; + } addr; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return 0; + + memset(&addr, 0, sizeof(addr)); + addr.su.sun_family = AF_UNIX; + + if (len > sizeof(addr.su.sun_path)) + return 0; + memcpy(addr.su.sun_path, path, len); + if (connect(fd, &addr.sa, sizeof(addr.su) - (sizeof(addr.su.sun_path) - len)) == 0) { + close(fd); + return 1; + } + close(fd); + return 0; +} + +static int check_console_name(pam_handle_t *pamh, const char *consolename, int nonroot_ok, int on_set) { int found = 0; int statted = 0; @@ -186,22 +214,29 @@ check_console_name(pam_handle_t *pamh, c if (!statted && (consolename[0] == ':')) { int l; char *dot = NULL; - strcpy(full_path, "/tmp/.X11-unix/X"); - l = sizeof(full_path) - 1 - strlen(full_path); + char *path = full_path + 1; + + full_path[0] = '\0'; + strcpy(path, "/tmp/.X11-unix/X"); + l = sizeof(full_path) - 2 - strlen(path); dot = strchr(consolename + 1, '.'); if (dot != NULL) { l = (l < dot - consolename - 1) ? l : dot - consolename - 1; } - strncat(full_path, consolename + 1, l); + strncat(path, consolename + 1, l); full_path[sizeof(full_path) - 1] = '\0'; - _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible console \"%s\"", - full_path); - if (lstat(full_path, &st) != -1) { + _pam_log(pamh, LOG_DEBUG, TRUE, "checking possible X socket \"%s\"", + path); + + /* this will work because st.st_uid is 0 */ + if (try_xsocket(full_path, strlen(path)+1)) { + statted = 1; + } else if (try_xsocket(path, strlen(path))) { statted = 1; } else if (!on_set) { /* there is no X11 socket in case of X11 crash */ _pam_log(pamh, LOG_DEBUG, TRUE, "can't find X11 socket to examine for %s probably due to X crash", consolename); - statted = 1; /* this will work because st.st_uid is 0 */ + statted = 1; } }