Back to index

lightdm  1.3.2
Classes | Defines | Enumerations | Functions | Variables
greeter.c File Reference
#include <config.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "greeter.h"
#include "ldm-marshal.h"

Go to the source code of this file.

Classes

struct  GreeterPrivate

Defines

#define HEADER_SIZE   (sizeof (guint32) * 2)
#define MAX_MESSAGE_LENGTH   1024

Enumerations

enum  { CONNECTED, START_AUTHENTICATION, START_SESSION, LAST_SIGNAL }
enum  GreeterMessage {
  GREETER_MESSAGE_CONNECT = 0, GREETER_MESSAGE_AUTHENTICATE, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, GREETER_MESSAGE_CONTINUE_AUTHENTICATION,
  GREETER_MESSAGE_START_SESSION, GREETER_MESSAGE_CANCEL_AUTHENTICATION, GREETER_MESSAGE_SET_LANGUAGE, GREETER_MESSAGE_CONNECT = 0,
  GREETER_MESSAGE_AUTHENTICATE, GREETER_MESSAGE_AUTHENTICATE_AS_GUEST, GREETER_MESSAGE_CONTINUE_AUTHENTICATION, GREETER_MESSAGE_START_SESSION,
  GREETER_MESSAGE_CANCEL_AUTHENTICATION, GREETER_MESSAGE_SET_LANGUAGE
}
enum  ServerMessage {
  SERVER_MESSAGE_CONNECTED = 0, SERVER_MESSAGE_PROMPT_AUTHENTICATION, SERVER_MESSAGE_END_AUTHENTICATION, SERVER_MESSAGE_SESSION_RESULT,
  SERVER_MESSAGE_CONNECTED = 0, SERVER_MESSAGE_PROMPT_AUTHENTICATION, SERVER_MESSAGE_END_AUTHENTICATION, SERVER_MESSAGE_SESSION_RESULT
}

Functions

 G_DEFINE_TYPE (Greeter, greeter, G_TYPE_OBJECT)
static gboolean read_cb (GIOChannel *source, GIOCondition condition, gpointer data)
Greetergreeter_new (Session *session, const gchar *pam_service)
void greeter_set_allow_guest (Greeter *greeter, gboolean allow_guest)
void greeter_set_hint (Greeter *greeter, const gchar *name, const gchar *value)
static guint32 int_length ()
static void write_message (Greeter *greeter, guint8 *message, gsize message_length)
static void write_int (guint8 *buffer, gint buffer_length, guint32 value, gsize *offset)
static void write_string (guint8 *buffer, gint buffer_length, const gchar *value, gsize *offset)
static void write_header (guint8 *buffer, gint buffer_length, guint32 id, guint32 length, gsize *offset)
static guint32 string_length (const gchar *value)
static void handle_connect (Greeter *greeter, const gchar *version)
static void pam_messages_cb (Session *session, Greeter *greeter)
static void send_end_authentication (Greeter *greeter, guint32 sequence_number, const gchar *username, int result)
static void authentication_complete_cb (Session *session, Greeter *greeter)
static void reset_session (Greeter *greeter)
static void handle_login (Greeter *greeter, guint32 sequence_number, const gchar *username)
static void handle_login_as_guest (Greeter *greeter, guint32 sequence_number)
static void handle_continue_authentication (Greeter *greeter, gchar **secrets)
static void handle_cancel_authentication (Greeter *greeter)
static void handle_start_session (Greeter *greeter, const gchar *session)
static void handle_set_language (Greeter *greeter, const gchar *language)
static guint32 read_int (Greeter *greeter, gsize *offset)
static gchar * read_string (Greeter *greeter, gsize *offset)
gboolean greeter_get_guest_authenticated (Greeter *greeter)
Sessiongreeter_get_authentication_session (Greeter *greeter)
gboolean greeter_get_start_session (Greeter *greeter)
gboolean greeter_start (Greeter *greeter, const gchar *service, const gchar *username)
static Sessiongreeter_real_start_authentication (Greeter *greeter, const gchar *username)
static gboolean greeter_real_start_session (Greeter *greeter, const gchar *session, gboolean is_guest)
static void greeter_init (Greeter *greeter)
static void greeter_finalize (GObject *object)
static void greeter_class_init (GreeterClass *klass)

Variables

static guint signals [LAST_SIGNAL] = { 0 }

