2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: xdmcp.c /main/5 1998/04/06 13:36:04 mgreess $ */
24 /* (c) Copyright 1997 The Open Group */
26 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
27 * (c) Copyright 1993, 1994 International Business Machines Corp. *
28 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
29 * (c) Copyright 1993, 1994 Novell, Inc. *
38 * Revision 1.1.2.3 1995/06/06 20:25:54 Chris_Beute
39 * Code snapshot merge from March 15 and SIA changes
40 * [1995/05/31 20:17:42 Chris_Beute]
42 * Revision 1.1.2.2 1995/04/21 13:05:47 Peter_Derr
43 * dtlogin auth key fixes from deltacde
44 * [1995/04/14 18:03:44 Peter_Derr]
46 * Merge in dtlogin changes to WaitForSomething() to support command
48 * [1995/04/14 17:40:05 Peter_Derr]
50 * Use R6 xdm code to handle XDMCP
51 * [1995/04/10 19:24:11 Peter_Derr]
57 Copyright (c) 1988 X Consortium
59 Permission is hereby granted, free of charge, to any person obtaining
60 a copy of this software and associated documentation files (the
61 "Software"), to deal in the Software without restriction, including
62 without limitation the rights to use, copy, modify, merge, publish,
63 distribute, sublicense, and/or sell copies of the Software, and to
64 permit persons to whom the Software is furnished to do so, subject to
65 the following conditions:
67 The above copyright notice and this permission notice shall be included
68 in all copies or substantial portions of the Software.
70 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
71 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
72 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
73 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
74 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
75 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
76 OTHER DEALINGS IN THE SOFTWARE.
78 Except as contained in this notice, the name of the X Consortium shall
79 not be used in advertising or otherwise to promote the sale, use or
80 other dealings in this Software without prior written authorization
81 from the X Consortium.
86 * xdm - display manager daemon
87 * Author: Keith Packard, MIT X Consortium
89 * xdmcp.c - Support for XDMCP
95 # include <X11/Xfuncs.h>
96 # include <sys/types.h>
99 #include <sys/socket.h>
100 #include <netinet/in.h>
104 #ifdef X_NOT_STDC_ENV
106 extern Time_t time ();
109 #define Time_t time_t
112 #define getString(name,len) ((name = malloc (len + 1)) ? 1 : 0)
115 * interface to policy routines
118 extern ARRAY8Ptr ChooseAuthentication ();
119 extern int SelectConnectionTypeIndex ();
121 void query_respond (from, fromlen, length);
122 void forward_respond (struct sockaddr *from, int fromlen, int length);
123 void request_respond (struct sockaddr *from, int fromlen, int length);
124 void send_willing (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status);
125 void send_unwilling (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status);
126 void send_accept (struct sockaddr *to, int tolen, CARD32 sessionID, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr authorizationName, ARRAY8Ptr authorizationData);
127 void manage (struct sockaddr *from, int fromlen, int length);
128 void send_decline (struct sockaddr *to, int tolen, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr status);
134 FD_TYPE WellKnownSocketsMask;
135 int WellKnownSocketsMax;
137 #define pS(s) ((s) ? ((char *) (s)) : "empty string")
140 DestroyWellKnownSockets (void)
155 AnyWellKnownSockets (void)
157 return xdmcpFd != -1 || chooserFd != -1;
160 static XdmcpBuffer buffer;
164 sendForward (CARD16 connectionType, ARRAY8Ptr address, char *closure)
167 struct sockaddr_in in_addr;
171 struct sockaddr *addr;
174 switch (connectionType)
178 addr = (struct sockaddr *) &in_addr;
179 bzero ((char *) &in_addr, sizeof (in_addr));
181 in_addr.sin_len = sizeof(in_addr);
183 in_addr.sin_family = AF_INET;
184 in_addr.sin_port = htons ((short) XDM_UDP_PORT);
185 if (address->length != 4)
187 memmove( (char *) &in_addr.sin_addr, address->data, address->length);
188 addrlen = sizeof (struct sockaddr_in);
197 XdmcpFlush (xdmcpFd, &buffer, addr, addrlen);
201 extern char *NetaddrAddress();
202 extern char *NetaddrPort();
205 ClientAddress (struct sockaddr *from, ARRAY8Ptr addr, ARRAY8Ptr port, CARD16 *type)
210 data = NetaddrPort(from, &length);
211 XdmcpAllocARRAY8 (port, length);
212 memmove( port->data, data, length);
213 port->length = length;
215 family = ConvertAddr((char *)from, &length, &data);
217 XdmcpAllocARRAY8 (addr, length);
218 memmove( addr->data, data, length);
219 addr->length = length;
225 all_query_respond (struct sockaddr *from, int fromlen, ARRAYofARRAY8Ptr authenticationNames, xdmOpCode type)
227 ARRAY8Ptr authenticationName;
230 CARD16 connectionType;
234 family = ConvertAddr((char *)from, &length, (char **) &(addr.data));
236 addr.length = length; /* convert int to short */
237 Debug ("all_query_respond: conntype=%d, addr=%lx, len=%d\n",
238 family, *(addr.data), addr.length);
241 connectionType = family;
243 if (type == INDIRECT_QUERY)
244 RememberIndirectClient (&addr, connectionType);
246 ForgetIndirectClient (&addr, connectionType);
248 authenticationName = ChooseAuthentication (authenticationNames);
249 if (Willing (&addr, connectionType, authenticationName, &status, type))
250 send_willing (from, fromlen, authenticationName, &status);
253 send_unwilling (from, fromlen, authenticationName, &status);
254 XdmcpDisposeARRAY8 (&status);
258 indirect_respond (struct sockaddr *from, int fromlen, int length)
260 ARRAYofARRAY8 queryAuthenticationNames;
261 ARRAY8 clientAddress;
263 CARD16 connectionType;
269 Debug ("Indirect respond %d\n", length);
270 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
273 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
274 expectedLen += 2 + queryAuthenticationNames.data[i].length;
275 if (length == expectedLen)
277 ClientAddress (from, &clientAddress, &clientPort, &connectionType);
279 * set up the forward query packet
281 header.version = XDM_PROTOCOL_VERSION;
282 header.opcode = (CARD16) FORWARD_QUERY;
284 header.length += 2 + clientAddress.length;
285 header.length += 2 + clientPort.length;
287 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
288 header.length += 2 + queryAuthenticationNames.data[i].length;
289 XdmcpWriteHeader (&buffer, &header);
290 XdmcpWriteARRAY8 (&buffer, &clientAddress);
291 XdmcpWriteARRAY8 (&buffer, &clientPort);
292 XdmcpWriteARRAYofARRAY8 (&buffer, &queryAuthenticationNames);
294 localHostAsWell = ForEachMatchingIndirectHost (&clientAddress, connectionType, sendForward, (char *) 0);
296 XdmcpDisposeARRAY8 (&clientAddress);
297 XdmcpDisposeARRAY8 (&clientPort);
299 all_query_respond (from, fromlen, &queryAuthenticationNames,
304 Debug ("Indirect length error got %d expect %d\n", length, expectedLen);
306 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
310 ProcessRequestSocket (void)
313 struct sockaddr_in addr;
314 int addrlen = sizeof addr;
316 Debug ("ProcessRequestSocket\n");
317 bzero ((char *) &addr, sizeof (addr));
318 if (!XdmcpFill (xdmcpFd, &buffer, &addr, &addrlen)) {
319 Debug ("XdmcpFill failed\n");
322 if (!XdmcpReadHeader (&buffer, &header)) {
323 Debug ("XdmcpReadHeader failed\n");
326 if (header.version != XDM_PROTOCOL_VERSION) {
327 Debug ("XDMCP header version read was %d, expected %d\n",
328 header.version, XDM_PROTOCOL_VERSION);
331 Debug ("header: %d %d %d\n", header.version, header.opcode, header.length);
332 switch (header.opcode)
334 case BROADCAST_QUERY:
335 broadcast_respond (&addr, addrlen, header.length);
338 query_respond (&addr, addrlen, header.length);
341 indirect_respond (&addr, addrlen, header.length);
344 forward_respond (&addr, addrlen, header.length);
347 request_respond (&addr, addrlen, header.length);
350 manage (&addr, addrlen, header.length);
353 send_alive (&addr, addrlen, header.length);
359 * dtlogin changes to WaitForSomething () merged in to support command line
362 void WaitForSomething (void)
365 struct timeval timeout, *ptimeout;
367 extern int Rescan, ChildReady, wakeupTime;
369 Debug ("WaitForSomething\n");
370 if (AnyWellKnownSockets () && !ChildReady || wakeupTime > 0 ) {
371 reads = WellKnownSocketsMask;
373 if (wakeupTime >= 0 ) {
374 timeout.tv_sec = wakeupTime;
375 timeout.tv_usec = 10;
377 Debug("Setting timer on select() for %d seconds.\n", wakeupTime);
383 nready = select (WellKnownSocketsMax + 1, (int *) &reads, 0, 0, ptimeout);
385 nready = select (WellKnownSocketsMax + 1, &reads, 0, 0, ptimeout);
387 Debug ("select returns %d. Rescan: %d ChildReady: %d\n",
388 nready, Rescan, ChildReady);
391 if (xdmcpFd >= 0 && FD_ISSET (xdmcpFd, &reads))
392 ProcessRequestSocket ();
393 if (chooserFd >= 0 && FD_ISSET (chooserFd, &reads))
394 ProcessChooserSocket (chooserFd);
407 * respond to a request on the UDP socket.
410 static ARRAY8 Hostname;
413 registerHostname (char *name, int namelen)
417 if (!XdmcpReallocARRAY8 (&Hostname, namelen))
419 for (i = 0; i < namelen; i++)
420 Hostname.data[i] = name[i];
424 direct_query_respond (struct sockaddr *from, int fromlen, int length, xdmOpCode type)
426 ARRAYofARRAY8 queryAuthenticationNames;
430 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
433 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
434 expectedLen += 2 + queryAuthenticationNames.data[i].length;
435 if (length == expectedLen)
436 all_query_respond (from, fromlen, &queryAuthenticationNames, type);
437 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
441 query_respond (struct sockaddr *from, int fromlen, int length)
443 Debug ("Query respond %d\n", length);
444 direct_query_respond (from, fromlen, length, QUERY);
448 broadcast_respond (struct sockaddr *from, int fromlen, int length)
450 direct_query_respond (from, fromlen, length, BROADCAST_QUERY);
453 /* computes an X display name */
454 #if NeedWidePrototypes
456 NetworkAddressToName(int connectionType, ARRAY8Ptr connectionAddress, int displayNumber)
459 NetworkAddressToName(CARD16 connectionType, ARRAY8Ptr connectionAddress, CARD16 displayNumber)
462 switch (connectionType)
467 struct hostent *hostent;
469 char *localhost, *localHostname();
471 data = connectionAddress->data;
472 hostent = gethostbyaddr ((char *)data,
473 connectionAddress->length, AF_INET);
475 localhost = localHostname ();
478 * protect against bogus host names
480 if (hostent && hostent->h_name && hostent->h_name[0]
481 && (hostent->h_name[0] != '.'))
483 if (!strcmp (localhost, hostent->h_name))
485 if (!getString (name, 10))
487 sprintf (name, ":%d", displayNumber);
491 if (removeDomainname)
493 char *localDot, *remoteDot;
495 /* check for a common domain name. This
496 * could reduce names by recognising common
497 * super-domain names as well, but I don't think
498 * this is as useful, and will confuse more
501 if ((localDot = strchr(localhost, '.')) &&
502 (remoteDot = strchr(hostent->h_name, '.')))
504 /* smash the name in place; it won't
507 if (!strcmp (localDot+1, remoteDot+1))
512 if (!getString (name, strlen (hostent->h_name) + 10))
514 sprintf (name, "%s:%d", hostent->h_name, displayNumber);
519 if (!getString (name, 25))
521 sprintf(name, "%d.%d.%d.%d:%d",
522 data[0], data[1], data[2], data[3], displayNumber);
537 forward_respond (struct sockaddr *from, int fromlen, int length)
539 ARRAY8 clientAddress;
541 ARRAYofARRAY8 authenticationNames;
542 struct sockaddr *client;
547 Debug ("Forward respond %d\n", length);
548 clientAddress.length = 0;
549 clientAddress.data = 0;
550 clientPort.length = 0;
552 authenticationNames.length = 0;
553 authenticationNames.data = 0;
554 if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
555 XdmcpReadARRAY8 (&buffer, &clientPort) &&
556 XdmcpReadARRAYofARRAY8 (&buffer, &authenticationNames))
559 expectedLen += 2 + clientAddress.length;
560 expectedLen += 2 + clientPort.length;
561 expectedLen += 1; /* authenticationNames */
562 for (i = 0; i < (int)authenticationNames.length; i++)
563 expectedLen += 2 + authenticationNames.data[i].length;
564 if (length == expectedLen)
569 for (i = 0; i < (int)clientPort.length; i++)
570 j = j * 256 + clientPort.data[i];
571 Debug ("Forward client address (port %d)", j);
572 for (i = 0; i < (int)clientAddress.length; i++)
573 Debug (" %d", clientAddress.data[i]);
575 switch (from->sa_family)
580 struct sockaddr_in in_addr;
582 if (clientAddress.length != 4 ||
583 clientPort.length != 2)
587 bzero ((char *) &in_addr, sizeof (in_addr));
589 in_addr.sin_len = sizeof(in_addr);
591 in_addr.sin_family = AF_INET;
592 memmove( &in_addr.sin_addr, clientAddress.data, 4);
593 memmove( (char *) &in_addr.sin_port, clientPort.data, 2);
594 client = (struct sockaddr *) &in_addr;
595 clientlen = sizeof (in_addr);
602 struct sockaddr_un un_addr;
604 if (clientAddress.length >= sizeof (un_addr.sun_path))
606 bzero ((char *) &un_addr, sizeof (un_addr));
607 un_addr.sun_family = AF_UNIX;
608 memmove( un_addr.sun_path, clientAddress.data, clientAddress.length);
609 un_addr.sun_path[clientAddress.length] = '\0';
610 client = (struct sockaddr *) &un_addr;
612 un_addr.sun_len = strlen(un_addr.sun_path);
613 clientlen = SUN_LEN(&un_addr);
615 clientlen = sizeof (un_addr);
629 all_query_respond (client, clientlen, &authenticationNames,
634 Debug ("Forward length error got %d expect %d\n", length, expectedLen);
638 XdmcpDisposeARRAY8 (&clientAddress);
639 XdmcpDisposeARRAY8 (&clientPort);
640 XdmcpDisposeARRAYofARRAY8 (&authenticationNames);
644 send_willing (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status)
648 Debug ("Send willing %*.*s %*.*s\n", authenticationName->length,
649 authenticationName->length,
650 pS(authenticationName->data),
654 header.version = XDM_PROTOCOL_VERSION;
655 header.opcode = (CARD16) WILLING;
656 header.length = 6 + authenticationName->length +
657 Hostname.length + status->length;
658 XdmcpWriteHeader (&buffer, &header);
659 XdmcpWriteARRAY8 (&buffer, authenticationName);
660 XdmcpWriteARRAY8 (&buffer, &Hostname);
661 XdmcpWriteARRAY8 (&buffer, status);
662 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
666 send_unwilling (struct sockaddr *from, int fromlen, ARRAY8Ptr authenticationName, ARRAY8Ptr status)
670 Debug ("Send unwilling %*.*s %*.*s\n", authenticationName->length,
671 authenticationName->length,
672 pS(authenticationName->data),
676 header.version = XDM_PROTOCOL_VERSION;
677 header.opcode = (CARD16) UNWILLING;
678 header.length = 4 + Hostname.length + status->length;
679 XdmcpWriteHeader (&buffer, &header);
680 XdmcpWriteARRAY8 (&buffer, &Hostname);
681 XdmcpWriteARRAY8 (&buffer, status);
682 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
685 static unsigned long globalSessionID;
687 #define NextSessionID() (++globalSessionID)
690 init_session_id(void)
692 /* Set randomly so we are unlikely to reuse id's from a previous
693 * incarnation so we don't say "Alive" to those displays.
694 * Start with low digits 0 to make debugging easier.
696 globalSessionID = (time((Time_t)0)&0x7fff) * 16000;
699 static ARRAY8 outOfMemory = { (CARD16) 13, (CARD8Ptr) "Out of memory" };
700 static ARRAY8 noValidAddr = { (CARD16) 16, (CARD8Ptr) "No valid address" };
701 static ARRAY8 noValidAuth = { (CARD16) 22, (CARD8Ptr) "No valid authorization" };
702 static ARRAY8 noAuthentic = { (CARD16) 29, (CARD8Ptr) "XDM has no authentication key" };
705 request_respond (struct sockaddr *from, int fromlen, int length)
707 CARD16 displayNumber;
708 ARRAY16 connectionTypes;
709 ARRAYofARRAY8 connectionAddresses;
710 ARRAY8 authenticationName;
711 ARRAY8 authenticationData;
712 ARRAYofARRAY8 authorizationNames;
713 ARRAY8 manufacturerDisplayID;
717 struct protoDisplay *pdpy;
718 ARRAY8 authorizationName, authorizationData;
719 ARRAY8Ptr connectionAddress;
721 Debug ("Request respond %d\n", length);
722 connectionTypes.data = 0;
723 connectionAddresses.data = 0;
724 authenticationName.data = 0;
725 authenticationData.data = 0;
726 authorizationNames.data = 0;
727 authorizationName.length = 0;
728 authorizationData.length = 0;
729 manufacturerDisplayID.data = 0;
730 if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
731 XdmcpReadARRAY16 (&buffer, &connectionTypes) &&
732 XdmcpReadARRAYofARRAY8 (&buffer, &connectionAddresses) &&
733 XdmcpReadARRAY8 (&buffer, &authenticationName) &&
734 XdmcpReadARRAY8 (&buffer, &authenticationData) &&
735 XdmcpReadARRAYofARRAY8 (&buffer, &authorizationNames) &&
736 XdmcpReadARRAY8 (&buffer, &manufacturerDisplayID))
739 expectlen += 2; /* displayNumber */
740 expectlen += 1 + 2*connectionTypes.length; /* connectionTypes */
741 expectlen += 1; /* connectionAddresses */
742 for (i = 0; i < (int)connectionAddresses.length; i++)
743 expectlen += 2 + connectionAddresses.data[i].length;
744 expectlen += 2 + authenticationName.length; /* authenticationName */
745 expectlen += 2 + authenticationData.length; /* authenticationData */
746 expectlen += 1; /* authoriationNames */
747 for (i = 0; i < (int)authorizationNames.length; i++)
748 expectlen += 2 + authorizationNames.data[i].length;
749 expectlen += 2 + manufacturerDisplayID.length; /* displayID */
750 if (expectlen != length)
752 Debug ("Request length error got %d expect %d\n", length, expectlen);
755 if (connectionTypes.length == 0 ||
756 connectionAddresses.length != connectionTypes.length)
758 reason = &noValidAddr;
762 pdpy = FindProtoDisplay (from, fromlen, displayNumber);
765 /* Check this Display against the Manager's policy */
766 reason = Accept (from, fromlen, displayNumber);
770 /* Check the Display's stream services against Manager's policy */
771 i = SelectConnectionTypeIndex (&connectionTypes,
772 &connectionAddresses);
774 reason = &noValidAddr;
778 /* The Manager considers this a new session */
779 connectionAddress = &connectionAddresses.data[i];
780 pdpy = NewProtoDisplay (from, fromlen, displayNumber,
781 connectionTypes.data[i], connectionAddress,
783 Debug ("NewProtoDisplay 0x%x\n", pdpy);
785 reason = &outOfMemory;
789 if (authorizationNames.length == 0)
792 j = SelectAuthorizationTypeIndex (&authenticationName,
793 &authorizationNames);
796 reason = &noValidAuth;
799 if (!CheckAuthentication (pdpy,
800 &manufacturerDisplayID,
802 &authenticationData))
804 reason = &noAuthentic;
807 if (j < (int)authorizationNames.length)
810 SetProtoDisplayAuthorization (pdpy,
811 (unsigned short) authorizationNames.data[j].length,
812 (char *) authorizationNames.data[j].data);
813 auth = pdpy->xdmcpAuthorization;
815 auth = pdpy->fileAuthorization;
818 authorizationName.length = auth->name_length;
819 authorizationName.data = (CARD8Ptr) auth->name;
820 authorizationData.length = auth->data_length;
821 authorizationData.data = (CARD8Ptr) auth->data;
826 send_accept (from, fromlen, pdpy->sessionID,
835 send_decline (from, fromlen, &authenticationName,
839 DisposeProtoDisplay (pdpy);
843 XdmcpDisposeARRAY16 (&connectionTypes);
844 XdmcpDisposeARRAYofARRAY8 (&connectionAddresses);
845 XdmcpDisposeARRAY8 (&authenticationName);
846 XdmcpDisposeARRAY8 (&authenticationData);
847 XdmcpDisposeARRAYofARRAY8 (&authorizationNames);
848 XdmcpDisposeARRAY8 (&manufacturerDisplayID);
852 send_accept (struct sockaddr *to, int tolen, CARD32 sessionID, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr authorizationName, ARRAY8Ptr authorizationData)
856 Debug ("Accept Session ID %d\n", sessionID);
857 header.version = XDM_PROTOCOL_VERSION;
858 header.opcode = (CARD16) ACCEPT;
859 header.length = 4; /* session ID */
860 header.length += 2 + authenticationName->length;
861 header.length += 2 + authenticationData->length;
862 header.length += 2 + authorizationName->length;
863 header.length += 2 + authorizationData->length;
864 XdmcpWriteHeader (&buffer, &header);
865 XdmcpWriteCARD32 (&buffer, sessionID);
866 XdmcpWriteARRAY8 (&buffer, authenticationName);
867 XdmcpWriteARRAY8 (&buffer, authenticationData);
868 XdmcpWriteARRAY8 (&buffer, authorizationName);
869 XdmcpWriteARRAY8 (&buffer, authorizationData);
870 XdmcpFlush (xdmcpFd, &buffer, to, tolen);
874 send_decline (struct sockaddr *to, int tolen, ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData, ARRAY8Ptr status)
878 Debug ("Decline %*.*s\n", status->length, status->length, pS(status->data));
879 header.version = XDM_PROTOCOL_VERSION;
880 header.opcode = (CARD16) DECLINE;
882 header.length += 2 + status->length;
883 header.length += 2 + authenticationName->length;
884 header.length += 2 + authenticationData->length;
885 XdmcpWriteHeader (&buffer, &header);
886 XdmcpWriteARRAY8 (&buffer, status);
887 XdmcpWriteARRAY8 (&buffer, authenticationName);
888 XdmcpWriteARRAY8 (&buffer, authenticationData);
889 XdmcpFlush (xdmcpFd, &buffer, to, tolen);
893 manage (struct sockaddr *from, int fromlen, int length)
896 CARD16 displayNumber;
899 struct protoDisplay *pdpy;
903 XdmcpNetaddr from_save;
904 ARRAY8 clientAddress, clientPort;
905 CARD16 connectionType;
907 Debug ("Manage %d\n", length);
908 displayClass.data = 0;
909 displayClass.length = 0;
910 if (XdmcpReadCARD32 (&buffer, &sessionID) &&
911 XdmcpReadCARD16 (&buffer, &displayNumber) &&
912 XdmcpReadARRAY8 (&buffer, &displayClass))
914 expectlen = 4 + /* session ID */
915 2 + /* displayNumber */
916 2 + displayClass.length; /* displayClass */
917 if (expectlen != length)
919 Debug ("Manage length error got %d expect %d\n", length, expectlen);
922 pdpy = FindProtoDisplay (from, fromlen, displayNumber);
923 Debug ("Manage Session ID %d, pdpy 0x%x\n", sessionID, pdpy);
924 if (!pdpy || pdpy->sessionID != sessionID)
927 * We may have already started a session for this display
928 * but it hasn't seen the response in the form of an
929 * XOpenDisplay() yet. So check if it is in the list of active
930 * displays, and if so check that the session id's match.
931 * If all this is true, then we have a duplicate request that
935 && (d = FindDisplayByAddress(from, fromlen, displayNumber))
936 && d->sessionID == sessionID) {
937 Debug("manage: got duplicate pkt, ignoring\n");
940 Debug ("Session ID %d refused\n", sessionID);
942 Debug ("Existing Session ID %d\n", pdpy->sessionID);
943 send_refuse (from, fromlen, sessionID);
947 name = NetworkAddressToName (pdpy->connectionType,
948 &pdpy->connectionAddress,
949 pdpy->displayNumber);
950 Debug ("Computed display name: %s\n", name);
953 send_failed (from, fromlen, "(no name)", sessionID, "out of memory");
956 d = FindDisplayByName (name);
959 extern void StopDisplay ();
961 Debug ("Terminating active session for %s\n", d->name);
964 class = malloc (displayClass.length + 1);
967 send_failed (from, fromlen, name, sessionID, "out of memory");
970 if (displayClass.length)
972 memmove( class, displayClass.data, displayClass.length);
973 class[displayClass.length] = '\0';
977 free ((char *) class);
978 class = (char *) NULL;
980 from_save = (XdmcpNetaddr) malloc (fromlen);
983 send_failed (from, fromlen, name, sessionID, "out of memory");
986 memmove( from_save, from, fromlen);
987 d = NewDisplay (name, class);
990 free ((char *) from_save);
991 send_failed (from, fromlen, name, sessionID, "out of memory");
994 d->displayType.location = Foreign;
995 d->displayType.lifetime = Transient;
996 d->displayType.origin = FromXDMCP;
997 d->sessionID = pdpy->sessionID;
998 d->from = (struct sockaddr *)from_save;
999 d->fromlen = fromlen;
1000 d->displayNumber = pdpy->displayNumber;
1003 #endif /* BYPASSLOGIN */
1004 ClientAddress (from, &clientAddress, &clientPort, &connectionType);
1006 if (IsIndirectClient (&clientAddress, connectionType))
1008 Debug ("IsIndirectClient\n");
1009 ForgetIndirectClient (&clientAddress, connectionType);
1010 if (UseChooser (&clientAddress, connectionType))
1013 Debug ("Use chooser for %s\n", d->name);
1016 d->clientAddr = clientAddress;
1017 d->connectionType = connectionType;
1018 XdmcpDisposeARRAY8 (&clientPort);
1019 if (pdpy->fileAuthorization)
1021 d->authorizations = (Xauth **) malloc (sizeof (Xauth *));
1022 if (!d->authorizations)
1024 free ((char *) from_save);
1026 send_failed (from, fromlen, name, sessionID, "out of memory");
1029 d->authorizations[0] = pdpy->fileAuthorization;
1031 pdpy->fileAuthorization = 0;
1033 DisposeProtoDisplay (pdpy);
1034 Debug ("Starting display %s,%s\n", d->name, d->class);
1039 XdmcpDisposeARRAY8 (&displayClass);
1040 if (name) free ((char*) name);
1041 if (class) free ((char*) class);
1045 SendFailed (struct display *d, char *reason)
1047 Debug ("Display start failed, sending Failed\n");
1048 send_failed (d->from, d->fromlen, d->name, d->sessionID, reason);
1052 send_failed (struct sockaddr *from, int fromlen, char *name, CARD32 sessionID, char *reason)
1054 static char buf[256];
1058 sprintf (buf, "Session %d failed for display %s: %s",
1059 sessionID, name, reason);
1060 Debug ("Send failed %d %s\n", sessionID, buf);
1061 status.length = strlen (buf);
1062 status.data = (CARD8Ptr) buf;
1063 header.version = XDM_PROTOCOL_VERSION;
1064 header.opcode = (CARD16) FAILED;
1065 header.length = 6 + status.length;
1066 XdmcpWriteHeader (&buffer, &header);
1067 XdmcpWriteCARD32 (&buffer, sessionID);
1068 XdmcpWriteARRAY8 (&buffer, &status);
1069 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1073 send_refuse (struct sockaddr *from, int fromlen, CARD32 sessionID)
1077 Debug ("Send refuse %d\n", sessionID);
1078 header.version = XDM_PROTOCOL_VERSION;
1079 header.opcode = (CARD16) REFUSE;
1081 XdmcpWriteHeader (&buffer, &header);
1082 XdmcpWriteCARD32 (&buffer, sessionID);
1083 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1087 send_alive (struct sockaddr *from, int fromlen, int length)
1090 CARD16 displayNumber;
1094 CARD32 sendSessionID;
1096 Debug ("Send alive\n");
1097 if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
1098 XdmcpReadCARD32 (&buffer, &sessionID))
1102 d = FindDisplayBySessionID (sessionID);
1104 d = FindDisplayByAddress (from, fromlen, displayNumber);
1108 if (d && d->status == running)
1110 if (d->sessionID == sessionID)
1112 sendSessionID = d->sessionID;
1114 header.version = XDM_PROTOCOL_VERSION;
1115 header.opcode = (CARD16) ALIVE;
1117 Debug ("alive: %d %d\n", sendRunning, sendSessionID);
1118 XdmcpWriteHeader (&buffer, &header);
1119 XdmcpWriteCARD8 (&buffer, sendRunning);
1120 XdmcpWriteCARD32 (&buffer, sendSessionID);
1121 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1126 #if NeedWidePrototypes
1128 NetworkAddressToHostname (int connectionType, ARRAY8Ptr connectionAddress)
1131 NetworkAddressToHostname (CARD16 connectionType, ARRAY8Ptr connectionAddress)
1136 switch (connectionType)
1138 case FamilyInternet:
1140 struct hostent *hostent;
1144 hostent = gethostbyaddr ((char *)connectionAddress->data,
1145 connectionAddress->length, AF_INET);
1148 local_name = hostent->h_name;
1150 /* can't get name, so use emergency fallback */
1151 sprintf(dotted, "%d.%d.%d.%d",
1152 connectionAddress->data[0],
1153 connectionAddress->data[1],
1154 connectionAddress->data[2],
1155 connectionAddress->data[3]);
1156 local_name = dotted;
1158 LogError ((unsigned char *)"Cannot convert Internet address %s to host name\n",
1161 if (!getString (name, strlen (local_name)))
1163 strcpy (name, local_name);
1177 HostnameToNetworkAddress (char *name, CARD16 connectionType, ARRAY8Ptr connectionAddress)
1179 switch (connectionType)
1181 case FamilyInternet:
1183 struct hostent *hostent;
1185 hostent = gethostbyname (name);
1188 if (!XdmcpAllocARRAY8 (connectionAddress, hostent->h_length))
1190 memmove( connectionAddress->data, hostent->h_addr, hostent->h_length);
1202 * converts a display name into a network address, using
1203 * the same rules as XOpenDisplay (algorithm cribbed from there)
1207 NameToNetworkAddress(char *name, CARD16Ptr connectionTypep, ARRAY8Ptr connectionAddress, CARD16Ptr displayNumber)
1209 char *colon, *display_number;
1210 char hostname[1024];
1213 CARD16 connectionType;
1215 colon = strchr(name, ':');
1220 if (colon - name > sizeof (hostname))
1222 strncpy (hostname, name, colon - name);
1223 hostname[colon - name] = '\0';
1227 strcpy (hostname, localHostname ());
1229 if (colon[1] == ':')
1238 display_number = colon + 1;
1239 while (*display_number && *display_number != '.')
1241 if (!isascii (*display_number) || !isdigit(*display_number))
1244 if (display_number == colon + 1)
1246 number = atoi (colon + 1);
1249 connectionType = FamilyDECnet;
1252 connectionType = FamilyInternet;
1253 if (!HostnameToNetworkAddress (hostname, connectionType, connectionAddress))
1255 *displayNumber = number;
1256 *connectionTypep = connectionType;