Commit 5cc352a2 authored by Jiri (George) Lebl's avatar Jiri (George) Lebl Committed by George Lebl

Minor cleanup and paranoia

Sun Aug 26 01:45:33 2001  George Lebl <jirka@5z.com>

	* daemon/auth.c, daemon/cookie.c:   Minor cleanup and paranoia

	* daemon/gdm-net.[ch], daemon/gdm.[ch], daemon/server.c,
	  daemon/slave.[ch]: The daemon now keeps track of the cookies in
	  text form at least so that it can do authentication of it's own.
	  FLEXI_XSERVER now requires an "authenticated" socket connection
	  using AUTH_LOCAL (a new opcode).  This way only those users that
	  are logged in from gdm on a console can start new
	  console/fullscreen flexi servers.  I mean for remote people it
	  wouldn't work anyway.

	* gui/gdmflexiserver.c: implement AUTH_LOCAL authentication scheme
	  by reading from the .Xauthority file and looking for FamilyLocal
	  entries from gdm. (or those looking like it).  Tests all candidates
	  and find the one that works for gdm.  This could cause some
	  gdm_info messages in the log, but I suppose that's ok, vast
	  majority of the time there will only be one that is even tried.
	  Also added a debug flag and get xauth filename from XauFileName
	  rather then my own hand created method.