Class Documentation

struct GreeterPrivate

Definition at line 30 of file greeter.c.

Collaboration diagram for GreeterPrivate:
Class Members
gboolean allow_guest
guint32 authentication_sequence_number
Session * authentication_session
gchar * default_session
GIOChannel * from_greeter_channel
gboolean guest_account_authenticated
GHashTable * hints
gsize n_read
gchar * pam_service
guint8 * read_buffer
Session * session
gboolean start_session
GIOChannel * to_greeter_channel

Define Documentation

#define HEADER_SIZE   (sizeof (guint32) * 2)

Definition at line 123 of file greeter.c.

#define MAX_MESSAGE_LENGTH   1024

Definition at line 124 of file greeter.c.


Enumeration Type Documentation

anonymous enum
Enumerator:
CONNECTED 
START_AUTHENTICATION 
START_SESSION 
LAST_SIGNAL 

Definition at line 22 of file greeter.c.

Enumerator:
GREETER_MESSAGE_CONNECT 
GREETER_MESSAGE_AUTHENTICATE 
GREETER_MESSAGE_AUTHENTICATE_AS_GUEST 
GREETER_MESSAGE_CONTINUE_AUTHENTICATION 
GREETER_MESSAGE_START_SESSION 
GREETER_MESSAGE_CANCEL_AUTHENTICATION 
GREETER_MESSAGE_SET_LANGUAGE 
GREETER_MESSAGE_CONNECT 
GREETER_MESSAGE_AUTHENTICATE 
GREETER_MESSAGE_AUTHENTICATE_AS_GUEST 
GREETER_MESSAGE_CONTINUE_AUTHENTICATION 
GREETER_MESSAGE_START_SESSION 
GREETER_MESSAGE_CANCEL_AUTHENTICATION 
GREETER_MESSAGE_SET_LANGUAGE 

Definition at line 71 of file greeter.c.

Enumerator:
SERVER_MESSAGE_CONNECTED 
SERVER_MESSAGE_PROMPT_AUTHENTICATION 
SERVER_MESSAGE_END_AUTHENTICATION 
SERVER_MESSAGE_SESSION_RESULT 
SERVER_MESSAGE_CONNECTED 
SERVER_MESSAGE_PROMPT_AUTHENTICATION 
SERVER_MESSAGE_END_AUTHENTICATION 
SERVER_MESSAGE_SESSION_RESULT 

Definition at line 83 of file greeter.c.


Function Documentation

static void authentication_complete_cb ( Session session,
Greeter greeter 
) [static]

Definition at line 272 of file greeter.c.

{
    int result;

    g_debug ("Authenticate result for user %s: %s", session_get_username (session), session_get_authentication_result_string (session));

    result = session_get_authentication_result (session);
    if (session_get_is_authenticated (session))
    {
        if (session_get_user (session))
            g_debug ("User %s authorized", session_get_username (session));
        else
        {
            g_debug ("User %s authorized, but no account of that name exists", session_get_username (session));          
            result = PAM_USER_UNKNOWN;
        }
    }

    send_end_authentication (greeter, greeter->priv->authentication_sequence_number, session_get_username (session), result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

G_DEFINE_TYPE ( Greeter  ,
greeter  ,
G_TYPE_OBJECT   
)
static void greeter_class_init ( GreeterClass klass) [static]

Definition at line 712 of file greeter.c.

{
    GObjectClass *object_class = G_OBJECT_CLASS (klass);

    klass->start_authentication = greeter_real_start_authentication;
    klass->start_session = greeter_real_start_session;
    object_class->finalize = greeter_finalize;

    signals[CONNECTED] =
        g_signal_new ("connected",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GreeterClass, connected),
                      NULL, NULL,
                      g_cclosure_marshal_VOID__VOID,
                      G_TYPE_NONE, 0);

    signals[START_AUTHENTICATION] =
        g_signal_new ("start-authentication",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GreeterClass, start_authentication),
                      g_signal_accumulator_first_wins,
                      NULL,
                      ldm_marshal_OBJECT__STRING,
                      SESSION_TYPE, 1, G_TYPE_STRING);

    signals[START_SESSION] =
        g_signal_new ("start-session",
                      G_TYPE_FROM_CLASS (klass),
                      G_SIGNAL_RUN_LAST,
                      G_STRUCT_OFFSET (GreeterClass, start_session),
                      g_signal_accumulator_true_handled,
                      NULL,
                      ldm_marshal_BOOLEAN__STRING,
                      G_TYPE_BOOLEAN, 1, G_TYPE_STRING);

    g_type_class_add_private (klass, sizeof (GreeterPrivate));
}

