[gtk+/gtk-3-8] broadway: Add support for password authentication
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-3-8] broadway: Add support for password authentication
- Date: Fri, 29 Mar 2013 13:03:51 +0000 (UTC)
commit 1045dca1486e9eed13a1361b1317b9742bf03dd0
Author: Alexander Larsson <alexl redhat com>
Date: Thu Mar 28 22:57:33 2013 +0100
broadway: Add support for password authentication
docs/reference/gtk/broadwayd.xml | 9 +++
gdk/broadway/Makefile.am | 2 +-
gdk/broadway/broadway-output.c | 25 +++++++
gdk/broadway/broadway-output.h | 5 ++
gdk/broadway/broadway-protocol.h | 3 +
gdk/broadway/broadway-server.c | 138 ++++++++++++++++++++++++++++----------
gdk/broadway/broadway.js | 70 ++++++++++++++++---
7 files changed, 202 insertions(+), 50 deletions(-)
---
diff --git a/docs/reference/gtk/broadwayd.xml b/docs/reference/gtk/broadwayd.xml
index be41c1a..14f7064 100644
--- a/docs/reference/gtk/broadwayd.xml
+++ b/docs/reference/gtk/broadwayd.xml
@@ -54,6 +54,15 @@ Start your applications like this:
BROADWAY_DISPLAY=:5 gtk3-demo
</programlisting>
+You can add password protection for your session by creating a file in
+<filename>$XDG_CONFIG_HOME/broadway.passwd</filename> or <filename>$HOME/.config/broadway.passwd</filename>
+with a crypt(3) style password hash.
+
+A simple way to generate it is with openssl:
+<programlisting>
+openssl passwd -1 > ~/.config/broadway.passwd
+</programlisting>
+
</para>
</refsect1>
diff --git a/gdk/broadway/Makefile.am b/gdk/broadway/Makefile.am
index a062240..dd4b189 100644
--- a/gdk/broadway/Makefile.am
+++ b/gdk/broadway/Makefile.am
@@ -83,7 +83,7 @@ broadwayd_SOURCES = \
broadway-output.h \
broadway-output.c
-broadwayd_LDADD = $(GDK_DEP_LIBS) -lrt
+broadwayd_LDADD = $(GDK_DEP_LIBS) -lrt -lcrypt
MAINTAINERCLEANFILES = $(broadway_built_sources)
EXTRA_DIST += $(broadway_built_sources)
diff --git a/gdk/broadway/broadway-output.c b/gdk/broadway/broadway-output.c
index 3e1fb1e..774cca3 100644
--- a/gdk/broadway/broadway-output.c
+++ b/gdk/broadway/broadway-output.c
@@ -317,6 +317,13 @@ broadway_output_get_next_serial (BroadwayOutput *output)
return output->serial;
}
+void
+broadway_output_set_next_serial (BroadwayOutput *output,
+ guint32 serial)
+{
+ output->serial = serial;
+}
+
/************************************************************************
* Core rendering operations *
@@ -472,6 +479,24 @@ broadway_output_new_surface(BroadwayOutput *output,
}
void
+broadway_output_request_auth (BroadwayOutput *output)
+{
+ write_header (output, BROADWAY_OP_REQUEST_AUTH);
+}
+
+void
+broadway_output_auth_ok (BroadwayOutput *output)
+{
+ write_header (output, BROADWAY_OP_AUTH_OK);
+}
+
+void
+broadway_output_disconnected (BroadwayOutput *output)
+{
+ write_header (output, BROADWAY_OP_DISCONNECTED);
+}
+
+void
broadway_output_show_surface(BroadwayOutput *output, int id)
{
write_header (output, BROADWAY_OP_SHOW_SURFACE);
diff --git a/gdk/broadway/broadway-output.h b/gdk/broadway/broadway-output.h
index 02436f4..ea57c7e 100644
--- a/gdk/broadway/broadway-output.h
+++ b/gdk/broadway/broadway-output.h
@@ -23,6 +23,8 @@ BroadwayOutput *broadway_output_new (GOutputStream *out,
void broadway_output_free (BroadwayOutput *output);
int broadway_output_flush (BroadwayOutput *output);
int broadway_output_has_error (BroadwayOutput *output);
+void broadway_output_set_next_serial (BroadwayOutput *output,
+ guint32 serial);
guint32 broadway_output_get_next_serial (BroadwayOutput *output);
void broadway_output_new_surface (BroadwayOutput *output,
int id,
@@ -31,6 +33,9 @@ void broadway_output_new_surface (BroadwayOutput *output,
int w,
int h,
gboolean is_temp);
+void broadway_output_request_auth (BroadwayOutput *output);
+void broadway_output_auth_ok (BroadwayOutput *output);
+void broadway_output_disconnected (BroadwayOutput *output);
void broadway_output_show_surface (BroadwayOutput *output,
int id);
void broadway_output_hide_surface (BroadwayOutput *output,
diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h
index c098fdf..fe7a8a4 100644
--- a/gdk/broadway/broadway-protocol.h
+++ b/gdk/broadway/broadway-protocol.h
@@ -36,6 +36,9 @@ typedef enum {
BROADWAY_OP_SET_TRANSIENT_FOR = 'p',
BROADWAY_OP_PUT_RGB = 'i',
BROADWAY_OP_FLUSH = 'f',
+ BROADWAY_OP_REQUEST_AUTH = 'l',
+ BROADWAY_OP_AUTH_OK = 'L',
+ BROADWAY_OP_DISCONNECTED = 'D',
} BroadwayOpType;
typedef struct {
diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c
index 77dd894..5b6bb96 100644
--- a/gdk/broadway/broadway-server.c
+++ b/gdk/broadway/broadway-server.c
@@ -2,6 +2,8 @@
#include "broadway-output.h"
+#define _XOPEN_SOURCE /* for crypt */
+
#include <glib.h>
#include <glib/gprintf.h>
#include "gdktypes.h"
@@ -9,6 +11,7 @@
#include <string.h>
#include <errno.h>
#include <unistd.h>
+#include <crypt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -19,6 +22,7 @@ typedef struct BroadwayWindow BroadwayWindow;
struct _BroadwayServer {
GObject parent_instance;
+ char *password;
char *address;
int port;
GSocketService *service;
@@ -69,6 +73,7 @@ typedef struct HttpRequest {
struct BroadwayInput {
BroadwayServer *server;
+ BroadwayOutput *output;
GSocketConnection *connection;
GByteArray *buffer;
GSource *source;
@@ -76,6 +81,7 @@ struct BroadwayInput {
gint64 time_base;
gboolean proto_v7_plus;
gboolean binary;
+ gboolean active;
};
struct BroadwayWindow {
@@ -100,6 +106,8 @@ static void
broadway_server_init (BroadwayServer *server)
{
BroadwayWindow *root;
+ char *passwd_file;
+ char *password, *p;
server->service = g_socket_service_new ();
server->pointer_grab_window_id = -1;
@@ -108,6 +116,22 @@ broadway_server_init (BroadwayServer *server)
server->id_ht = g_hash_table_new (NULL, NULL);
server->id_counter = 0;
+ passwd_file = g_build_filename (g_get_user_config_dir (),
+ "broadway.passwd", NULL);
+
+ if (g_file_get_contents (passwd_file,
+ &password, NULL, NULL))
+ {
+ p = strchr (password, '\n');
+ if (p)
+ *p = 0;
+ g_strstrip (password);
+ if (strlen (password) > 3)
+ server->password = password;
+ else
+ g_free (password);
+ }
+
root = g_new0 (BroadwayWindow, 1);
root->id = server->id_counter++;
root->width = 1024;
@@ -139,7 +163,7 @@ broadway_server_class_init (BroadwayServerClass * class)
object_class->finalize = broadway_server_finalize;
}
-static void start_output (HttpRequest *request, gboolean proto_v7_plus, gboolean binary);
+static void start (BroadwayInput *input);
static void
http_request_free (HttpRequest *request)
@@ -349,6 +373,14 @@ update_future_pointer_info (BroadwayServer *server, BroadwayInputPointerMsg *dat
server->future_mouse_in_toplevel = data->mouse_window_id;
}
+static gboolean
+verify_password (BroadwayServer *server, const char *password)
+{
+ char *hash;
+ hash = crypt (password, server->password);
+ return strcmp (hash, server->password) == 0;
+}
+
static void
parse_input_message (BroadwayInput *input, const char *message)
{
@@ -357,6 +389,22 @@ parse_input_message (BroadwayInput *input, const char *message)
char *p;
gint64 time_;
+ if (!input->active)
+ {
+ /* The input has not been activated yet, handle auth/start */
+
+ if (message[0] != 'l' ||
+ !verify_password (server, message+1))
+ {
+ broadway_output_request_auth (input->output);
+ broadway_output_flush (input->output);
+ }
+ else
+ start (input);
+
+ return;
+ }
+
memset (&msg, 0, sizeof (msg));
p = (char *)message;
@@ -570,7 +618,7 @@ parse_input (BroadwayInput *input)
}
break;
case BROADWAY_WS_CNX_PING:
- broadway_output_pong (server->output);
+ broadway_output_pong (input->output);
break;
case BROADWAY_WS_CNX_PONG:
break; /* we never send pings, but tolerate pongs */
@@ -596,7 +644,8 @@ parse_input (BroadwayInput *input)
if (buf[0] != 0)
{
- server->input = NULL;
+ if (server->input == input)
+ server->input = NULL;
broadway_input_free (input);
return;
}
@@ -613,7 +662,8 @@ parse_input (BroadwayInput *input)
if (len > 0 && buf[0] != 0)
{
- server->input = NULL;
+ if (server->input == input)
+ server->input = NULL;
broadway_input_free (input);
break;
}
@@ -640,19 +690,16 @@ queue_process_input_at_idle (BroadwayServer *server)
}
static void
-broadway_server_read_all_input_nonblocking (BroadwayServer *server)
+broadway_server_read_all_input_nonblocking (BroadwayInput *input)
{
GInputStream *in;
gssize res;
guint8 buffer[1024];
GError *error;
- BroadwayInput *input;
- if (server->input == NULL)
+ if (input == NULL)
return;
- input = server->input;
-
in = g_io_stream_get_input_stream (G_IO_STREAM (input->connection));
error = NULL;
@@ -668,7 +715,8 @@ broadway_server_read_all_input_nonblocking (BroadwayServer *server)
return;
}
- server->input = NULL;
+ if (input->server->input == input)
+ input->server->input = NULL;
broadway_input_free (input);
if (res < 0)
{
@@ -686,7 +734,7 @@ broadway_server_read_all_input_nonblocking (BroadwayServer *server)
static void
broadway_server_consume_all_input (BroadwayServer *server)
{
- broadway_server_read_all_input_nonblocking (server);
+ broadway_server_read_all_input_nonblocking (server->input);
/* Since we're parsing input but not processing the resulting messages
we might not get a readable callback on the stream, so queue an idle to
@@ -701,9 +749,10 @@ input_data_cb (GObject *stream,
{
BroadwayServer *server = input->server;
- broadway_server_read_all_input_nonblocking (server);
+ broadway_server_read_all_input_nonblocking (input);
- process_input_messages (server);
+ if (input->active)
+ process_input_messages (server);
return TRUE;
}
@@ -878,15 +927,14 @@ start_input (HttpRequest *request, gboolean binary)
gsize len;
GChecksum *checksum;
char *origin, *host;
- BroadwayServer *server;
BroadwayInput *input;
const void *data_buffer;
gsize data_buffer_size;
GInputStream *in;
char *key_v7;
gboolean proto_v7_plus;
-
- server = request->server;
+ GSocket *socket;
+ int flag = 1;
#ifdef DEBUG_WEBSOCKETS
g_print ("incoming request:\n%s\n", request->request->str);
@@ -1033,15 +1081,11 @@ start_input (HttpRequest *request, gboolean binary)
proto_v7_plus = FALSE;
}
-
- if (server->input != NULL)
- {
- broadway_input_free (server->input);
- server->input = NULL;
- }
+ socket = g_socket_connection_get_socket (request->connection);
+ setsockopt (g_socket_get_fd (socket), IPPROTO_TCP,
+ TCP_NODELAY, (char *) &flag, sizeof(int));
input = g_new0 (BroadwayInput, 1);
-
input->server = request->server;
input->connection = g_object_ref (request->connection);
input->proto_v7_plus = proto_v7_plus;
@@ -1051,9 +1095,9 @@ start_input (HttpRequest *request, gboolean binary)
input->buffer = g_byte_array_sized_new (data_buffer_size);
g_byte_array_append (input->buffer, data_buffer, data_buffer_size);
- server->input = input;
-
- start_output (request, proto_v7_plus, binary);
+ input->output =
+ broadway_output_new (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+ 0, proto_v7_plus, binary);
/* This will free and close the data input stream, but we got all the buffered content already */
http_request_free (request);
@@ -1063,35 +1107,53 @@ start_input (HttpRequest *request, gboolean binary)
g_source_set_callback (input->source, (GSourceFunc)input_data_cb, input, NULL);
g_source_attach (input->source, NULL);
+ if (input->server->password)
+ {
+ broadway_output_request_auth (input->output);
+ broadway_output_flush (input->output);
+ }
+ else
+ start (input);
+
/* Process any data in the pipe already */
parse_input (input);
- process_input_messages (server);
g_strfreev (lines);
}
static void
-start_output (HttpRequest *request, gboolean proto_v7_plus, gboolean binary)
+start (BroadwayInput *input)
{
- GSocket *socket;
BroadwayServer *server;
- int flag = 1;
- socket = g_socket_connection_get_socket (request->connection);
- setsockopt(g_socket_get_fd (socket), IPPROTO_TCP,
- TCP_NODELAY, (char *) &flag, sizeof(int));
+ input->active = TRUE;
+
+ server = BROADWAY_SERVER (input->server);
+
+ if (server->output)
+ {
+ broadway_output_disconnected (server->output);
+ broadway_output_flush (server->output);
+ }
+
+ if (server->input != NULL)
+ {
+ broadway_input_free (server->input);
+ server->input = NULL;
+ }
- server = BROADWAY_SERVER (request->server);
+ server->input = input;
if (server->output)
{
server->saved_serial = broadway_output_get_next_serial (server->output);
broadway_output_free (server->output);
}
+ server->output = input->output;
- server->output =
- broadway_output_new (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
- server->saved_serial, proto_v7_plus, binary);
+ broadway_output_set_next_serial (server->output, server->saved_serial);
+ broadway_output_auth_ok (server->output);
+ broadway_output_flush (server->output);
broadway_server_resync_windows (server);
@@ -1099,6 +1161,8 @@ start_output (HttpRequest *request, gboolean proto_v7_plus, gboolean binary)
broadway_output_grab_pointer (server->output,
server->pointer_grab_window_id,
server->pointer_grab_owner_events);
+
+ process_input_messages (server);
}
static void
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index fb4cffe..3f51e65 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -537,6 +537,21 @@ function handleCommands(cmd)
var command = cmd.get_char();
lastSerial = cmd.get_32();
switch (command) {
+ case 'l':
+ login ();
+ break;
+
+ case 'L':
+ if (loginDiv != null)
+ loginDiv.parentNode.removeChild(loginDiv);
+ start ();
+ break;
+
+ case 'D':
+ alert ("disconnected");
+ inputSocket = null;
+ break;
+
case 's': // create new surface
id = cmd.get_16();
x = cmd.get_16s();
@@ -2625,6 +2640,47 @@ function newWS(loc) {
return ws;
}
+function start()
+{
+ setupDocument(document);
+
+ var w, h;
+ w = window.innerWidth;
+ h = window.innerHeight;
+ window.onresize = function(ev) {
+ var w, h;
+ w = window.innerWidth;
+ h = window.innerHeight;
+ sendInput ("d", [w, h]);
+ };
+ sendInput ("d", [w, h]);
+}
+
+var loginDiv = null;
+function login()
+{
+ if (loginDiv == null) {
+ var div = document.createElement('div');
+ document.body.appendChild(div);
+ div.innerHTML = "Please enter password<br>";
+ div.style.marginTop = "40px";
+ div.style.textAlign = "center";
+
+ var input = document.createElement("input");
+ input.setAttribute("type", "password");
+ div.appendChild(input);
+ input.onkeyup = function(e) {
+ if (e.keyCode === 13) {
+ inputSocket.send ("l" + input.value);
+ }
+ }
+ input.focus ();
+ loginDiv = div;
+ } else {
+ alert ("Wrong password");
+ }
+}
+
function connect()
{
var url = window.location.toString();
@@ -2646,23 +2702,13 @@ function connect()
ws.onopen = function() {
inputSocket = ws;
- var w, h;
- w = window.innerWidth;
- h = window.innerHeight;
- window.onresize = function(ev) {
- var w, h;
- w = window.innerWidth;
- h = window.innerHeight;
- sendInput ("d", [w, h]);
- };
- sendInput ("d", [w, h]);
};
ws.onclose = function() {
+ if (inputSocket != null)
+ alert ("disconnected");
inputSocket = null;
};
ws.onmessage = function(event) {
handleMessage(event.data);
};
-
- setupDocument(document);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]