File: | cafe-session/csm-xsmp-server.c |
Warning: | line 404, column 22 Value of 'errno' was not checked and may be overwritten by function 'malloc' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- | |||
2 | * | |||
3 | * Copyright (C) 2007 Novell, Inc. | |||
4 | * Copyright (C) 2008 Red Hat, Inc. | |||
5 | * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com> | |||
6 | * | |||
7 | * This program is free software; you can redistribute it and/or modify | |||
8 | * it under the terms of the GNU General Public License as published by | |||
9 | * the Free Software Foundation; either version 2 of the License, or | |||
10 | * (at your option) any later version. | |||
11 | * | |||
12 | * This program is distributed in the hope that it will be useful, | |||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
15 | * GNU General Public License for more details. | |||
16 | * | |||
17 | * You should have received a copy of the GNU General Public License | |||
18 | * along with this program; if not, write to the Free Software | |||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |||
20 | * | |||
21 | */ | |||
22 | ||||
23 | #include "config.h" | |||
24 | ||||
25 | #include <stdlib.h> | |||
26 | #include <stdio.h> | |||
27 | #include <unistd.h> | |||
28 | #include <sys/types.h> | |||
29 | #include <sys/stat.h> | |||
30 | #include <fcntl.h> | |||
31 | #include <string.h> | |||
32 | ||||
33 | #include <glib.h> | |||
34 | #include <glib/gi18n.h> | |||
35 | #include <glib-object.h> | |||
36 | ||||
37 | #include <X11/ICE/ICElib.h> | |||
38 | #include <X11/ICE/ICEutil.h> | |||
39 | #include <X11/ICE/ICEconn.h> | |||
40 | #include <X11/SM/SMlib.h> | |||
41 | ||||
42 | #if HAVE_XTRANS1 | |||
43 | /* Get the proto for _IceTransNoListen */ | |||
44 | #define ICE_t | |||
45 | #define TRANS_SERVER | |||
46 | #include <X11/Xtrans/Xtrans.h> | |||
47 | #undef ICE_t | |||
48 | #undef TRANS_SERVER | |||
49 | #endif /* HAVE_XTRANS */ | |||
50 | ||||
51 | #include "csm-xsmp-server.h" | |||
52 | #include "csm-xsmp-client.h" | |||
53 | #include "csm-util.h" | |||
54 | ||||
55 | /* ICEauthority stuff */ | |||
56 | /* Various magic numbers stolen from iceauth.c */ | |||
57 | #define CSM_ICE_AUTH_RETRIES10 10 | |||
58 | #define CSM_ICE_AUTH_INTERVAL2 2 /* 2 seconds */ | |||
59 | #define CSM_ICE_AUTH_LOCK_TIMEOUT600 600 /* 10 minutes */ | |||
60 | ||||
61 | #define CSM_ICE_MAGIC_COOKIE_AUTH_NAME"MIT-MAGIC-COOKIE-1" "MIT-MAGIC-COOKIE-1" | |||
62 | #define CSM_ICE_MAGIC_COOKIE_LEN16 16 | |||
63 | ||||
64 | struct _CsmXsmpServer | |||
65 | { | |||
66 | GObject parent; | |||
67 | CsmStore *client_store; | |||
68 | ||||
69 | IceListenObj *xsmp_sockets; | |||
70 | int num_xsmp_sockets; | |||
71 | int num_local_xsmp_sockets; | |||
72 | ||||
73 | }; | |||
74 | ||||
75 | enum { | |||
76 | PROP_0, | |||
77 | PROP_CLIENT_STORE | |||
78 | }; | |||
79 | ||||
80 | static void csm_xsmp_server_finalize (GObject *object); | |||
81 | ||||
82 | static gpointer xsmp_server_object = NULL((void*)0); | |||
83 | ||||
84 | G_DEFINE_TYPE (CsmXsmpServer, csm_xsmp_server, G_TYPE_OBJECT)static void csm_xsmp_server_init (CsmXsmpServer *self); static void csm_xsmp_server_class_init (CsmXsmpServerClass *klass); static GType csm_xsmp_server_get_type_once (void); static gpointer csm_xsmp_server_parent_class = ((void*)0); static gint CsmXsmpServer_private_offset ; static void csm_xsmp_server_class_intern_init (gpointer klass ) { csm_xsmp_server_parent_class = g_type_class_peek_parent ( klass); if (CsmXsmpServer_private_offset != 0) g_type_class_adjust_private_offset (klass, &CsmXsmpServer_private_offset); csm_xsmp_server_class_init ((CsmXsmpServerClass*) klass); } __attribute__ ((__unused__) ) static inline gpointer csm_xsmp_server_get_instance_private (CsmXsmpServer *self) { return (((gpointer) ((guint8*) (self ) + (glong) (CsmXsmpServer_private_offset)))); } GType csm_xsmp_server_get_type (void) { static GType static_g_define_type_id = 0; if ((__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer), "Expression evaluates to false"); (void) ( 0 ? (gpointer) * (&static_g_define_type_id) : ((void*)0)) ; (!(__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id ) == sizeof (gpointer), "Expression evaluates to false"); __typeof__ (*(&static_g_define_type_id)) gapg_temp_newval; __typeof__ ((&static_g_define_type_id)) gapg_temp_atomic = (&static_g_define_type_id ); __atomic_load (gapg_temp_atomic, &gapg_temp_newval, 5) ; gapg_temp_newval; })) && g_once_init_enter_pointer ( &static_g_define_type_id)); })) ) { GType g_define_type_id = csm_xsmp_server_get_type_once (); (__extension__ ({ _Static_assert (sizeof *(&static_g_define_type_id) == sizeof (gpointer) , "Expression evaluates to false"); 0 ? (void) (*(&static_g_define_type_id ) = (g_define_type_id)) : (void) 0; g_once_init_leave_pointer ((&static_g_define_type_id), (gpointer) (guintptr) (g_define_type_id )); })) ; } return static_g_define_type_id; } __attribute__ ( (__noinline__)) static GType csm_xsmp_server_get_type_once (void ) { GType g_define_type_id = g_type_register_static_simple (( (GType) ((20) << (2))), g_intern_static_string ("CsmXsmpServer" ), sizeof (CsmXsmpServerClass), (GClassInitFunc)(void (*)(void )) csm_xsmp_server_class_intern_init, sizeof (CsmXsmpServer), (GInstanceInitFunc)(void (*)(void)) csm_xsmp_server_init, (GTypeFlags ) 0); { {{};} } return g_define_type_id; } | |||
85 | ||||
86 | typedef struct { | |||
87 | CsmXsmpServer *server; | |||
88 | IceListenObj listener; | |||
89 | } CsmIceConnectionData; | |||
90 | ||||
91 | typedef struct { | |||
92 | guint watch_id; | |||
93 | guint protocol_timeout; | |||
94 | } CsmIceConnectionWatch; | |||
95 | ||||
96 | static void | |||
97 | disconnect_ice_connection (IceConn ice_conn) | |||
98 | { | |||
99 | IceSetShutdownNegotiation (ice_conn, FALSE(0)); | |||
100 | IceCloseConnection (ice_conn); | |||
101 | } | |||
102 | ||||
103 | static void | |||
104 | free_ice_connection_watch (CsmIceConnectionWatch *data) | |||
105 | { | |||
106 | if (data->watch_id) { | |||
107 | g_source_remove (data->watch_id); | |||
108 | data->watch_id = 0; | |||
109 | } | |||
110 | ||||
111 | if (data->protocol_timeout) { | |||
112 | g_source_remove (data->protocol_timeout); | |||
113 | data->protocol_timeout = 0; | |||
114 | } | |||
115 | ||||
116 | g_free (data); | |||
117 | } | |||
118 | ||||
119 | static gboolean | |||
120 | ice_protocol_timeout (IceConn ice_conn) | |||
121 | { | |||
122 | CsmIceConnectionWatch *data; | |||
123 | ||||
124 | g_debug ("CsmXsmpServer: ice_protocol_timeout for IceConn %p with status %d", | |||
125 | ice_conn, IceConnectionStatus (ice_conn)); | |||
126 | ||||
127 | data = ice_conn->context; | |||
128 | ||||
129 | free_ice_connection_watch (data); | |||
130 | disconnect_ice_connection (ice_conn); | |||
131 | ||||
132 | return FALSE(0); | |||
133 | } | |||
134 | ||||
135 | static gboolean | |||
136 | auth_iochannel_watch (GIOChannel *source, | |||
137 | GIOCondition condition, | |||
138 | IceConn ice_conn) | |||
139 | { | |||
140 | ||||
141 | CsmIceConnectionWatch *data; | |||
142 | gboolean keep_going; | |||
143 | ||||
144 | data = ice_conn->context; | |||
145 | ||||
146 | switch (IceProcessMessages (ice_conn, NULL((void*)0), NULL((void*)0))) { | |||
147 | case IceProcessMessagesSuccess: | |||
148 | keep_going = TRUE(!(0)); | |||
149 | break; | |||
150 | case IceProcessMessagesIOError: | |||
151 | g_debug ("CsmXsmpServer: IceProcessMessages returned IceProcessMessagesIOError"); | |||
152 | free_ice_connection_watch (data); | |||
153 | disconnect_ice_connection (ice_conn); | |||
154 | keep_going = FALSE(0); | |||
155 | break; | |||
156 | case IceProcessMessagesConnectionClosed: | |||
157 | g_debug ("CsmXsmpServer: IceProcessMessages returned IceProcessMessagesConnectionClosed"); | |||
158 | free_ice_connection_watch (data); | |||
159 | keep_going = FALSE(0); | |||
160 | break; | |||
161 | default: | |||
162 | g_assert_not_reached ()do { g_assertion_message_expr (((gchar*) 0), "csm-xsmp-server.c" , 162, ((const char*) (__func__)), ((void*)0)); } while (0); | |||
163 | } | |||
164 | ||||
165 | return keep_going; | |||
166 | } | |||
167 | ||||
168 | /* IceAcceptConnection returns a new ICE connection that is in a "pending" state, | |||
169 | * this is because authentification may be necessary. | |||
170 | * So we've to authenticate it, before accept_xsmp_connection() is called. | |||
171 | * Then each CsmXSMPClient will have its own IceConn watcher | |||
172 | */ | |||
173 | static void | |||
174 | auth_ice_connection (IceConn ice_conn) | |||
175 | { | |||
176 | GIOChannel *channel; | |||
177 | CsmIceConnectionWatch *data; | |||
178 | int fd; | |||
179 | ||||
180 | g_debug ("CsmXsmpServer: auth_ice_connection()"); | |||
181 | ||||
182 | fd = IceConnectionNumber (ice_conn); | |||
183 | fcntl (fd, F_SETFD2, fcntl (fd, F_GETFD1, 0) | FD_CLOEXEC1); | |||
184 | channel = g_io_channel_unix_new (fd); | |||
185 | ||||
186 | data = g_new0 (CsmIceConnectionWatch, 1)((CsmIceConnectionWatch *) g_malloc0_n ((1), sizeof (CsmIceConnectionWatch ))); | |||
187 | ice_conn->context = data; | |||
188 | ||||
189 | data->protocol_timeout = g_timeout_add_seconds (5, | |||
190 | (GSourceFunc)ice_protocol_timeout, | |||
191 | ice_conn); | |||
192 | data->watch_id = g_io_add_watch (channel, | |||
193 | G_IO_IN | G_IO_ERR, | |||
194 | (GIOFunc)auth_iochannel_watch, | |||
195 | ice_conn); | |||
196 | g_io_channel_unref (channel); | |||
197 | } | |||
198 | ||||
199 | /* This is called (by glib via xsmp->ice_connection_watch) when a | |||
200 | * connection is first received on the ICE listening socket. | |||
201 | */ | |||
202 | static gboolean | |||
203 | accept_ice_connection (GIOChannel *source, | |||
204 | GIOCondition condition, | |||
205 | CsmIceConnectionData *data) | |||
206 | { | |||
207 | IceConn ice_conn; | |||
208 | IceAcceptStatus status; | |||
209 | ||||
210 | g_debug ("CsmXsmpServer: accept_ice_connection()"); | |||
211 | ||||
212 | ice_conn = IceAcceptConnection (data->listener, &status); | |||
213 | if (status != IceAcceptSuccess) { | |||
214 | g_debug ("CsmXsmpServer: IceAcceptConnection returned %d", status); | |||
215 | return TRUE(!(0)); | |||
216 | } | |||
217 | ||||
218 | auth_ice_connection (ice_conn); | |||
219 | ||||
220 | return TRUE(!(0)); | |||
221 | } | |||
222 | ||||
223 | void | |||
224 | csm_xsmp_server_start (CsmXsmpServer *server) | |||
225 | { | |||
226 | GIOChannel *channel; | |||
227 | int i; | |||
228 | ||||
229 | for (i = 0; i < server->num_local_xsmp_sockets; i++) { | |||
230 | CsmIceConnectionData *data; | |||
231 | ||||
232 | data = g_new0 (CsmIceConnectionData, 1)((CsmIceConnectionData *) g_malloc0_n ((1), sizeof (CsmIceConnectionData ))); | |||
233 | data->server = server; | |||
234 | data->listener = server->xsmp_sockets[i]; | |||
235 | ||||
236 | channel = g_io_channel_unix_new (IceGetListenConnectionNumber (server->xsmp_sockets[i])); | |||
237 | g_io_add_watch_full (channel, | |||
238 | G_PRIORITY_DEFAULT0, | |||
239 | G_IO_IN | G_IO_HUP | G_IO_ERR, | |||
240 | (GIOFunc)accept_ice_connection, | |||
241 | data, | |||
242 | (GDestroyNotify)g_free); | |||
243 | g_io_channel_unref (channel); | |||
244 | } | |||
245 | } | |||
246 | ||||
247 | static void | |||
248 | csm_xsmp_server_set_client_store (CsmXsmpServer *xsmp_server, | |||
249 | CsmStore *store) | |||
250 | { | |||
251 | g_return_if_fail (CSM_IS_XSMP_SERVER (xsmp_server))do { if ((CSM_IS_XSMP_SERVER (xsmp_server))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CSM_IS_XSMP_SERVER (xsmp_server)" ); return; } } while (0); | |||
252 | ||||
253 | if (store != NULL((void*)0)) { | |||
254 | g_object_ref (store)((__typeof__ (store)) (g_object_ref) (store)); | |||
255 | } | |||
256 | ||||
257 | if (xsmp_server->client_store != NULL((void*)0)) { | |||
258 | g_object_unref (xsmp_server->client_store); | |||
259 | } | |||
260 | ||||
261 | xsmp_server->client_store = store; | |||
262 | } | |||
263 | ||||
264 | static void | |||
265 | csm_xsmp_server_set_property (GObject *object, | |||
266 | guint prop_id, | |||
267 | const GValue *value, | |||
268 | GParamSpec *pspec) | |||
269 | { | |||
270 | CsmXsmpServer *self; | |||
271 | ||||
272 | self = CSM_XSMP_SERVER (object); | |||
273 | ||||
274 | switch (prop_id) { | |||
275 | case PROP_CLIENT_STORE: | |||
276 | csm_xsmp_server_set_client_store (self, g_value_get_object (value)); | |||
277 | break; | |||
278 | default: | |||
279 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec *_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id = ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'" , "csm-xsmp-server.c", 279, ("property"), _glib__property_id, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance *) (_glib__pspec))->g_class))->g_type)))), (g_type_name ((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class ))->g_type)))))); } while (0); | |||
280 | break; | |||
281 | } | |||
282 | } | |||
283 | ||||
284 | static void | |||
285 | csm_xsmp_server_get_property (GObject *object, | |||
286 | guint prop_id, | |||
287 | GValue *value, | |||
288 | GParamSpec *pspec) | |||
289 | { | |||
290 | CsmXsmpServer *self; | |||
291 | ||||
292 | self = CSM_XSMP_SERVER (object); | |||
293 | ||||
294 | switch (prop_id) { | |||
295 | case PROP_CLIENT_STORE: | |||
296 | g_value_set_object (value, self->client_store); | |||
297 | break; | |||
298 | default: | |||
299 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec)do { GObject *_glib__object = (GObject*) ((object)); GParamSpec *_glib__pspec = (GParamSpec*) ((pspec)); guint _glib__property_id = ((prop_id)); g_warning ("%s:%d: invalid %s id %u for \"%s\" of type '%s' in '%s'" , "csm-xsmp-server.c", 299, ("property"), _glib__property_id, _glib__pspec->name, g_type_name ((((((GTypeClass*) (((GTypeInstance *) (_glib__pspec))->g_class))->g_type)))), (g_type_name ((((((GTypeClass*) (((GTypeInstance*) (_glib__object))->g_class ))->g_type)))))); } while (0); | |||
300 | break; | |||
301 | } | |||
302 | } | |||
303 | ||||
304 | /* This is called (by libSM) when XSMP is initiated on an ICE | |||
305 | * connection that was already accepted by accept_ice_connection. | |||
306 | */ | |||
307 | static Statusint | |||
308 | accept_xsmp_connection (SmsConn sms_conn, | |||
309 | CsmXsmpServer *server, | |||
310 | unsigned long *mask_ret, | |||
311 | SmsCallbacks *callbacks_ret, | |||
312 | char **failure_reason_ret) | |||
313 | { | |||
314 | IceConn ice_conn; | |||
315 | CsmClient *client; | |||
316 | CsmIceConnectionWatch *data; | |||
317 | ||||
318 | /* FIXME: what about during shutdown but before csm_xsmp_shutdown? */ | |||
319 | if (server->xsmp_sockets == NULL((void*)0)) { | |||
320 | g_debug ("CsmXsmpServer: In shutdown, rejecting new client"); | |||
321 | ||||
322 | *failure_reason_ret = strdup (_("Refusing new client connection because the session is currently being shut down\n")gettext ("Refusing new client connection because the session is currently being shut down\n" )); | |||
323 | return FALSE(0); | |||
324 | } | |||
325 | ||||
326 | ice_conn = SmsGetIceConnection (sms_conn); | |||
327 | data = ice_conn->context; | |||
328 | ||||
329 | /* Each CsmXSMPClient has its own IceConn watcher */ | |||
330 | free_ice_connection_watch (data); | |||
331 | ||||
332 | client = csm_xsmp_client_new (ice_conn); | |||
333 | ||||
334 | csm_store_add (server->client_store, csm_client_peek_id (client), G_OBJECT (client)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((client)), (((GType) ((20) << (2))))))))); | |||
335 | /* the store will own the ref */ | |||
336 | g_object_unref (client); | |||
337 | ||||
338 | csm_xsmp_client_connect (CSM_XSMP_CLIENT (client), sms_conn, mask_ret, callbacks_ret); | |||
339 | ||||
340 | return TRUE(!(0)); | |||
341 | } | |||
342 | ||||
343 | static void | |||
344 | ice_error_handler (IceConn conn, | |||
345 | Boolint swap, | |||
346 | int offending_minor_opcode, | |||
347 | unsigned long offending_sequence, | |||
348 | int error_class, | |||
349 | int severity, | |||
350 | IcePointer values) | |||
351 | { | |||
352 | g_debug ("CsmXsmpServer: ice_error_handler (%p, %s, %d, %lx, %d, %d)", | |||
353 | conn, swap ? "TRUE" : "FALSE", offending_minor_opcode, | |||
354 | offending_sequence, error_class, severity); | |||
355 | ||||
356 | if (severity == IceCanContinue0) { | |||
357 | return; | |||
358 | } | |||
359 | ||||
360 | /* FIXME: the ICElib docs are completely vague about what we're | |||
361 | * supposed to do in this case. Need to verify that calling | |||
362 | * IceCloseConnection() here is guaranteed to cause neither | |||
363 | * free-memory-reads nor leaks. | |||
364 | */ | |||
365 | IceCloseConnection (conn); | |||
366 | } | |||
367 | ||||
368 | static void | |||
369 | ice_io_error_handler (IceConn conn) | |||
370 | { | |||
371 | g_debug ("CsmXsmpServer: ice_io_error_handler (%p)", conn); | |||
372 | ||||
373 | /* We don't need to do anything here; the next call to | |||
374 | * IceProcessMessages() for this connection will receive | |||
375 | * IceProcessMessagesIOError and we can handle the error there. | |||
376 | */ | |||
377 | } | |||
378 | ||||
379 | static void | |||
380 | sms_error_handler (SmsConn conn, | |||
381 | Boolint swap, | |||
382 | int offending_minor_opcode, | |||
383 | unsigned long offending_sequence_num, | |||
384 | int error_class, | |||
385 | int severity, | |||
386 | IcePointer values) | |||
387 | { | |||
388 | g_debug ("CsmXsmpServer: sms_error_handler (%p, %s, %d, %lx, %d, %d)", | |||
389 | conn, swap ? "TRUE" : "FALSE", offending_minor_opcode, | |||
390 | offending_sequence_num, error_class, severity); | |||
391 | ||||
392 | /* We don't need to do anything here; if the connection needs to be | |||
393 | * closed, libSM will do that itself. | |||
394 | */ | |||
395 | } | |||
396 | ||||
397 | static IceAuthFileEntry * | |||
398 | auth_entry_new (const char *protocol, | |||
399 | const char *network_id) | |||
400 | { | |||
401 | IceAuthFileEntry *file_entry; | |||
402 | IceAuthDataEntry data_entry; | |||
403 | ||||
404 | file_entry = malloc (sizeof (IceAuthFileEntry)); | |||
| ||||
405 | ||||
406 | file_entry->protocol_name = strdup (protocol); | |||
407 | file_entry->protocol_data = NULL((void*)0); | |||
408 | file_entry->protocol_data_length = 0; | |||
409 | file_entry->network_id = strdup (network_id); | |||
410 | file_entry->auth_name = strdup (CSM_ICE_MAGIC_COOKIE_AUTH_NAME"MIT-MAGIC-COOKIE-1"); | |||
411 | file_entry->auth_data = IceGenerateMagicCookie (CSM_ICE_MAGIC_COOKIE_LEN16); | |||
412 | file_entry->auth_data_length = CSM_ICE_MAGIC_COOKIE_LEN16; | |||
413 | ||||
414 | /* Also create an in-memory copy, which is what the server will | |||
415 | * actually use for checking client auth. | |||
416 | */ | |||
417 | data_entry.protocol_name = file_entry->protocol_name; | |||
418 | data_entry.network_id = file_entry->network_id; | |||
419 | data_entry.auth_name = file_entry->auth_name; | |||
420 | data_entry.auth_data = file_entry->auth_data; | |||
421 | data_entry.auth_data_length = file_entry->auth_data_length; | |||
422 | IceSetPaAuthData (1, &data_entry); | |||
423 | ||||
424 | return file_entry; | |||
425 | } | |||
426 | ||||
427 | static gboolean | |||
428 | update_iceauthority (CsmXsmpServer *server, | |||
429 | gboolean adding) | |||
430 | { | |||
431 | char *filename; | |||
432 | char **our_network_ids; | |||
433 | FILE *fp; | |||
434 | IceAuthFileEntry *auth_entry; | |||
435 | GSList *entries; | |||
436 | GSList *e; | |||
437 | int i; | |||
438 | gboolean ok = FALSE(0); | |||
439 | ||||
440 | filename = IceAuthFileName (); | |||
441 | if (IceLockAuthFile (filename, | |||
442 | CSM_ICE_AUTH_RETRIES10, | |||
443 | CSM_ICE_AUTH_INTERVAL2, | |||
444 | CSM_ICE_AUTH_LOCK_TIMEOUT600) != IceAuthLockSuccess0) { | |||
445 | return FALSE(0); | |||
446 | } | |||
447 | ||||
448 | our_network_ids = g_malloc (server->num_local_xsmp_sockets * sizeof (char *)); | |||
449 | for (i = 0; i < server->num_local_xsmp_sockets; i++) { | |||
450 | our_network_ids[i] = IceGetListenConnectionString (server->xsmp_sockets[i]); | |||
451 | } | |||
452 | ||||
453 | entries = NULL((void*)0); | |||
454 | ||||
455 | fp = fopen (filename, "r+"); | |||
456 | if (fp
| |||
457 | while ((auth_entry = IceReadAuthFileEntry (fp)) != NULL((void*)0)) { | |||
458 | /* Skip/delete entries with no network ID (invalid), or with | |||
459 | * our network ID; if we're starting up, an entry with our | |||
460 | * ID must be a stale entry left behind by an old process, | |||
461 | * and if we're shutting down, it won't be valid in the | |||
462 | * future, so either way we want to remove it from the list. | |||
463 | */ | |||
464 | if (!auth_entry->network_id) { | |||
465 | IceFreeAuthFileEntry (auth_entry); | |||
466 | continue; | |||
467 | } | |||
468 | ||||
469 | for (i = 0; i < server->num_local_xsmp_sockets; i++) { | |||
470 | if (!strcmp (auth_entry->network_id, our_network_ids[i])) { | |||
471 | IceFreeAuthFileEntry (auth_entry); | |||
472 | break; | |||
473 | } | |||
474 | } | |||
475 | if (i != server->num_local_xsmp_sockets) { | |||
476 | continue; | |||
477 | } | |||
478 | ||||
479 | entries = g_slist_prepend (entries, auth_entry); | |||
480 | } | |||
481 | ||||
482 | rewind (fp); | |||
483 | } else { | |||
484 | int fd; | |||
485 | ||||
486 | if (g_file_test (filename, G_FILE_TEST_EXISTS)) { | |||
487 | g_warning ("Unable to read ICE authority file: %s", filename); | |||
488 | goto cleanup; | |||
489 | } | |||
490 | ||||
491 | fd = open (filename, O_CREAT0100 | O_WRONLY01, 0600); | |||
492 | fp = fdopen (fd, "w"); | |||
493 | if (!fp) { | |||
494 | g_warning ("Unable to write to ICE authority file: %s", filename); | |||
495 | if (fd != -1) { | |||
496 | close (fd); | |||
497 | } | |||
498 | goto cleanup; | |||
499 | } | |||
500 | } | |||
501 | ||||
502 | if (adding
| |||
503 | for (i = 0; i < server->num_local_xsmp_sockets; i++) { | |||
504 | entries = g_slist_append (entries, | |||
505 | auth_entry_new ("ICE", our_network_ids[i])); | |||
506 | entries = g_slist_prepend (entries, | |||
507 | auth_entry_new ("XSMP", our_network_ids[i])); | |||
508 | } | |||
509 | } | |||
510 | ||||
511 | for (e = entries; e; e = e->next) { | |||
512 | IceAuthFileEntry *auth_entry = e->data; | |||
513 | IceWriteAuthFileEntry (fp, auth_entry); | |||
514 | IceFreeAuthFileEntry (auth_entry); | |||
515 | } | |||
516 | g_slist_free (entries); | |||
517 | ||||
518 | fclose (fp); | |||
519 | ok = TRUE(!(0)); | |||
520 | ||||
521 | cleanup: | |||
522 | IceUnlockAuthFile (filename); | |||
523 | for (i = 0; i < server->num_local_xsmp_sockets; i++) { | |||
524 | free (our_network_ids[i]); | |||
525 | } | |||
526 | g_free (our_network_ids); | |||
527 | ||||
528 | return ok; | |||
529 | } | |||
530 | ||||
531 | ||||
532 | static void | |||
533 | setup_listener (CsmXsmpServer *server) | |||
534 | { | |||
535 | char error[256]; | |||
536 | mode_t saved_umask; | |||
537 | char *network_id_list; | |||
538 | int i; | |||
539 | int res; | |||
540 | ||||
541 | /* Set up sane error handlers */ | |||
542 | IceSetErrorHandler (ice_error_handler); | |||
543 | IceSetIOErrorHandler (ice_io_error_handler); | |||
544 | SmsSetErrorHandler (sms_error_handler); | |||
545 | ||||
546 | /* Initialize libSM; we pass NULL for hostBasedAuthProc to disable | |||
547 | * host-based authentication. | |||
548 | */ | |||
549 | res = SmsInitialize (PACKAGE"cafe-session-manager", | |||
550 | VERSION"1.25.0", | |||
551 | (SmsNewClientProc)accept_xsmp_connection, | |||
552 | server, | |||
553 | NULL((void*)0), | |||
554 | sizeof (error), | |||
555 | error); | |||
556 | if (! res) { | |||
557 | csm_util_init_error (TRUE(!(0)), "Could not initialize libSM: %s", error); | |||
558 | } | |||
559 | ||||
560 | #if HAVE_XTRANS1 | |||
561 | /* By default, IceListenForConnections will open one socket for each | |||
562 | * transport type known to X. We don't want connections from remote | |||
563 | * hosts, so for security reasons it would be best if ICE didn't | |||
564 | * even open any non-local sockets. So we use an internal ICElib | |||
565 | * method to disable them here. Unfortunately, there is no way to | |||
566 | * ask X what transport types it knows about, so we're forced to | |||
567 | * guess. | |||
568 | */ | |||
569 | _IceTransNoListen ("tcp"); | |||
570 | #endif | |||
571 | ||||
572 | /* Create the XSMP socket. Older versions of IceListenForConnections | |||
573 | * have a bug which causes the umask to be set to 0 on certain types | |||
574 | * of failures. Probably not an issue on any modern systems, but | |||
575 | * we'll play it safe. | |||
576 | */ | |||
577 | saved_umask = umask (0); | |||
578 | umask (saved_umask); | |||
579 | res = IceListenForConnections (&server->num_xsmp_sockets, | |||
580 | &server->xsmp_sockets, | |||
581 | sizeof (error), | |||
582 | error); | |||
583 | if (! res) { | |||
584 | csm_util_init_error (TRUE(!(0)), _("Could not create ICE listening socket: %s")gettext ("Could not create ICE listening socket: %s"), error); | |||
585 | } | |||
586 | ||||
587 | umask (saved_umask); | |||
588 | ||||
589 | /* Find the local sockets in the returned socket list and move them | |||
590 | * to the start of the list. | |||
591 | */ | |||
592 | for (i = server->num_local_xsmp_sockets = 0; i < server->num_xsmp_sockets; i++) { | |||
593 | char *id = IceGetListenConnectionString (server->xsmp_sockets[i]); | |||
594 | ||||
595 | if (!strncmp (id, "local/", sizeof ("local/") - 1) || | |||
596 | !strncmp (id, "unix/", sizeof ("unix/") - 1)) { | |||
597 | if (i
| |||
598 | IceListenObj tmp; | |||
599 | tmp = server->xsmp_sockets[i]; | |||
600 | server->xsmp_sockets[i] = server->xsmp_sockets[server->num_local_xsmp_sockets]; | |||
601 | server->xsmp_sockets[server->num_local_xsmp_sockets] = tmp; | |||
602 | } | |||
603 | server->num_local_xsmp_sockets++; | |||
604 | } | |||
605 | free (id); | |||
606 | } | |||
607 | ||||
608 | if (server->num_local_xsmp_sockets
| |||
609 | csm_util_init_error (TRUE(!(0)), "IceListenForConnections did not return a local listener!"); | |||
610 | } | |||
611 | ||||
612 | #ifdef HAVE_XTRANS1 | |||
613 | if (server->num_local_xsmp_sockets
| |||
614 | /* Xtrans was apparently compiled with support for some | |||
615 | * non-local transport besides TCP (which we disabled above); we | |||
616 | * won't create IO watches on those extra sockets, so | |||
617 | * connections to them will never be noticed, but they're still | |||
618 | * there, which is inelegant. | |||
619 | * | |||
620 | * If the g_warning below is triggering for you and you want to | |||
621 | * stop it, the fix is to add additional _IceTransNoListen() | |||
622 | * calls above. | |||
623 | */ | |||
624 | network_id_list = IceComposeNetworkIdList (server->num_xsmp_sockets - server->num_local_xsmp_sockets, | |||
625 | server->xsmp_sockets + server->num_local_xsmp_sockets); | |||
626 | g_warning ("IceListenForConnections returned %d non-local listeners: %s", | |||
627 | server->num_xsmp_sockets - server->num_local_xsmp_sockets, | |||
628 | network_id_list); | |||
629 | free (network_id_list); | |||
630 | } | |||
631 | #endif | |||
632 | ||||
633 | /* Update .ICEauthority with new auth entries for our socket */ | |||
634 | if (!update_iceauthority (server, TRUE(!(0)))) { | |||
635 | /* FIXME: is this really fatal? Hm... */ | |||
636 | csm_util_init_error (TRUE(!(0)), | |||
637 | "Could not update ICEauthority file %s", | |||
638 | IceAuthFileName ()); | |||
639 | } | |||
640 | ||||
641 | network_id_list = IceComposeNetworkIdList (server->num_local_xsmp_sockets, | |||
642 | server->xsmp_sockets); | |||
643 | ||||
644 | csm_util_setenv ("SESSION_MANAGER", network_id_list); | |||
645 | g_debug ("CsmXsmpServer: SESSION_MANAGER=%s\n", network_id_list); | |||
646 | free (network_id_list); | |||
647 | } | |||
648 | ||||
649 | static GObject * | |||
650 | csm_xsmp_server_constructor (GType type, | |||
651 | guint n_construct_properties, | |||
652 | GObjectConstructParam *construct_properties) | |||
653 | { | |||
654 | CsmXsmpServer *xsmp_server; | |||
655 | ||||
656 | xsmp_server = CSM_XSMP_SERVER (G_OBJECT_CLASS (csm_xsmp_server_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((csm_xsmp_server_parent_class)), (((GType) ((20) << (2))))))))->constructor (type, | |||
657 | n_construct_properties, | |||
658 | construct_properties)); | |||
659 | setup_listener (xsmp_server); | |||
| ||||
660 | ||||
661 | return G_OBJECT (xsmp_server)((((GObject*) (void *) g_type_check_instance_cast ((GTypeInstance *) ((xsmp_server)), (((GType) ((20) << (2)))))))); | |||
662 | } | |||
663 | ||||
664 | static void | |||
665 | csm_xsmp_server_class_init (CsmXsmpServerClass *klass) | |||
666 | { | |||
667 | GObjectClass *object_class = G_OBJECT_CLASS (klass)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((klass)), (((GType) ((20) << (2)))))))); | |||
668 | ||||
669 | object_class->get_property = csm_xsmp_server_get_property; | |||
670 | object_class->set_property = csm_xsmp_server_set_property; | |||
671 | object_class->constructor = csm_xsmp_server_constructor; | |||
672 | object_class->finalize = csm_xsmp_server_finalize; | |||
673 | ||||
674 | g_object_class_install_property (object_class, | |||
675 | PROP_CLIENT_STORE, | |||
676 | g_param_spec_object ("client-store", | |||
677 | NULL((void*)0), | |||
678 | NULL((void*)0), | |||
679 | CSM_TYPE_STORE(csm_store_get_type ()), | |||
680 | G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); | |||
681 | } | |||
682 | ||||
683 | static void | |||
684 | csm_xsmp_server_init (CsmXsmpServer *xsmp_server) | |||
685 | { | |||
686 | } | |||
687 | ||||
688 | static void | |||
689 | csm_xsmp_server_finalize (GObject *object) | |||
690 | { | |||
691 | CsmXsmpServer *xsmp_server; | |||
692 | ||||
693 | g_return_if_fail (object != NULL)do { if ((object != ((void*)0))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "object != NULL") ; return; } } while (0); | |||
694 | g_return_if_fail (CSM_IS_XSMP_SERVER (object))do { if ((CSM_IS_XSMP_SERVER (object))) { } else { g_return_if_fail_warning (((gchar*) 0), ((const char*) (__func__)), "CSM_IS_XSMP_SERVER (object)" ); return; } } while (0); | |||
695 | ||||
696 | xsmp_server = CSM_XSMP_SERVER (object); | |||
697 | ||||
698 | IceFreeListenObjs (xsmp_server->num_xsmp_sockets, | |||
699 | xsmp_server->xsmp_sockets); | |||
700 | ||||
701 | if (xsmp_server->client_store != NULL((void*)0)) { | |||
702 | g_object_unref (xsmp_server->client_store); | |||
703 | } | |||
704 | ||||
705 | G_OBJECT_CLASS (csm_xsmp_server_parent_class)((((GObjectClass*) (void *) g_type_check_class_cast ((GTypeClass *) ((csm_xsmp_server_parent_class)), (((GType) ((20) << (2))))))))->finalize (object); | |||
706 | } | |||
707 | ||||
708 | CsmXsmpServer * | |||
709 | csm_xsmp_server_new (CsmStore *client_store) | |||
710 | { | |||
711 | if (xsmp_server_object != NULL((void*)0)) { | |||
712 | g_object_ref (xsmp_server_object)((__typeof__ (xsmp_server_object)) (g_object_ref) (xsmp_server_object )); | |||
713 | } else { | |||
714 | xsmp_server_object = g_object_new (CSM_TYPE_XSMP_SERVER(csm_xsmp_server_get_type ()), | |||
715 | "client-store", client_store, | |||
716 | NULL((void*)0)); | |||
717 | ||||
718 | g_object_add_weak_pointer (xsmp_server_object, | |||
719 | (gpointer *) &xsmp_server_object); | |||
720 | } | |||
721 | ||||
722 | return CSM_XSMP_SERVER (xsmp_server_object); | |||
723 | } |