Here is the call graph for this function:

static void greeter_finalize ( GObject *  object) [static]

Definition at line 687 of file greeter.c.

{
    Greeter *self;

    self = GREETER (object);

    g_signal_handlers_disconnect_matched (self->priv->session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);    
    g_object_unref (self->priv->session);
    g_free (self->priv->pam_service);
    g_free (self->priv->read_buffer);
    g_hash_table_unref (self->priv->hints);
    if (self->priv->authentication_session)
    {
        g_signal_handlers_disconnect_matched (self->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, self);
        g_object_unref (self->priv->authentication_session);
    }
    if (self->priv->to_greeter_channel)
        g_io_channel_unref (self->priv->to_greeter_channel);
    if (self->priv->from_greeter_channel)
        g_io_channel_unref (self->priv->from_greeter_channel);

    G_OBJECT_CLASS (greeter_parent_class)->finalize (object);
}

Here is the caller graph for this function:

Definition at line 612 of file greeter.c.

{
    g_return_val_if_fail (greeter != NULL, NULL);
    return greeter->priv->authentication_session;
}

Here is the caller graph for this function:

gboolean greeter_get_guest_authenticated ( Greeter greeter)

Definition at line 605 of file greeter.c.

{
    g_return_val_if_fail (greeter != NULL, FALSE);
    return greeter->priv->guest_account_authenticated;
}

Here is the caller graph for this function:

gboolean greeter_get_start_session ( Greeter greeter)

Definition at line 619 of file greeter.c.

{
    g_return_val_if_fail (greeter != NULL, FALSE);
    return greeter->priv->start_session;
}

Here is the caller graph for this function:

static void greeter_init ( Greeter greeter) [static]

Definition at line 679 of file greeter.c.

{
    greeter->priv = G_TYPE_INSTANCE_GET_PRIVATE (greeter, GREETER_TYPE, GreeterPrivate);
    greeter->priv->read_buffer = g_malloc (HEADER_SIZE);
    greeter->priv->hints = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
}
Greeter* greeter_new ( Session session,
const gchar *  pam_service 
)

Definition at line 94 of file greeter.c.

{
    Greeter *greeter;

    greeter = g_object_new (GREETER_TYPE, NULL);
    greeter->priv->session = g_object_ref (session);
    greeter->priv->pam_service = g_strdup (pam_service);

    return greeter;
}

Here is the caller graph for this function:

static Session* greeter_real_start_authentication ( Greeter greeter,
const gchar *  username 
) [static]

Definition at line 667 of file greeter.c.

{
    return NULL;
}

Here is the caller graph for this function:

static gboolean greeter_real_start_session ( Greeter greeter,
const gchar *  session,
gboolean  is_guest 
) [static]

Definition at line 673 of file greeter.c.

{
    return FALSE;
}

Here is the caller graph for this function:

void greeter_set_allow_guest ( Greeter greeter,
gboolean  allow_guest 
)

Definition at line 106 of file greeter.c.

{
    greeter->priv->allow_guest = allow_guest;
}

Here is the caller graph for this function:

void greeter_set_hint ( Greeter greeter,
const gchar *  name,
const gchar *  value 
)

Definition at line 112 of file greeter.c.

{
    g_hash_table_insert (greeter->priv->hints, g_strdup (name), g_strdup (value));
}

Here is the caller graph for this function:

gboolean greeter_start ( Greeter greeter,
const gchar *  service,
const gchar *  username 
)

Definition at line 626 of file greeter.c.

