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 ();
124 FD_TYPE WellKnownSocketsMask;
125 int WellKnownSocketsMax;
127 #define pS(s) ((s) ? ((char *) (s)) : "empty string")
129 void DestroyWellKnownSockets ()
143 AnyWellKnownSockets ()
145 return xdmcpFd != -1 || chooserFd != -1;
148 static XdmcpBuffer buffer;
152 sendForward (connectionType, address, closure)
153 CARD16 connectionType;
158 struct sockaddr_in in_addr;
162 struct sockaddr *addr;
165 switch (connectionType)
169 addr = (struct sockaddr *) &in_addr;
170 bzero ((char *) &in_addr, sizeof (in_addr));
172 in_addr.sin_len = sizeof(in_addr);
174 in_addr.sin_family = AF_INET;
175 in_addr.sin_port = htons ((short) XDM_UDP_PORT);
176 if (address->length != 4)
178 memmove( (char *) &in_addr.sin_addr, address->data, address->length);
179 addrlen = sizeof (struct sockaddr_in);
188 XdmcpFlush (xdmcpFd, &buffer, addr, addrlen);
192 extern char *NetaddrAddress();
193 extern char *NetaddrPort();
196 ClientAddress (from, addr, port, type)
197 struct sockaddr *from;
198 ARRAY8Ptr addr, port; /* return */
199 CARD16 *type; /* return */
204 data = NetaddrPort(from, &length);
205 XdmcpAllocARRAY8 (port, length);
206 memmove( port->data, data, length);
207 port->length = length;
209 family = ConvertAddr((char *)from, &length, &data);
211 XdmcpAllocARRAY8 (addr, length);
212 memmove( addr->data, data, length);
213 addr->length = length;
219 all_query_respond (from, fromlen, authenticationNames, type)
220 struct sockaddr *from;
222 ARRAYofARRAY8Ptr authenticationNames;
225 ARRAY8Ptr authenticationName;
228 CARD16 connectionType;
232 family = ConvertAddr((char *)from, &length, (char **) &(addr.data));
234 addr.length = length; /* convert int to short */
235 Debug ("all_query_respond: conntype=%d, addr=%lx, len=%d\n",
236 family, *(addr.data), addr.length);
239 connectionType = family;
241 if (type == INDIRECT_QUERY)
242 RememberIndirectClient (&addr, connectionType);
244 ForgetIndirectClient (&addr, connectionType);
246 authenticationName = ChooseAuthentication (authenticationNames);
247 if (Willing (&addr, connectionType, authenticationName, &status, type))
248 send_willing (from, fromlen, authenticationName, &status);
251 send_unwilling (from, fromlen, authenticationName, &status);
252 XdmcpDisposeARRAY8 (&status);
256 indirect_respond (from, fromlen, length)
257 struct sockaddr *from;
261 ARRAYofARRAY8 queryAuthenticationNames;
262 ARRAY8 clientAddress;
264 CARD16 connectionType;
270 Debug ("Indirect respond %d\n", length);
271 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
274 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
275 expectedLen += 2 + queryAuthenticationNames.data[i].length;
276 if (length == expectedLen)
278 ClientAddress (from, &clientAddress, &clientPort, &connectionType);
280 * set up the forward query packet
282 header.version = XDM_PROTOCOL_VERSION;
283 header.opcode = (CARD16) FORWARD_QUERY;
285 header.length += 2 + clientAddress.length;
286 header.length += 2 + clientPort.length;
288 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
289 header.length += 2 + queryAuthenticationNames.data[i].length;
290 XdmcpWriteHeader (&buffer, &header);
291 XdmcpWriteARRAY8 (&buffer, &clientAddress);
292 XdmcpWriteARRAY8 (&buffer, &clientPort);
293 XdmcpWriteARRAYofARRAY8 (&buffer, &queryAuthenticationNames);
295 localHostAsWell = ForEachMatchingIndirectHost (&clientAddress, connectionType, sendForward, (char *) 0);
297 XdmcpDisposeARRAY8 (&clientAddress);
298 XdmcpDisposeARRAY8 (&clientPort);
300 all_query_respond (from, fromlen, &queryAuthenticationNames,
305 Debug ("Indirect length error got %d expect %d\n", length, expectedLen);
307 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
311 ProcessRequestSocket ()
314 struct sockaddr_in addr;
315 int addrlen = sizeof addr;
317 Debug ("ProcessRequestSocket\n");
318 bzero ((char *) &addr, sizeof (addr));
319 if (!XdmcpFill (xdmcpFd, &buffer, &addr, &addrlen)) {
320 Debug ("XdmcpFill failed\n");
323 if (!XdmcpReadHeader (&buffer, &header)) {
324 Debug ("XdmcpReadHeader failed\n");
327 if (header.version != XDM_PROTOCOL_VERSION) {
328 Debug ("XDMCP header version read was %d, expected %d\n",
329 header.version, XDM_PROTOCOL_VERSION);
332 Debug ("header: %d %d %d\n", header.version, header.opcode, header.length);
333 switch (header.opcode)
335 case BROADCAST_QUERY:
336 broadcast_respond (&addr, addrlen, header.length);
339 query_respond (&addr, addrlen, header.length);
342 indirect_respond (&addr, addrlen, header.length);
345 forward_respond (&addr, addrlen, header.length);
348 request_respond (&addr, addrlen, header.length);
351 manage (&addr, addrlen, header.length);
354 send_alive (&addr, addrlen, header.length);
360 * dtlogin changes to WaitForSomething () merged in to support command line
363 void WaitForSomething ()
366 struct timeval timeout, *ptimeout;
368 extern int Rescan, ChildReady, wakeupTime;
370 Debug ("WaitForSomething\n");
371 if (AnyWellKnownSockets () && !ChildReady || wakeupTime > 0 ) {
372 reads = WellKnownSocketsMask;
374 if (wakeupTime >= 0 ) {
375 timeout.tv_sec = wakeupTime;
376 timeout.tv_usec = 10;
378 Debug("Setting timer on select() for %d seconds.\n", wakeupTime);
384 nready = select (WellKnownSocketsMax + 1, (int *) &reads, 0, 0, ptimeout);
386 nready = select (WellKnownSocketsMax + 1, &reads, 0, 0, ptimeout);
388 Debug ("select returns %d. Rescan: %d ChildReady: %d\n",
389 nready, Rescan, ChildReady);
392 if (xdmcpFd >= 0 && FD_ISSET (xdmcpFd, &reads))
393 ProcessRequestSocket ();
394 if (chooserFd >= 0 && FD_ISSET (chooserFd, &reads))
395 ProcessChooserSocket (chooserFd);
408 * respond to a request on the UDP socket.
411 static ARRAY8 Hostname;
414 registerHostname (name, namelen)
420 if (!XdmcpReallocARRAY8 (&Hostname, namelen))
422 for (i = 0; i < namelen; i++)
423 Hostname.data[i] = name[i];
427 direct_query_respond (from, fromlen, length, type)
428 struct sockaddr *from;
433 ARRAYofARRAY8 queryAuthenticationNames;
437 if (!XdmcpReadARRAYofARRAY8 (&buffer, &queryAuthenticationNames))
440 for (i = 0; i < (int)queryAuthenticationNames.length; i++)
441 expectedLen += 2 + queryAuthenticationNames.data[i].length;
442 if (length == expectedLen)
443 all_query_respond (from, fromlen, &queryAuthenticationNames, type);
444 XdmcpDisposeARRAYofARRAY8 (&queryAuthenticationNames);
447 query_respond (from, fromlen, length)
448 struct sockaddr *from;
452 Debug ("Query respond %d\n", length);
453 direct_query_respond (from, fromlen, length, QUERY);
456 broadcast_respond (from, fromlen, length)
457 struct sockaddr *from;
461 direct_query_respond (from, fromlen, length, BROADCAST_QUERY);
464 /* computes an X display name */
467 NetworkAddressToName(connectionType, connectionAddress, displayNumber)
468 #if NeedWidePrototypes
471 CARD16 connectionType;
473 ARRAY8Ptr connectionAddress;
474 #if NeedWidePrototypes
477 CARD16 displayNumber;
480 switch (connectionType)
485 struct hostent *hostent;
487 char *localhost, *localHostname();
489 data = connectionAddress->data;
490 hostent = gethostbyaddr ((char *)data,
491 connectionAddress->length, AF_INET);
493 localhost = localHostname ();
496 * protect against bogus host names
498 if (hostent && hostent->h_name && hostent->h_name[0]
499 && (hostent->h_name[0] != '.'))
501 if (!strcmp (localhost, hostent->h_name))
503 if (!getString (name, 10))
505 sprintf (name, ":%d", displayNumber);
509 if (removeDomainname)
511 char *localDot, *remoteDot;
513 /* check for a common domain name. This
514 * could reduce names by recognising common
515 * super-domain names as well, but I don't think
516 * this is as useful, and will confuse more
519 if ((localDot = strchr(localhost, '.')) &&
520 (remoteDot = strchr(hostent->h_name, '.')))
522 /* smash the name in place; it won't
525 if (!strcmp (localDot+1, remoteDot+1))
530 if (!getString (name, strlen (hostent->h_name) + 10))
532 sprintf (name, "%s:%d", hostent->h_name, displayNumber);
537 if (!getString (name, 25))
539 sprintf(name, "%d.%d.%d.%d:%d",
540 data[0], data[1], data[2], data[3], displayNumber);
554 forward_respond (from, fromlen, length)
555 struct sockaddr *from;
559 ARRAY8 clientAddress;
561 ARRAYofARRAY8 authenticationNames;
562 struct sockaddr *client;
567 Debug ("Forward respond %d\n", length);
568 clientAddress.length = 0;
569 clientAddress.data = 0;
570 clientPort.length = 0;
572 authenticationNames.length = 0;
573 authenticationNames.data = 0;
574 if (XdmcpReadARRAY8 (&buffer, &clientAddress) &&
575 XdmcpReadARRAY8 (&buffer, &clientPort) &&
576 XdmcpReadARRAYofARRAY8 (&buffer, &authenticationNames))
579 expectedLen += 2 + clientAddress.length;
580 expectedLen += 2 + clientPort.length;
581 expectedLen += 1; /* authenticationNames */
582 for (i = 0; i < (int)authenticationNames.length; i++)
583 expectedLen += 2 + authenticationNames.data[i].length;
584 if (length == expectedLen)
589 for (i = 0; i < (int)clientPort.length; i++)
590 j = j * 256 + clientPort.data[i];
591 Debug ("Forward client address (port %d)", j);
592 for (i = 0; i < (int)clientAddress.length; i++)
593 Debug (" %d", clientAddress.data[i]);
595 switch (from->sa_family)
600 struct sockaddr_in in_addr;
602 if (clientAddress.length != 4 ||
603 clientPort.length != 2)
607 bzero ((char *) &in_addr, sizeof (in_addr));
609 in_addr.sin_len = sizeof(in_addr);
611 in_addr.sin_family = AF_INET;
612 memmove( &in_addr.sin_addr, clientAddress.data, 4);
613 memmove( (char *) &in_addr.sin_port, clientPort.data, 2);
614 client = (struct sockaddr *) &in_addr;
615 clientlen = sizeof (in_addr);
622 struct sockaddr_un un_addr;
624 if (clientAddress.length >= sizeof (un_addr.sun_path))
626 bzero ((char *) &un_addr, sizeof (un_addr));
627 un_addr.sun_family = AF_UNIX;
628 memmove( un_addr.sun_path, clientAddress.data, clientAddress.length);
629 un_addr.sun_path[clientAddress.length] = '\0';
630 client = (struct sockaddr *) &un_addr;
632 un_addr.sun_len = strlen(un_addr.sun_path);
633 clientlen = SUN_LEN(&un_addr);
635 clientlen = sizeof (un_addr);
649 all_query_respond (client, clientlen, &authenticationNames,
654 Debug ("Forward length error got %d expect %d\n", length, expectedLen);
658 XdmcpDisposeARRAY8 (&clientAddress);
659 XdmcpDisposeARRAY8 (&clientPort);
660 XdmcpDisposeARRAYofARRAY8 (&authenticationNames);
663 send_willing (from, fromlen, authenticationName, status)
664 struct sockaddr *from;
666 ARRAY8Ptr authenticationName;
671 Debug ("Send willing %*.*s %*.*s\n", authenticationName->length,
672 authenticationName->length,
673 pS(authenticationName->data),
677 header.version = XDM_PROTOCOL_VERSION;
678 header.opcode = (CARD16) WILLING;
679 header.length = 6 + authenticationName->length +
680 Hostname.length + status->length;
681 XdmcpWriteHeader (&buffer, &header);
682 XdmcpWriteARRAY8 (&buffer, authenticationName);
683 XdmcpWriteARRAY8 (&buffer, &Hostname);
684 XdmcpWriteARRAY8 (&buffer, status);
685 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
688 send_unwilling (from, fromlen, authenticationName, status)
689 struct sockaddr *from;
691 ARRAY8Ptr authenticationName;
696 Debug ("Send unwilling %*.*s %*.*s\n", authenticationName->length,
697 authenticationName->length,
698 pS(authenticationName->data),
702 header.version = XDM_PROTOCOL_VERSION;
703 header.opcode = (CARD16) UNWILLING;
704 header.length = 4 + Hostname.length + status->length;
705 XdmcpWriteHeader (&buffer, &header);
706 XdmcpWriteARRAY8 (&buffer, &Hostname);
707 XdmcpWriteARRAY8 (&buffer, status);
708 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
711 static unsigned long globalSessionID;
713 #define NextSessionID() (++globalSessionID)
715 void init_session_id()
717 /* Set randomly so we are unlikely to reuse id's from a previous
718 * incarnation so we don't say "Alive" to those displays.
719 * Start with low digits 0 to make debugging easier.
721 globalSessionID = (time((Time_t)0)&0x7fff) * 16000;
724 static ARRAY8 outOfMemory = { (CARD16) 13, (CARD8Ptr) "Out of memory" };
725 static ARRAY8 noValidAddr = { (CARD16) 16, (CARD8Ptr) "No valid address" };
726 static ARRAY8 noValidAuth = { (CARD16) 22, (CARD8Ptr) "No valid authorization" };
727 static ARRAY8 noAuthentic = { (CARD16) 29, (CARD8Ptr) "XDM has no authentication key" };
729 request_respond (from, fromlen, length)
730 struct sockaddr *from;
734 CARD16 displayNumber;
735 ARRAY16 connectionTypes;
736 ARRAYofARRAY8 connectionAddresses;
737 ARRAY8 authenticationName;
738 ARRAY8 authenticationData;
739 ARRAYofARRAY8 authorizationNames;
740 ARRAY8 manufacturerDisplayID;
744 struct protoDisplay *pdpy;
745 ARRAY8 authorizationName, authorizationData;
746 ARRAY8Ptr connectionAddress;
748 Debug ("Request respond %d\n", length);
749 connectionTypes.data = 0;
750 connectionAddresses.data = 0;
751 authenticationName.data = 0;
752 authenticationData.data = 0;
753 authorizationNames.data = 0;
754 authorizationName.length = 0;
755 authorizationData.length = 0;
756 manufacturerDisplayID.data = 0;
757 if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
758 XdmcpReadARRAY16 (&buffer, &connectionTypes) &&
759 XdmcpReadARRAYofARRAY8 (&buffer, &connectionAddresses) &&
760 XdmcpReadARRAY8 (&buffer, &authenticationName) &&
761 XdmcpReadARRAY8 (&buffer, &authenticationData) &&
762 XdmcpReadARRAYofARRAY8 (&buffer, &authorizationNames) &&
763 XdmcpReadARRAY8 (&buffer, &manufacturerDisplayID))
766 expectlen += 2; /* displayNumber */
767 expectlen += 1 + 2*connectionTypes.length; /* connectionTypes */
768 expectlen += 1; /* connectionAddresses */
769 for (i = 0; i < (int)connectionAddresses.length; i++)
770 expectlen += 2 + connectionAddresses.data[i].length;
771 expectlen += 2 + authenticationName.length; /* authenticationName */
772 expectlen += 2 + authenticationData.length; /* authenticationData */
773 expectlen += 1; /* authoriationNames */
774 for (i = 0; i < (int)authorizationNames.length; i++)
775 expectlen += 2 + authorizationNames.data[i].length;
776 expectlen += 2 + manufacturerDisplayID.length; /* displayID */
777 if (expectlen != length)
779 Debug ("Request length error got %d expect %d\n", length, expectlen);
782 if (connectionTypes.length == 0 ||
783 connectionAddresses.length != connectionTypes.length)
785 reason = &noValidAddr;
789 pdpy = FindProtoDisplay (from, fromlen, displayNumber);
792 /* Check this Display against the Manager's policy */
793 reason = Accept (from, fromlen, displayNumber);
797 /* Check the Display's stream services against Manager's policy */
798 i = SelectConnectionTypeIndex (&connectionTypes,
799 &connectionAddresses);
801 reason = &noValidAddr;
805 /* The Manager considers this a new session */
806 connectionAddress = &connectionAddresses.data[i];
807 pdpy = NewProtoDisplay (from, fromlen, displayNumber,
808 connectionTypes.data[i], connectionAddress,
810 Debug ("NewProtoDisplay 0x%x\n", pdpy);
812 reason = &outOfMemory;
816 if (authorizationNames.length == 0)
819 j = SelectAuthorizationTypeIndex (&authenticationName,
820 &authorizationNames);
823 reason = &noValidAuth;
826 if (!CheckAuthentication (pdpy,
827 &manufacturerDisplayID,
829 &authenticationData))
831 reason = &noAuthentic;
834 if (j < (int)authorizationNames.length)
837 SetProtoDisplayAuthorization (pdpy,
838 (unsigned short) authorizationNames.data[j].length,
839 (char *) authorizationNames.data[j].data);
840 auth = pdpy->xdmcpAuthorization;
842 auth = pdpy->fileAuthorization;
845 authorizationName.length = auth->name_length;
846 authorizationName.data = (CARD8Ptr) auth->name;
847 authorizationData.length = auth->data_length;
848 authorizationData.data = (CARD8Ptr) auth->data;
853 send_accept (from, fromlen, pdpy->sessionID,
862 send_decline (from, fromlen, &authenticationName,
866 DisposeProtoDisplay (pdpy);
870 XdmcpDisposeARRAY16 (&connectionTypes);
871 XdmcpDisposeARRAYofARRAY8 (&connectionAddresses);
872 XdmcpDisposeARRAY8 (&authenticationName);
873 XdmcpDisposeARRAY8 (&authenticationData);
874 XdmcpDisposeARRAYofARRAY8 (&authorizationNames);
875 XdmcpDisposeARRAY8 (&manufacturerDisplayID);
878 send_accept (to, tolen, sessionID,
879 authenticationName, authenticationData,
880 authorizationName, authorizationData)
884 ARRAY8Ptr authenticationName, authenticationData;
885 ARRAY8Ptr authorizationName, authorizationData;
889 Debug ("Accept Session ID %d\n", sessionID);
890 header.version = XDM_PROTOCOL_VERSION;
891 header.opcode = (CARD16) ACCEPT;
892 header.length = 4; /* session ID */
893 header.length += 2 + authenticationName->length;
894 header.length += 2 + authenticationData->length;
895 header.length += 2 + authorizationName->length;
896 header.length += 2 + authorizationData->length;
897 XdmcpWriteHeader (&buffer, &header);
898 XdmcpWriteCARD32 (&buffer, sessionID);
899 XdmcpWriteARRAY8 (&buffer, authenticationName);
900 XdmcpWriteARRAY8 (&buffer, authenticationData);
901 XdmcpWriteARRAY8 (&buffer, authorizationName);
902 XdmcpWriteARRAY8 (&buffer, authorizationData);
903 XdmcpFlush (xdmcpFd, &buffer, to, tolen);
906 send_decline (to, tolen, authenticationName, authenticationData, status)
909 ARRAY8Ptr authenticationName, authenticationData;
914 Debug ("Decline %*.*s\n", status->length, status->length, pS(status->data));
915 header.version = XDM_PROTOCOL_VERSION;
916 header.opcode = (CARD16) DECLINE;
918 header.length += 2 + status->length;
919 header.length += 2 + authenticationName->length;
920 header.length += 2 + authenticationData->length;
921 XdmcpWriteHeader (&buffer, &header);
922 XdmcpWriteARRAY8 (&buffer, status);
923 XdmcpWriteARRAY8 (&buffer, authenticationName);
924 XdmcpWriteARRAY8 (&buffer, authenticationData);
925 XdmcpFlush (xdmcpFd, &buffer, to, tolen);
928 manage (from, fromlen, length)
929 struct sockaddr *from;
934 CARD16 displayNumber;
937 struct protoDisplay *pdpy;
941 XdmcpNetaddr from_save;
942 ARRAY8 clientAddress, clientPort;
943 CARD16 connectionType;
945 Debug ("Manage %d\n", length);
946 displayClass.data = 0;
947 displayClass.length = 0;
948 if (XdmcpReadCARD32 (&buffer, &sessionID) &&
949 XdmcpReadCARD16 (&buffer, &displayNumber) &&
950 XdmcpReadARRAY8 (&buffer, &displayClass))
952 expectlen = 4 + /* session ID */
953 2 + /* displayNumber */
954 2 + displayClass.length; /* displayClass */
955 if (expectlen != length)
957 Debug ("Manage length error got %d expect %d\n", length, expectlen);
960 pdpy = FindProtoDisplay (from, fromlen, displayNumber);
961 Debug ("Manage Session ID %d, pdpy 0x%x\n", sessionID, pdpy);
962 if (!pdpy || pdpy->sessionID != sessionID)
965 * We may have already started a session for this display
966 * but it hasn't seen the response in the form of an
967 * XOpenDisplay() yet. So check if it is in the list of active
968 * displays, and if so check that the session id's match.
969 * If all this is true, then we have a duplicate request that
973 && (d = FindDisplayByAddress(from, fromlen, displayNumber))
974 && d->sessionID == sessionID) {
975 Debug("manage: got duplicate pkt, ignoring\n");
978 Debug ("Session ID %d refused\n", sessionID);
980 Debug ("Existing Session ID %d\n", pdpy->sessionID);
981 send_refuse (from, fromlen, sessionID);
985 name = NetworkAddressToName (pdpy->connectionType,
986 &pdpy->connectionAddress,
987 pdpy->displayNumber);
988 Debug ("Computed display name: %s\n", name);
991 send_failed (from, fromlen, "(no name)", sessionID, "out of memory");
994 d = FindDisplayByName (name);
997 extern void StopDisplay ();
999 Debug ("Terminating active session for %s\n", d->name);
1002 class = malloc (displayClass.length + 1);
1005 send_failed (from, fromlen, name, sessionID, "out of memory");
1008 if (displayClass.length)
1010 memmove( class, displayClass.data, displayClass.length);
1011 class[displayClass.length] = '\0';
1015 free ((char *) class);
1016 class = (char *) NULL;
1018 from_save = (XdmcpNetaddr) malloc (fromlen);
1021 send_failed (from, fromlen, name, sessionID, "out of memory");
1024 memmove( from_save, from, fromlen);
1025 d = NewDisplay (name, class);
1028 free ((char *) from_save);
1029 send_failed (from, fromlen, name, sessionID, "out of memory");
1032 d->displayType.location = Foreign;
1033 d->displayType.lifetime = Transient;
1034 d->displayType.origin = FromXDMCP;
1035 d->sessionID = pdpy->sessionID;
1036 d->from = (struct sockaddr *)from_save;
1037 d->fromlen = fromlen;
1038 d->displayNumber = pdpy->displayNumber;
1041 #endif /* BYPASSLOGIN */
1042 ClientAddress (from, &clientAddress, &clientPort, &connectionType);
1044 if (IsIndirectClient (&clientAddress, connectionType))
1046 Debug ("IsIndirectClient\n");
1047 ForgetIndirectClient (&clientAddress, connectionType);
1048 if (UseChooser (&clientAddress, connectionType))
1051 Debug ("Use chooser for %s\n", d->name);
1054 d->clientAddr = clientAddress;
1055 d->connectionType = connectionType;
1056 XdmcpDisposeARRAY8 (&clientPort);
1057 if (pdpy->fileAuthorization)
1059 d->authorizations = (Xauth **) malloc (sizeof (Xauth *));
1060 if (!d->authorizations)
1062 free ((char *) from_save);
1064 send_failed (from, fromlen, name, sessionID, "out of memory");
1067 d->authorizations[0] = pdpy->fileAuthorization;
1069 pdpy->fileAuthorization = 0;
1071 DisposeProtoDisplay (pdpy);
1072 Debug ("Starting display %s,%s\n", d->name, d->class);
1077 XdmcpDisposeARRAY8 (&displayClass);
1078 if (name) free ((char*) name);
1079 if (class) free ((char*) class);
1082 void SendFailed (d, reason)
1086 Debug ("Display start failed, sending Failed\n");
1087 send_failed (d->from, d->fromlen, d->name, d->sessionID, reason);
1090 send_failed (from, fromlen, name, sessionID, reason)
1091 struct sockaddr *from;
1097 static char buf[256];
1101 sprintf (buf, "Session %d failed for display %s: %s",
1102 sessionID, name, reason);
1103 Debug ("Send failed %d %s\n", sessionID, buf);
1104 status.length = strlen (buf);
1105 status.data = (CARD8Ptr) buf;
1106 header.version = XDM_PROTOCOL_VERSION;
1107 header.opcode = (CARD16) FAILED;
1108 header.length = 6 + status.length;
1109 XdmcpWriteHeader (&buffer, &header);
1110 XdmcpWriteCARD32 (&buffer, sessionID);
1111 XdmcpWriteARRAY8 (&buffer, &status);
1112 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1115 send_refuse (from, fromlen, sessionID)
1116 struct sockaddr *from;
1122 Debug ("Send refuse %d\n", sessionID);
1123 header.version = XDM_PROTOCOL_VERSION;
1124 header.opcode = (CARD16) REFUSE;
1126 XdmcpWriteHeader (&buffer, &header);
1127 XdmcpWriteCARD32 (&buffer, sessionID);
1128 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1131 send_alive (from, fromlen, length)
1132 struct sockaddr *from;
1137 CARD16 displayNumber;
1141 CARD32 sendSessionID;
1143 Debug ("Send alive\n");
1144 if (XdmcpReadCARD16 (&buffer, &displayNumber) &&
1145 XdmcpReadCARD32 (&buffer, &sessionID))
1149 d = FindDisplayBySessionID (sessionID);
1151 d = FindDisplayByAddress (from, fromlen, displayNumber);
1155 if (d && d->status == running)
1157 if (d->sessionID == sessionID)
1159 sendSessionID = d->sessionID;
1161 header.version = XDM_PROTOCOL_VERSION;
1162 header.opcode = (CARD16) ALIVE;
1164 Debug ("alive: %d %d\n", sendRunning, sendSessionID);
1165 XdmcpWriteHeader (&buffer, &header);
1166 XdmcpWriteCARD8 (&buffer, sendRunning);
1167 XdmcpWriteCARD32 (&buffer, sendSessionID);
1168 XdmcpFlush (xdmcpFd, &buffer, from, fromlen);
1174 NetworkAddressToHostname (connectionType, connectionAddress)
1175 #if NeedWidePrototypes
1178 CARD16 connectionType;
1180 ARRAY8Ptr connectionAddress;
1184 switch (connectionType)
1186 case FamilyInternet:
1188 struct hostent *hostent;
1192 hostent = gethostbyaddr ((char *)connectionAddress->data,
1193 connectionAddress->length, AF_INET);
1196 local_name = hostent->h_name;
1198 /* can't get name, so use emergency fallback */
1199 sprintf(dotted, "%d.%d.%d.%d",
1200 connectionAddress->data[0],
1201 connectionAddress->data[1],
1202 connectionAddress->data[2],
1203 connectionAddress->data[3]);
1204 local_name = dotted;
1206 LogError ((unsigned char *)"Cannot convert Internet address %s to host name\n",
1209 if (!getString (name, strlen (local_name)))
1211 strcpy (name, local_name);
1225 HostnameToNetworkAddress (name, connectionType, connectionAddress)
1227 CARD16 connectionType;
1228 ARRAY8Ptr connectionAddress;
1230 switch (connectionType)
1232 case FamilyInternet:
1234 struct hostent *hostent;
1236 hostent = gethostbyname (name);
1239 if (!XdmcpAllocARRAY8 (connectionAddress, hostent->h_length))
1241 memmove( connectionAddress->data, hostent->h_addr, hostent->h_length);
1253 * converts a display name into a network address, using
1254 * the same rules as XOpenDisplay (algorithm cribbed from there)
1258 NameToNetworkAddress(name, connectionTypep, connectionAddress, displayNumber)
1260 CARD16Ptr connectionTypep;
1261 ARRAY8Ptr connectionAddress;
1262 CARD16Ptr displayNumber;
1264 char *colon, *display_number;
1265 char hostname[1024];
1268 CARD16 connectionType;
1270 colon = strchr(name, ':');
1275 if (colon - name > sizeof (hostname))
1277 strncpy (hostname, name, colon - name);
1278 hostname[colon - name] = '\0';
1282 strcpy (hostname, localHostname ());
1284 if (colon[1] == ':')
1293 display_number = colon + 1;
1294 while (*display_number && *display_number != '.')
1296 if (!isascii (*display_number) || !isdigit(*display_number))
1299 if (display_number == colon + 1)
1301 number = atoi (colon + 1);
1304 connectionType = FamilyDECnet;
1307 connectionType = FamilyInternet;
1308 if (!HostnameToNetworkAddress (hostname, connectionType, connectionAddress))
1310 *displayNumber = number;
1311 *connectionTypep = connectionType;