xdmcp.c 46 KB

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