{
    int to_greeter_pipe[2], from_greeter_pipe[2];
    gboolean result = FALSE;
    gchar *value;

    /* Create a pipe to talk with the greeter */
    if (pipe (to_greeter_pipe) != 0 || pipe (from_greeter_pipe) != 0)
    {
        g_warning ("Failed to create pipes: %s", strerror (errno));
        return FALSE;
    }
    greeter->priv->to_greeter_channel = g_io_channel_unix_new (to_greeter_pipe[1]);
    g_io_channel_set_encoding (greeter->priv->to_greeter_channel, NULL, NULL);
    greeter->priv->from_greeter_channel = g_io_channel_unix_new (from_greeter_pipe[0]);
    g_io_channel_set_encoding (greeter->priv->from_greeter_channel, NULL, NULL);
    g_io_channel_set_buffered (greeter->priv->from_greeter_channel, FALSE);
    g_io_add_watch (greeter->priv->from_greeter_channel, G_IO_IN | G_IO_HUP, read_cb, greeter);

    /* Let the greeter session know how to communicate with the daemon */
    value = g_strdup_printf ("%d", from_greeter_pipe[1]);
    session_set_env (greeter->priv->session, "LIGHTDM_TO_SERVER_FD", value);
    g_free (value);
    value = g_strdup_printf ("%d", to_greeter_pipe[0]);
    session_set_env (greeter->priv->session, "LIGHTDM_FROM_SERVER_FD", value);
    g_free (value);

    /* Don't allow the daemon end of the pipes to be accessed in child processes */
    fcntl (to_greeter_pipe[1], F_SETFD, FD_CLOEXEC);
    fcntl (from_greeter_pipe[0], F_SETFD, FD_CLOEXEC);

    result = session_start (greeter->priv->session, service, username, FALSE, FALSE);

    /* Close the session ends of the pipe */
    close (to_greeter_pipe[0]);
    close (from_greeter_pipe[1]);

    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_cancel_authentication ( Greeter greeter) [static]

Definition at line 399 of file greeter.c.

{
    /* Not in authentication */
    if (greeter->priv->authentication_session == NULL)
        return;

    g_debug ("Cancel authentication");
    reset_session (greeter);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_connect ( Greeter greeter,
const gchar *  version 
) [static]

Definition at line 186 of file greeter.c.

{
    guint8 message[MAX_MESSAGE_LENGTH];
    gsize offset = 0;
    guint32 length;
    GHashTableIter iter;
    gpointer key, value;

    g_debug ("Greeter connected version=%s", version);

    length = string_length (VERSION);
    g_hash_table_iter_init (&iter, greeter->priv->hints);
    while (g_hash_table_iter_next (&iter, &key, &value))
        length += string_length (key) + string_length (value);

    write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_CONNECTED, length, &offset);
    write_string (message, MAX_MESSAGE_LENGTH, VERSION, &offset);
    g_hash_table_iter_init (&iter, greeter->priv->hints);
    while (g_hash_table_iter_next (&iter, &key, &value))
    {
        write_string (message, MAX_MESSAGE_LENGTH, key, &offset);
        write_string (message, MAX_MESSAGE_LENGTH, value, &offset);
    }
    write_message (greeter, message, offset);

    g_signal_emit (greeter, signals[CONNECTED], 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_continue_authentication ( Greeter greeter,
gchar **  secrets 
) [static]

Definition at line 354 of file greeter.c.

{
    int messages_length;
    const struct pam_message *messages;
    struct pam_response *response;
    int i, j, n_prompts = 0;

    /* Not in authentication */
    if (greeter->priv->authentication_session == NULL)
        return;

    messages_length = session_get_messages_length (greeter->priv->authentication_session);
    messages = session_get_messages (greeter->priv->authentication_session);

    /* Check correct number of responses */
    for (i = 0; i < messages_length; i++)
    {
        int msg_style = messages[i].msg_style;
        if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
            n_prompts++;
    }
    if (g_strv_length (secrets) != n_prompts)
    {
        session_respond_error (greeter->priv->authentication_session, PAM_CONV_ERR);
        return;
    }

    g_debug ("Continue authentication");

    /* Build response */
    response = calloc (messages_length, sizeof (struct pam_response));
    for (i = 0, j = 0; i < messages_length; i++)
    {
        int msg_style = messages[i].msg_style;
        if (msg_style == PAM_PROMPT_ECHO_OFF || msg_style == PAM_PROMPT_ECHO_ON)
        {
            response[i].resp = strdup (secrets[j]); // FIXME: Need to convert from UTF-8
            j++;
        }
    }

    session_respond (greeter->priv->authentication_session, response);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_login ( Greeter greeter,
guint32  sequence_number,
const gchar *  username 
) [static]

Definition at line 308 of file greeter.c.

{
    if (username[0] == '\0')
    {
        g_debug ("Greeter start authentication");
        username = NULL;
    }
    else
        g_debug ("Greeter start authentication for %s", username);

    reset_session (greeter);

    greeter->priv->authentication_sequence_number = sequence_number;
    g_signal_emit (greeter, signals[START_AUTHENTICATION], 0, username, &greeter->priv->authentication_session);
    if (!greeter->priv->authentication_session)
    {
        send_end_authentication (greeter, sequence_number, "", PAM_USER_UNKNOWN);
        return;
    }

    g_signal_connect (G_OBJECT (greeter->priv->authentication_session), "got-messages", G_CALLBACK (pam_messages_cb), greeter);
    g_signal_connect (G_OBJECT (greeter->priv->authentication_session), "authentication-complete", G_CALLBACK (authentication_complete_cb), greeter);

    /* Run the session process */
    session_start (greeter->priv->authentication_session, greeter->priv->pam_service, username, TRUE, TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_login_as_guest ( Greeter greeter,
guint32  sequence_number 
) [static]

Definition at line 336 of file greeter.c.

{
    g_debug ("Greeter start authentication for guest account");

    reset_session (greeter);

    if (!greeter->priv->allow_guest)
    {
        g_debug ("Guest account is disabled");
        send_end_authentication (greeter, sequence_number, "", PAM_USER_UNKNOWN);
        return;
    }

    greeter->priv->guest_account_authenticated = TRUE;  
    send_end_authentication (greeter, sequence_number, "", PAM_SUCCESS);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_set_language ( Greeter greeter,
const gchar *  language 
) [static]

Definition at line 440 of file greeter.c.

{
    User *user;

    if (!greeter->priv->guest_account_authenticated && !session_get_is_authenticated (greeter->priv->authentication_session))
    {
        g_debug ("Ignoring set language request, user is not authorized");
        return;
    }

    // FIXME: Could use this
    if (greeter->priv->guest_account_authenticated)
    {
        g_debug ("Ignoring set language request for guest user");
        return;
    }

    g_debug ("Greeter sets language %s", language);
    user = session_get_user (greeter->priv->authentication_session);
    user_set_language (user, language);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void handle_start_session ( Greeter greeter,
const gchar *  session 
) [static]

Definition at line 410 of file greeter.c.

{
    gboolean result;
    guint8 message[MAX_MESSAGE_LENGTH];
    gsize offset = 0;

    if (strcmp (session, "") == 0)
        session = NULL;

    if (greeter->priv->guest_account_authenticated || session_get_is_authenticated (greeter->priv->authentication_session))
    {
        if (session)
            g_debug ("Greeter requests session %s", session);
        else
            g_debug ("Greeter requests default session");
        greeter->priv->start_session = TRUE;
        g_signal_emit (greeter, signals[START_SESSION], 0, session, &result);
    }
    else
    {
        g_debug ("Ignoring start session request, user is not authorized");
        result = FALSE;
    }

    write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_SESSION_RESULT, int_length (), &offset);
    write_int (message, MAX_MESSAGE_LENGTH, result ? 0 : 1, &offset);
    write_message (greeter, message, offset);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static guint32 int_length ( ) [static]

Definition at line 118 of file greeter.c.

{
    return 4;
}

Here is the caller graph for this function:

static void pam_messages_cb ( Session session,
Greeter greeter 
) [static]

Definition at line 215 of file greeter.c.

{
    int i;
    guint32 size;
    guint8 message[MAX_MESSAGE_LENGTH];
    const struct pam_message *messages;
    int messages_length;
    gsize offset = 0;
    int n_prompts = 0;

    messages = session_get_messages (session);
    messages_length = session_get_messages_length (session);

    /* Respond to d-bus query with messages */
    g_debug ("Prompt greeter with %d message(s)", messages_length);
    size = int_length () + string_length (session_get_username (session)) + int_length ();
    for (i = 0; i < messages_length; i++)
        size += int_length () + string_length (messages[i].msg);
  
    write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_PROMPT_AUTHENTICATION, size, &offset);
    write_int (message, MAX_MESSAGE_LENGTH, greeter->priv->authentication_sequence_number, &offset);
    write_string (message, MAX_MESSAGE_LENGTH, session_get_username (session), &offset);
    write_int (message, MAX_MESSAGE_LENGTH, messages_length, &offset);
    for (i = 0; i < messages_length; i++)
    {
        write_int (message, MAX_MESSAGE_LENGTH, messages[i].msg_style, &offset);
        write_string (message, MAX_MESSAGE_LENGTH, messages[i].msg, &offset);

        if (messages[i].msg_style == PAM_PROMPT_ECHO_OFF || messages[i].msg_style == PAM_PROMPT_ECHO_ON)
            n_prompts++;
    }
    write_message (greeter, message, offset);

    /* Continue immediately if nothing to respond with */
    // FIXME: Should probably give the greeter a chance to ack the message
    if (n_prompts == 0)
    {
        struct pam_response *response;
        response = calloc (messages_length, sizeof (struct pam_response));
        session_respond (greeter->priv->authentication_session, response);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gboolean read_cb ( GIOChannel *  source,
GIOCondition  condition,
gpointer  data 
) [static]

Definition at line 500 of file greeter.c.

{
    Greeter *greeter = data;
    gsize n_to_read, n_read, offset;
    GIOStatus status;
    int id, n_secrets, i;
    guint32 sequence_number;
    gchar *version, *username, *session_name, *language;
    gchar **secrets;
    GError *error = NULL;

    if (condition == G_IO_HUP)
    {
        g_debug ("Greeter closed communication channel");
        return FALSE;
    }
  
    n_to_read = HEADER_SIZE;
    if (greeter->priv->n_read >= HEADER_SIZE)
    {
        offset = int_length ();
        n_to_read += read_int (greeter, &offset);
    }

    status = g_io_channel_read_chars (greeter->priv->from_greeter_channel,
                                      (gchar *) greeter->priv->read_buffer + greeter->priv->n_read,
                                      n_to_read - greeter->priv->n_read,
                                      &n_read,
                                      &error);
    if (error)
        g_warning ("Error reading from greeter: %s", error->message);
    g_clear_error (&error);
    if (status != G_IO_STATUS_NORMAL)
        return TRUE;

    greeter->priv->n_read += n_read;
    if (greeter->priv->n_read != n_to_read)
        return TRUE;

    /* If have header, rerun for content */
    if (greeter->priv->n_read == HEADER_SIZE)
    {
        gsize offset = int_length ();
        n_to_read = read_int (greeter, &offset);
        if (n_to_read > 0)
        {
            greeter->priv->read_buffer = g_realloc (greeter->priv->read_buffer, HEADER_SIZE + n_to_read);
            read_cb (source, condition, greeter);
            return TRUE;
        }
    }
  
    offset = 0;
    id = read_int (greeter, &offset);
    read_int (greeter, &offset);
    switch (id)
    {
    case GREETER_MESSAGE_CONNECT:
        version = read_string (greeter, &offset);
        handle_connect (greeter, version);
        g_free (version);
        break;
    case GREETER_MESSAGE_AUTHENTICATE:
        sequence_number = read_int (greeter, &offset);
        username = read_string (greeter, &offset);
        handle_login (greeter, sequence_number, username);
        g_free (username);
        break;
    case GREETER_MESSAGE_AUTHENTICATE_AS_GUEST:
        sequence_number = read_int (greeter, &offset);
        handle_login_as_guest (greeter, sequence_number);
        break;
    case GREETER_MESSAGE_CONTINUE_AUTHENTICATION:
        n_secrets = read_int (greeter, &offset);
        secrets = g_malloc (sizeof (gchar *) * (n_secrets + 1));
        for (i = 0; i < n_secrets; i++)
            secrets[i] = read_string (greeter, &offset);
        secrets[i] = NULL;
        handle_continue_authentication (greeter, secrets);
        g_strfreev (secrets);
        break;
    case GREETER_MESSAGE_CANCEL_AUTHENTICATION:
        handle_cancel_authentication (greeter);
        break;
    case GREETER_MESSAGE_START_SESSION:
        session_name = read_string (greeter, &offset);
        handle_start_session (greeter, session_name);
        g_free (session_name);
        break;
    case GREETER_MESSAGE_SET_LANGUAGE:
        language = read_string (greeter, &offset);
        handle_set_language (greeter, language);
        g_free (language);
        break;
    default:
        g_warning ("Unknown message from greeter: %d", id);
        break;
    }

    greeter->priv->n_read = 0;

    return TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static guint32 read_int ( Greeter greeter,
gsize *  offset 
) [static]

Definition at line 463 of file greeter.c.

{
    guint32 value;
    guint8 *buffer;
    if (greeter->priv->n_read - *offset < sizeof (guint32))
    {
        g_warning ("Not enough space for int, need %zu, got %zu", sizeof (guint32), greeter->priv->n_read - *offset);
        return 0;
    }
    buffer = greeter->priv->read_buffer + *offset;
    value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
    *offset += int_length ();
    return value;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gchar* read_string ( Greeter greeter,
gsize *  offset 
) [static]

Definition at line 479 of file greeter.c.

{
    guint32 length;
    gchar *value;

    length = read_int (greeter, offset);
    if (greeter->priv->n_read - *offset < length)
    {
        g_warning ("Not enough space for string, need %u, got %zu", length, greeter->priv->n_read - *offset);
        return g_strdup ("");
    }

    value = g_malloc (sizeof (gchar *) * (length + 1));
    memcpy (value, greeter->priv->read_buffer + *offset, length);
    value[length] = '\0';
    *offset += length;

    return value;
}

Here is the call graph for this function:

static void reset_session ( Greeter greeter) [static]

Definition at line 294 of file greeter.c.

{
    if (greeter->priv->authentication_session)
    {
        g_signal_handlers_disconnect_matched (greeter->priv->authentication_session, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, greeter);
        session_stop (greeter->priv->authentication_session);
        g_object_unref (greeter->priv->authentication_session);
        greeter->priv->authentication_session = NULL;
    }

    greeter->priv->guest_account_authenticated = FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void send_end_authentication ( Greeter greeter,
guint32  sequence_number,
const gchar *  username,
int  result 
) [static]

Definition at line 259 of file greeter.c.

{
    guint8 message[MAX_MESSAGE_LENGTH];
    gsize offset = 0;

    write_header (message, MAX_MESSAGE_LENGTH, SERVER_MESSAGE_END_AUTHENTICATION, int_length () + string_length (username) + int_length (), &offset);
    write_int (message, MAX_MESSAGE_LENGTH, sequence_number, &offset);
    write_string (message, MAX_MESSAGE_LENGTH, username, &offset);
    write_int (message, MAX_MESSAGE_LENGTH, result, &offset);
    write_message (greeter, message, offset); 
}

Here is the call graph for this function:

Here is the caller graph for this function:

static guint32 string_length ( const gchar *  value) [static]

Definition at line 177 of file greeter.c.

{
    if (value == NULL)
        return int_length ();
    else
        return int_length () + strlen (value);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void write_header ( guint8 *  buffer,
gint  buffer_length,
guint32  id,
guint32  length,
gsize *  offset 
) [static]

Definition at line 170 of file greeter.c.

{
    write_int (buffer, buffer_length, id, offset);
    write_int (buffer, buffer_length, length, offset);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void write_int ( guint8 *  buffer,
gint  buffer_length,
guint32  value,
gsize *  offset 
) [static]

Definition at line 139 of file greeter.c.

{
    if (*offset + 4 >= buffer_length)
        return;
    buffer[*offset] = value >> 24;
    buffer[*offset+1] = (value >> 16) & 0xFF;
    buffer[*offset+2] = (value >> 8) & 0xFF;
    buffer[*offset+3] = value & 0xFF;
    *offset += 4;
}

Here is the caller graph for this function:

static void write_message ( Greeter greeter,
guint8 *  message,
gsize  message_length 
) [static]

Definition at line 127 of file greeter.c.

{
    GError *error = NULL;

    g_io_channel_write_chars (greeter->priv->to_greeter_channel, (gchar *) message, message_length, NULL, &error);
    if (error)
        g_warning ("Error writing to greeter: %s", error->message);
    g_clear_error (&error);
    g_io_channel_flush (greeter->priv->to_greeter_channel, NULL);
}

Here is the caller graph for this function:

static void write_string ( guint8 *  buffer,
gint  buffer_length,
const gchar *  value,
gsize *  offset 
) [static]

Definition at line 151 of file greeter.c.

{
    gint length;
  
    if (value)
        length = strlen (value);
    else
        length = 0;
    write_int (buffer, buffer_length, length, offset);
    if (*offset + length >= buffer_length)
        return;
    if (length > 0)
    {
        memcpy (buffer + *offset, value, length);
        *offset += length;
    }
}

Here is the call graph for this function:


Variable Documentation

guint signals[LAST_SIGNAL] = { 0 } [static]

Definition at line 28 of file greeter.c.