3
Copyright 1988, 1998 The Open Group
4
Copyright 2002 Sun Microsystems, Inc. All rights reserved.
5
Copyright 2001-2004 Oswald Buddenhagen <ossi@kde.org>
7
Permission to use, copy, modify, distribute, and sell this software and its
8
documentation for any purpose is hereby granted without fee, provided that
9
the above copyright notice appear in all copies and that both that
10
copyright notice and this permission notice appear in supporting
13
The above copyright notice and this permission notice shall be included
14
in all copies or substantial portions of the Software.
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
OTHER DEALINGS IN THE SOFTWARE.
24
Except as contained in this notice, the name of a copyright holder shall
25
not be used in advertising or otherwise to promote the sale, use or
26
other dealings in this Software without prior written authorization
27
from the copyright holder.
32
* xdm - display manager daemon
33
* Author: Keith Packard, MIT X Consortium
35
* xdmcp.c - Support for XDMCP
41
#include "dm_socket.h"
43
#include <sys/types.h>
47
#if defined(IPv6) && defined(AF_INET6)
48
# include <arpa/inet.h>
53
networkAddressToHostname(CARD16 connectionType, ARRAY8Ptr connectionAddress)
55
switch (connectionType) {
57
#if defined(IPv6) && defined(AF_INET6)
62
char *myDot, *name, *lname;
64
#if defined(IPv6) && defined(AF_INET6)
65
char dotted[INET6_ADDRSTRLEN];
67
if (connectionType == FamilyInternet6)
73
he = gethostbyaddr((char *)connectionAddress->data,
74
connectionAddress->length, af_type);
76
#if defined(IPv6) && defined(AF_INET6)
77
struct addrinfo *ai, *nai;
78
if (!getaddrinfo(he->h_name, 0, 0, &ai)) {
79
for (nai = ai; nai; nai = nai->ai_next) {
80
if (af_type == nai->ai_family &&
81
!memcmp(nai->ai_family == AF_INET ?
82
(char *)&((struct sockaddr_in *)nai->ai_addr)->sin_addr :
83
(char *)&((struct sockaddr_in6 *)nai->ai_addr)->sin6_addr,
84
connectionAddress->data,
85
connectionAddress->length))
93
if ((he = gethostbyname(he->h_name)) &&
94
he->h_addrtype == AF_INET)
97
for (i = 0; he->h_addr_list[i]; i++)
98
if (!memcmp(he->h_addr_list[i],
99
connectionAddress->data, 4))
102
logError("DNS spoof attempt or misconfigured resolver.\n");
106
if (strDup(&name, he->h_name) &&
107
!strchr(name, '.') &&
108
(myDot = strchr(localHostname(), '.')))
110
if (ASPrintf(&lname, "%s%s", name, myDot)) {
111
#if defined(IPv6) && defined(AF_INET6)
112
if (!getaddrinfo(lname, 0, 0, &ai)) {
113
for (nai = ai; nai; nai = nai->ai_next) {
114
if (af_type == nai->ai_family &&
115
!memcmp(nai->ai_family == AF_INET ?
116
(char *)&((struct sockaddr_in *)nai->ai_addr)->sin_addr :
117
(char *)&((struct sockaddr_in6 *)nai->ai_addr)->sin6_addr,
118
connectionAddress->data,
119
connectionAddress->length)) {
128
if ((he = gethostbyname(lname)) && he->h_addrtype == AF_INET) {
130
for (i = 0; he->h_addr_list[i]; i++)
131
if (!memcmp(he->h_addr_list[i], connectionAddress->data, 4)) {
142
/* can't get name, so use emergency fallback */
143
#if defined(IPv6) && defined(AF_INET6)
144
inet_ntop(af_type, connectionAddress->data,
145
dotted, sizeof(dotted));
146
strDup(&name, dotted);
148
ASPrintf(&name, "%[4|'.'hhu", connectionAddress->data);
150
logWarn("Cannot convert Internet address %s to host name\n", name);
165
networkAddressToName(CARD16 connectionType, ARRAY8Ptr connectionAddress,
166
struct sockaddr *originalAddress, CARD16 displayNumber)
168
switch (connectionType) {
170
#if defined(IPv6) && defined(AF_INET6)
171
case FamilyInternet6:
175
struct hostent *hostent;
178
const char *localhost;
179
int multiHomed = False;
181
#if defined(IPv6) && defined(AF_INET6)
182
struct addrinfo *ai = 0, *nai, hints;
183
char dotted[INET6_ADDRSTRLEN];
185
if (connectionType == FamilyInternet6)
191
data = connectionAddress->data;
192
hostent = gethostbyaddr((char *)data,
193
connectionAddress->length, type);
196
#if defined(IPv6) && defined(AF_INET6)
197
bzero(&hints, sizeof(hints));
198
hints.ai_flags = AI_CANONNAME;
199
if (!getaddrinfo(hostent->h_name, 0, &hints, &ai)) {
200
hostname = ai->ai_canonname;
201
for (nai = ai->ai_next; nai; nai = nai->ai_next)
202
if (ai->ai_protocol == nai->ai_protocol &&
203
memcmp(ai->ai_addr, nai->ai_addr,
208
hostent = gethostbyname(hostent->h_name);
209
if (hostent && hostent->h_addrtype == AF_INET) {
210
multiHomed = hostent->h_addr_list[1] != 0;
211
hostname = hostent->h_name;
215
hostname = hostent->h_name;
219
localhost = localHostname();
222
* protect against bogus host names
224
if (hostname && *hostname && *hostname != '.' && !multiHomed) {
225
if (!strcmp(localhost, hostname)) {
226
ASPrintf(&name, "localhost:%d", displayNumber);
228
if (removeDomainname) {
229
char *localDot, *remoteDot;
231
/* check for a common domain name. This
232
* could reduce names by recognising common
233
* super-domain names as well, but I don't think
234
* this is as useful, and will confuse more
237
if ((localDot = strchr(localhost, '.')) &&
238
(remoteDot = strchr(hostname, '.')))
240
/* smash the name in place; it won't
243
if (!strcmp(localDot + 1, remoteDot + 1))
248
ASPrintf(&name, "%s:%d", hostname, displayNumber);
251
#if defined(IPv6) && defined(AF_INET6)
253
if (connectionType == FamilyInternet) {
255
&((struct sockaddr_in *)originalAddress)->sin_addr;
258
&((struct sockaddr_in6 *)originalAddress)->sin6_addr;
261
inet_ntop(type, data, dotted, sizeof(dotted));
262
ASPrintf(&name, "%s:%d", dotted, displayNumber);
266
&((struct sockaddr_in *)originalAddress)->sin_addr;
267
ASPrintf(&name, "%[4|'.'hhu:%d", data, displayNumber);
270
#if defined(IPv6) && defined(AF_INET6)
286
convertClientAddress(struct sockaddr *from,
287
ARRAY8Ptr addr, /* return */
288
ARRAY8Ptr port, /* return */
289
CARD16 *type) /* return */
294
data = netaddrPort((XdmcpNetaddr)from, &length);
295
XdmcpAllocARRAY8(port, length);
296
memmove(port->data, data, length);
297
port->length = length;
299
family = convertAddr((XdmcpNetaddr)from, &length, &data);
300
XdmcpAllocARRAY8(addr, length);
301
memmove(addr->data, data, length);
302
addr->length = length;
307
static XdmcpBuffer buffer;
309
static ARRAY8 Hostname;
310
static unsigned long globalSessionID;
312
#define nextSessionID() (++globalSessionID)
316
/* Set randomly so we are unlikely to reuse id's from a previous
317
* incarnation so we don't say "Alive" to those displays.
318
* Start with low digits 0 to make debugging easier.
320
globalSessionID = (time((time_t *)0) & 0x7fff) * 16000;
322
Hostname.data = (unsigned char *)localHostname();
323
Hostname.length = strlen((char *)Hostname.data);
327
send_willing(struct sockaddr *from, int fromlen,
328
ARRAY8Ptr authenticationName, ARRAY8Ptr status, int fd)
332
debug("send <willing> %.*s %.*s\n", authenticationName->length,
333
authenticationName->data,
336
header.version = XDM_PROTOCOL_VERSION;
337
header.opcode = (CARD16)WILLING;
339
6 + authenticationName->length + Hostname.length + status->length;
340
XdmcpWriteHeader(&buffer, &header);
341
XdmcpWriteARRAY8(&buffer, authenticationName);
342
XdmcpWriteARRAY8(&buffer, &Hostname);
343
XdmcpWriteARRAY8(&buffer, status);
344
XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
348
send_unwilling(struct sockaddr *from, int fromlen,
349
ARRAY8Ptr authenticationName, ARRAY8Ptr status, int fd)
353
debug("send <unwilling> %.*s %.*s\n", authenticationName->length,
354
authenticationName->data,
357
header.version = XDM_PROTOCOL_VERSION;
358
header.opcode = (CARD16)UNWILLING;
359
header.length = 4 + Hostname.length + status->length;
360
XdmcpWriteHeader(&buffer, &header);
361
XdmcpWriteARRAY8(&buffer, &Hostname);
362
XdmcpWriteARRAY8(&buffer, status);
363
XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
367
all_query_respond(struct sockaddr *from, int fromlen,
368
ARRAYofARRAY8Ptr authenticationNames,
369
xdmOpCode type, int fd)
371
ARRAY8Ptr authenticationName;
375
CARD16 connectionType;
379
family = convertAddr((XdmcpNetaddr)from, &length, &addr.data);
380
addr.length = length; /* convert int to short */
381
port.data = netaddrPort((XdmcpNetaddr)from, &length);
382
port.length = length; /* convert int to short */
383
debug("all_query_respond: conntype=%d, addr=%02[*:hhx\n",
384
family, addr.length, addr.data);
387
connectionType = family;
389
if (type == INDIRECT_QUERY)
390
registerIndirectChoice(&addr, &port, connectionType, 0);
392
checkIndirectChoice(&addr, &port, connectionType);
394
authenticationName = chooseAuthentication(authenticationNames);
395
if (isWilling(&addr, connectionType, authenticationName, &status, type))
396
send_willing(from, fromlen, authenticationName, &status, fd);
399
send_unwilling(from, fromlen, authenticationName, &status, fd);
400
XdmcpDisposeARRAY8(&status);
404
sendForward(CARD16 connectionType, ARRAY8Ptr address, char *closure)
407
struct sockaddr_in in_addr;
409
#if defined(IPv6) && defined(AF_INET6)
410
struct sockaddr_in6 in6_addr;
414
struct sockaddr *addr;
417
switch (connectionType) {
420
addr = (struct sockaddr *)&in_addr;
421
bzero((char *)&in_addr, sizeof(in_addr));
422
# ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
423
in_addr.sin_len = sizeof(in_addr);
425
in_addr.sin_family = AF_INET;
426
in_addr.sin_port = htons((short)requestPort);
427
if (address->length != 4)
429
memmove(&in_addr.sin_addr, address->data, address->length);
430
addrlen = sizeof(struct sockaddr_in);
433
#if defined(IPv6) && defined(AF_INET6)
434
case FamilyInternet6:
435
addr = (struct sockaddr *)&in6_addr;
436
bzero(&in6_addr, sizeof(in6_addr));
437
# ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
438
in6_addr.sin6_len = sizeof(in6_addr);
440
in6_addr.sin6_family = AF_INET6;
441
in6_addr.sin6_port = htons((short)requestPort);
442
if (address->length != 16)
444
memmove(&in6_addr.sin6_addr, address->data, address->length);
445
addrlen = sizeof(struct sockaddr_in6);
454
XdmcpFlush((int)(long)closure, &buffer, (XdmcpNetaddr)addr, addrlen);
459
indirect_respond(struct sockaddr *from, int fromlen, int length, int fd)
461
ARRAYofARRAY8 queryAuthenticationNames;
462
ARRAY8 clientAddress;
464
CARD16 connectionType;
470
debug("<indirect> respond %d\n", length);
471
if (!XdmcpReadARRAYofARRAY8(&buffer, &queryAuthenticationNames))
474
for (i = 0; i < (int)queryAuthenticationNames.length; i++)
475
expectedLen += 2 + queryAuthenticationNames.data[i].length;
476
if (length == expectedLen) {
477
convertClientAddress(from,
478
&clientAddress, &clientPort, &connectionType);
480
* set up the forward query packet
482
header.version = XDM_PROTOCOL_VERSION;
483
header.opcode = (CARD16)FORWARD_QUERY;
485
header.length += 2 + clientAddress.length;
486
header.length += 2 + clientPort.length;
488
for (i = 0; i < (int)queryAuthenticationNames.length; i++)
489
header.length += 2 + queryAuthenticationNames.data[i].length;
490
XdmcpWriteHeader(&buffer, &header);
491
XdmcpWriteARRAY8(&buffer, &clientAddress);
492
XdmcpWriteARRAY8(&buffer, &clientPort);
493
XdmcpWriteARRAYofARRAY8(&buffer, &queryAuthenticationNames);
496
forEachMatchingIndirectHost(&clientAddress, &clientPort, connectionType,
497
sendForward, (char *)(long)fd);
499
XdmcpDisposeARRAY8(&clientAddress);
500
XdmcpDisposeARRAY8(&clientPort);
502
all_query_respond(from, fromlen, &queryAuthenticationNames,
505
debug("<indirect> length error got %d expect %d\n",
506
length, expectedLen);
507
XdmcpDisposeARRAYofARRAY8(&queryAuthenticationNames);
511
* respond to a request on the UDP socket.
515
direct_query_respond(struct sockaddr *from, int fromlen,
516
int length, xdmOpCode type, int fd)
518
ARRAYofARRAY8 queryAuthenticationNames;
522
if (!XdmcpReadARRAYofARRAY8(&buffer, &queryAuthenticationNames))
525
for (i = 0; i < (int)queryAuthenticationNames.length; i++)
526
expectedLen += 2 + queryAuthenticationNames.data[i].length;
527
if (length == expectedLen)
528
all_query_respond(from, fromlen, &queryAuthenticationNames, type, fd);
529
XdmcpDisposeARRAYofARRAY8(&queryAuthenticationNames);
533
query_respond(struct sockaddr *from, int fromlen, int length, int fd)
535
debug("<query> respond %d\n", length);
536
direct_query_respond(from, fromlen, length, QUERY, fd);
540
broadcast_respond(struct sockaddr *from, int fromlen, int length, int fd)
542
direct_query_respond(from, fromlen, length, BROADCAST_QUERY, fd);
547
forward_respond(struct sockaddr *from, int fromlen ATTR_UNUSED,
550
ARRAY8 clientAddress;
552
ARRAYofARRAY8 authenticationNames;
553
struct sockaddr *client;
558
debug("<forward> respond %d\n", length);
559
clientAddress.length = 0;
560
clientAddress.data = 0;
561
clientPort.length = 0;
563
authenticationNames.length = 0;
564
authenticationNames.data = 0;
565
if (XdmcpReadARRAY8(&buffer, &clientAddress) &&
566
XdmcpReadARRAY8(&buffer, &clientPort) &&
567
XdmcpReadARRAYofARRAY8(&buffer, &authenticationNames))
570
expectedLen += 2 + clientAddress.length;
571
expectedLen += 2 + clientPort.length;
572
expectedLen += 1; /* authenticationNames */
573
for (i = 0; i < (int)authenticationNames.length; i++)
574
expectedLen += 2 + authenticationNames.data[i].length;
575
if (length == expectedLen) {
579
for (i = 0; i < (int)clientPort.length; i++)
580
j = j * 256 + clientPort.data[i];
581
debug("<forward> client address (port %d) %[*hhu\n", j,
582
clientAddress.length, clientAddress.data);
583
switch (from->sa_family) {
586
struct sockaddr_in in_addr;
588
if (clientAddress.length != 4 || clientPort.length != 2)
590
bzero(&in_addr, sizeof(in_addr));
591
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
592
in_addr.sin_len = sizeof(in_addr);
594
in_addr.sin_family = AF_INET;
595
memmove(&in_addr.sin_addr, clientAddress.data, 4);
596
memmove(&in_addr.sin_port, clientPort.data, 2);
597
client = (struct sockaddr *)&in_addr;
598
clientlen = sizeof(in_addr);
599
all_query_respond(client, clientlen, &authenticationNames,
603
#if defined(IPv6) && defined(AF_INET6)
605
struct sockaddr_in6 in6_addr;
607
if ((clientAddress.length != 16 && clientAddress.length != 4) ||
608
clientPort.length != 2)
610
bzero(&in6_addr, sizeof(in6_addr));
611
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
612
in6_addr.sin6_len = sizeof(in6_addr);
614
in6_addr.sin6_family = AF_INET6;
615
if (clientAddress.length == 16) {
616
memmove(in6_addr.sin6_addr.s6_addr, clientAddress.data, 16);
618
/* If the client wants to forward the xdm server to an
619
* IPv4 hosts it sends an IPv4 address in the forward
620
* packet. On dual-stack hosts the packet arrives as a
621
* IPv6 packet. To respond to the IPv4 host one has
622
* to create an IPv4-mapped address.
623
* One example where this is necessary is an IPv4-only
624
* thin client that connects to a dual-stacked xdm.
626
in6_addr.sin6_addr.s6_addr[10] = 0xff;
627
in6_addr.sin6_addr.s6_addr[11] = 0xff;
628
memmove(in6_addr.sin6_addr.s6_addr + 12, clientAddress.data, 4);
630
memmove(&in6_addr.sin6_port, clientPort.data, 2);
631
client = (struct sockaddr *)&in6_addr;
632
clientlen = sizeof(in6_addr);
633
all_query_respond(client, clientlen, &authenticationNames,
639
struct sockaddr_un un_addr;
641
if (clientAddress.length >= sizeof(un_addr.sun_path))
643
bzero(&un_addr, sizeof(un_addr));
644
un_addr.sun_family = AF_UNIX;
645
memmove(un_addr.sun_path, clientAddress.data, clientAddress.length);
646
un_addr.sun_path[clientAddress.length] = '\0';
647
client = (struct sockaddr *)&un_addr;
648
#if defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN) && !defined(__Lynx__) && defined(UNIXCONN)
649
un_addr.sun_len = strlen(un_addr.sun_path);
650
clientlen = SUN_LEN(&un_addr);
652
clientlen = sizeof(un_addr);
654
all_query_respond(client, clientlen, &authenticationNames,
668
debug("<forward> length error got %d expect %d\n", length, expectedLen);
672
XdmcpDisposeARRAY8(&clientAddress);
673
XdmcpDisposeARRAY8(&clientPort);
674
XdmcpDisposeARRAYofARRAY8(&authenticationNames);
679
send_accept(struct sockaddr *to, int tolen, CARD32 sessionID,
680
ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData,
681
ARRAY8Ptr authorizationName, ARRAY8Ptr authorizationData,
686
debug("<accept> session ID %ld\n", (long)sessionID);
687
header.version = XDM_PROTOCOL_VERSION;
688
header.opcode = (CARD16)ACCEPT;
689
header.length = 4; /* session ID */
690
header.length += 2 + authenticationName->length;
691
header.length += 2 + authenticationData->length;
692
header.length += 2 + authorizationName->length;
693
header.length += 2 + authorizationData->length;
694
XdmcpWriteHeader(&buffer, &header);
695
XdmcpWriteCARD32(&buffer, sessionID);
696
XdmcpWriteARRAY8(&buffer, authenticationName);
697
XdmcpWriteARRAY8(&buffer, authenticationData);
698
XdmcpWriteARRAY8(&buffer, authorizationName);
699
XdmcpWriteARRAY8(&buffer, authorizationData);
700
XdmcpFlush(fd, &buffer, (XdmcpNetaddr)to, tolen);
704
send_decline(struct sockaddr *to, int tolen,
705
ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData,
706
ARRAY8Ptr status, int fd)
710
debug("<decline> %.*s\n", status->length, status->data);
711
header.version = XDM_PROTOCOL_VERSION;
712
header.opcode = (CARD16)DECLINE;
714
header.length += 2 + status->length;
715
header.length += 2 + authenticationName->length;
716
header.length += 2 + authenticationData->length;
717
XdmcpWriteHeader(&buffer, &header);
718
XdmcpWriteARRAY8(&buffer, status);
719
XdmcpWriteARRAY8(&buffer, authenticationName);
720
XdmcpWriteARRAY8(&buffer, authenticationData);
721
XdmcpFlush(fd, &buffer, (XdmcpNetaddr)to, tolen);
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" };
730
request_respond(struct sockaddr *from, int fromlen, int length, int fd)
732
CARD16 displayNumber;
733
ARRAY16 connectionTypes;
734
ARRAYofARRAY8 connectionAddresses;
735
ARRAY8 authenticationName;
736
ARRAY8 authenticationData;
737
ARRAYofARRAY8 authorizationNames;
738
ARRAY8 manufacturerDisplayID;
739
ARRAY8Ptr reason = 0;
742
struct protoDisplay *pdpy;
743
ARRAY8 authorizationName, authorizationData;
744
ARRAY8Ptr connectionAddress;
746
debug("<request> respond %d\n", length);
747
connectionTypes.data = 0;
748
connectionAddresses.data = 0;
749
authenticationName.data = 0;
750
authenticationData.data = 0;
751
authorizationNames.data = 0;
752
authorizationName.length = 0;
753
authorizationData.length = 0;
754
manufacturerDisplayID.data = 0;
755
if (XdmcpReadCARD16(&buffer, &displayNumber) &&
756
XdmcpReadARRAY16(&buffer, &connectionTypes) &&
757
XdmcpReadARRAYofARRAY8(&buffer, &connectionAddresses) &&
758
XdmcpReadARRAY8(&buffer, &authenticationName) &&
759
XdmcpReadARRAY8(&buffer, &authenticationData) &&
760
XdmcpReadARRAYofARRAY8(&buffer, &authorizationNames) &&
761
XdmcpReadARRAY8(&buffer, &manufacturerDisplayID))
764
expectlen += 2; /* displayNumber */
765
expectlen += 1 + 2 * connectionTypes.length; /* connectionTypes */
766
expectlen += 1; /* connectionAddresses */
767
for (i = 0; i < (int)connectionAddresses.length; i++)
768
expectlen += 2 + connectionAddresses.data[i].length;
769
expectlen += 2 + authenticationName.length; /* authenticationName */
770
expectlen += 2 + authenticationData.length; /* authenticationData */
771
expectlen += 1; /* authoriationNames */
772
for (i = 0; i < (int)authorizationNames.length; i++)
773
expectlen += 2 + authorizationNames.data[i].length;
774
expectlen += 2 + manufacturerDisplayID.length; /* displayID */
775
if (expectlen != length) {
776
debug("<request> length error got %d expect %d\n",
780
if (connectionTypes.length == 0 ||
781
connectionAddresses.length != connectionTypes.length)
783
reason = &noValidAddr;
787
pdpy = findProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber);
790
/* Check this Display against the Manager's policy */
791
reason = isAccepting(from, fromlen, displayNumber);
795
/* Check the Display's stream services against Manager's policy */
796
i = selectConnectionTypeIndex(&connectionTypes,
797
&connectionAddresses);
799
reason = &noValidAddr;
803
/* The Manager considers this a new session */
804
connectionAddress = &connectionAddresses.data[i];
805
pdpy = newProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber,
806
connectionTypes.data[i], connectionAddress,
808
debug("newProtoDisplay %p\n", pdpy);
810
reason = &outOfMemory;
814
if (authorizationNames.length == 0)
817
j = selectAuthorizationTypeIndex(&authenticationName,
818
&authorizationNames);
820
reason = &noValidAuth;
823
if (!checkAuthentication(pdpy,
824
&manufacturerDisplayID,
826
&authenticationData))
828
reason = &noAuthentic;
831
if (j < (int)authorizationNames.length) {
833
setProtoDisplayAuthorization(pdpy,
834
(unsigned short)authorizationNames.data[j].length,
835
(char *)authorizationNames.data[j].data);
836
auth = pdpy->xdmcpAuthorization;
838
auth = pdpy->fileAuthorization;
840
authorizationName.length = auth->name_length;
841
authorizationName.data = (CARD8Ptr) auth->name;
842
authorizationData.length = auth->data_length;
843
authorizationData.data = (CARD8Ptr) auth->data;
847
send_accept(from, fromlen, pdpy->sessionID,
851
&authorizationData, fd);
854
send_decline(from, fromlen, &authenticationName,
858
disposeProtoDisplay(pdpy);
862
XdmcpDisposeARRAY16(&connectionTypes);
863
XdmcpDisposeARRAYofARRAY8(&connectionAddresses);
864
XdmcpDisposeARRAY8(&authenticationName);
865
XdmcpDisposeARRAY8(&authenticationData);
866
XdmcpDisposeARRAYofARRAY8(&authorizationNames);
867
XdmcpDisposeARRAY8(&manufacturerDisplayID);
872
send_failed(struct sockaddr *from, int fromlen,
873
const char *name, CARD32 sessionID, const char *reason, int fd)
879
sprintf(buf, "Session %ld failed for display %.260s: %s",
880
(long)sessionID, name, reason);
881
debug("send_failed(%\"s)\n", buf);
882
status.length = strlen(buf);
883
status.data = (CARD8Ptr) buf;
884
header.version = XDM_PROTOCOL_VERSION;
885
header.opcode = (CARD16)FAILED;
886
header.length = 6 + status.length;
887
XdmcpWriteHeader(&buffer, &header);
888
XdmcpWriteCARD32(&buffer, sessionID);
889
XdmcpWriteARRAY8(&buffer, &status);
890
XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
894
sendFailed(struct display *d, const char *reason)
896
debug("display start failed, sending <failed>\n");
897
send_failed((struct sockaddr *)(d->from.data), d->from.length, d->name,
898
d->sessionID, reason, d->xdmcpFd);
902
send_refuse(struct sockaddr *from, int fromlen, CARD32 sessionID, int fd)
906
debug("send <refuse> %ld\n", (long)sessionID);
907
header.version = XDM_PROTOCOL_VERSION;
908
header.opcode = (CARD16)REFUSE;
910
XdmcpWriteHeader(&buffer, &header);
911
XdmcpWriteCARD32(&buffer, sessionID);
912
XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
916
manage(struct sockaddr *from, int fromlen, int length, int fd)
919
CARD16 displayNumber;
922
struct protoDisplay *pdpy;
926
XdmcpNetaddr from_save;
927
ARRAY8 clientAddress, clientPort;
928
CARD16 connectionType;
930
debug("<manage> %d\n", length);
931
displayClass.data = 0;
932
displayClass.length = 0;
933
if (XdmcpReadCARD32(&buffer, &sessionID) &&
934
XdmcpReadCARD16(&buffer, &displayNumber) &&
935
XdmcpReadARRAY8(&buffer, &displayClass))
937
expectlen = 4 + /* session ID */
938
2 + /* displayNumber */
939
2 + displayClass.length; /* displayClass */
940
if (expectlen != length) {
941
debug("<manage> length error got %d expect %d\n", length, expectlen);
944
pdpy = findProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber);
945
debug("<manage> session ID %ld, pdpy %p\n", (long)sessionID, pdpy);
946
if (!pdpy || pdpy->sessionID != sessionID) {
948
* We may have already started a session for this display
949
* but it hasn't seen the response in the form of an
950
* XOpenDisplay() yet. So check if it is in the list of active
951
* displays, and if so check that the session id's match.
952
* If all this is true, then we have a duplicate request that
956
(d = findDisplayByAddress((XdmcpNetaddr)from, fromlen,
958
d->sessionID == sessionID)
960
debug("manage: got duplicate pkt, ignoring\n");
963
debug("session ID %ld refused\n", (long)sessionID);
965
debug("existing session ID %ld\n", (long)pdpy->sessionID);
966
send_refuse(from, fromlen, sessionID, fd);
968
name = networkAddressToName(pdpy->connectionType,
969
&pdpy->connectionAddress,
971
pdpy->displayNumber);
973
debug("could not compute display name\n");
974
send_failed(from, fromlen, "(no name)", sessionID,
975
"out of memory", fd);
978
debug("computed display name: %s\n", name);
979
if ((d = findDisplayByName(name))) {
980
debug("terminating active session for %s\n", d->name);
983
if (displayClass.length) {
984
if (!strNDup(&class2, (char *)displayClass.data,
985
displayClass.length))
987
send_failed(from, fromlen, name, sessionID,
988
"out of memory", fd);
992
if (!(from_save = Malloc(fromlen))) {
993
send_failed(from, fromlen, name, sessionID,
994
"out of memory", fd);
997
memmove(from_save, from, fromlen);
998
if (!(d = newDisplay(name))) {
1000
send_failed(from, fromlen, name, sessionID,
1001
"out of memory", fd);
1006
d->displayType = dForeign | dTransient | dFromXDMCP;
1007
d->sessionID = pdpy->sessionID;
1008
d->from.data = (unsigned char *)from_save;
1009
d->from.length = fromlen;
1010
d->displayNumber = pdpy->displayNumber;
1011
convertClientAddress(from,
1012
&clientAddress, &clientPort, &connectionType);
1013
d->useChooser = False;
1015
if (checkIndirectChoice(&clientAddress, &clientPort, connectionType) &&
1016
useChooser(&clientAddress, connectionType))
1018
d->useChooser = True;
1019
debug("use chooser for %s\n", d->name);
1021
d->clientAddr = clientAddress;
1022
d->clientPort = clientPort;
1023
d->connectionType = connectionType;
1024
if (pdpy->fileAuthorization) {
1025
d->authorizations = Malloc(sizeof(Xauth *));
1026
if (!d->authorizations) {
1028
send_failed(from, fromlen, name, sessionID,
1029
"out of memory", fd);
1032
d->authorizations[0] = pdpy->fileAuthorization;
1034
pdpy->fileAuthorization = 0;
1036
disposeProtoDisplay(pdpy);
1040
XdmcpDisposeARRAY8(&displayClass);
1046
send_alive(struct sockaddr *from, int fromlen, int length, int fd)
1049
CARD16 displayNumber;
1053
CARD32 sendSessionID;
1055
debug("send <alive>\n");
1056
if (XdmcpReadCARD16(&buffer, &displayNumber) &&
1057
XdmcpReadCARD32(&buffer, &sessionID))
1060
if (!(d = findDisplayBySessionID(sessionID)))
1061
d = findDisplayByAddress((XdmcpNetaddr)from, fromlen,
1065
if (d && d->status == running) {
1066
if (d->sessionID == sessionID)
1068
sendSessionID = d->sessionID;
1070
header.version = XDM_PROTOCOL_VERSION;
1071
header.opcode = (CARD16)ALIVE;
1073
debug("<alive>: %d %ld\n", sendRunning, (long)sendSessionID);
1074
XdmcpWriteHeader(&buffer, &header);
1075
XdmcpWriteCARD8(&buffer, sendRunning);
1076
XdmcpWriteCARD32(&buffer, sendSessionID);
1077
XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen);
1084
processRequestSocket(int fd)
1087
#if defined(IPv6) && defined(AF_INET6)
1088
struct sockaddr_storage addr;
1090
struct sockaddr addr;
1092
int addrlen = sizeof(addr);
1094
debug("processRequestSocket\n");
1095
bzero(&addr, sizeof(addr));
1096
if (!XdmcpFill(fd, &buffer, (XdmcpNetaddr)&addr, &addrlen)) {
1097
debug("XdmcpFill failed\n");
1100
if (!XdmcpReadHeader(&buffer, &header)) {
1101
debug("XdmcpReadHeader failed\n");
1104
if (header.version != XDM_PROTOCOL_VERSION) {
1105
debug("XDMCP header version read was %d, expected %d\n",
1106
header.version, XDM_PROTOCOL_VERSION);
1109
debug("header: %d %d %d\n", header.version, header.opcode, header.length);
1110
switch (header.opcode) {
1111
case BROADCAST_QUERY:
1112
broadcast_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
1115
query_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
1117
case INDIRECT_QUERY:
1118
indirect_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
1121
forward_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
1124
request_respond((struct sockaddr *)&addr, addrlen, header.length, fd);
1127
manage((struct sockaddr *)&addr, addrlen, header.length, fd);
1130
send_alive((struct sockaddr *)&addr, addrlen, header.length, fd);