parent 15c88eb6
Sun Aug 26 01:45:33 2001 George Lebl <jirka@5z.com>
* daemon/auth.c, daemon/cookie.c: Minor cleanup and paranoia
* daemon/gdm-net.[ch], daemon/gdm.[ch], daemon/server.c,
daemon/slave.[ch]: The daemon now keeps track of the cookies in
text form at least so that it can do authentication of it's own.
FLEXI_XSERVER now requires an "authenticated" socket connection
using AUTH_LOCAL (a new opcode). This way only those users that
are logged in from gdm on a console can start new
console/fullscreen flexi servers. I mean for remote people it
wouldn't work anyway.
* gui/gdmflexiserver.c: implement AUTH_LOCAL authentication scheme
by reading from the .Xauthority file and looking for FamilyLocal
entries from gdm. (or those looking like it). Tests all candidates
and find the one that works for gdm. This could cause some
gdm_info messages in the log, but I suppose that's ok, vast
majority of the time there will only be one that is even tried.
Also added a debug flag and get xauth filename from XauFileName
rather then my own hand created method.
Sat Aug 25 21:35:29 2001 George Lebl <jirka@5z.com>
* daemon/display.c, daemon/gdm.c: don't use an extra printf, if
......
......@@ -139,11 +139,10 @@ gdm_auth_secure_display (GdmDisplay *d)
g_slist_free (d->auths);
d->auths = NULL;
if (d->cookie)
g_free (d->cookie);
if (d->bcookie)
g_free (d->bcookie);
g_free (d->cookie);
d->cookie = NULL;
g_free (d->bcookie);
d->bcookie = NULL;
}
/* Create new random cookie */
......
......@@ -65,10 +65,8 @@ gdm_cookie_generate (GdmDisplay *d)
int r;
struct timeval tv;
struct timezone tz;
char sub[8];
char cookie[40];
char cookie[40 /* 2*16 == 32, so 40 is enough */];
sub[0] = '\0';
cookie[0] = '\0';
gdm_md5_init (&ctx);
......@@ -99,8 +97,9 @@ gdm_cookie_generate (GdmDisplay *d)
gdm_md5_final (digest, &ctx);
for (i = 0; i < 16; i++) {
g_snprintf (sub, sizeof (sub), "%02x", digest[i]);
strcat (cookie, sub);
char sub[3];
g_snprintf (sub, sizeof (sub), "%02x", (guint)digest[i]);
strcat (cookie, sub);
}
d->cookie = g_strdup (cookie);
......
......@@ -53,8 +53,9 @@ struct _GdmConnection {
1 - no close, when called raise to 2
2 - close was requested */
char *filename; /* unix socket or fifo filename,
* will be unlinked on close */
char *filename; /* unix socket or fifo filename */
guint32 user_flags;
GdmConnectionHandler handler;
gpointer data;
......@@ -170,13 +171,15 @@ gdm_socket_handler (GIOChannel *source,
GIOChannel *unixchan;
GdmConnection *conn = data;
GdmConnection *newconn;
struct sockaddr addr;
struct sockaddr_un addr;
socklen_t addr_size = sizeof (addr);
if ( ! (cond & G_IO_IN))
return TRUE;
fd = accept (conn->fd, &addr, &addr_size);
fd = accept (conn->fd,
(struct sockaddr *)&addr,
&addr_size);
if (fd < 0) {
gdm_debug ("gdm_socket_handler: Rejecting connection");
return TRUE;
......@@ -189,6 +192,7 @@ gdm_socket_handler (GIOChannel *source,
newconn->fd = fd;
newconn->writable = TRUE;
newconn->filename = NULL;
newconn->user_flags = 0;
newconn->buffer = NULL;
newconn->parent = conn;
newconn->subconnections = NULL;
......@@ -253,6 +257,7 @@ gdm_connection_open_unix (const char *sockname, mode_t mode)
conn->writable = FALSE;
conn->buffer = NULL;
conn->filename = g_strdup (sockname);
conn->user_flags = 0;
conn->parent = NULL;
conn->subconnections = NULL;
conn->n_subconnections = 0;
......@@ -300,6 +305,7 @@ gdm_connection_open_fifo (const char *fifo, mode_t mode)
conn->writable = FALSE;
conn->buffer = NULL;
conn->filename = g_strdup (fifo);
conn->user_flags = 0;
conn->parent = NULL;
conn->subconnections = NULL;
conn->n_subconnections = 0;
......@@ -330,6 +336,23 @@ gdm_connection_set_handler (GdmConnection *conn,
conn->destroy_notify = destroy_notify;
}
guint32
gdm_connection_get_user_flags (GdmConnection *conn)
{
g_return_val_if_fail (conn != NULL, 0);
return conn->user_flags;
}
void
gdm_connection_set_user_flags (GdmConnection *conn,
guint32 flags)
{
g_return_if_fail (conn != NULL);
conn->user_flags = flags;
}
void
gdm_connection_close (GdmConnection *conn)
{
......
......@@ -49,6 +49,20 @@ void gdm_connection_set_handler (GdmConnection *conn,
gpointer data,
GDestroyNotify destroy_notify);
guint32 gdm_connection_get_user_flags (GdmConnection *conn);
void gdm_connection_set_user_flags (GdmConnection *conn,
guint32 flags);
#define GDM_CONNECTION_SET_USER_FLAG(conn,flag) { \
guint32 _flags = gdm_connection_get_user_flags (conn); \
_flags |= flag; \
gdm_connection_set_user_flags (conn, _flags); \
}
#define GDM_CONNECTION_UNSET_USER_FLAG(conn,flag) { \
guint32 _flags = gdm_connection_get_user_flags (conn); \
_flags &= ~flag; \
gdm_connection_set_user_flags (conn, _flags); \
}
void gdm_connection_close (GdmConnection *conn);
#endif /* GDM_NET_H */
......
......@@ -1432,7 +1432,19 @@ gdm_quit (void)
static void
gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data)
{
gdm_debug ("Handeling message: '%s'", msg);
/* Evil!, all this for debugging? */
if (GdmDebug) {
if (strncmp (msg, GDM_SOP_COOKIE " ",
strlen (GDM_SOP_COOKIE " ")) == 0) {
char *s = g_strndup
(msg, strlen (GDM_SOP_COOKIE " XXXX XX"));
/* cut off most of the cookie for "security" */
gdm_debug ("Handeling message: '%s...'", s);
g_free (s);
} else {
gdm_debug ("Handeling message: '%s'", msg);
}
}
if (strncmp (msg, GDM_SOP_CHOSEN " ",
strlen (GDM_SOP_CHOSEN " ")) == 0) {
......@@ -1604,6 +1616,33 @@ gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data)
/* send ack */
kill (slave_pid, SIGUSR2);
}
} else if (strncmp (msg, GDM_SOP_COOKIE " ",
strlen (GDM_SOP_COOKIE " ")) == 0) {
GdmDisplay *d;
long slave_pid;
char *p;
if (sscanf (msg, GDM_SOP_COOKIE " %ld",
&slave_pid) != 1)
return;
p = strchr (msg, ' ');
if (p != NULL)
p = strchr (p+1, ' ');
if (p == NULL)
return;
p++;
/* Find out who this slave belongs to */
d = gdm_display_lookup (slave_pid);
if (d != NULL) {
g_free (d->cookie);
d->cookie = g_strdup (p);
gdm_debug ("Got COOKIE == <secret>");
/* send ack */
kill (slave_pid, SIGUSR2);
}
} else if (strncmp (msg, GDM_SOP_FLEXI_ERR " ",
strlen (GDM_SOP_FLEXI_ERR " ")) == 0) {
GdmDisplay *d;
......@@ -1815,16 +1854,68 @@ gdm_handle_user_message (GdmConnection *conn, const char *msg, gpointer data)
{
gdm_debug ("Handeling user message: '%s'", msg);
if (strcmp (msg, GDM_SUP_FLEXI_XSERVER) == 0) {
if (strncmp (msg, GDM_SUP_AUTH_LOCAL " ",
strlen (GDM_SUP_AUTH_LOCAL " ")) == 0) {
GSList *li;
char *cookie = g_strdup
(&msg[strlen (GDM_SUP_AUTH_LOCAL " ")]);
g_strstrip (cookie);
if (strlen (cookie) != 16*2) /* 16 bytes in hex form */ {
/* evil, just whack the connection in this case */
gdm_connection_write (conn,
"ERROR 100 Not authenticated\n");
gdm_connection_close (conn);
g_free (cookie);
return;
}
/* check if cookie matches one of the console displays */
for (li = displays; li != NULL; li = li->next) {
GdmDisplay *disp = li->data;
if (disp->console &&
disp->cookie != NULL &&
strcmp (disp->cookie, cookie) == 0) {
g_free (cookie);
GDM_CONNECTION_SET_USER_FLAG
(conn, GDM_SUP_FLAG_AUTHENTICATED);
gdm_connection_write (conn, "OK\n");
return;
}
}
/* Hmmm, perhaps this is better defined behaviour */
GDM_CONNECTION_UNSET_USER_FLAG
(conn, GDM_SUP_FLAG_AUTHENTICATED);
gdm_connection_write (conn, "ERROR 100 Not authenticated\n");
g_free (cookie);
} else if (strcmp (msg, GDM_SUP_FLEXI_XSERVER) == 0) {
/* Only allow locally authenticated connections */
if ( ! (gdm_connection_get_user_flags (conn) &
GDM_SUP_FLAG_AUTHENTICATED)) {
gdm_info (_("Flexible server request denied: "
"Not authenticated"));
gdm_connection_write (conn,
"ERROR 100 Not authenticated\n");
return;
}
handle_flexi_server (conn, TYPE_FLEXI, GdmStandardXServer,
NULL, NULL);
} else if (strncmp (msg, GDM_SUP_FLEXI_XSERVER " ",
strlen (GDM_SUP_FLEXI_XSERVER " ")) == 0) {
char *name = g_strdup
(&msg[strlen (GDM_SUP_FLEXI_XSERVER " ")]);
char *name;
const char *command = NULL;
GdmXServer *svr;
/* Only allow locally authenticated connections */
if ( ! (gdm_connection_get_user_flags (conn) &
GDM_SUP_FLAG_AUTHENTICATED)) {
gdm_info (_("Flexible server request denied: "
"Not authenticated"));
gdm_connection_write (conn,
"ERROR 100 Not authenticated\n");
return;
}
name = g_strdup (&msg[strlen (GDM_SUP_FLEXI_XSERVER " ")]);
g_strstrip (name);
if (ve_string_empty (name)) {
g_free (name);
......
......@@ -376,6 +376,7 @@ void gdm_quit (void);
#define GDM_SOP_CHOOSERPID "CHOOSERPID" /* <slave pid> <chooserpid> */
#define GDM_SOP_LOGGED_IN "LOGGED_IN" /* <slave pid> <logged_in as int> */
#define GDM_SOP_LOGIN "LOGIN" /* <slave pid> <username> */
#define GDM_SOP_COOKIE "COOKIE" /* <slave pid> <cookie> */
#define GDM_SOP_DISP_NUM "DISP_NUM" /* <slave pid> <display as int> */
/* For linux only currently */
#define GDM_SOP_VT_NUM "VT_NUM" /* <slave pid> <vt as int> */
......@@ -398,6 +399,7 @@ void gdm_quit (void);
* value.
*/
/* The user protocol, using /tmp/.gdm_socket */
#define GDM_SUP_VERSION "VERSION" /* no arguments */
/* VERSION: Query version
* Supported since: 2.2.4.0
......@@ -405,8 +407,26 @@ void gdm_quit (void);
* Answers:
* GDM <gdm version>
*/
#define GDM_SUP_AUTH_LOCAL "AUTH_LOCAL" /* <xauth cookie> */
/* AUTH_LOCAL: Setup this connection as authenticated for FLEXI_SERVER
* Because all full blown (non-Xnest) servers can be started
* only from users logged in locally, and here gdm assumes
* only users logged in from gdm. They must pass the xauth
* MIT-MAGIC-COOKIE-1 that they were passed before the
* connection is authenticated.
* Supported since: 2.2.4.0
* Arguments: <xauth cookie>
* <xauth cookie> is in hex form with no 0x prefix
* Answers:
* OK
* ERROR <err number> <english error description>
* 0 = Not implemented
* 100 = Not authenticated
* 999 = Unknown error
*/
#define GDM_SUP_FLEXI_XSERVER "FLEXI_XSERVER" /* <xserver type> */
/* FLEXI_XSERVER: Start a new X flexible server
* Only supported on connection that passed AUTH_LOCAL
* Supported since: 2.2.4.0
* Arguments: <xserver type>
* If no arguments, starts the standard x server
......@@ -419,6 +439,7 @@ void gdm_quit (void);
* 3 = X failed
* 4 = X too busy
* 6 = No server binary
* 100 = Not authenticated
* 999 = Unknown error
*/
#define GDM_SUP_FLEXI_XNEST "FLEXI_XNEST" /* <display> <xauth file> */
......@@ -458,6 +479,12 @@ void gdm_quit (void);
* Supported since: 2.2.4.0
*/
/* User flags for the SUP protocol */
enum {
GDM_SUP_FLAG_AUTHENTICATED = 0x1 /* authenticated as a local user,
* from a local display we started */
};
#endif /* GDM_H */
/* EOF */
......@@ -293,6 +293,7 @@ gdm_server_start (GdmDisplay *disp, gboolean treat_as_flexi,
/* Create new cookie */
if ( ! gdm_auth_secure_display (d))
return FALSE;
gdm_slave_send_string (GDM_SOP_COOKIE, d->cookie);
ve_setenv ("DISPLAY", d->name, TRUE);
/* Catch USR1 from X server */
......
......@@ -113,6 +113,7 @@ extern gboolean GdmAllowRoot;
extern sigset_t sysmask;
extern gchar *GdmGlobalFaceDir;
extern gboolean GdmBrowser;
extern gboolean GdmDebug;
/* Local prototypes */
......@@ -134,7 +135,6 @@ static void gdm_child_exit (gint status, const gchar *format, ...) G_GNUC_PR
static gint gdm_slave_exec_script (GdmDisplay *d, const gchar *dir,
const char *login, struct passwd *pwent);
static gchar * gdm_parse_enriched_login (const gchar *s, GdmDisplay *display);
static void gdm_send_login (const char *login);
/* Yay thread unsafety */
......@@ -249,10 +249,11 @@ gdm_slave_start (GdmDisplay *display)
gdm_server_stop (display);
gdm_slave_send_num (GDM_SOP_XPID, 0);
} else {
/* OK about to start again so redo our cookies and reinit
/* OK about to start again so rebake our cookies and reinit
* the server */
if ( ! gdm_auth_secure_display (d))
break;
gdm_slave_send_string (GDM_SOP_COOKIE, d->cookie);
gdm_server_reinit (d);
}
......@@ -441,14 +442,14 @@ gdm_slave_run (GdmDisplay *display)
gdm_first_login = FALSE;
gdm_slave_send_num (GDM_SOP_LOGGED_IN, TRUE);
gdm_send_login (ParsedAutomaticLogin);
gdm_slave_send_string (GDM_SOP_LOGIN, ParsedAutomaticLogin);
setup_automatic_session (d, ParsedAutomaticLogin);
gdm_slave_session_start();
gdm_slave_send_num (GDM_SOP_LOGGED_IN, FALSE);
gdm_send_login ("");
gdm_slave_send_string (GDM_SOP_LOGIN, "");
gdm_debug ("gdm_slave_run: Automatic login done");
} else {
......@@ -463,14 +464,15 @@ gdm_slave_run (GdmDisplay *display)
/* timed out into a timed login */
do_timed_login = FALSE;
setup_automatic_session (d, ParsedTimedLogin);
gdm_send_login (ParsedTimedLogin);
gdm_slave_send_string (GDM_SOP_LOGIN,
ParsedTimedLogin);
} else {
gdm_send_login (login);
gdm_slave_send_string (GDM_SOP_LOGIN, login);
}
gdm_slave_session_start ();
gdm_slave_send_num (GDM_SOP_LOGGED_IN, FALSE);
gdm_send_login ("");
gdm_slave_send_string (GDM_SOP_LOGIN, "");
}
}
......@@ -746,7 +748,7 @@ gdm_slave_wait_for_login (void)
gdm_slave_send_num (GDM_SOP_LOGGED_IN, TRUE);
/* Note: nobody really logged in */
gdm_send_login ("");
gdm_slave_send_string (GDM_SOP_LOGIN, "");
/* disable the login screen, we don't want people to
* log in in the meantime */
......@@ -1230,16 +1232,25 @@ gdm_slave_send_num (const char *opcode, long num)
sleep (10);
}
static void
gdm_send_login (const char *login)
void
gdm_slave_send_string (const char *opcode, const char *str)
{
char *msg;
int fd;
char *fifopath;
gdm_debug ("Sending login == %s for slave %ld",
ve_sure_string (login),
(long)getpid ());
/* Evil!, all this for debugging? */
if (GdmDebug) {
if (strcmp (opcode, GDM_SOP_COOKIE) == 0)
gdm_debug ("Sending %s == <secret> for slave %ld",
opcode,
(long)getpid ());
else
gdm_debug ("Sending %s == %s for slave %ld",
opcode,
ve_sure_string (str),
(long)getpid ());
}
gdm_got_usr2 = FALSE;
......@@ -1248,12 +1259,12 @@ gdm_send_login (const char *login)
fd = open (fifopath, O_WRONLY);
/* eek */
if (fd < 0) {
gdm_error (_("%s: Can't open fifo!"), "gdm_send_login");
gdm_error (_("%s: Can't open fifo!"), "gdm_slave_send_string");
return;
}
msg = g_strdup_printf ("\n%s %ld %s\n", GDM_SOP_LOGIN,
(long)getpid (), ve_sure_string (login));
msg = g_strdup_printf ("\n%s %ld %s\n", opcode,
(long)getpid (), ve_sure_string (str));
write (fd, msg, strlen (msg));
......
......@@ -30,6 +30,7 @@ gboolean gdm_slave_greeter_check_interruption (const char *msg);
gboolean gdm_slave_should_complain (void);
void gdm_slave_send_num (const char *opcode, long num);
void gdm_slave_send_string (const char *opcode, const char *str);
#endif /* GDM_SLAVE_H */
......
......@@ -20,8 +20,11 @@
#include "config.h"
#include <gnome.h>
#include <gdk/gdkx.h>
#include <X11/Xauth.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
......@@ -35,6 +38,15 @@
#include "gdm.h"
static GSList *xservers = NULL;
static gboolean got_standard = FALSE;
static gboolean use_xnest = FALSE;
static const char *send_command = NULL;
static const char *server = NULL;
static const char *chosen_server = NULL;
static gboolean debug = FALSE;
static char *
do_command (int fd, const char *command, gboolean get_response)
{
......@@ -42,7 +54,8 @@ do_command (int fd, const char *command, gboolean get_response)
char buf[1];
char *cstr;
/* g_print ("Sending command: '%s'\n", command); */
if (debug)
g_print ("Sending command: '%s'\n", command);
cstr = g_strdup_printf ("%s\n", command);
if (send (fd, cstr, strlen (cstr), MSG_NOSIGNAL) < 0)
......@@ -57,7 +70,8 @@ do_command (int fd, const char *command, gboolean get_response)
g_string_append_c (str, buf[0]);
}
/* g_print (" Got response: '%s'\n", str->str); */
if (debug)
g_print (" Got response: '%s'\n", str->str);
cstr = str->str;
g_string_free (str, FALSE);
......@@ -85,7 +99,7 @@ version_ok_p (const char *version, const char *min_version)
}
static char *
call_gdm (const char *command, const char *min_version, int tries)
call_gdm (const char *command, const char * auth_cookie, const char *min_version, int tries)
{
struct sockaddr_un addr;
int fd;
......@@ -96,7 +110,7 @@ call_gdm (const char *command, const char *min_version, int tries)
fd = socket (AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
return call_gdm (command, min_version, tries - 1);
return call_gdm (command, auth_cookie, min_version, tries - 1);
}
strcpy (addr.sun_path, GDM_SUP_SOCKET);
......@@ -104,14 +118,14 @@ call_gdm (const char *command, const char *min_version, int tries)
if (connect (fd, (struct sockaddr *)&addr, sizeof (addr)) < 0) {
close (fd);
return call_gdm (command, min_version, tries - 1);
return call_gdm (command, auth_cookie, min_version, tries - 1);
}
/* Version check first */
ret = do_command (fd, GDM_SUP_VERSION, TRUE /* get_response */);
if (ret == NULL) {
close (fd);
return call_gdm (command, min_version, tries - 1);
return call_gdm (command, auth_cookie, min_version, tries - 1);
}
if (strncmp (ret, "GDM ", strlen ("GDM ")) != 0) {
g_free (ret);
......@@ -124,11 +138,34 @@ call_gdm (const char *command, const char *min_version, int tries)
close (fd);
return NULL;
}
g_free (ret);
/* require authentication */
if (auth_cookie != NULL) {
char *auth_cmd = g_strdup_printf
(GDM_SUP_AUTH_LOCAL " %s", auth_cookie);
ret = do_command (fd, auth_cmd, TRUE /* get_response */);
g_free (auth_cmd);
if (ret == NULL) {
close (fd);
return call_gdm (command, auth_cookie,
min_version, tries - 1);
}
/* not auth'ed */
if (strcmp (ret, "OK") != 0) {
do_command (fd, GDM_SUP_CLOSE,
FALSE /* get_response */);
close (fd);
/* returns the error */
return ret;
}
g_free (ret);
}
ret = do_command (fd, command, TRUE /* get_response */);
if (ret == NULL) {
close (fd);
return call_gdm (command, min_version, tries - 1);
return call_gdm (command, auth_cookie, min_version, tries - 1);
}
do_command (fd, GDM_SUP_CLOSE, FALSE /* get_response */);
......@@ -144,39 +181,97 @@ get_display (void)
static char *display = NULL;
if (display == NULL) {
display = g_strdup (g_getenv ("DISPLAY"));
if (display == NULL) /*eek!*/
display = g_strdup (":0");
display = g_strdup (gdk_display_name);
if (display == NULL) {
display = g_strdup (g_getenv ("DISPLAY"));
if (display == NULL) /*eek!*/ {
display = g_strdup (":0");
}
}
}
return display;
}
static char *
get_xauthfile (void)
get_auth_cookie (void)
{
static char *xauthfile = NULL;
if (xauthfile == NULL) {
xauthfile = g_strdup (g_getenv ("XAUTHORITY"));
if (ve_string_empty (xauthfile)) {
g_strdup (xauthfile);
xauthfile = g_concat_dir_and_file (g_get_home_dir (),
".Xauthority");
/* FIXME: perhaps if it doesn't exist, run
* xauth generate on this */
FILE *fp;
char *number;
static gboolean tried = FALSE;
static char *cookie = NULL;
Xauth *xau;
if (tried)
return cookie;
fp = fopen (XauFileName (), "r");
if (fp == NULL) {
cookie = NULL;
tried = TRUE;
return NULL;
}
number = get_display ();
/* whee! handles even DECnet crap */
number = strchr (number, ':');
if (number != NULL) {
while (*number == ':') {
number++;
}
} else {
number = "0";
}
return xauthfile;
}
cookie = NULL;
while ((xau = XauReadAuth (fp)) != NULL) {
char *cmd;
char *ret;
int i;
char buffer[40 /* 2*16 == 32, so 40 is enough */];
/* Only Family local things are considered, all console
* logins DO have this family (and even some local xdmcp
* logins, though those will not pass by gdm itself of
* course) */
if (xau->family != FamilyLocal ||
xau->number == NULL ||
strncmp (xau->number, number, xau->number_length) != 0 ||
/* gdm sends MIT-MAGIC-COOKIE-1 cookies of length 16,
* so just do those */
xau->name_length != strlen ("MIT-MAGIC-COOKIE-1") ||
strncmp (xau->name, "MIT-MAGIC-COOKIE-1", xau->name_length) != 0 ||
xau->data_length != 16) {
XauDisposeAuth (xau);
continue;
}
static GSList *xservers = NULL;
static gboolean got_standard = FALSE;
static gboolean use_xnest = FALSE;
const char *send_command = NULL;
const char *server = NULL;
const char *chosen_server = NULL;
buffer[0] = '\0';
for (i = 0; i < 16; i++) {
char sub[3];
g_snprintf (sub, sizeof (sub), "%02x", (guint)(guchar)xau->data[i]);
strcat (buffer, sub);
}
XauDisposeAuth (xau);
cmd = g_strdup_printf (GDM_SUP_AUTH_LOCAL " %s", buffer);
ret = call_gdm (cmd, NULL /* auth cookie */, "2.2.4.0", 5);
if (ret != NULL &&
strcmp (ret, "OK") == 0) {
g_free (ret);
cookie = g_strdup (buffer);
break;
}
g_free (ret);
}
fclose (fp);
tried = TRUE;
return cookie;
}
static void
read_servers (void)
......@@ -318,6 +413,7 @@ choose_server (void)
struct poptOption options [] = {
{ "command", 'c', POPT_ARG_STRING, &send_command, 0, N_("Send the specified protocol command to gdm"), N_("COMMAND") },
{ "xnest", 'n', POPT_ARG_NONE, &use_xnest, 0, N_("Xnest mode"), NULL },
{ "debug", 'd', POPT_ARG_NONE, &debug, 0, N_("Debugging output"), NULL },
POPT_AUTOHELP
{ NULL, 0, 0, NULL, 0}
};
......@@ -334,6 +430,7 @@ main (int argc, char *argv[])
char *version;
char *ret;
char *message;
char *auth_cookie = NULL;
poptContext ctx;
const char **args;
......@@ -380,7 +477,8 @@ main (int argc, char *argv[])
}
if (send_command != NULL) {
ret = call_gdm (send_command, "2.2.3.2", 5);
ret = call_gdm (send_command, NULL /* auth cookie */,
"2.2.4.0", 5);
if (ret != NULL) {
g_print ("%s\n", ret);
return 0;
......@@ -397,21 +495,13 @@ main (int argc, char *argv[])
command = g_strdup_printf (GDM_SUP_FLEXI_XNEST
" %s %s",
get_display (),
get_xauthfile ());