Fingerprint GUI

A place to discuss issues of the Fingerprint GUI.

You can subscribe to this discussion group using an RSS feed reader.

Patch for getting DISPLAY & XAUTHORITY on later GDMs

Hello,

Here's a patch that will make fingerprint-gui get the DISPLAY and XAUTHORITY environment variables when running GDM. I used /proc to get the GDM process then get the child of it that has the environment variables.

First of all, you need to make GDM use X11 by editing /etc/gdm3/custom.conf and setting WaylandEnable to false.

I don't know why it doesn't work sometimes. Maybe because the button for submitting is disabled.

Anyway, here's the patch:

--- fingerprint-gui-1.09-dfsg1.orig/src/FingerprintPAM.cpp
+++ fingerprint-gui-1.09-dfsg1/src/FingerprintPAM.cpp
@@ -5,6 +5,7 @@
  *
  * @author  Wolfgang Ullrich
  * Copyright (C) 2008-2016 Wolfgang Ullrich
+ * Copyright (C) 2016 Shem Pasamba
  */

/*
@@ -40,6 +41,13 @@
#include <pwd.h>
#include <string>

+// for proc functions
+#include <sys/types.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <stdint.h>
+#include <ctype.h>
+
#include "../include/Globals.h"

//#define DEBUG_ALL // Debug all function calls. If not defined pam_sm_authenticate is debugged only
@@ -224,6 +232,306 @@ bool getargs(int argc,const char **argv)
    return debug;
}

+// Functions used to lookup /proc values
+/**
+ * Get the file pointer of /proc/$pid/$filename,
+ * given $pid and $filename.
+ *
+ * @param  pid Pid of process to get.
+ * @param  filename Filename of file under /proc/$pid/ to get.
+ * @return  pointer to file. Note: make sure you free it.
+ */
+FILE *get_proc_file(pid_t pid, const char *filename)
+{
+    enum { BUFFER_SIZE = 1024 };
+    char *buff = (char *) malloc(BUFFER_SIZE * sizeof(*buff));
+    FILE *fi = NULL;
+
+    int length = snprintf(buff, BUFFER_SIZE, "/proc/%d/%s", (int) pid, filename);
+    if (length >= BUFFER_SIZE)
+        buff[BUFFER_SIZE - 1] = '\0';
+
+    if (getpgid(pid) >= 0)
+    {
+        fi = fopen(buff, "r");
+        if (fi == NULL)
+        {
+            syslog(LOG_DEBUG, "Unable to access file %s! Probably permission denied.\n", buff);
+        }
+    }
+    free(buff);
+
+    return fi;
+}
+
+/**
+ * Get the pid as a string from /proc/$pid/status
+ *
+ * @param  pid Pid of process to get parent of.
+ * @return  pid_t  The parent pid.
+ */
+pid_t get_parent_pid(pid_t pid)
+{
+    enum { BUFFER_SIZE = 1024 };
+    char *parent_pid_str = NULL;
+    char *buff = (char *) malloc(BUFFER_SIZE * sizeof(*buff)),
+        *tmp_ptr,
+        *null_ptr;
+    char *line = (char *) malloc(BUFFER_SIZE * sizeof(*line));
+    FILE *fi;
+   
+    fi = get_proc_file(pid, "status");
+    if (!fi)
+        return 0;
+    while (fgets(line, BUFFER_SIZE, fi))
+    {
+        // get parent of parent pid (grand parent); should be gdm3
+        if (strncmp(line, "PPid:", 5) == 0)
+        {
+            // get pid part
+            tmp_ptr = strchr(line, '\t');
+            if (tmp_ptr != NULL)
+                tmp_ptr++;
+            // remove \n at the back end
+            null_ptr = strchr(tmp_ptr,'\n');
+            if (null_ptr) *null_ptr = '\0';
+           
+            parent_pid_str = strdup(tmp_ptr);
+           
+            break;
+        }
+    }       
+    fclose(fi);
+   
+    pid_t parent_pid = (pid_t) strtol(parent_pid_str, NULL, 0);
+    free(parent_pid_str);
+    return parent_pid;
+}
+
+/**
+ * Get contents of /proc/$pid/cmdline given the $pid
+ *
+ * @param  pid Pid of process to get parent of.
+ * @return  char * string contents of cmdline.
+ *          Note: make sure you free it
+ */
+char *get_cmdline_of_pid(pid_t pid)
+{
+    size_t BUFFER_SIZE = 1024;
+    ssize_t line_length = 0;
+    char *str_ptr;
+    char *line = (char *) malloc(BUFFER_SIZE * sizeof(*line));
+    FILE *fi;
+
+    fi = get_proc_file(pid, "cmdline");
+    if (!fi)
+        return NULL;
+
+    line_length = getdelim(&line, &BUFFER_SIZE, '\0', fi);
+    if (line_length == -1)
+        return NULL;
+           
+    fclose(fi);
+   
+    str_ptr = strdup(line);
+    free(line);
+   
+    return str_ptr;
+}
+
+/**
+ * Get direct children pids a given parent $pid.
+ *
+ * @param  pid    Parent pid to search.
+ * @return  pid_t * Dynamically allocated array of pids terminated
+ *                  by a 0.
+ *                  NULL if not found.
+ *                  Make sure you free this.
+ */
+pid_t *get_children_of_pid(pid_t pid)
+{
+    DIR *dirp;
+    struct dirent *dp;
+    char *tmp_ptr = NULL;
+    size_t pid_cnt = 10;
+    size_t pid_ctr = 0;
+    pid_t *found_pids = (pid_t *) malloc(sizeof(pid_t) * pid_cnt);
+    pid_t *tmp_realloc = NULL;
+   
+    dirp = opendir("/proc");
+    while((dp = readdir(dirp)) !=NULL)
+    {
+        // check for pids (digits) only
+        tmp_ptr = (char *) &(dp->d_name);
+        while (*tmp_ptr && isdigit(*tmp_ptr))
+          tmp_ptr++;
+        if (*tmp_ptr == '\0')  // all is digit
+        {
+            // check if child of parent
+            pid_t child_pid = strtol(dp->d_name, NULL, 0);
+            if (get_parent_pid(child_pid) == pid)
+            {
+                // found a child!
+                found_pids[pid_ctr++] = child_pid;
+                if (pid_ctr == pid_cnt)
+                {
+                    pid_cnt += 10;
+                    tmp_realloc = (pid_t *) realloc(found_pids, sizeof(pid_t) * pid_cnt);
+                    if (tmp_realloc)
+                        found_pids = tmp_realloc;
+                    else
+                        break;
+                }
+            }
+        }
+    }
+   
+    if (pid_ctr != 0)
+    {
+        tmp_realloc = (pid_t *) realloc(found_pids, sizeof(pid_t) * (pid_ctr + 1));
+        if (tmp_realloc)
+            found_pids = tmp_realloc;
+        found_pids[pid_ctr] = 0;
+    }
+    else
+    {
+        free(found_pids);
+        found_pids = NULL;
+    }
+    return found_pids;
+}
+
+/**
+ * Get pid of first ancestor of a $pid
+ * having cmdline that has $needle.
+ *
+ * @param  pid    Child pid to search.
+ * @param  needle  The search string to match with child's cmdline.
+ * @return  pid_t  String representation of the pid found.
+ *                  Zero if not found.
+ */
+pid_t get_first_ancestor_pid_having(pid_t pid, const char *needle)
+{
+    pid_t found_pid = 0;
+    pid_t parent_pid = get_parent_pid(pid);
+
+    if (parent_pid == 0)
+        return 0;
+       
+    char *cmdline = get_cmdline_of_pid(parent_pid);
+
+    syslog(LOG_DEBUG,"Searching parent with PID %d and cmdline %s.", (int) parent_pid, cmdline);
+    if (cmdline != NULL && strstr(cmdline, needle) != NULL)
+    {
+        found_pid = parent_pid;
+        syslog(LOG_DEBUG,"Found parent pid %d with cmdline %s.", (int) found_pid, cmdline);
+    }
+    else
+    {
+        found_pid = get_first_ancestor_pid_having(parent_pid, needle);
+    }
+    free(cmdline);
+
+    return found_pid;
+}
+
+/**
+ * Get pid of first descendant of a $pid
+ * having cmdline that has $needle.
+ *
+ * @param  pid    Parent pid to search.
+ * @param  needle  The search string to match with child's cmdline.
+ * @return  pid_t  String representation of the pid found.
+ *                  Zero if not found.
+ */
+pid_t get_first_descendant_pid_having(pid_t pid, const char *needle)
+{
+    pid_t found_pid = 0;
+    pid_t *children_pids = get_children_of_pid(pid);
+    for(size_t i=0; children_pids != NULL && children_pids[i] != 0; ++i)
+    {
+        char *cmdline = get_cmdline_of_pid(children_pids[i]);
+        syslog(LOG_DEBUG,"Searching child with PID %d and cmdline %s.", (int) children_pids[i], cmdline);
+        if (cmdline != NULL && strstr(cmdline, needle) != NULL)
+        {
+            found_pid = children_pids[i];
+            syslog(LOG_DEBUG,"Found child pid %d with cmdline %s.", (int) found_pid, cmdline);
+
+            break;
+            free(cmdline);
+        }
+        else
+        {
+            found_pid = get_first_descendant_pid_having(children_pids[i], needle);
+            if (found_pid)
+            {
+                break;
+                free(cmdline);
+            }
+        }
+        free(cmdline);
+    }
+    free(children_pids);
+
+    return found_pid;
+}
+
+/**
+ * Get DISPLAY and XAUTHORITITY environments from
+ * /proc/$pid/cmdline given the $pid
+ *
+ * @param  pid Pid of process to get parent of.
+ * @return (as param) display The value of DISPLAY environment variable
+ * @return (as param) xauthority The value of XAUTHORITY environment var
+ */
+void get_display_and_xauth_env_of_pid(
+        pid_t pid,
+        char **display,
+        char **xauthority
+    )
+{
+    enum { BUFFER_SIZE = 1024 };
+    char *tmp_ptr;
+    char *line = (char *) malloc(BUFFER_SIZE * sizeof(*line));
+    size_t size = BUFFER_SIZE * sizeof(*line);
+    *display = NULL;
+    *xauthority = NULL;
+    FILE *fi;
+   
+    fi = get_proc_file(pid, "environ");
+    if (!fi)
+    {
+        return;
+    }
+    while (getdelim(&line, &size, '\0', fi) != -1)
+    {
+        // if found DISPLAY=
+        if (display != NULL &&strncmp(line, "DISPLAY=", 8) == 0)
+        {
+            // get value part
+            tmp_ptr = strchr(line, '=');
+            if (tmp_ptr != NULL)
+                tmp_ptr++;
+           
+            *display = strdup(tmp_ptr);           
+        }
+        // if found XAUTHORITY=
+        if (xauthority != NULL && strncmp(line, "XAUTHORITY=", 11) == 0)
+        {
+            // get value part
+            tmp_ptr = strchr(line, '=');
+            if (tmp_ptr != NULL)
+                tmp_ptr++;
+           
+            *xauthority = strdup(tmp_ptr);
+        }
+        if (*display && *xauthority)
+            break;
+    }
+    free(line);
+    fclose(fi);
+}
+
// Call from PAM ---------------------------------------------------------------
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,const char **argv){
    bool debug=false;
@@ -252,6 +560,9 @@ PAM_EXTERN int pam_sm_authenticate(pam_h
    int xlock,i;
    struct pollfd pfds;
    struct passwd *p_entry;
+    // for /proc gdm
+    pid_t gdm_pid = 0;
+    char *cmdline = NULL;
   
    debug=getargs(argc,argv);
    if(debug)
@@ -367,6 +678,23 @@ PAM_EXTERN int pam_sm_authenticate(pam_h
    else
        syslog(LOG_DEBUG,"Have DISPLAY %s from getenv.",xdisp);

+    // For gdm. Try to look for the DISPLAY & XAUTHROTY using child of gdm
+    // using /proc
+    gdm_pid = get_first_ancestor_pid_having(getpid(), "/usr/sbin/gdm");
+    if (gdm_pid)
+    {
+        syslog(LOG_DEBUG,"Got gdm PID %d.", (int) gdm_pid);
+        get_display_and_xauth_env_of_pid(
+                get_first_descendant_pid_having(
+                    gdm_pid,
+                    "/usr/lib/gnome-session/gnome-session-binary"
+                ),
+                &xdisp,
+                &xauth
+            );
+    }
+    free(cmdline);
+
// The following section is only required for systems, who have no XAUTHORITY variable in gdm environment
// Gentoo is a candidate
    if(xdisp!=NULL){
Permalink Shem Pasamba 
August 24th, 2016 12:57pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics