]> rtime.felk.cvut.cz Git - sojka/lightdm.git/blobdiff - tests/src/libsystem.c
Allow greeters to run in-session
[sojka/lightdm.git] / tests / src / libsystem.c
index 0f1da6ac60e6c3865b636efd435da0da2fd10048..d4ec11676b23d482684ac1509fa9971d27718ee1 100644 (file)
@@ -1,6 +1,8 @@
 #define _GNU_SOURCE
 #define __USE_GNU
 
+#include <config.h>
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -8,6 +10,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
 #include <pwd.h>
 #include <unistd.h>
 #include <dirent.h>
 #include <xcb/xcb.h>
 #include <gio/gunixsocketaddress.h>
 
+#if HAVE_LIBAUDIT
+#include <libaudit.h>
+#endif
+
 #include "status.h"
 
 #define LOGIN_PROMPT "login:"
 
-static int console_fd = -1;
+static int tty_fd = -1;
 
 static GList *user_entries = NULL;
 static GList *getpwent_link = NULL;
@@ -64,6 +73,13 @@ struct pam_handle
     struct pam_conv conversation;
 };
 
+int
+gethostname (char *name, size_t len)
+{
+   snprintf (name, len, "lightdm-test");
+   return 0;
+}
+
 uid_t
 getuid (void)
 {
@@ -196,6 +212,9 @@ redirect_path (const gchar *path)
     if (g_str_has_prefix (path, "/tmp"))
         return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "tmp", path + strlen ("/tmp"), NULL);
 
+    if (g_str_has_prefix (path, "/run"))
+        return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "run", path + strlen ("/run"), NULL);
+
     if (g_str_has_prefix (path, "/etc/xdg"))
         return g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), "etc", "xdg", path + strlen ("/etc/xdg"), NULL);
 
@@ -215,14 +234,14 @@ open_wrapper (const char *func, const char *pathname, int flags, mode_t mode)
 
     _open = (int (*)(const char *pathname, int flags, mode_t mode)) dlsym (RTLD_NEXT, func);
 
-    if (strcmp (pathname, "/dev/console") == 0)
+    if (strcmp (pathname, "/dev/tty0") == 0)
     {
-        if (console_fd < 0)
+        if (tty_fd < 0)
         {
-            console_fd = _open ("/dev/null", flags, mode);
-            fcntl (console_fd, F_SETFD, FD_CLOEXEC);
+            tty_fd = _open ("/dev/null", flags, mode);
+            fcntl (tty_fd, F_SETFD, FD_CLOEXEC);
         }
-        return console_fd;
+        return tty_fd;
     }
 
     new_path = redirect_path (pathname);
@@ -333,6 +352,11 @@ access (const char *pathname, int mode)
 
     _access = (int (*)(const char *pathname, int mode)) dlsym (RTLD_NEXT, "access");
 
+    if (strcmp (pathname, "/dev/tty0") == 0)
+        return F_OK;
+    if (strcmp (pathname, "/sys/class/tty/tty0/active") == 0)
+        return F_OK;
+
     new_path = redirect_path (pathname);
     ret = _access (new_path, mode);
     g_free (new_path);
@@ -346,7 +370,7 @@ stat (const char *path, struct stat *buf)
     int (*_stat) (const char *path, struct stat *buf);
     gchar *new_path = NULL;
     int ret;
