3 Copyright 1990, 1998 The Open Group
4 Copyright 2001,2004 Oswald Buddenhagen <ossi@kde.org>
5 Copyright 2002 Sun Microsystems, Inc. All rights reserved.
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 * Access control for XDMCP - keep a database of allowable display addresses
36 * and (potentially) a list of hosts to send ForwardQuery packets to
41 #include "dm_socket.h"
47 #if defined(IPv6) && defined(AF_INET6)
48 # include <arpa/inet.h>
56 struct _displayAddress
{
57 CARD16 connectionType
;
85 ListenEntry
*listenList
;
86 AliasEntry
*aliasList
;
88 short int nHosts
, nListens
, nAliases
, nAcls
;
92 static AccArr accData
[1];
95 static ARRAY8 localAddress
;
98 getLocalAddress( void )
100 static int haveLocalAddress
;
102 if (!haveLocalAddress
) {
103 #if defined(IPv6) && defined(AF_INET6)
106 if (getaddrinfo( localHostname(), NULL
, NULL
, &ai
)) {
107 XdmcpAllocARRAY8( &localAddress
, 4 );
108 localAddress
.data
[0] = 127;
109 localAddress
.data
[1] = 0;
110 localAddress
.data
[2] = 0;
111 localAddress
.data
[3] = 1;
113 if (ai
->ai_family
== AF_INET
) {
114 XdmcpAllocARRAY8( &localAddress
, sizeof(struct in_addr
) );
115 memcpy( localAddress
.data
,
116 &((struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
,
117 sizeof(struct in_addr
) );
118 } else /* if (ai->ai_family == AF_INET6) */ {
119 XdmcpAllocARRAY8( &localAddress
, sizeof(struct in6_addr
) );
120 memcpy( localAddress
.data
,
121 &((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_addr
,
122 sizeof(struct in6_addr
) );
126 struct hostent
*hostent
;
128 if ((hostent
= gethostbyname( localHostname() ))) {
129 XdmcpAllocARRAY8( &localAddress
, hostent
->h_length
);
130 memmove( localAddress
.data
, hostent
->h_addr
, hostent
->h_length
);
132 haveLocalAddress
= True
;
135 return &localAddress
;
140 scanAccessDatabase( int force
)
142 struct _displayAddress
*da
;
146 debug( "scanAccessDatabase\n" );
147 if (Setjmp( cnftalk
.errjmp
))
148 return; /* may memleak */
149 if (startConfig( GC_gXaccess
, &accData
->dep
, force
) <= 0)
151 if (accData
->hostList
)
152 free( accData
->hostList
);
153 accData
->nHosts
= gRecvInt();
154 accData
->nListens
= gRecvInt();
155 accData
->nAliases
= gRecvInt();
156 accData
->nAcls
= gRecvInt();
158 if (!(accData
->hostList
= (HostEntry
*)
159 Malloc( accData
->nHosts
* sizeof(HostEntry
) +
160 accData
->nListens
* sizeof(ListenEntry
) +
161 accData
->nAliases
* sizeof(AliasEntry
) +
162 accData
->nAcls
* sizeof(AclEntry
) +
168 accData
->listenList
= (ListenEntry
*)(accData
->hostList
+ accData
->nHosts
);
169 accData
->aliasList
= (AliasEntry
*)(accData
->listenList
+ accData
->nListens
);
170 accData
->acList
= (AclEntry
*)(accData
->aliasList
+ accData
->nAliases
);
171 cptr
= (char *)(accData
->acList
+ accData
->nAcls
);
172 for (i
= 0; i
< accData
->nHosts
; i
++) {
173 switch ((accData
->hostList
[i
].type
= gRecvInt())) {
175 accData
->hostList
[i
].entry
.aliasPattern
= cptr
;
176 cptr
+= gRecvStrBuf( cptr
);
179 accData
->hostList
[i
].entry
.hostPattern
= cptr
;
180 cptr
+= gRecvStrBuf( cptr
);
183 da
= &accData
->hostList
[i
].entry
.displayAddress
;
184 da
->hostAddress
.data
= (unsigned char *)cptr
;
185 cptr
+= (da
->hostAddress
.length
= gRecvArrBuf( cptr
));
190 da
->connectionType
= FamilyInternet
;
193 #if defined(IPv6) && defined(AF_INET6)
195 da
->connectionType
= FamilyInternet6
;
200 da
->connectionType
= FamilyDECnet
;
207 da
->connectionType
= FamilyLocal
;
214 logError( "Received unknown host type %d from config reader\n", accData
->hostList
[i
].type
);
218 for (i
= 0; i
< accData
->nListens
; i
++) {
219 accData
->listenList
[i
].iface
= gRecvInt();
220 accData
->listenList
[i
].mcasts
= gRecvInt();
221 accData
->listenList
[i
].nmcasts
= gRecvInt();
223 for (i
= 0; i
< accData
->nAliases
; i
++) {
224 accData
->aliasList
[i
].name
= cptr
;
225 cptr
+= gRecvStrBuf( cptr
);
226 accData
->aliasList
[i
].hosts
= gRecvInt();
227 accData
->aliasList
[i
].nhosts
= gRecvInt();
229 for (i
= 0; i
< accData
->nAcls
; i
++) {
230 accData
->acList
[i
].entries
= gRecvInt();
231 accData
->acList
[i
].nentries
= gRecvInt();
232 accData
->acList
[i
].hosts
= gRecvInt();
233 accData
->acList
[i
].nhosts
= gRecvInt();
234 accData
->acList
[i
].flags
= gRecvInt();
239 /* Returns True if string is matched by pattern. Does case folding.
242 patternMatch( const char *string
, const char *pattern
)
251 switch (p
= *pattern
++) {
255 for (string
--; *string
; string
++)
256 if (patternMatch( string
, pattern
))
269 if (tolower( p
) != tolower( s
))
279 scanHostlist( int fh
, int nh
,
280 ARRAY8Ptr clientAddress
, CARD16 connectionType
,
281 ChooserFunc function
, char *closure
,
282 int broadcast
, int *haveLocalhost
)
288 for (h
= accData
->hostList
+ fh
; nh
; nh
--, h
++) {
291 for (a
= accData
->aliasList
, na
= accData
->nAliases
; na
; na
--, a
++)
292 if (patternMatch( a
->name
, h
->entry
.aliasPattern
)) /* XXX originally swapped, no wildcards in alias name matching */
293 scanHostlist( a
->hosts
, a
->nhosts
,
294 clientAddress
, connectionType
,
295 function
, closure
, broadcast
,
300 XdmcpARRAY8Equal( getLocalAddress(), &h
->entry
.displayAddress
.hostAddress
))
301 *haveLocalhost
= True
;
303 (*function
)( connectionType
, &h
->entry
.displayAddress
.hostAddress
, closure
);
306 if (broadcast
&& function
)
307 (*function
)( FamilyBroadcast
, 0, closure
);
316 scanEntrylist( int fh
, int nh
,
317 ARRAY8Ptr clientAddress
, CARD16 connectionType
,
324 for (h
= accData
->hostList
+ fh
; nh
; nh
--, h
++) {
327 for (a
= accData
->aliasList
, na
= accData
->nAliases
; na
; na
--, a
++)
328 if (patternMatch( a
->name
, h
->entry
.aliasPattern
))
329 if (scanEntrylist( a
->hosts
, a
->nhosts
,
330 clientAddress
, connectionType
,
336 *clientName
= networkAddressToHostname( connectionType
,
338 if (patternMatch( *clientName
, h
->entry
.hostPattern
))
342 if (h
->entry
.displayAddress
.connectionType
== connectionType
&&
343 XdmcpARRAY8Equal( &h
->entry
.displayAddress
.hostAddress
,
355 matchAclEntry( ARRAY8Ptr clientAddress
, CARD16 connectionType
, int direct
)
358 char *clientName
= 0;
361 for (e
= accData
->acList
, ne
= accData
->nAcls
, re
= 0; ne
; ne
--, e
++)
362 if (!e
->nhosts
== direct
)
363 if (scanEntrylist( e
->entries
, e
->nentries
,
364 clientAddress
, connectionType
,
376 * calls the given function for each valid indirect entry. Returns True if
377 * the local host exists on any of the lists, else False
380 forEachMatchingIndirectHost( ARRAY8Ptr clientAddress
, ARRAY8Ptr clientPort
,
381 CARD16 connectionType
,
382 ChooserFunc function
, char *closure
)
385 int haveLocalhost
= False
;
387 e
= matchAclEntry( clientAddress
, connectionType
, False
);
388 if (e
&& !(e
->flags
& a_notAllowed
)) {
389 if (e
->flags
& a_useChooser
) {
392 choice
= indirectChoice( clientAddress
, clientPort
, connectionType
);
393 if (!choice
|| XdmcpARRAY8Equal( getLocalAddress(), choice
))
394 /* If nothing was chosen yet, we want to pop up the chooser.
395 * If we were chosen, we want to pop up the greeter. */
396 haveLocalhost
= True
;
398 /* If something else was chosen, we forward the query to
399 * the chosen host. */
400 (*function
)( connectionType
, choice
, closure
);
402 /* Just forward the query to each listed host. */
403 scanHostlist( e
->hosts
, e
->nhosts
, clientAddress
, connectionType
,
404 function
, closure
, False
, &haveLocalhost
);
406 return haveLocalhost
;
410 useChooser( ARRAY8Ptr clientAddress
, CARD16 connectionType
)
414 e
= matchAclEntry( clientAddress
, connectionType
, False
);
415 return e
&& !(e
->flags
& a_notAllowed
) && (e
->flags
& a_useChooser
);
419 forEachChooserHost( ARRAY8Ptr clientAddress
, CARD16 connectionType
,
420 ChooserFunc function
, char *closure
)
424 e
= matchAclEntry( clientAddress
, connectionType
, False
);
425 if (e
&& !(e
->flags
& a_notAllowed
) && (e
->flags
& a_useChooser
))
426 scanHostlist( e
->hosts
, e
->nhosts
, clientAddress
, connectionType
,
427 function
, closure
, True
, 0 );
431 * returns True if the given client is acceptable to the local host. The
432 * given display client is acceptable if it occurs without a host list.
435 acceptableDisplayAddress( ARRAY8Ptr clientAddress
, CARD16 connectionType
,
440 if (type
== INDIRECT_QUERY
)
443 e
= matchAclEntry( clientAddress
, connectionType
, True
);
444 return e
&& !(e
->flags
& a_notAllowed
) &&
445 (type
!= BROADCAST_QUERY
|| !(e
->flags
& a_notBroadcast
));
449 forEachListenAddr( ListenFunc listenfunction
, ListenFunc mcastfunction
,
452 int i
, j
, ifc
, mc
, nmc
;
454 for (i
= 0; i
< accData
->nListens
; i
++) {
455 ifc
= accData
->listenList
[i
].iface
;
456 (*listenfunction
)( ifc
< 0 ? 0 :
457 &accData
->hostList
[ifc
].entry
.displayAddress
.hostAddress
,
459 mc
= accData
->listenList
[i
].mcasts
;
460 nmc
= accData
->listenList
[i
].nmcasts
;
461 for (j
= 0; j
< nmc
; j
++, mc
++)
462 (*mcastfunction
)( &accData
->hostList
[mc
].entry
.displayAddress
.hostAddress
,