1 /*
2 * Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
3 *
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of N.C.D. not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. N.C.D. makes no representations about the
11 * suitability of this software for any purpose. It is provided "as is"
12 * without express or implied warranty.
13 *
14 */
15
16 #ifdef HAVE_DIX_CONFIG_H
17 #include <dix-config.h>
18 #endif
19
20 #ifdef WIN32
21 #include <X11/Xwinsock.h>
22 #define XSERV_t
23 #define TRANS_SERVER
24 #define TRANS_REOPEN
25 #include <X11/Xtrans/Xtrans.h>
26 #endif
27
28 #include <X11/Xos.h>
29
30 #if !defined(WIN32)
31 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <netdb.h>
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <X11/X.h>
40 #include <X11/Xmd.h>
41 #include "misc.h"
42 #include "osdep.h"
43 #include "input.h"
44 #include "dixstruct.h"
45 #include "opaque.h"
46 #include "site.h"
47
48 #define XSERV_t
49 #define TRANS_SERVER
50 #define TRANS_REOPEN
51 #include <X11/Xtrans/Xtrans.h>
52
53 #ifdef XDMCP
54 #undef REQUEST
55
56 #ifdef XDMCP_NO_IPV6
57 #undef IPv6
58 #endif
59
60 #include <X11/Xdmcp.h>
61
62 #define X_INCLUDE_NETDB_H
63 #include <X11/Xos_r.h>
64
65 static const char *defaultDisplayClass = COMPILEDDISPLAYCLASS;
66
67 static int xdmcpSocket, sessionSocket;
68 static xdmcp_states state;
69
70 #if defined(IPv6) && defined(AF_INET6)
71 static int xdmcpSocket6;
72 static struct sockaddr_storage req_sockaddr;
73 #else
74 static struct sockaddr_in req_sockaddr;
75 #endif
76 static int req_socklen;
77 static CARD32 SessionID;
78 static int timeOutRtx;
79 static CARD16 DisplayNumber;
80 static xdmcp_states XDM_INIT_STATE = XDM_OFF;
81 static OsTimerPtr xdmcp_timer;
82
83 #ifdef HASXDMAUTH
84 static char *xdmAuthCookie;
85 #endif
86
87 static XdmcpBuffer buffer;
88
89 #if defined(IPv6) && defined(AF_INET6)
90
91 static struct addrinfo *mgrAddr;
92 static struct addrinfo *mgrAddrFirst;
93
94 #define SOCKADDR_TYPE struct sockaddr_storage
95 #define SOCKADDR_FAMILY(s) ((struct sockaddr *)&(s))->sa_family
96
97 #ifdef BSD44SOCKETS
98 #define SOCKLEN_FIELD(s) ((struct sockaddr *)&(s))->sa_len
99 #define SOCKLEN_TYPE unsigned char
100 #else
101 #define SOCKLEN_TYPE unsigned int
102 #endif
103
104 #else
105
106 #define SOCKADDR_TYPE struct sockaddr_in
107 #define SOCKADDR_FAMILY(s) (s).sin_family
108
109 #ifdef BSD44SOCKETS
110 #define SOCKLEN_FIELD(s) (s).sin_len
111 #define SOCKLEN_TYPE unsigned char
112 #else
113 #define SOCKLEN_TYPE size_t
114 #endif
115
116 #endif
117
118 static SOCKADDR_TYPE ManagerAddress;
119 static SOCKADDR_TYPE FromAddress;
120
121 #ifdef SOCKLEN_FIELD
122 #define ManagerAddressLen SOCKLEN_FIELD(ManagerAddress)
123 #define FromAddressLen SOCKLEN_FIELD(FromAddress)
124 #else
125 static SOCKLEN_TYPE ManagerAddressLen, FromAddressLen;
126 #endif
127
128 #if defined(IPv6) && defined(AF_INET6)
129 static struct multicastinfo {
130 struct multicastinfo *next;
131 struct addrinfo *ai;
132 int hops;
133 } *mcastlist;
134 #endif
135
136 static void XdmcpAddHost(const struct sockaddr *from,
137 int fromlen,
138 ARRAY8Ptr AuthenticationName,
139 ARRAY8Ptr hostname, ARRAY8Ptr status);
140
141 static void XdmcpSelectHost(const struct sockaddr *host_sockaddr,
142 int host_len, ARRAY8Ptr AuthenticationName);
143
144 static void get_xdmcp_sock(void);
145
146 static void send_query_msg(void);
147
148 static void recv_willing_msg(struct sockaddr *from,
149 int fromlen,
150 unsigned length);
151
152 static void send_request_msg(void);
153
154 static void recv_accept_msg(unsigned length);
155
156 static void recv_decline_msg(unsigned length);
157
158 static void send_manage_msg(void);
159
160 static void recv_refuse_msg(unsigned length);
161
162 static void recv_failed_msg(unsigned length);
163
164 static void send_keepalive_msg(void);
165
166 static void recv_alive_msg(unsigned length );
167
168 static void XdmcpFatal(const char *type,
169 ARRAY8Ptr status);
170
171 static void XdmcpWarning(const char *str);
172
173 static void get_manager_by_name(int argc,
174 char **argv,
175 int i);
176
177 static void get_fromaddr_by_name(int argc,
178 char **argv,
179 int i);
180
181 #if defined(IPv6) && defined(AF_INET6)
182 static int get_mcast_options(int argc,
183 char **argv,
184 int i);
185 #endif
186
187 static void receive_packet(int socketfd);
188
189 static void send_packet(void);
190
191 static void timeout(void);
192
193 static void XdmcpSocketNotify(int fd, int ready, void *data);
194
195 static CARD32 XdmcpTimerNotify(OsTimerPtr timer, CARD32 time, void *arg);
196
197 /*
198 * Register the Manufacturer display ID
199 */
200
201 static ARRAY8 ManufacturerDisplayID;
202
203 static void
XdmcpRegisterManufacturerDisplayID(const char * name,int length)204 XdmcpRegisterManufacturerDisplayID(const char *name, int length)
205 {
206 int i;
207
208 XdmcpDisposeARRAY8(&ManufacturerDisplayID);
209 if (!XdmcpAllocARRAY8(&ManufacturerDisplayID, length))
210 return;
211 for (i = 0; i < length; i++)
212 ManufacturerDisplayID.data[i] = (CARD8) name[i];
213 }
214
215 static unsigned short xdm_udp_port = XDM_UDP_PORT;
216 static Bool OneSession = FALSE;
217 static const char *xdm_from = NULL;
218
219 void
XdmcpUseMsg(void)220 XdmcpUseMsg(void)
221 {
222 ErrorF("-query host-name contact named host for XDMCP\n");
223 ErrorF("-broadcast broadcast for XDMCP\n");
224 #if defined(IPv6) && defined(AF_INET6)
225 ErrorF("-multicast [addr [hops]] IPv6 multicast for XDMCP\n");
226 #endif
227 ErrorF("-indirect host-name contact named host for indirect XDMCP\n");
228 ErrorF("-port port-num UDP port number to send messages to\n");
229 ErrorF
230 ("-from local-address specify the local address to connect from\n");
231 ErrorF("-once Terminate server after one session\n");
232 ErrorF("-class display-class specify display class to send in manage\n");
233 #ifdef HASXDMAUTH
234 ErrorF("-cookie xdm-auth-bits specify the magic cookie for XDMCP\n");
235 #endif
236 ErrorF("-displayID display-id manufacturer display ID for request\n");
237 }
238
239 static void
XdmcpDefaultListen(void)240 XdmcpDefaultListen(void)
241 {
242 /* Even when configured --disable-listen-tcp, we should listen on tcp in
243 XDMCP modes */
244 _XSERVTransListen("tcp");
245 }
246
247 int
XdmcpOptions(int argc,char ** argv,int i)248 XdmcpOptions(int argc, char **argv, int i)
249 {
250 if (strcmp(argv[i], "-query") == 0) {
251 get_manager_by_name(argc, argv, i++);
252 XDM_INIT_STATE = XDM_QUERY;
253 AccessUsingXdmcp();
254 XdmcpDefaultListen();
255 return i + 1;
256 }
257 if (strcmp(argv[i], "-broadcast") == 0) {
258 XDM_INIT_STATE = XDM_BROADCAST;
259 AccessUsingXdmcp();
260 XdmcpDefaultListen();
261 return i + 1;
262 }
263 #if defined(IPv6) && defined(AF_INET6)
264 if (strcmp(argv[i], "-multicast") == 0) {
265 i = get_mcast_options(argc, argv, ++i);
266 XDM_INIT_STATE = XDM_MULTICAST;
267 AccessUsingXdmcp();
268 XdmcpDefaultListen();
269 return i + 1;
270 }
271 #endif
272 if (strcmp(argv[i], "-indirect") == 0) {
273 get_manager_by_name(argc, argv, i++);
274 XDM_INIT_STATE = XDM_INDIRECT;
275 AccessUsingXdmcp();
276 XdmcpDefaultListen();
277 return i + 1;
278 }
279 if (strcmp(argv[i], "-port") == 0) {
280 if (++i == argc) {
281 FatalError("Xserver: missing port number in command line\n");
282 }
283 xdm_udp_port = (unsigned short) atoi(argv[i]);
284 return i + 1;
285 }
286 if (strcmp(argv[i], "-from") == 0) {
287 get_fromaddr_by_name(argc, argv, ++i);
288 return i + 1;
289 }
290 if (strcmp(argv[i], "-once") == 0) {
291 OneSession = TRUE;
292 return i + 1;
293 }
294 if (strcmp(argv[i], "-class") == 0) {
295 if (++i == argc) {
296 FatalError("Xserver: missing class name in command line\n");
297 }
298 defaultDisplayClass = argv[i];
299 return i + 1;
300 }
301 #ifdef HASXDMAUTH
302 if (strcmp(argv[i], "-cookie") == 0) {
303 if (++i == argc) {
304 FatalError("Xserver: missing cookie data in command line\n");
305 }
306 xdmAuthCookie = argv[i];
307 return i + 1;
308 }
309 #endif
310 if (strcmp(argv[i], "-displayID") == 0) {
311 if (++i == argc) {
312 FatalError("Xserver: missing displayID in command line\n");
313 }
314 XdmcpRegisterManufacturerDisplayID(argv[i], strlen(argv[i]));
315 return i + 1;
316 }
317 return i;
318 }
319
320 /*
321 * This section is a collection of routines for
322 * registering server-specific data with the XDMCP
323 * state machine.
324 */
325
326 /*
327 * Save all broadcast addresses away so BroadcastQuery
328 * packets get sent everywhere
329 */
330
331 #define MAX_BROADCAST 10
332
333 /* This stays sockaddr_in since IPv6 doesn't support broadcast */
334 static struct sockaddr_in BroadcastAddresses[MAX_BROADCAST];
335 static int NumBroadcastAddresses;
336
337 void
XdmcpRegisterBroadcastAddress(const struct sockaddr_in * addr)338 XdmcpRegisterBroadcastAddress(const struct sockaddr_in *addr)
339 {
340 struct sockaddr_in *bcast;
341
342 if (NumBroadcastAddresses >= MAX_BROADCAST)
343 return;
344 bcast = &BroadcastAddresses[NumBroadcastAddresses++];
345 memset(bcast, 0, sizeof(struct sockaddr_in));
346 #ifdef BSD44SOCKETS
347 bcast->sin_len = addr->sin_len;
348 #endif
349 bcast->sin_family = addr->sin_family;
350 bcast->sin_port = htons(xdm_udp_port);
351 bcast->sin_addr = addr->sin_addr;
352 }
353
354 /*
355 * Each authentication type is registered here; Validator
356 * will be called to check all access attempts using
357 * the specified authentication type
358 */
359
360 static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas;
361 typedef struct _AuthenticationFuncs {
362 ValidatorFunc Validator;
363 GeneratorFunc Generator;
364 AddAuthorFunc AddAuth;
365 } AuthenticationFuncsRec, *AuthenticationFuncsPtr;
366
367 static AuthenticationFuncsPtr AuthenticationFuncsList;
368
369 void
XdmcpRegisterAuthentication(const char * name,int namelen,const char * data,int datalen,ValidatorFunc Validator,GeneratorFunc Generator,AddAuthorFunc AddAuth)370 XdmcpRegisterAuthentication(const char *name,
371 int namelen,
372 const char *data,
373 int datalen,
374 ValidatorFunc Validator,
375 GeneratorFunc Generator, AddAuthorFunc AddAuth)
376 {
377 int i;
378 ARRAY8 AuthenticationName, AuthenticationData;
379 static AuthenticationFuncsPtr newFuncs;
380
381 if (!XdmcpAllocARRAY8(&AuthenticationName, namelen))
382 return;
383 if (!XdmcpAllocARRAY8(&AuthenticationData, datalen)) {
384 XdmcpDisposeARRAY8(&AuthenticationName);
385 return;
386 }
387 for (i = 0; i < namelen; i++)
388 AuthenticationName.data[i] = name[i];
389 for (i = 0; i < datalen; i++)
390 AuthenticationData.data[i] = data[i];
391 if (!(XdmcpReallocARRAYofARRAY8(&AuthenticationNames,
392 AuthenticationNames.length + 1) &&
393 XdmcpReallocARRAYofARRAY8(&AuthenticationDatas,
394 AuthenticationDatas.length + 1) &&
395 (newFuncs =
396 malloc((AuthenticationNames.length +
397 1) * sizeof(AuthenticationFuncsRec))))) {
398 XdmcpDisposeARRAY8(&AuthenticationName);
399 XdmcpDisposeARRAY8(&AuthenticationData);
400 return;
401 }
402 for (i = 0; i < AuthenticationNames.length - 1; i++)
403 newFuncs[i] = AuthenticationFuncsList[i];
404 newFuncs[AuthenticationNames.length - 1].Validator = Validator;
405 newFuncs[AuthenticationNames.length - 1].Generator = Generator;
406 newFuncs[AuthenticationNames.length - 1].AddAuth = AddAuth;
407 free(AuthenticationFuncsList);
408 AuthenticationFuncsList = newFuncs;
409 AuthenticationNames.data[AuthenticationNames.length - 1] =
410 AuthenticationName;
411 AuthenticationDatas.data[AuthenticationDatas.length - 1] =
412 AuthenticationData;
413 }
414
415 /*
416 * Select the authentication type to be used; this is
417 * set by the manager of the host to be connected to.
418 */
419
420 static ARRAY8 noAuthenticationName = { (CARD16) 0, (CARD8Ptr) 0 };
421 static ARRAY8 noAuthenticationData = { (CARD16) 0, (CARD8Ptr) 0 };
422
423 static ARRAY8Ptr AuthenticationName = &noAuthenticationName;
424 static ARRAY8Ptr AuthenticationData = &noAuthenticationData;
425 static AuthenticationFuncsPtr AuthenticationFuncs;
426
427 static void
XdmcpSetAuthentication(const ARRAY8Ptr name)428 XdmcpSetAuthentication(const ARRAY8Ptr name)
429 {
430 int i;
431
432 for (i = 0; i < AuthenticationNames.length; i++)
433 if (XdmcpARRAY8Equal(&AuthenticationNames.data[i], name)) {
434 AuthenticationName = &AuthenticationNames.data[i];
435 AuthenticationData = &AuthenticationDatas.data[i];
436 AuthenticationFuncs = &AuthenticationFuncsList[i];
437 break;
438 }
439 }
440
441 /*
442 * Register the host address for the display
443 */
444
445 static ARRAY16 ConnectionTypes;
446 static ARRAYofARRAY8 ConnectionAddresses;
447 static long xdmcpGeneration;
448
449 void
XdmcpRegisterConnection(int type,const char * address,int addrlen)450 XdmcpRegisterConnection(int type, const char *address, int addrlen)
451 {
452 int i;
453 CARD8 *newAddress;
454
455 if (xdmcpGeneration != serverGeneration) {
456 XdmcpDisposeARRAY16(&ConnectionTypes);
457 XdmcpDisposeARRAYofARRAY8(&ConnectionAddresses);
458 xdmcpGeneration = serverGeneration;
459 }
460 if (xdm_from != NULL) { /* Only register the requested address */
461 const void *regAddr = address;
462 const void *fromAddr = NULL;
463 int regAddrlen = addrlen;
464
465 if (addrlen == sizeof(struct in_addr)) {
466 if (SOCKADDR_FAMILY(FromAddress) == AF_INET) {
467 fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr;
468 }
469 #if defined(IPv6) && defined(AF_INET6)
470 else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) &&
471 IN6_IS_ADDR_V4MAPPED(&
472 ((struct sockaddr_in6 *)
473 &FromAddress)->sin6_addr)) {
474 fromAddr =
475 &((struct sockaddr_in6 *) &FromAddress)->sin6_addr.
476 s6_addr[12];
477 }
478 #endif
479 }
480 #if defined(IPv6) && defined(AF_INET6)
481 else if (addrlen == sizeof(struct in6_addr)) {
482 if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) {
483 fromAddr = &((struct sockaddr_in6 *) &FromAddress)->sin6_addr;
484 }
485 else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) &&
486 IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) address)) {
487 fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr;
488 regAddr =
489 &((struct sockaddr_in6 *) address)->sin6_addr.s6_addr[12];
490 regAddrlen = sizeof(struct in_addr);
491 }
492 }
493 #endif
494 if (!fromAddr || memcmp(regAddr, fromAddr, regAddrlen) != 0) {
495 return;
496 }
497 }
498 if (ConnectionAddresses.length + 1 == 256)
499 return;
500 newAddress = malloc(addrlen * sizeof(CARD8));
501 if (!newAddress)
502 return;
503 if (!XdmcpReallocARRAY16(&ConnectionTypes, ConnectionTypes.length + 1)) {
504 free(newAddress);
505 return;
506 }
507 if (!XdmcpReallocARRAYofARRAY8(&ConnectionAddresses,
508 ConnectionAddresses.length + 1)) {
509 free(newAddress);
510 return;
511 }
512 ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type;
513 for (i = 0; i < addrlen; i++)
514 newAddress[i] = address[i];
515 ConnectionAddresses.data[ConnectionAddresses.length - 1].data = newAddress;
516 ConnectionAddresses.data[ConnectionAddresses.length - 1].length = addrlen;
517 }
518
519 /*
520 * Register an Authorization Name. XDMCP advertises this list
521 * to the manager.
522 */
523
524 static ARRAYofARRAY8 AuthorizationNames;
525
526 void
XdmcpRegisterAuthorizations(void)527 XdmcpRegisterAuthorizations(void)
528 {
529 XdmcpDisposeARRAYofARRAY8(&AuthorizationNames);
530 RegisterAuthorizations();
531 }
532
533 void
XdmcpRegisterAuthorization(const char * name,int namelen)534 XdmcpRegisterAuthorization(const char *name, int namelen)
535 {
536 ARRAY8 authName;
537 int i;
538
539 authName.data = malloc(namelen * sizeof(CARD8));
540 if (!authName.data)
541 return;
542 if (!XdmcpReallocARRAYofARRAY8
543 (&AuthorizationNames, AuthorizationNames.length + 1)) {
544 free(authName.data);
545 return;
546 }
547 for (i = 0; i < namelen; i++)
548 authName.data[i] = (CARD8) name[i];
549 authName.length = namelen;
550 AuthorizationNames.data[AuthorizationNames.length - 1] = authName;
551 }
552
553 /*
554 * Register the DisplayClass string
555 */
556
557 static ARRAY8 DisplayClass;
558
559 static void
XdmcpRegisterDisplayClass(const char * name,int length)560 XdmcpRegisterDisplayClass(const char *name, int length)
561 {
562 int i;
563
564 XdmcpDisposeARRAY8(&DisplayClass);
565 if (!XdmcpAllocARRAY8(&DisplayClass, length))
566 return;
567 for (i = 0; i < length; i++)
568 DisplayClass.data[i] = (CARD8) name[i];
569 }
570
571 static void
xdmcp_reset(void)572 xdmcp_reset(void)
573 {
574 timeOutRtx = 0;
575 if (xdmcpSocket >= 0)
576 SetNotifyFd(xdmcpSocket, XdmcpSocketNotify, X_NOTIFY_READ, NULL);
577 #if defined(IPv6) && defined(AF_INET6)
578 if (xdmcpSocket6 >= 0)
579 SetNotifyFd(xdmcpSocket6, XdmcpSocketNotify, X_NOTIFY_READ, NULL);
580 #endif
581 xdmcp_timer = TimerSet(NULL, 0, 0, XdmcpTimerNotify, NULL);
582 send_packet();
583 }
584
585 static void
xdmcp_start(void)586 xdmcp_start(void)
587 {
588 get_xdmcp_sock();
589 xdmcp_reset();
590 }
591
592 /*
593 * initialize XDMCP; create the socket, compute the display
594 * number, set up the state machine
595 */
596
597 void
XdmcpInit(void)598 XdmcpInit(void)
599 {
600 state = XDM_INIT_STATE;
601 #ifdef HASXDMAUTH
602 if (xdmAuthCookie)
603 XdmAuthenticationInit(xdmAuthCookie, strlen(xdmAuthCookie));
604 #endif
605 if (state != XDM_OFF) {
606 XdmcpRegisterAuthorizations();
607 XdmcpRegisterDisplayClass(defaultDisplayClass,
608 strlen(defaultDisplayClass));
609 AccessUsingXdmcp();
610 DisplayNumber = (CARD16) atoi(display);
611 xdmcp_start();
612 }
613 }
614
615 void
XdmcpReset(void)616 XdmcpReset(void)
617 {
618 state = XDM_INIT_STATE;
619 if (state != XDM_OFF)
620 xdmcp_reset();
621 }
622
623 /*
624 * Called whenever a new connection is created; notices the
625 * first connection and saves it to terminate the session
626 * when it is closed
627 */
628
629 void
XdmcpOpenDisplay(int sock)630 XdmcpOpenDisplay(int sock)
631 {
632 if (state != XDM_AWAIT_MANAGE_RESPONSE)
633 return;
634 state = XDM_RUN_SESSION;
635 TimerSet(xdmcp_timer, 0, XDM_DEF_DORMANCY * 1000, XdmcpTimerNotify, NULL);
636 sessionSocket = sock;
637 }
638
639 void
XdmcpCloseDisplay(int sock)640 XdmcpCloseDisplay(int sock)
641 {
642 if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE)
643 || sessionSocket != sock)
644 return;
645 state = XDM_INIT_STATE;
646 if (OneSession)
647 dispatchException |= DE_TERMINATE;
648 else
649 dispatchException |= DE_RESET;
650 isItTimeToYield = TRUE;
651 }
652
653 static void
XdmcpSocketNotify(int fd,int ready,void * data)654 XdmcpSocketNotify(int fd, int ready, void *data)
655 {
656 if (state == XDM_OFF)
657 return;
658 receive_packet(fd);
659 }
660
661 static CARD32
XdmcpTimerNotify(OsTimerPtr timer,CARD32 time,void * arg)662 XdmcpTimerNotify(OsTimerPtr timer, CARD32 time, void *arg)
663 {
664 if (state == XDM_RUN_SESSION) {
665 state = XDM_KEEPALIVE;
666 send_packet();
667 }
668 else
669 timeout();
670 return 0;
671 }
672
673 /*
674 * This routine should be called from the routine that drives the
675 * user's host menu when the user selects a host
676 */
677
678 static void
XdmcpSelectHost(const struct sockaddr * host_sockaddr,int host_len,ARRAY8Ptr auth_name)679 XdmcpSelectHost(const struct sockaddr *host_sockaddr,
680 int host_len, ARRAY8Ptr auth_name)
681 {
682 state = XDM_START_CONNECTION;
683 memmove(&req_sockaddr, host_sockaddr, host_len);
684 req_socklen = host_len;
685 XdmcpSetAuthentication(auth_name);
686 send_packet();
687 }
688
689 /*
690 * !!! this routine should be replaced by a routine that adds
691 * the host to the user's host menu. the current version just
692 * selects the first host to respond with willing message.
693 */
694
695 /*ARGSUSED*/ static void
XdmcpAddHost(const struct sockaddr * from,int fromlen,ARRAY8Ptr auth_name,ARRAY8Ptr hostname,ARRAY8Ptr status)696 XdmcpAddHost(const struct sockaddr *from,
697 int fromlen,
698 ARRAY8Ptr auth_name, ARRAY8Ptr hostname, ARRAY8Ptr status)
699 {
700 XdmcpSelectHost(from, fromlen, auth_name);
701 }
702
703 /*
704 * A message is queued on the socket; read it and
705 * do the appropriate thing
706 */
707
708 static ARRAY8 UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" };
709
710 static void
receive_packet(int socketfd)711 receive_packet(int socketfd)
712 {
713 #if defined(IPv6) && defined(AF_INET6)
714 struct sockaddr_storage from;
715 #else
716 struct sockaddr_in from;
717 #endif
718 int fromlen = sizeof(from);
719 XdmcpHeader header;
720
721 /* read message off socket */
722 if (!XdmcpFill(socketfd, &buffer, (XdmcpNetaddr) &from, &fromlen))
723 return;
724
725 /* reset retransmission backoff */
726 timeOutRtx = 0;
727
728 if (!XdmcpReadHeader(&buffer, &header))
729 return;
730
731 if (header.version != XDM_PROTOCOL_VERSION)
732 return;
733
734 switch (header.opcode) {
735 case WILLING:
736 recv_willing_msg((struct sockaddr *) &from, fromlen, header.length);
737 break;
738 case UNWILLING:
739 XdmcpFatal("Manager unwilling", &UnwillingMessage);
740 break;
741 case ACCEPT:
742 recv_accept_msg(header.length);
743 break;
744 case DECLINE:
745 recv_decline_msg(header.length);
746 break;
747 case REFUSE:
748 recv_refuse_msg(header.length);
749 break;
750 case FAILED:
751 recv_failed_msg(header.length);
752 break;
753 case ALIVE:
754 recv_alive_msg(header.length);
755 break;
756 }
757 }
758
759 /*
760 * send the appropriate message given the current state
761 */
762
763 static void
send_packet(void)764 send_packet(void)
765 {
766 int rtx;
767
768 switch (state) {
769 case XDM_QUERY:
770 case XDM_BROADCAST:
771 case XDM_INDIRECT:
772 #if defined(IPv6) && defined(AF_INET6)
773 case XDM_MULTICAST:
774 #endif
775 send_query_msg();
776 break;
777 case XDM_START_CONNECTION:
778 send_request_msg();
779 break;
780 case XDM_MANAGE:
781 send_manage_msg();
782 break;
783 case XDM_KEEPALIVE:
784 send_keepalive_msg();
785 break;
786 default:
787 break;
788 }
789 rtx = (XDM_MIN_RTX << timeOutRtx);
790 if (rtx > XDM_MAX_RTX)
791 rtx = XDM_MAX_RTX;
792 TimerSet(xdmcp_timer, 0, rtx * 1000, XdmcpTimerNotify, NULL);
793 }
794
795 /*
796 * The session is declared dead for some reason; too many
797 * timeouts, or Keepalive failure.
798 */
799
800 static void
XdmcpDeadSession(const char * reason)801 XdmcpDeadSession(const char *reason)
802 {
803 ErrorF("XDM: %s, declaring session dead\n", reason);
804 state = XDM_INIT_STATE;
805 isItTimeToYield = TRUE;
806 dispatchException |= (OneSession ? DE_TERMINATE : DE_RESET);
807 TimerCancel(xdmcp_timer);
808 timeOutRtx = 0;
809 send_packet();
810 }
811
812 /*
813 * Timeout waiting for an XDMCP response.
814 */
815
816 static void
timeout(void)817 timeout(void)
818 {
819 timeOutRtx++;
820 if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT) {
821 XdmcpDeadSession("too many keepalive retransmissions");
822 return;
823 }
824 else if (timeOutRtx >= XDM_RTX_LIMIT) {
825 /* Quit if "-once" specified, otherwise reset and try again. */
826 if (OneSession) {
827 dispatchException |= DE_TERMINATE;
828 ErrorF("XDM: too many retransmissions\n");
829 }
830 else {
831 XdmcpDeadSession("too many retransmissions");
832 }
833 return;
834 }
835
836 #if defined(IPv6) && defined(AF_INET6)
837 if (state == XDM_COLLECT_QUERY || state == XDM_COLLECT_INDIRECT_QUERY) {
838 /* Try next address */
839 for (mgrAddr = mgrAddr->ai_next;; mgrAddr = mgrAddr->ai_next) {
840 if (mgrAddr == NULL) {
841 mgrAddr = mgrAddrFirst;
842 }
843 if (mgrAddr->ai_family == AF_INET || mgrAddr->ai_family == AF_INET6)
844 break;
845 }
846 #ifndef SIN6_LEN
847 ManagerAddressLen = mgrAddr->ai_addrlen;
848 #endif
849 memcpy(&ManagerAddress, mgrAddr->ai_addr, mgrAddr->ai_addrlen);
850 }
851 #endif
852
853 switch (state) {
854 case XDM_COLLECT_QUERY:
855 state = XDM_QUERY;
856 break;
857 case XDM_COLLECT_BROADCAST_QUERY:
858 state = XDM_BROADCAST;
859 break;
860 #if defined(IPv6) && defined(AF_INET6)
861 case XDM_COLLECT_MULTICAST_QUERY:
862 state = XDM_MULTICAST;
863 break;
864 #endif
865 case XDM_COLLECT_INDIRECT_QUERY:
866 state = XDM_INDIRECT;
867 break;
868 case XDM_AWAIT_REQUEST_RESPONSE:
869 state = XDM_START_CONNECTION;
870 break;
871 case XDM_AWAIT_MANAGE_RESPONSE:
872 state = XDM_MANAGE;
873 break;
874 case XDM_AWAIT_ALIVE_RESPONSE:
875 state = XDM_KEEPALIVE;
876 break;
877 default:
878 break;
879 }
880 send_packet();
881 }
882
883 static int
XdmcpCheckAuthentication(ARRAY8Ptr Name,ARRAY8Ptr Data,int packet_type)884 XdmcpCheckAuthentication(ARRAY8Ptr Name, ARRAY8Ptr Data, int packet_type)
885 {
886 return (XdmcpARRAY8Equal(Name, AuthenticationName) &&
887 (AuthenticationName->length == 0 ||
888 (*AuthenticationFuncs->Validator) (AuthenticationData, Data,
889 packet_type)));
890 }
891
892 static int
XdmcpAddAuthorization(ARRAY8Ptr name,ARRAY8Ptr data)893 XdmcpAddAuthorization(ARRAY8Ptr name, ARRAY8Ptr data)
894 {
895 AddAuthorFunc AddAuth;
896
897 if (AuthenticationFuncs && AuthenticationFuncs->AddAuth)
898 AddAuth = AuthenticationFuncs->AddAuth;
899 else
900 AddAuth = AddAuthorization;
901 return (*AddAuth) ((unsigned short) name->length,
902 (char *) name->data,
903 (unsigned short) data->length, (char *) data->data);
904 }
905
906 /*
907 * from here to the end of this file are routines private
908 * to the state machine.
909 */
910
911 static void
get_xdmcp_sock(void)912 get_xdmcp_sock(void)
913 {
914 int soopts = 1;
915
916 #if defined(IPv6) && defined(AF_INET6)
917 if ((xdmcpSocket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
918 XdmcpWarning("INET6 UDP socket creation failed");
919 #endif
920 if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
921 XdmcpWarning("UDP socket creation failed");
922 #ifdef SO_BROADCAST
923 else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *) &soopts,
924 sizeof(soopts)) < 0)
925 XdmcpWarning("UDP set broadcast socket-option failed");
926 #endif /* SO_BROADCAST */
927 if (xdmcpSocket >= 0 && xdm_from != NULL) {
928 if (bind(xdmcpSocket, (struct sockaddr *) &FromAddress,
929 FromAddressLen) < 0) {
930 FatalError("Xserver: failed to bind to -from address: %s\n",
931 xdm_from);
932 }
933 }
934 }
935
936 static void
send_query_msg(void)937 send_query_msg(void)
938 {
939 XdmcpHeader header;
940 Bool broadcast = FALSE;
941
942 #if defined(IPv6) && defined(AF_INET6)
943 Bool multicast = FALSE;
944 #endif
945 int i;
946 int socketfd = xdmcpSocket;
947
948 header.version = XDM_PROTOCOL_VERSION;
949 switch (state) {
950 case XDM_QUERY:
951 header.opcode = (CARD16) QUERY;
952 state = XDM_COLLECT_QUERY;
953 break;
954 case XDM_BROADCAST:
955 header.opcode = (CARD16) BROADCAST_QUERY;
956 state = XDM_COLLECT_BROADCAST_QUERY;
957 broadcast = TRUE;
958 break;
959 #if defined(IPv6) && defined(AF_INET6)
960 case XDM_MULTICAST:
961 header.opcode = (CARD16) BROADCAST_QUERY;
962 state = XDM_COLLECT_MULTICAST_QUERY;
963 multicast = TRUE;
964 break;
965 #endif
966 case XDM_INDIRECT:
967 header.opcode = (CARD16) INDIRECT_QUERY;
968 state = XDM_COLLECT_INDIRECT_QUERY;
969 break;
970 default:
971 break;
972 }
973 header.length = 1;
974 for (i = 0; i < AuthenticationNames.length; i++)
975 header.length += 2 + AuthenticationNames.data[i].length;
976
977 XdmcpWriteHeader(&buffer, &header);
978 XdmcpWriteARRAYofARRAY8(&buffer, &AuthenticationNames);
979 if (broadcast) {
980 for (i = 0; i < NumBroadcastAddresses; i++)
981 XdmcpFlush(xdmcpSocket, &buffer,
982 (XdmcpNetaddr) &BroadcastAddresses[i],
983 sizeof(struct sockaddr_in));
984 }
985 #if defined(IPv6) && defined(AF_INET6)
986 else if (multicast) {
987 struct multicastinfo *mcl;
988 struct addrinfo *ai;
989
990 for (mcl = mcastlist; mcl != NULL; mcl = mcl->next) {
991 for (ai = mcl->ai; ai != NULL; ai = ai->ai_next) {
992 if (ai->ai_family == AF_INET) {
993 unsigned char hopflag = (unsigned char) mcl->hops;
994
995 socketfd = xdmcpSocket;
996 setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_TTL,
997 &hopflag, sizeof(hopflag));
998 }
999 else if (ai->ai_family == AF_INET6) {
1000 int hopflag6 = mcl->hops;
1001
1002 socketfd = xdmcpSocket6;
1003 setsockopt(socketfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
1004 &hopflag6, sizeof(hopflag6));
1005 }
1006 else {
1007 continue;
1008 }
1009 XdmcpFlush(socketfd, &buffer,
1010 (XdmcpNetaddr) ai->ai_addr, ai->ai_addrlen);
1011 break;
1012 }
1013 }
1014 }
1015 #endif
1016 else {
1017 #if defined(IPv6) && defined(AF_INET6)
1018 if (SOCKADDR_FAMILY(ManagerAddress) == AF_INET6)
1019 socketfd = xdmcpSocket6;
1020 #endif
1021 XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &ManagerAddress,
1022 ManagerAddressLen);
1023 }
1024 }
1025
1026 static void
recv_willing_msg(struct sockaddr * from,int fromlen,unsigned length)1027 recv_willing_msg(struct sockaddr *from, int fromlen, unsigned length)
1028 {
1029 ARRAY8 authenticationName;
1030 ARRAY8 hostname;
1031 ARRAY8 status;
1032
1033 authenticationName.data = 0;
1034 hostname.data = 0;
1035 status.data = 0;
1036 if (XdmcpReadARRAY8(&buffer, &authenticationName) &&
1037 XdmcpReadARRAY8(&buffer, &hostname) &&
1038 XdmcpReadARRAY8(&buffer, &status)) {
1039 if (length == 6 + authenticationName.length +
1040 hostname.length + status.length) {
1041 switch (state) {
1042 case XDM_COLLECT_QUERY:
1043 XdmcpSelectHost(from, fromlen, &authenticationName);
1044 break;
1045 case XDM_COLLECT_BROADCAST_QUERY:
1046 #if defined(IPv6) && defined(AF_INET6)
1047 case XDM_COLLECT_MULTICAST_QUERY:
1048 #endif
1049 case XDM_COLLECT_INDIRECT_QUERY:
1050 XdmcpAddHost(from, fromlen, &authenticationName, &hostname,
1051 &status);
1052 break;
1053 default:
1054 break;
1055 }
1056 }
1057 }
1058 XdmcpDisposeARRAY8(&authenticationName);
1059 XdmcpDisposeARRAY8(&hostname);
1060 XdmcpDisposeARRAY8(&status);
1061 }
1062
1063 static void
send_request_msg(void)1064 send_request_msg(void)
1065 {
1066 XdmcpHeader header;
1067 int length;
1068 int i;
1069 CARD16 XdmcpConnectionType;
1070 ARRAY8 authenticationData;
1071 int socketfd = xdmcpSocket;
1072
1073 switch (SOCKADDR_FAMILY(ManagerAddress)) {
1074 case AF_INET:
1075 XdmcpConnectionType = FamilyInternet;
1076 break;
1077 #if defined(IPv6) && defined(AF_INET6)
1078 case AF_INET6:
1079 XdmcpConnectionType = FamilyInternet6;
1080 break;
1081 #endif
1082 default:
1083 XdmcpConnectionType = 0xffff;
1084 break;
1085 }
1086
1087 header.version = XDM_PROTOCOL_VERSION;
1088 header.opcode = (CARD16) REQUEST;
1089
1090 length = 2; /* display number */
1091 length += 1 + 2 * ConnectionTypes.length; /* connection types */
1092 length += 1; /* connection addresses */
1093 for (i = 0; i < ConnectionAddresses.length; i++)
1094 length += 2 + ConnectionAddresses.data[i].length;
1095 authenticationData.length = 0;
1096 authenticationData.data = 0;
1097 if (AuthenticationFuncs) {
1098 (*AuthenticationFuncs->Generator) (AuthenticationData,
1099 &authenticationData, REQUEST);
1100 }
1101 length += 2 + AuthenticationName->length; /* authentication name */
1102 length += 2 + authenticationData.length; /* authentication data */
1103 length += 1; /* authorization names */
1104 for (i = 0; i < AuthorizationNames.length; i++)
1105 length += 2 + AuthorizationNames.data[i].length;
1106 length += 2 + ManufacturerDisplayID.length; /* display ID */
1107 header.length = length;
1108
1109 if (!XdmcpWriteHeader(&buffer, &header)) {
1110 XdmcpDisposeARRAY8(&authenticationData);
1111 return;
1112 }
1113 XdmcpWriteCARD16(&buffer, DisplayNumber);
1114 XdmcpWriteCARD8(&buffer, ConnectionTypes.length);
1115
1116 /* The connection array is send reordered, so that connections of */
1117 /* the same address type as the XDMCP manager connection are send */
1118 /* first. This works around a bug in xdm. mario@klebsch.de */
1119 for (i = 0; i < (int) ConnectionTypes.length; i++)
1120 if (ConnectionTypes.data[i] == XdmcpConnectionType)
1121 XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]);
1122 for (i = 0; i < (int) ConnectionTypes.length; i++)
1123 if (ConnectionTypes.data[i] != XdmcpConnectionType)
1124 XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]);
1125
1126 XdmcpWriteCARD8(&buffer, ConnectionAddresses.length);
1127 for (i = 0; i < (int) ConnectionAddresses.length; i++)
1128 if ((i < ConnectionTypes.length) &&
1129 (ConnectionTypes.data[i] == XdmcpConnectionType))
1130 XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]);
1131 for (i = 0; i < (int) ConnectionAddresses.length; i++)
1132 if ((i >= ConnectionTypes.length) ||
1133 (ConnectionTypes.data[i] != XdmcpConnectionType))
1134 XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]);
1135
1136 XdmcpWriteARRAY8(&buffer, AuthenticationName);
1137 XdmcpWriteARRAY8(&buffer, &authenticationData);
1138 XdmcpDisposeARRAY8(&authenticationData);
1139 XdmcpWriteARRAYofARRAY8(&buffer, &AuthorizationNames);
1140 XdmcpWriteARRAY8(&buffer, &ManufacturerDisplayID);
1141 #if defined(IPv6) && defined(AF_INET6)
1142 if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
1143 socketfd = xdmcpSocket6;
1144 #endif
1145 if (XdmcpFlush(socketfd, &buffer,
1146 (XdmcpNetaddr) &req_sockaddr, req_socklen))
1147 state = XDM_AWAIT_REQUEST_RESPONSE;
1148 }
1149
1150 static void
recv_accept_msg(unsigned length)1151 recv_accept_msg(unsigned length)
1152 {
1153 CARD32 AcceptSessionID;
1154 ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData;
1155 ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData;
1156
1157 if (state != XDM_AWAIT_REQUEST_RESPONSE)
1158 return;
1159 AcceptAuthenticationName.data = 0;
1160 AcceptAuthenticationData.data = 0;
1161 AcceptAuthorizationName.data = 0;
1162 AcceptAuthorizationData.data = 0;
1163 if (XdmcpReadCARD32(&buffer, &AcceptSessionID) &&
1164 XdmcpReadARRAY8(&buffer, &AcceptAuthenticationName) &&
1165 XdmcpReadARRAY8(&buffer, &AcceptAuthenticationData) &&
1166 XdmcpReadARRAY8(&buffer, &AcceptAuthorizationName) &&
1167 XdmcpReadARRAY8(&buffer, &AcceptAuthorizationData)) {
1168 if (length == 12 + AcceptAuthenticationName.length +
1169 AcceptAuthenticationData.length +
1170 AcceptAuthorizationName.length + AcceptAuthorizationData.length) {
1171 if (!XdmcpCheckAuthentication(&AcceptAuthenticationName,
1172 &AcceptAuthenticationData, ACCEPT)) {
1173 XdmcpFatal("Authentication Failure", &AcceptAuthenticationName);
1174 }
1175 /* permit access control manipulations from this host */
1176 AugmentSelf(&req_sockaddr, req_socklen);
1177 /* if the authorization specified in the packet fails
1178 * to be acceptable, enable the local addresses
1179 */
1180 if (!XdmcpAddAuthorization(&AcceptAuthorizationName,
1181 &AcceptAuthorizationData)) {
1182 AddLocalHosts();
1183 }
1184 SessionID = AcceptSessionID;
1185 state = XDM_MANAGE;
1186 send_packet();
1187 }
1188 }
1189 XdmcpDisposeARRAY8(&AcceptAuthenticationName);
1190 XdmcpDisposeARRAY8(&AcceptAuthenticationData);
1191 XdmcpDisposeARRAY8(&AcceptAuthorizationName);
1192 XdmcpDisposeARRAY8(&AcceptAuthorizationData);
1193 }
1194
1195 static void
recv_decline_msg(unsigned length)1196 recv_decline_msg(unsigned length)
1197 {
1198 ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData;
1199
1200 status.data = 0;
1201 DeclineAuthenticationName.data = 0;
1202 DeclineAuthenticationData.data = 0;
1203 if (XdmcpReadARRAY8(&buffer, &status) &&
1204 XdmcpReadARRAY8(&buffer, &DeclineAuthenticationName) &&
1205 XdmcpReadARRAY8(&buffer, &DeclineAuthenticationData)) {
1206 if (length == 6 + status.length +
1207 DeclineAuthenticationName.length +
1208 DeclineAuthenticationData.length &&
1209 XdmcpCheckAuthentication(&DeclineAuthenticationName,
1210 &DeclineAuthenticationData, DECLINE)) {
1211 XdmcpFatal("Session declined", &status);
1212 }
1213 }
1214 XdmcpDisposeARRAY8(&status);
1215 XdmcpDisposeARRAY8(&DeclineAuthenticationName);
1216 XdmcpDisposeARRAY8(&DeclineAuthenticationData);
1217 }
1218
1219 static void
send_manage_msg(void)1220 send_manage_msg(void)
1221 {
1222 XdmcpHeader header;
1223 int socketfd = xdmcpSocket;
1224
1225 header.version = XDM_PROTOCOL_VERSION;
1226 header.opcode = (CARD16) MANAGE;
1227 header.length = 8 + DisplayClass.length;
1228
1229 if (!XdmcpWriteHeader(&buffer, &header))
1230 return;
1231 XdmcpWriteCARD32(&buffer, SessionID);
1232 XdmcpWriteCARD16(&buffer, DisplayNumber);
1233 XdmcpWriteARRAY8(&buffer, &DisplayClass);
1234 state = XDM_AWAIT_MANAGE_RESPONSE;
1235 #if defined(IPv6) && defined(AF_INET6)
1236 if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
1237 socketfd = xdmcpSocket6;
1238 #endif
1239 XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
1240 }
1241
1242 static void
recv_refuse_msg(unsigned length)1243 recv_refuse_msg(unsigned length)
1244 {
1245 CARD32 RefusedSessionID;
1246
1247 if (state != XDM_AWAIT_MANAGE_RESPONSE)
1248 return;
1249 if (length != 4)
1250 return;
1251 if (XdmcpReadCARD32(&buffer, &RefusedSessionID)) {
1252 if (RefusedSessionID == SessionID) {
1253 state = XDM_START_CONNECTION;
1254 send_packet();
1255 }
1256 }
1257 }
1258
1259 static void
recv_failed_msg(unsigned length)1260 recv_failed_msg(unsigned length)
1261 {
1262 CARD32 FailedSessionID;
1263 ARRAY8 status;
1264
1265 if (state != XDM_AWAIT_MANAGE_RESPONSE)
1266 return;
1267 status.data = 0;
1268 if (XdmcpReadCARD32(&buffer, &FailedSessionID) &&
1269 XdmcpReadARRAY8(&buffer, &status)) {
1270 if (length == 6 + status.length && SessionID == FailedSessionID) {
1271 XdmcpFatal("Session failed", &status);
1272 }
1273 }
1274 XdmcpDisposeARRAY8(&status);
1275 }
1276
1277 static void
send_keepalive_msg(void)1278 send_keepalive_msg(void)
1279 {
1280 XdmcpHeader header;
1281 int socketfd = xdmcpSocket;
1282
1283 header.version = XDM_PROTOCOL_VERSION;
1284 header.opcode = (CARD16) KEEPALIVE;
1285 header.length = 6;
1286
1287 XdmcpWriteHeader(&buffer, &header);
1288 XdmcpWriteCARD16(&buffer, DisplayNumber);
1289 XdmcpWriteCARD32(&buffer, SessionID);
1290
1291 state = XDM_AWAIT_ALIVE_RESPONSE;
1292 #if defined(IPv6) && defined(AF_INET6)
1293 if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
1294 socketfd = xdmcpSocket6;
1295 #endif
1296 XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
1297 }
1298
1299 static void
recv_alive_msg(unsigned length)1300 recv_alive_msg(unsigned length)
1301 {
1302 CARD8 SessionRunning;
1303 CARD32 AliveSessionID;
1304
1305 if (state != XDM_AWAIT_ALIVE_RESPONSE)
1306 return;
1307 if (length != 5)
1308 return;
1309 if (XdmcpReadCARD8(&buffer, &SessionRunning) &&
1310 XdmcpReadCARD32(&buffer, &AliveSessionID)) {
1311 if (SessionRunning && AliveSessionID == SessionID) {
1312 state = XDM_RUN_SESSION;
1313 TimerSet(xdmcp_timer, 0, XDM_DEF_DORMANCY * 1000, XdmcpTimerNotify, NULL);
1314 }
1315 else {
1316 XdmcpDeadSession("Alive response indicates session dead");
1317 }
1318 }
1319 }
1320
1321 _X_NORETURN
1322 static void
XdmcpFatal(const char * type,ARRAY8Ptr status)1323 XdmcpFatal(const char *type, ARRAY8Ptr status)
1324 {
1325 FatalError("XDMCP fatal error: %s %*.*s\n", type,
1326 status->length, status->length, status->data);
1327 }
1328
1329 static void
XdmcpWarning(const char * str)1330 XdmcpWarning(const char *str)
1331 {
1332 ErrorF("XDMCP warning: %s\n", str);
1333 }
1334
1335 static void
get_addr_by_name(const char * argtype,const char * namestr,int port,int socktype,SOCKADDR_TYPE * addr,SOCKLEN_TYPE * addrlen,struct addrinfo ** aip,struct addrinfo ** aifirstp)1336 get_addr_by_name(const char *argtype,
1337 const char *namestr,
1338 int port,
1339 int socktype, SOCKADDR_TYPE * addr, SOCKLEN_TYPE * addrlen
1340 #if defined(IPv6) && defined(AF_INET6)
1341 , struct addrinfo **aip, struct addrinfo **aifirstp
1342 #endif
1343 )
1344 {
1345 #if defined(IPv6) && defined(AF_INET6)
1346 struct addrinfo *ai;
1347 struct addrinfo hints;
1348 char portstr[6];
1349 char *pport = portstr;
1350 int gaierr;
1351
1352 memset(&hints, 0, sizeof(hints));
1353 hints.ai_socktype = socktype;
1354
1355 if (port == 0) {
1356 pport = NULL;
1357 }
1358 else if (port > 0 && port < 65535) {
1359 snprintf(portstr, sizeof(portstr), "%d", port);
1360 }
1361 else {
1362 FatalError("Xserver: port out of range: %d\n", port);
1363 }
1364
1365 if (*aifirstp != NULL) {
1366 freeaddrinfo(*aifirstp);
1367 *aifirstp = NULL;
1368 }
1369
1370 if ((gaierr = getaddrinfo(namestr, pport, &hints, aifirstp)) == 0) {
1371 for (ai = *aifirstp; ai != NULL; ai = ai->ai_next) {
1372 if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6)
1373 break;
1374 }
1375 if ((ai == NULL) || (ai->ai_addrlen > sizeof(SOCKADDR_TYPE))) {
1376 FatalError("Xserver: %s host %s not on supported network type\n",
1377 argtype, namestr);
1378 }
1379 else {
1380 *aip = ai;
1381 *addrlen = ai->ai_addrlen;
1382 memcpy(addr, ai->ai_addr, ai->ai_addrlen);
1383 }
1384 }
1385 else {
1386 FatalError("Xserver: %s: %s %s\n", gai_strerror(gaierr), argtype,
1387 namestr);
1388 }
1389 #else
1390 struct hostent *hep;
1391
1392 #ifdef XTHREADS_NEEDS_BYNAMEPARAMS
1393 _Xgethostbynameparams hparams;
1394 #endif
1395 #if defined(WIN32) && defined(TCPCONN)
1396 _XSERVTransWSAStartup();
1397 #endif
1398 if (!(hep = _XGethostbyname(namestr, hparams))) {
1399 FatalError("Xserver: %s unknown host: %s\n", argtype, namestr);
1400 }
1401 if (hep->h_length == sizeof(struct in_addr)) {
1402 memmove(&addr->sin_addr, hep->h_addr, hep->h_length);
1403 *addrlen = sizeof(struct sockaddr_in);
1404 addr->sin_family = AF_INET;
1405 addr->sin_port = htons(port);
1406 }
1407 else {
1408 FatalError("Xserver: %s host on strange network %s\n", argtype,
1409 namestr);
1410 }
1411 #endif
1412 }
1413
1414 static void
get_manager_by_name(int argc,char ** argv,int i)1415 get_manager_by_name(int argc, char **argv, int i)
1416 {
1417
1418 if ((i + 1) == argc) {
1419 FatalError("Xserver: missing %s host name in command line\n", argv[i]);
1420 }
1421
1422 get_addr_by_name(argv[i], argv[i + 1], xdm_udp_port, SOCK_DGRAM,
1423 &ManagerAddress, &ManagerAddressLen
1424 #if defined(IPv6) && defined(AF_INET6)
1425 , &mgrAddr, &mgrAddrFirst
1426 #endif
1427 );
1428 }
1429
1430 static void
get_fromaddr_by_name(int argc,char ** argv,int i)1431 get_fromaddr_by_name(int argc, char **argv, int i)
1432 {
1433 #if defined(IPv6) && defined(AF_INET6)
1434 struct addrinfo *ai = NULL;
1435 struct addrinfo *aifirst = NULL;
1436 #endif
1437 if (i == argc) {
1438 FatalError("Xserver: missing -from host name in command line\n");
1439 }
1440 get_addr_by_name("-from", argv[i], 0, 0, &FromAddress, &FromAddressLen
1441 #if defined(IPv6) && defined(AF_INET6)
1442 , &ai, &aifirst
1443 #endif
1444 );
1445 #if defined(IPv6) && defined(AF_INET6)
1446 if (aifirst != NULL)
1447 freeaddrinfo(aifirst);
1448 #endif
1449 xdm_from = argv[i];
1450 }
1451
1452 #if defined(IPv6) && defined(AF_INET6)
1453 static int
get_mcast_options(int argc,char ** argv,int i)1454 get_mcast_options(int argc, char **argv, int i)
1455 {
1456 const char *address = XDM_DEFAULT_MCAST_ADDR6;
1457 int hopcount = 1;
1458 struct addrinfo hints;
1459 char portstr[6];
1460 int gaierr;
1461 struct addrinfo *ai, *firstai;
1462
1463 if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
1464 address = argv[i++];
1465 if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
1466 hopcount = strtol(argv[i++], NULL, 10);
1467 if ((hopcount < 1) || (hopcount > 255)) {
1468 FatalError("Xserver: multicast hop count out of range: %d\n",
1469 hopcount);
1470 }
1471 }
1472 }
1473
1474 if (xdm_udp_port > 0 && xdm_udp_port < 65535) {
1475 snprintf(portstr, sizeof(portstr), "%d", xdm_udp_port);
1476 }
1477 else {
1478 FatalError("Xserver: port out of range: %d\n", xdm_udp_port);
1479 }
1480 memset(&hints, 0, sizeof(hints));
1481 hints.ai_socktype = SOCK_DGRAM;
1482
1483 if ((gaierr = getaddrinfo(address, portstr, &hints, &firstai)) == 0) {
1484 for (ai = firstai; ai != NULL; ai = ai->ai_next) {
1485 if (((ai->ai_family == AF_INET) &&
1486 IN_MULTICAST(((struct sockaddr_in *) ai->ai_addr)
1487 ->sin_addr.s_addr))
1488 || ((ai->ai_family == AF_INET6) &&
1489 IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *) ai->ai_addr)
1490 ->sin6_addr)))
1491 break;
1492 }
1493 if (ai == NULL) {
1494 FatalError("Xserver: address not supported multicast type %s\n",
1495 address);
1496 }
1497 else {
1498 struct multicastinfo *mcastinfo, *mcl;
1499
1500 mcastinfo = malloc(sizeof(struct multicastinfo));
1501 mcastinfo->next = NULL;
1502 mcastinfo->ai = firstai;
1503 mcastinfo->hops = hopcount;
1504
1505 if (mcastlist == NULL) {
1506 mcastlist = mcastinfo;
1507 }
1508 else {
1509 for (mcl = mcastlist; mcl->next != NULL; mcl = mcl->next) {
1510 /* Do nothing - just find end of list */
1511 }
1512 mcl->next = mcastinfo;
1513 }
1514 }
1515 }
1516 else {
1517 FatalError("Xserver: %s: %s\n", gai_strerror(gaierr), address);
1518 }
1519 return i;
1520 }
1521 #endif
1522
1523 #else
1524 static int xdmcp_non_empty; /* avoid complaint by ranlib */
1525 #endif /* XDMCP */
1526