-  
+
     _stat = (int (*)(const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "stat");
 
     new_path = redirect_path (path);
@@ -378,7 +402,7 @@ __xstat (int version, const char *path, struct stat *buf)
     int (*___xstat) (int version, const char *path, struct stat *buf);
     gchar *new_path = NULL;
     int ret;
-  
+
     ___xstat = (int (*)(int version, const char *path, struct stat *buf)) dlsym (RTLD_NEXT, "__xstat");
 
     new_path = redirect_path (path);
@@ -394,7 +418,7 @@ __xstat64 (int version, const char *path, struct stat64 *buf)
     int (*___xstat64) (int version, const char *path, struct stat64 *buf);
     gchar *new_path = NULL;
     int ret;
-  
+
     ___xstat64 = (int (*)(int version, const char *path, struct stat64 *buf)) dlsym (RTLD_NEXT, "__xstat64");
 
     new_path = redirect_path (path);
@@ -410,7 +434,7 @@ __fxstatat(int ver, int dirfd, const char *pathname, struct stat *buf, int flags
     int (*___fxstatat) (int ver, int dirfd, const char *pathname, struct stat *buf, int flags);
     gchar *new_path = NULL;
     int ret;
-  
+
     ___fxstatat = (int (*)(int ver, int dirfd, const char *pathname, struct stat *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat");
 
     new_path = redirect_path (pathname);
@@ -426,7 +450,7 @@ __fxstatat64(int ver, int dirfd, const char *pathname, struct stat64 *buf, int f
     int (*___fxstatat64) (int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags);
     gchar *new_path = NULL;
     int ret;
-  
+
     ___fxstatat64 = (int (*)(int ver, int dirfd, const char *pathname, struct stat64 *buf, int flags)) dlsym (RTLD_NEXT, "__fxstatat64");
 
     new_path = redirect_path (pathname);
@@ -449,7 +473,7 @@ opendir (const char *name)
     result = _opendir (new_path);
     g_free (new_path);
 
-    return result; 
+    return result;
 }
 
 int
@@ -497,9 +521,9 @@ ioctl (int d, unsigned long request, ...)
     int (*_ioctl) (int d, int request, ...);
 
     _ioctl = (int (*)(int d, int request, ...)) dlsym (RTLD_NEXT, "ioctl");
-    if (d > 0 && d == console_fd)
+    if (d > 0 && d == tty_fd)
     {
-        struct vt_stat *console_state;
+        struct vt_stat *vt_state;
         int vt;
         va_list ap;
 
@@ -507,9 +531,9 @@ ioctl (int d, unsigned long request, ...)
         {
         case VT_GETSTATE:
             va_start (ap, request);
-            console_state = va_arg (ap, struct vt_stat *);
+            vt_state = va_arg (ap, struct vt_stat *);
             va_end (ap);
-            console_state->v_active = active_vt;
+            vt_state->v_active = active_vt;
             break;
         case VT_ACTIVATE:
             va_start (ap, request);
@@ -539,12 +563,235 @@ ioctl (int d, unsigned long request, ...)
     }
 }
 
+static void
+add_port_redirect (int requested_port, int redirected_port)
+{
+    GKeyFile *file;
+    gchar *path, *name, *data;
+
+    file = g_key_file_new ();
+    path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), ".port-redirects", NULL);
+    g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, NULL);
+
+    name = g_strdup_printf ("%d", requested_port);
+    g_key_file_set_integer (file, name, "redirected", redirected_port);
+    g_free (name);
+  
+    data = g_key_file_to_data (file, NULL, NULL);
+    g_file_set_contents (path, data, -1, NULL);
+    g_free (data);
+    g_free (path);
+
+    g_key_file_free (file);
+}
+
+static int
+find_port_redirect (int port)
+{
+    GKeyFile *file;
+    gchar *path, *name;
+    int redirected_port;
+
+    file = g_key_file_new ();
+    path = g_build_filename (g_getenv ("LIGHTDM_TEST_ROOT"), ".port-redirects", NULL);
+    g_key_file_load_from_file (file, path, G_KEY_FILE_NONE, NULL);
+    g_free (path);
+
+    name = g_strdup_printf ("%d", port);
+    redirected_port = g_key_file_get_integer (file, name, "redirected", NULL);
+    g_free (name);
+    g_key_file_free (file);
+
+    return redirected_port;
+}
+
+int
+bind (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+    int port = 0, redirected_port = 0;
+    const char *path;
+    int (*_bind) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+    const struct sockaddr *modified_addr = addr;
+    struct sockaddr_in temp_addr_in;
+    struct sockaddr_in6 temp_addr_in6;
+    struct sockaddr_un temp_addr_un;
+    int retval;
+
+    _bind = (int (*)(int sockfd, const struct sockaddr *addr, socklen_t addrlen)) dlsym (RTLD_NEXT, "bind");
+
+    switch (addr->sa_family)
+    {
+    case AF_UNIX:
+        path = ((const struct sockaddr_un *) addr)->sun_path;
+        if (path[0] != '\0')
+        {
+            gchar *new_path = redirect_path (path);
+            memcpy (&temp_addr_un, addr, sizeof (struct sockaddr_un));
+            strncpy (temp_addr_un.sun_path, new_path, sizeof (temp_addr_un.sun_path) - 1);
+            g_free (new_path);
+            modified_addr = (struct sockaddr *) &temp_addr_un;
+        }
+        break;
+    case AF_INET:
+        port = ntohs (((const struct sockaddr_in *) addr)->sin_port);
+        redirected_port = find_port_redirect (port);
+        memcpy (&temp_addr_in, addr, sizeof (struct sockaddr_in));
+        modified_addr = (struct sockaddr *) &temp_addr_in;
+        if (redirected_port != 0)
+            temp_addr_in.sin_port = htons (redirected_port);
+        else
+            temp_addr_in.sin_port = 0;
+        break;
+    case AF_INET6:
+        port = ntohs (((const struct sockaddr_in6 *) addr)->sin6_port);
+        redirected_port = find_port_redirect (port);
+        memcpy (&temp_addr_in6, addr, sizeof (struct sockaddr_in6));
+        modified_addr = (struct sockaddr *) &temp_addr_in6;
+        if (redirected_port != 0)
+            temp_addr_in6.sin6_port = htons (redirected_port);
+        else
+            temp_addr_in6.sin6_port = 0;
+        break;
+    }
+
+    retval = _bind (sockfd, modified_addr, addrlen);
+
+    socklen_t temp_addr_len;
+    switch (addr->sa_family)
+    {
+    case AF_INET:
+        temp_addr_len = sizeof (temp_addr_in);
+        getsockname (sockfd, &temp_addr_in, &temp_addr_len);
+        if (redirected_port == 0)
+        {
+            redirected_port = ntohs (temp_addr_in.sin_port);
+            add_port_redirect (port, redirected_port);
+        }
+        break;
+    case AF_INET6:
+        temp_addr_len = sizeof (temp_addr_in6);
+        getsockname (sockfd, &temp_addr_in6, &temp_addr_len);
+        if (redirected_port == 0)
+        {
+            redirected_port = ntohs (temp_addr_in6.sin6_port);
+            add_port_redirect (port, redirected_port);
+        }
+        break;
+    }
+
+    return retval;
+}
+
+#include <ctype.h>
+
+int
+connect (int sockfd, const struct sockaddr *addr, socklen_t addrlen)
+{
+    int port, redirected_port;
+    const char *path;
+    const struct sockaddr *modified_addr = addr;
+    struct sockaddr_in temp_addr_in;
+    struct sockaddr_in6 temp_addr_in6;
+    struct sockaddr_un temp_addr_un;
+    int (*_connect) (int sockfd, const struct sockaddr *addr, socklen_t addrlen);
+
+    _connect = (int (*)(int sockfd, const struct sockaddr *addr, socklen_t addrlen)) dlsym (RTLD_NEXT, "connect");
+
+    switch (addr->sa_family)
+    {
+    case AF_UNIX:
+        path = ((const struct sockaddr_un *) addr)->sun_path;
+        if (path[0] != '\0') 
+        {
+            gchar *new_path = redirect_path (path);
+            memcpy (&temp_addr_un, addr, addrlen);
+            strncpy (temp_addr_un.sun_path, new_path, sizeof (temp_addr_un.sun_path) - 1);
+            g_free (new_path);
+            modified_addr = (struct sockaddr *) &temp_addr_un;
+        }
+        break;
+    case AF_INET:
+        port = ntohs (((const struct sockaddr_in *) addr)->sin_port);
+        redirected_port = find_port_redirect (port);
+        if (redirected_port != 0) 
+        {
+            memcpy (&temp_addr_in, addr, sizeof (struct sockaddr_in));
+            temp_addr_in.sin_port = htons (redirected_port);
+            modified_addr = (struct sockaddr *) &temp_addr_in;
+        }
+        break;
+    case AF_INET6:
+        port = ntohs (((const struct sockaddr_in6 *) addr)->sin6_port);
+        redirected_port = find_port_redirect (port);
+        if (redirected_port != 0) 
+        {
+            memcpy (&temp_addr_in6, addr, sizeof (struct sockaddr_in6));
+            temp_addr_in6.sin6_port = htons (redirected_port);
+            modified_addr = (struct sockaddr *) &temp_addr_in6;
+        }
+        break;
+    }
+
+    return _connect (sockfd, modified_addr, addrlen);
+}
+
+ssize_t
+sendto (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)
+{
+    int port, redirected_port;
+    const char *path;
+    const struct sockaddr *modified_addr = dest_addr;
+    struct sockaddr_in temp_addr_in;
+    struct sockaddr_in6 temp_addr_in6;
+    struct sockaddr_un temp_addr_un;  
+    ssize_t (*_sendto) (int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
+
+    _sendto = (ssize_t (*)(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)) dlsym (RTLD_NEXT, "sendto");
+
+    switch (dest_addr->sa_family)
+    {
+    case AF_UNIX:
+        path = ((const struct sockaddr_un *) dest_addr)->sun_path;
+        if (path[0] != '\0') 
+        {
+            gchar *new_path = redirect_path (path);
+            memcpy (&temp_addr_un, dest_addr, sizeof (struct sockaddr_un));
+            strncpy (temp_addr_un.sun_path, new_path, sizeof (temp_addr_un.sun_path) - 1);
+            g_free (new_path);
+            modified_addr = (struct sockaddr *) &temp_addr_un;
+        }
+        break;
+    case AF_INET:
+        port = ntohs (((const struct sockaddr_in *) dest_addr)->sin_port);
+        redirected_port = find_port_redirect (port);
+        if (redirected_port != 0) 
+        {
+            memcpy (&temp_addr_in, dest_addr, sizeof (struct sockaddr_in));
+            temp_addr_in.sin_port = htons (redirected_port);
+            modified_addr = (struct sockaddr *) &temp_addr_in;
+        }
+        break;
+    case AF_INET6:
+        port = ntohs (((const struct sockaddr_in6 *) dest_addr)->sin6_port);
+        redirected_port = find_port_redirect (port);
+        if (redirected_port != 0) 
+        {
+            memcpy (&temp_addr_in6, dest_addr, sizeof (struct sockaddr_in6));
+            temp_addr_in6.sin6_port = htons (redirected_port);
+            modified_addr = (struct sockaddr *) &temp_addr_in6;
+        }
+        break;
+    }
+
+    return _sendto (sockfd, buf, len, flags, modified_addr, addrlen);
+}
+
 int
 close (int fd)
 {
     int (*_close) (int fd);
 
-    if (fd > 0 && fd == console_fd)
+    if (fd > 0 && fd == tty_fd)
         return 0;
 
     _close = (int (*)(int fd)) dlsym (RTLD_NEXT, "close");
@@ -556,7 +803,7 @@ static void
 free_user (gpointer data)
 {
     struct passwd *entry = data;
-  
+
     g_free (entry->pw_name);
     g_free (entry->pw_passwd);
     g_free (entry->pw_gecos);
@@ -649,10 +896,10 @@ struct passwd *
 getpwnam (const char *name)
 {
     GList *link;
-  
+
     if (name == NULL)
         return NULL;
-  
+
     load_passwd_file ();
 
     for (link = user_entries; link; link = link->next)
@@ -690,7 +937,7 @@ static void
 free_group (gpointer data)
 {
     struct group *entry = data;
-  
+
     g_free (entry->gr_name);
     g_free (entry->gr_passwd);
     g_strfreev (entry->gr_mem);
@@ -847,7 +1094,7 @@ pam_authenticate (pam_handle_t *pamh, int flags)
         status_notify ("%s", status->str);
         g_string_free (status, TRUE);
     }
-  
+
     if (strcmp (pamh->service_name, "test-remote") == 0)
     {
         int result;
@@ -856,7 +1103,7 @@ pam_authenticate (pam_handle_t *pamh, int flags)
 
         msg = malloc (sizeof (struct pam_message *) * 1);
         msg[0] = malloc (sizeof (struct pam_message));
-        msg[0]->msg_style = PAM_PROMPT_ECHO_ON; 
+        msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
         msg[0]->msg = "remote-login:";
         result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
         free (msg[0]);
@@ -919,7 +1166,7 @@ pam_authenticate (pam_handle_t *pamh, int flags)
 
         msg = malloc (sizeof (struct pam_message *) * 1);
         msg[0] = malloc (sizeof (struct pam_message));
-        msg[0]->msg_style = PAM_PROMPT_ECHO_ON; 
+        msg[0]->msg_style = PAM_PROMPT_ECHO_ON;
         msg[0]->msg = LOGIN_PROMPT;
         result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
         free (msg[0]);
@@ -934,7 +1181,7 @@ pam_authenticate (pam_handle_t *pamh, int flags)
             free (resp);
             return PAM_CONV_ERR;
         }
-      
+
         pamh->user = strdup (resp[0].resp);
         free (resp[0].resp);
         free (resp);
@@ -1030,6 +1277,8 @@ pam_authenticate (pam_handle_t *pamh, int flags)
             result = pamh->conversation.conv (1, (const struct pam_message **) msg, &resp, pamh->conversation.appdata_ptr);
             free (msg[0]);
             free (msg);
+            if (result != PAM_SUCCESS)
+                return result;
 
             if (resp == NULL)
                 return PAM_CONV_ERR;
@@ -1072,7 +1321,7 @@ static const char *
 get_env_value (const char *name_value, const char *name)
 {
     int j;
-  
+
     for (j = 0; name[j] && name_value[j] && name[j] == name_value[j]; j++);
     if (name[j] == '\0' && name_value[j] == '=')
         return &name_value[j + 1];
@@ -1167,13 +1416,13 @@ pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
 {
     if (pamh == NULL || item == NULL)
         return PAM_SYSTEM_ERR;
-  
+
     switch (item_type)
     {
     case PAM_SERVICE:
         *item = pamh->service_name;
         return PAM_SUCCESS;
-      
+
     case PAM_USER:
         *item = pamh->user;
         return PAM_SUCCESS;
@@ -1185,11 +1434,11 @@ pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
     case PAM_RUSER:
         *item = pamh->ruser;
         return PAM_SUCCESS;
-     
+
     case PAM_USER_PROMPT:
         *item = LOGIN_PROMPT;
         return PAM_SUCCESS;
-      
+
     case PAM_TTY:
         *item = pamh->tty;
         return PAM_SUCCESS;
@@ -1310,7 +1559,7 @@ pam_acct_mgmt (pam_handle_t *pamh, int flags)
         status_notify ("%s", status->str);
         g_string_free (status, TRUE);
     }
-  
+
     if (!pamh->user)
         return PAM_USER_UNKNOWN;
 
@@ -1666,7 +1915,7 @@ xcb_connect_to_display_with_auth_info (const char *display, xcb_auth_info_t *aut
     xcb_connection_t *c;
     gchar *socket_path;
     GError *error = NULL;
-  
+
     c = malloc (sizeof (xcb_connection_t));
     c->display = g_strdup (display);
     c->error = 0;
@@ -1734,3 +1983,48 @@ xcb_disconnect (xcb_connection_t *c)
         g_object_unref (c->socket);
     free (c);
 }
+
+#if HAVE_LIBAUDIT
+int
+audit_open (void)
+{
+    connect_status ();  
+    if (g_key_file_get_boolean (config, "test-audit-config", "check-events", NULL))
+        status_notify ("AUDIT OPEN");
+
+    return dup (STDOUT_FILENO);
+}
+
+int
+audit_log_acct_message (int audit_fd, int type, const char *pgname,
+                        const char *op, const char *name, unsigned int id,
+                        const char *host, const char *addr, const char *tty, int result)
+{
+    gchar *type_string;
+
+    connect_status ();  
+    if (!g_key_file_get_boolean (config, "test-audit-config", "check-events", NULL))
+        return 1;
+
+    switch (type)
+    {
+    case AUDIT_USER_LOGIN:
+        type_string = g_strdup ("USER_LOGIN");
+        break;      
+    case AUDIT_USER_LOGOUT:
+        type_string = g_strdup ("USER_LOGOUT");
+        break;
+    default:
+        type_string = g_strdup_printf ("%d", type);
+        break;
+    }
+  
+    status_notify ("AUDIT LOG-ACCT TYPE=%s PGNAME=%s OP=%s NAME=%s ID=%u HOST=%s ADDR=%s TTY=%s RESULT=%d",
+                   type_string, pgname ? pgname : "", op ? op : "", name ? name : "", id, host ? host : "", addr ? addr : "", tty ? tty : "", result);
+
+    g_free (type_string);
+
+    return 1;
+}
+
+#endif