64
72
xdmcp_server_set_port (XDMCPServer *server, guint port)
66
g_return_if_fail (server != NULL);
67
74
server->priv->port = port;
71
78
xdmcp_server_get_port (XDMCPServer *server)
73
g_return_val_if_fail (server != NULL, 0);
74
80
return server->priv->port;
78
84
xdmcp_server_set_hostname (XDMCPServer *server, const gchar *hostname)
80
g_return_if_fail (server != NULL);
82
86
g_free (server->priv->hostname);
83
87
server->priv->hostname = g_strdup (hostname);
103
104
xdmcp_server_get_status (XDMCPServer *server)
105
g_return_val_if_fail (server != NULL, NULL);
106
106
return server->priv->status;
110
xdmcp_server_set_key (XDMCPServer *server, const gchar *key)
112
g_return_if_fail (server != NULL);
113
g_free (server->priv->key);
114
server->priv->key = g_strdup (key);
110
xdmcp_server_set_authentication (XDMCPServer *server, const gchar *name, const guchar *data, gsize data_length)
112
g_free (server->priv->authentication_name);
113
server->priv->authentication_name = g_strdup (name);
114
g_free (server->priv->authentication_data);
115
server->priv->authentication_data = g_malloc (data_length);
116
server->priv->authentication_data_length = data_length;
117
memcpy (server->priv->authentication_data, data, data_length);
121
xdmcp_server_get_authentication_name (XDMCPServer *server)
123
return server->priv->authentication_name;
127
xdmcp_server_get_authentication_data (XDMCPServer *server)
129
return server->priv->authentication_data;
133
xdmcp_server_get_authentication_data_length (XDMCPServer *server)
135
return server->priv->authentication_data_length;
139
xdmcp_server_set_authorization (XDMCPServer *server, const gchar *name, const guchar *data, gsize data_length)
141
g_free (server->priv->authorization_name);
142
server->priv->authorization_name = g_strdup (name);
143
g_free (server->priv->authorization_data);
144
server->priv->authorization_data = g_malloc (data_length);
145
server->priv->authorization_data_length = data_length;
146
memcpy (server->priv->authorization_data, data, data_length);
150
xdmcp_server_get_authorization_name (XDMCPServer *server)
152
return server->priv->authorization_name;
156
xdmcp_server_get_authorization_data (XDMCPServer *server)
158
return server->priv->authorization_data;
162
xdmcp_server_get_authorization_data_length (XDMCPServer *server)
164
return server->priv->authorization_data_length;
163
213
GError *error = NULL;
165
g_socket_send_to (socket, address, (gchar *) data, n_written, NULL, &error);
215
if (g_socket_send_to (socket, address, (gchar *) data, n_written, NULL, &error) < 0)
167
216
g_warning ("Error sending packet: %s", error->message);
168
218
g_clear_error (&error);
173
get_authentication_name (XDMCPServer *server)
175
if (server->priv->key)
176
return "XDM-AUTHENTICATION-1";
182
223
handle_query (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
184
225
XDMCPPacket *response;
186
gchar *authentication_name = NULL;
227
gboolean match_authentication = FALSE;
188
229
/* If no authentication requested and we are configured for none then allow */
189
if (packet->Query.authentication_names[0] == NULL && server->priv->key == NULL)
190
authentication_name = "";
230
if (packet->Query.authentication_names[0] == NULL && strcmp (server->priv->authentication_name, "") == 0)
231
match_authentication = TRUE;
192
233
for (i = packet->Query.authentication_names; *i; i++)
194
if (strcmp (*i, get_authentication_name (server)) == 0 && server->priv->key != NULL)
235
if (strcmp (*i, server->priv->authentication_name) == 0)
196
authentication_name = *i;
237
match_authentication = TRUE;
201
if (authentication_name)
242
if (match_authentication)
203
244
response = xdmcp_packet_alloc (XDMCP_Willing);
204
response->Willing.authentication_name = g_strdup (authentication_name);
245
response->Willing.authentication_name = g_strdup (server->priv->authentication_name);
205
246
response->Willing.hostname = g_strdup (server->priv->hostname);
206
247
response->Willing.status = g_strdup (server->priv->status);
210
251
response = xdmcp_packet_alloc (XDMCP_Unwilling);
211
response->Unwilling.hostname = g_strdup (server->priv->hostname);
212
if (server->priv->key)
213
response->Unwilling.status = g_strdup_printf ("No matching authentication, server requires %s", get_authentication_name (server));
215
response->Unwilling.status = g_strdup ("Server does not support authentication");
252
response->Willing.hostname = g_strdup (server->priv->hostname);
253
response->Willing.status = g_strdup (server->priv->status);
218
256
send_packet (socket, address, response);
220
258
xdmcp_packet_free (response);
226
if (c >= '0' && c <= '9')
228
if (c >= 'a' && c <= 'f')
230
if (c >= 'A' && c <= 'F')
236
decode_key (const gchar *key, guint8 *data)
240
memset (data, 0, sizeof (data));
241
if (strncmp (key, "0x", 2) == 0 || strncmp (key, "0X", 2) == 0)
243
for (i = 0; i < 8; i++)
245
if (key[i*2] == '\0')
247
data[i] |= atox (key[i*2]) << 8;
248
if (key[i*2+1] == '\0')
250
data[i] |= atox (key[i*2+1]);
255
for (i = 1; i < 8 && key[i-1]; i++)
261
262
handle_request (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
264
265
XDMCPPacket *response;
265
266
XDMCPSession *session;
266
guint8 *authentication_data = NULL;
267
guchar *authentication_data = NULL;
267
268
gsize authentication_data_length = 0;
268
269
gboolean match_authorization = FALSE;
269
gchar *authorization_name;
270
guint8 *authorization_data = NULL;
270
guchar *authorization_data = NULL;
271
271
gsize authorization_data_length = 0;
272
guint8 *session_authorization_data = NULL;
272
guchar *session_authorization_data = NULL;
273
273
gsize session_authorization_data_length = 0;
276
GInetAddress *xserver_address = NULL;
277
gchar *display_number;
275
GInetAddress *address4 = NULL, *address6 = NULL;
278
276
XdmAuthKeyRec rho;
280
/* Try and find an IPv6 address */
281
for (i = 0; i < packet->Request.n_connections; i++)
283
XDMCPConnection *connection = &packet->Request.connections[i];
284
if (connection->type == XAUTH_FAMILY_INTERNET6 && connection->address.length == 16)
286
family = connection->type;
287
xserver_address = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV6);
289
/* We can't use link-local addresses, as we need to know what interface it is on */
290
if (g_inet_address_get_is_link_local (xserver_address))
292
g_object_unref (xserver_address);
293
xserver_address = NULL;
300
/* If no IPv6 address, then try and find an IPv4 one */
301
if (!xserver_address)
303
for (i = 0; i < packet->Request.n_connections; i++)
305
XDMCPConnection *connection = &packet->Request.connections[i];
306
if (connection->type == XAUTH_FAMILY_INTERNET && connection->address.length == 4)
308
family = connection->type;
309
xserver_address = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV4);
315
/* Decline if haven't got an address we can connect on */
316
if (!xserver_address)
318
response = xdmcp_packet_alloc (XDMCP_Decline);
319
response->Decline.status = g_strdup ("No valid address found");
320
response->Decline.authentication_name = g_strdup (packet->Request.authentication_name);
321
response->Decline.authentication_data.data = authentication_data;
322
response->Decline.authentication_data.length = authentication_data_length;
323
send_packet (socket, address, response);
324
xdmcp_packet_free (response);
328
278
/* Must be using our authentication scheme */
329
if (strcmp (packet->Request.authentication_name, get_authentication_name (server)) != 0)
279
if (strcmp (packet->Request.authentication_name, server->priv->authentication_name) != 0)
331
281
response = xdmcp_packet_alloc (XDMCP_Decline);
332
if (server->priv->key)
333
response->Decline.status = g_strdup_printf ("Server only supports %s authentication", get_authentication_name (server));
282
if (strcmp (server->priv->authentication_name, "") == 0)
335
283
response->Decline.status = g_strdup ("Server does not support authentication");
285
response->Decline.status = g_strdup_printf ("Server only supports %s authentication", server->priv->authentication_name);
336
286
response->Decline.authentication_name = g_strdup ("");
337
287
send_packet (socket, address, response);
338
288
xdmcp_packet_free (response);
342
292
/* Perform requested authentication */
343
if (server->priv->key)
293
if (strcmp (server->priv->authentication_name, "XDM-AUTHENTICATION-1") == 0)
345
guint8 input[8], key[8];
295
guchar input[8], key[8];
347
297
memset (input, 0, 8);
348
298
memcpy (input, packet->Request.authentication_data.data, packet->Request.authentication_data.length > 8 ? 8 : packet->Request.authentication_data.length);
351
decode_key (server->priv->key, key);
302
memcpy (key, server->priv->authentication_data, server->priv->authentication_data_length > 8 ? 8 : server->priv->authentication_data_length);
353
304
/* Decode message from server */
354
authentication_data = g_malloc (sizeof (guint8) * 8);
305
authentication_data = g_malloc (sizeof (guchar) * 8);
355
306
authentication_data_length = 8;
357
308
XdmcpUnwrap (input, key, rho.data, authentication_data_length);
358
309
XdmcpIncrementKey (&rho);
359
310
XdmcpWrap (rho.data, key, authentication_data, authentication_data_length);
361
authorization_name = g_strdup ("XDM-AUTHORIZATION-1");
364
authorization_name = g_strdup ("MIT-MAGIC-COOKIE-1");
366
313
/* Check if they support our authorization */
367
314
for (j = packet->Request.authorization_names; *j; j++)
369
if (strcmp (*j, authorization_name) == 0)
316
if (strcmp (*j, server->priv->authorization_name) == 0)
371
318
match_authorization = TRUE;
376
/* Decline if don't support out authorization */
377
323
if (!match_authorization)
379
325
response = xdmcp_packet_alloc (XDMCP_Decline);
380
response->Decline.status = g_strdup_printf ("Server requires %s authorization", authorization_name);
381
g_free (authorization_name);
326
if (strcmp (server->priv->authorization_name, "") == 0)
327
response->Decline.status = g_strdup ("Server does not support authorization");
329
response->Decline.status = g_strdup_printf ("Server only supports %s authorization", server->priv->authorization_name);
382
330
response->Decline.authentication_name = g_strdup (packet->Request.authentication_name);
383
331
response->Decline.authentication_data.data = authentication_data;
384
332
response->Decline.authentication_data.length = authentication_data_length;
390
338
/* Perform requested authorization */
391
if (server->priv->key)
339
if (strcmp (server->priv->authorization_name, "MIT-MAGIC-COOKIE-1") == 0)
341
/* Data is the cookie */
342
authorization_data = g_malloc (sizeof (guchar) * server->priv->authorization_data_length);
343
memcpy (authorization_data, server->priv->authorization_data, server->priv->authorization_data_length);
344
authorization_data_length = server->priv->authorization_data_length;
346
else if (strcmp (server->priv->authorization_name, "XDM-AUTHORIZATION-1") == 0)
394
guint8 key[8], session_key[8];
349
guchar key[8], session_key[8];
397
decode_key (server->priv->key, key);
353
memcpy (key, server->priv->authentication_data, server->priv->authentication_data_length > 8 ? 8 : server->priv->authentication_data_length);
399
355
/* Generate a private session key */
400
356
// FIXME: Pick a good DES key?
414
370
memcpy (session_authorization_data, rho.data, 8);
415
371
memcpy (session_authorization_data + 8, session_key, 8);
421
/* Data is the cookie */
422
auth = xauth_new_cookie (XAUTH_FAMILY_WILD, NULL, 0, "");
423
authorization_data = xauth_copy_authorization_data (auth);
424
authorization_data_length = xauth_get_authorization_data_length (auth);
425
session_authorization_data = xauth_copy_authorization_data (auth);
426
session_authorization_data_length = xauth_get_authorization_data_length (auth);
428
g_object_unref (auth);
374
for (i = 0; i < packet->Request.n_connections; i++)
376
XDMCPConnection *connection;
378
connection = &packet->Request.connections[i];
379
switch (connection->type)
382
if (connection->address.length == 4)
383
address4 = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV4);
385
case FamilyInternet6:
386
if (connection->address.length == 16)
387
address6 = g_inet_address_new_from_bytes (connection->address.data, G_SOCKET_FAMILY_IPV6);
392
if (!address4) // FIXME: && !address6)
394
response = xdmcp_packet_alloc (XDMCP_Decline);
395
response->Decline.status = g_strdup ("No valid address found");
396
response->Decline.authentication_name = g_strdup (packet->Request.authentication_name);
397
response->Decline.authentication_data.data = authentication_data;
398
response->Decline.authentication_data.length = authentication_data_length;
399
send_packet (socket, address, response);
400
xdmcp_packet_free (response);
431
404
session = add_session (server);
432
session->priv->address = xserver_address;
433
session->priv->display_number = packet->Request.display_number;
434
display_number = g_strdup_printf ("%d", packet->Request.display_number);
436
/* We need to check if this is the loopback address and set the authority
437
* for a local connection if this is so as XCB treats "127.0.0.1" as local
439
if (g_inet_address_get_is_loopback (xserver_address))
441
gchar hostname[1024];
442
gethostname (hostname, 1024);
444
session->priv->authority = xauth_new (XAUTH_FAMILY_LOCAL,
449
session_authorization_data,
450
session_authorization_data_length);
453
session->priv->authority = xauth_new (family,
454
g_inet_address_to_bytes (G_INET_ADDRESS (xserver_address)),
455
g_inet_address_get_native_size (G_INET_ADDRESS (xserver_address)),
458
session_authorization_data,
459
session_authorization_data_length);
460
g_free (display_number);
405
session->priv->address = address4;
406
session->priv->address6 = address6;
407
session->priv->authorization_name = g_strdup (server->priv->authorization_name);
408
session->priv->authorization_data = session_authorization_data;
409
session->priv->authorization_data_length = session_authorization_data_length;
462
411
response = xdmcp_packet_alloc (XDMCP_Accept);
463
412
response->Accept.session_id = xdmcp_session_get_id (session);
464
413
response->Accept.authentication_name = g_strdup (packet->Request.authentication_name);
465
414
response->Accept.authentication_data.data = authentication_data;
466
415
response->Accept.authentication_data.length = authentication_data_length;
467
response->Accept.authorization_name = authorization_name;
416
response->Accept.authorization_name = g_strdup (server->priv->authorization_name);
468
417
response->Accept.authorization_data.data = authorization_data;
469
418
response->Accept.authorization_data.length = authorization_data_length;
470
419
send_packet (socket, address, response);
475
424
handle_manage (XDMCPServer *server, GSocket *socket, GSocketAddress *address, XDMCPPacket *packet)
477
426
XDMCPSession *session;
480
428
session = get_session (server, packet->Manage.session_id);
483
XDMCPPacket *response;
485
response = xdmcp_packet_alloc (XDMCP_Refuse);
486
response->Refuse.session_id = packet->Manage.session_id;
487
send_packet (socket, address, response);
488
xdmcp_packet_free (response);
493
/* Ignore duplicate requests */
494
if (session->priv->started)
496
if (session->priv->display_number != packet->Manage.display_number ||
497
strcmp (session->priv->display_class, packet->Manage.display_class) != 0)
498
g_debug ("Ignoring duplicate Manage with different data");
502
/* Reject if has changed display number */
503
if (packet->Manage.display_number != session->priv->display_number)
505
XDMCPPacket *response;
507
g_debug ("Received Manage for display number %d, but Request was %d", packet->Manage.display_number, session->priv->display_number);
508
response = xdmcp_packet_alloc (XDMCP_Refuse);
509
response->Refuse.session_id = packet->Manage.session_id;
510
send_packet (socket, address, response);
511
xdmcp_packet_free (response);
514
session->priv->display_class = g_strdup (packet->Manage.display_class);
516
g_signal_emit (server, signals[NEW_SESSION], 0, session, &result);
519
/* Cancel the inactive timer */
520
g_source_remove (session->priv->inactive_timeout);
522
session->priv->started = TRUE;
431
gchar *display_address;
434
/* Ignore duplicate requests */
435
if (session->priv->started)
437
if (session->priv->display_number != packet->Manage.display_number ||
438
strcmp (session->priv->display_class, packet->Manage.display_class) != 0)
439
g_warning ("Duplicate Manage received with different data");
443
session->priv->display_number = packet->Manage.display_number;
444
session->priv->display_class = g_strdup (packet->Manage.display_class);
446
g_signal_emit (server, signals[NEW_SESSION], 0, session, &result);
449
/* Cancel the inactive timer */
450
g_source_remove (session->priv->inactive_timeout);
452
session->priv->started = TRUE;
456
XDMCPPacket *response;
458
response = xdmcp_packet_alloc (XDMCP_Failed);
459
response->Failed.session_id = packet->Manage.session_id;
460
response->Failed.status = g_strdup_printf ("Failed to connect to display %s", display_address);
461
send_packet (socket, address, response);
462
xdmcp_packet_free (response);
465
g_free (display_address);
526
469
XDMCPPacket *response;
528
response = xdmcp_packet_alloc (XDMCP_Failed);
529
response->Failed.session_id = packet->Manage.session_id;
530
response->Failed.status = g_strdup_printf ("Failed to connect to display :%d", packet->Manage.display_number);
471
response = xdmcp_packet_alloc (XDMCP_Refuse);
472
response->Refuse.session_id = packet->Manage.session_id;
531
473
send_packet (socket, address, response);
532
474
xdmcp_packet_free (response);
630
572
GError *error = NULL;
632
g_return_val_if_fail (server != NULL, FALSE);
634
574
server->priv->socket = open_udp_socket (G_SOCKET_FAMILY_IPV4, server->priv->port, &error);
636
g_warning ("Failed to create IPv4 XDMCP socket: %s", error->message);
637
g_clear_error (&error);
639
575
if (server->priv->socket)
641
577
source = g_socket_create_source (server->priv->socket, G_IO_IN, NULL);
642
578
g_source_set_callback (source, (GSourceFunc) read_cb, server, NULL);
643
579
g_source_attach (source, NULL);
646
server->priv->socket6 = open_udp_socket (G_SOCKET_FAMILY_IPV6, server->priv->port, &error);
648
g_warning ("Failed to create IPv6 XDMCP socket: %s", error->message);
582
g_warning ("Failed to create IPv4 XDMCP socket: %s", error->message);
649
583
g_clear_error (&error);
584
server->priv->socket6 = open_udp_socket (G_SOCKET_FAMILY_IPV6, server->priv->port, &error);
651
585
if (server->priv->socket6)
653
587
source = g_socket_create_source (server->priv->socket6, G_IO_IN, NULL);
654
588
g_source_set_callback (source, (GSourceFunc) read_cb, server, NULL);
655
589
g_source_attach (source, NULL);
592
g_warning ("Failed to create IPv6 XDMCP socket: %s", error->message);
593
g_clear_error (&error);
658
595
if (!server->priv->socket && !server->priv->socket6)