3 Copyright 1988, 1998 The Open Group
4 Copyright 2000-2004 Oswald Buddenhagen <ossi@kde.org>
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of a copyright holder shall
24 not be used in advertising or otherwise to promote the sale, use or
25 other dealings in this Software without prior written authorization
26 from the copyright holder.
31 * xdm - display manager daemon
32 * Author: Keith Packard, MIT X Consortium
34 * maintain the authorization generation daemon
48 #include <sys/ioctl.h>
50 #include "dm_socket.h"
52 # include <netdnet/dnetdb.h>
55 #if (defined(_POSIX_SOURCE) && !defined(_AIX) && !defined(__QNX__)) || defined(__hpux) || defined(__svr4__) /* XXX */
57 # include <sys/utsname.h>
67 # include <sys/sockio.h>
68 # include <sys/stropts.h>
80 unsigned short name_length
;
82 void (*InitAuth
)( unsigned short len
, const char *name
);
83 Xauth
*(*GetAuth
)( unsigned short len
, const char *name
);
85 void (*GetXdmcpAuth
)( struct protoDisplay
*pdpy
,
86 unsigned short authorizationNameLen
,
87 const char *authorizationName
);
93 # define xdmcpauth(arg) , arg
95 # define xdmcpauth(arg)
98 static struct AuthProtocol authProtocols
[] = {
99 { (unsigned short)18, "MIT-MAGIC-COOKIE-1",
100 mitInitAuth
, mitGetAuth
xdmcpauth(NULL
), False
103 { (unsigned short)19, "XDM-AUTHORIZATION-1",
104 xdmInitAuth
, xdmGetAuth
xdmcpauth(xdmGetXdmcpAuth
), False
108 { (unsigned short)9, "SUN-DES-1",
109 secureRPCInitAuth
, secureRPCGetAuth
xdmcpauth(NULL
), False
113 { (unsigned short)14, "MIT-KERBEROS-5",
114 krb5InitAuth
, krb5GetAuth
xdmcpauth(NULL
), False
119 static struct AuthProtocol
*
120 findProtocol( unsigned short name_length
, const char *name
)
124 for (i
= 0; i
< as(authProtocols
); i
++)
125 if (authProtocols
[i
].name_length
== name_length
&&
126 memcmp( authProtocols
[i
].name
, name
, name_length
) == 0)
128 return &authProtocols
[i
];
130 return (struct AuthProtocol
*)0;
134 validAuthorization( unsigned short name_length
, const char *name
)
136 if (findProtocol( name_length
, name
))
142 generateAuthorization( unsigned short name_length
, const char *name
)
144 struct AuthProtocol
*a
;
147 debug( "generateAuthorization %s\n", name
);
148 if ((a
= findProtocol( name_length
, name
))) {
150 (*a
->InitAuth
)( name_length
, name
);
153 auth
= (*a
->GetAuth
)( name_length
, name
);
155 debug( "got %p (%d %.*s) %02[*hhx\n", auth
,
156 auth
->name_length
, auth
->name_length
, auth
->name
,
157 auth
->data_length
, auth
->data
);
159 debug( "got (null)\n" );
161 debug( "unknown authorization %s\n", name
);
168 setProtoDisplayAuthorization( struct protoDisplay
*pdpy
,
169 unsigned short authorizationNameLen
,
170 const char *authorizationName
)
172 struct AuthProtocol
*a
;
175 a
= findProtocol( authorizationNameLen
, authorizationName
);
176 pdpy
->xdmcpAuthorization
= pdpy
->fileAuthorization
= 0;
179 (*a
->InitAuth
)( authorizationNameLen
, authorizationName
);
182 if (a
->GetXdmcpAuth
) {
183 (*a
->GetXdmcpAuth
)( pdpy
, authorizationNameLen
, authorizationName
);
184 auth
= pdpy
->xdmcpAuthorization
;
186 auth
= (*a
->GetAuth
)( authorizationNameLen
, authorizationName
);
187 pdpy
->fileAuthorization
= auth
;
188 pdpy
->xdmcpAuthorization
= 0;
191 debug( "got %p (%d %.*s)\n", auth
,
192 auth
->name_length
, auth
->name_length
, auth
->name
);
194 debug( "got (null)\n" );
201 cleanUpFileName( const char *src
, char *dst
, int len
)
206 switch (*src
& 0x7f) {
214 *dst
++ = (*src
& 0x7f);
228 if ((f
= fdopen( fd
, "w" )))
239 makeServerAuthFile( struct display
*d
)
245 char cleanname
[NAMELEN
], nambuf
[NAMELEN
+128];
248 * Some paranoid, but still not sufficient (DoS was still possible)
249 * checks used to be here. I removed all this stuff because
250 * a) authDir is supposed to be /var/run/xauth (=safe) or similar and
251 * b) even if it's not (say, /tmp), we create files safely (hopefully).
253 if (mkdir( authDir
, 0755 ) < 0 && errno
!= EEXIST
)
255 cleanUpFileName( d
->name
, cleanname
, NAMELEN
- 8 );
257 sprintf( nambuf
, "%s/A%s-XXXXXX", authDir
, cleanname
);
258 if ((f
= fdOpenW( mkstemp( nambuf
) ))) {
259 strDup( &d
->authFile
, nambuf
);
263 for (r
= 0; r
< 100; r
++) {
264 sprintf( nambuf
, "%s/A%s-XXXXXX", authDir
, cleanname
);
265 (void)mktemp( nambuf
);
266 if ((f
= fdOpenW( open( nambuf
, O_WRONLY
| O_CREAT
| O_EXCL
, 0600 ) ))) {
267 strDup( &d
->authFile
, nambuf
);
276 saveServerAuthorizations( struct display
*d
, Xauth
**auths
, int count
)
284 if (!d
->authFile
&& d
->clientAuthFile
&& *d
->clientAuthFile
)
285 strDup( &d
->authFile
, d
->clientAuthFile
);
287 if (!(auth_file
= fdOpenW( creat( d
->authFile
, 0600 ) ))) {
288 logError( "Cannot open X server authorization file %s\n", d
->authFile
);
294 if (!(auth_file
= makeServerAuthFile( d
))) {
295 logError( "Cannot create X server authorization file\n" );
300 /* Give read capability to group _x11 */
301 if (!(x11
= getpwnam( "_x11" )))
302 logError( "Cannot find _x11 user\n" );
304 fchown( fileno( auth_file
), x11
->pw_uid
, x11
->pw_gid
);
307 debug( "file: %s auth: %p\n", d
->authFile
, auths
);
308 for (i
= 0; i
< count
; i
++) {
310 * User-based auths may not have data until
311 * a user logs in. In which case don't write
312 * to the auth file so xrdb and setup programs don't fail.
314 if (auths
[i
]->data_length
> 0)
315 if (!XauWriteAuth( auth_file
, auths
[i
] ) ||
316 fflush( auth_file
) == EOF
)
319 logError( "Cannot write X server authorization file %s\n",
331 setLocalAuthorization( struct display
*d
)
333 Xauth
*auth
, **auths
;
336 if (d
->authorizations
)
338 for (i
= 0; i
< d
->authNum
; i
++)
339 XauDisposeAuth( d
->authorizations
[i
] );
340 free( (char *)d
->authorizations
);
341 d
->authorizations
= (Xauth
**)NULL
;
344 debug( "setLocalAuthorization %s, auths %[s\n", d
->name
, d
->authNames
);
347 for (i
= 0; d
->authNames
[i
]; i
++)
351 free( (char *)d
->authNameLens
);
352 d
->authNameLens
= (unsigned short *)Malloc( d
->authNameNum
* sizeof(unsigned short) );
353 if (!d
->authNameLens
)
355 for (i
= 0; i
< d
->authNameNum
; i
++)
356 d
->authNameLens
[i
] = strlen( d
->authNames
[i
] );
357 auths
= (Xauth
**)Malloc( d
->authNameNum
* sizeof(Xauth
*) );
361 for (i
= 0; i
< d
->authNameNum
; i
++) {
362 auth
= generateAuthorization( d
->authNameLens
[i
], d
->authNames
[i
] );
366 if (saveServerAuthorizations( d
, auths
, j
)) {
367 d
->authorizations
= auths
;
370 for (i
= 0; i
< j
; i
++)
371 XauDisposeAuth( auths
[i
] );
372 free( (char *)auths
);
377 * Set the authorization to use for xdm's initial connection
378 * to the X server. Cannot use user-based authorizations
379 * because no one has logged in yet, so we don't have any
381 * Well, actually we could use SUN-DES-1 because we tell the server
382 * to allow root in. This is bogus and should be fixed.
385 setAuthorization( struct display
*d
)
387 register Xauth
**auth
= d
->authorizations
;
390 for (i
= 0; i
< d
->authNum
; i
++) {
391 if (auth
[i
]->name_length
== 9 &&
392 memcmp( auth
[i
]->name
, "SUN-DES-1", 9 ) == 0)
394 if (auth
[i
]->name_length
== 14 &&
395 memcmp( auth
[i
]->name
, "MIT-KERBEROS-5", 14 ) == 0)
397 XSetAuthorization( auth
[i
]->name
, (int)auth
[i
]->name_length
,
398 auth
[i
]->data
, (int)auth
[i
]->data_length
);
403 openFiles( const char *name
, char *new_name
, FILE **oldp
, FILE **newp
)
405 strcat( strcpy( new_name
, name
), "-n" );
407 fdOpenW( creat( new_name
, 0600 ) ))) {
408 debug( "cannot open new file %s\n", new_name
);
411 *oldp
= fopen( name
, "r" );
412 debug( "opens succeeded %s %s\n", name
, new_name
);
417 struct addrList
*next
;
418 unsigned short family
, address_length
, number_length
;
422 static struct addrList
*addrs
;
433 struct addrList
*a
, *n
;
434 for (a
= addrs
; a
; a
= n
) {
441 saveEntry( Xauth
*auth
)
443 struct addrList
*new;
445 if (!(new = Malloc( offsetof(struct addrList
, data
) +
446 auth
->address_length
+ auth
->number_length
)))
448 new->address_length
= auth
->address_length
;
449 new->number_length
= auth
->number_length
;
450 memcpy( new->data
, auth
->address
, (int)auth
->address_length
);
451 memcpy( new->data
+ (int)auth
->address_length
,
452 auth
->number
, (int)auth
->number_length
);
453 new->family
= auth
->family
;
459 checkEntry( Xauth
*auth
)
463 for (a
= addrs
; a
; a
= a
->next
)
464 if (a
->family
== auth
->family
&&
465 a
->address_length
== auth
->address_length
&&
466 !memcmp( a
->data
, auth
->address
, auth
->address_length
) &&
467 a
->number_length
== auth
->number_length
&&
468 !memcmp( a
->data
+ a
->address_length
,
469 auth
->number
, auth
->number_length
))
475 writeAuth( FILE *file
, Xauth
*auth
, int *ok
)
477 if (debugLevel
& DEBUG_AUTH
) /* normally too verbose */
478 debug( "writeAuth: doWrite = %d\n"
481 "number: %02[*:hhx\n"
485 auth
->address_length
, auth
->address
,
486 auth
->number_length
, auth
->number
,
487 auth
->name_length
, auth
->name
,
488 auth
->data_length
, auth
->data
);
489 if (ok
&& !XauWriteAuth( file
, auth
))
494 writeAddr( int family
, int addr_length
, CARD8
*addr
,
495 FILE *file
, Xauth
*auth
, int *ok
)
497 auth
->family
= (unsigned short)family
;
498 auth
->address_length
= addr_length
;
499 auth
->address
= (char *)addr
;
500 debug( "writeAddr: writing and saving an entry\n" );
501 writeAuth( file
, auth
, ok
);
502 if (!checkEntry( auth
))
507 defineLocal( FILE *file
, Xauth
*auth
, int *ok
)
509 #if !defined(NEED_UTSNAME) || defined(__hpux)
510 char displayname
[100];
516 /* stolen from xinit.c */
518 /* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c.
519 * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
521 * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
522 * to have sufficient information for interfacing to the network,
523 * and so, you may be better off using gethostname (if it exists).
529 * Why not use gethostname()? Well, at least on my system, I've had to
530 * make an ugly kernel patch to get a name longer than 8 characters, and
531 * uname() lets me access to the whole string (it smashes release, you
532 * see), whereas gethostname() kindly truncates it for me.
535 writeAddr( FamilyLocal
, strlen( name
.nodename
), (CARD8
*)name
.nodename
,
539 #if !defined(NEED_UTSNAME) || defined(__hpux)
541 * In _AIX, _POSIX_SOURCE is defined, but uname gives only first
542 * field of hostname. Thus, we use gethostname instead.
546 * For HP-UX, HP's Xlib expects a fully-qualified domain name, which
547 * is achieved by using gethostname(). For compatibility, we must
548 * also still create the entry using uname() above.
551 if (!gethostname( displayname
, sizeof(displayname
) ))
552 displayname
[sizeof(displayname
) - 1] = 0;
556 * If gethostname and uname both returned the same name,
557 * do not write a duplicate entry.
559 if (strcmp( displayname
, name
.nodename
))
561 writeAddr( FamilyLocal
, strlen( displayname
), (CARD8
*)displayname
,
566 #ifdef SYSV_SIOCGIFCONF
568 /* Deal with different SIOCGIFCONF ioctl semantics on SYSV, SVR4 */
571 ifioctl( int fd
, int cmd
, char *arg
)
576 bzero( (char *)&ioc
, sizeof(ioc
) );
579 if (cmd
== SIOCGIFCONF
) {
580 ioc
.ic_len
= ((struct ifconf
*)arg
)->ifc_len
;
581 ioc
.ic_dp
= ((struct ifconf
*)arg
)->ifc_buf
;
583 ioc
.ic_len
= sizeof(struct ifreq
);
586 ret
= ioctl( fd
, I_STR
, (char *)&ioc
);
587 if (ret
>= 0 && cmd
== SIOCGIFCONF
)
588 ((struct ifconf
*)arg
)->ifc_len
= ioc
.ic_len
;
592 #endif /* SYSV_SIOCGIFCONF */
594 #ifdef HAVE_GETIFADDRS
595 # include <ifaddrs.h>
598 defineSelf( FILE *file
, Xauth
*auth
, int *ok
)
600 struct ifaddrs
*ifap
, *ifr
;
604 if (getifaddrs( &ifap
) < 0)
606 for (ifr
= ifap
; ifr
; ifr
= ifr
->ifa_next
) {
609 family
= convertAddr( (char *)(ifr
->ifa_addr
), &len
, &addr
);
610 if (family
== -1 || family
== FamilyLocal
)
613 * don't write out 'localhost' entries, as
614 * they may conflict with other local entries.
615 * defineLocal will always be called to add
616 * the local entry anyway, so this one can
619 if (family
== FamilyInternet
&&
620 addr
[0] == 127 && addr
[1] == 0 && addr
[2] == 0 && addr
[3] == 1)
622 debug( "Skipping localhost address\n" );
625 # if defined(IPv6) && defined(AF_INET6)
626 if (family
== FamilyInternet6
) {
627 if (IN6_IS_ADDR_LOOPBACK( ((struct in6_addr
*)addr
) )) {
628 debug( "Skipping IPv6 localhost address\n" );
631 /* Also skip XDM-AUTHORIZATION-1 */
632 if (auth
->name_length
== 19 &&
633 !memcmp( auth
->name
, "XDM-AUTHORIZATION-1", 19 )) {
634 debug( "Skipping IPv6 XDM-AUTHORIZATION-1\n" );
639 writeAddr( family
, len
, addr
, file
, auth
, ok
);
643 #else /* GETIFADDRS */
645 #if defined(STREAMSCONN) && !defined(SYSV_SIOCGIFCONF) && !defined(WINTCP)
649 /* Define this host for access control. Find all the hosts the OS knows about
650 * for this fd and add them to the selfhosts list.
651 * TLI version, written without sufficient documentation.
654 defineSelf( int fd
, FILE *file
, Xauth
*auth
, int *ok
)
657 char addrret
[1024]; /* easier than t_alloc */
659 netb
.maxlen
= sizeof(addrret
);
661 if (t_getname( fd
, &netb
, LOCALNAME
) == -1)
662 t_error( "t_getname" );
664 writeAddr( FamilyInternet
, 4, (CARD8
*)netb
.buf
+4, file
, auth
, ok
);
669 #ifdef WINTCP /* NCR with Wollongong TCP */
674 #include <sys/stream.h>
676 #include <netinet/ip.h>
677 #include <netinet/ip_var.h>
678 #include <netinet/in.h>
679 #include <netinet/in_var.h>
682 defineSelf( int fd
, FILE *file
, Xauth
*auth
, int *ok
)
685 * The Wollongong drivers used by NCR SVR4/MP-RAS don't understand the
686 * socket IO calls that most other drivers seem to like. Because of
687 * this, this routine must be special cased for NCR. Eventually,
688 * this will be cleared up.
692 struct in_ifaddr ifaddr
;
696 if ((ipfd
= open( "/dev/ip", O_RDWR
, 0 )) < 0) {
697 logError( "Trouble getting interface configuration\n" );
701 /* Indicate that we want to start at the beginning */
702 ifnet
.ib_next
= (struct ipb
*)1;
704 while (ifnet
.ib_next
) {
705 str
.ic_cmd
= IPIOC_GETIPB
;
707 str
.ic_len
= sizeof(struct ipb
);
708 str
.ic_dp
= (char *)&ifnet
;
710 if (ioctl( ipfd
, (int)I_STR
, (char *)&str
) < 0) {
712 logError( "Trouble getting interface configuration\n" );
716 ifaddr
.ia_next
= (struct in_ifaddr
*)ifnet
.if_addrlist
;
717 str
.ic_cmd
= IPIOC_GETINADDR
;
719 str
.ic_len
= sizeof(struct in_ifaddr
);
720 str
.ic_dp
= (char *)&ifaddr
;
722 if (ioctl( ipfd
, (int)I_STR
, (char *)&str
) < 0) {
724 logError( "Trouble getting interface configuration\n" );
729 * Ignore the 127.0.0.1 entry.
731 if (IA_SIN( &ifaddr
)->sin_addr
.s_addr
== htonl( 0x7f000001 ))
734 writeAddr( FamilyInternet
, 4, (CARD8
*)&(IA_SIN( &ifaddr
)->sin_addr
),
743 /* Solaris provides an extended interface SIOCGLIFCONF. Other systems
744 * may have this as well, but the code has only been tested on Solaris
745 * so far, so we only enable it there. Other platforms may be added as
748 * Test for Solaris commented out -- TSI @ UQV 2003.06.13
751 /* #if defined(sun) */
752 # define USE_SIOCGLIFCONF
756 #if defined(SIOCGIFCONF) || defined (USE_SIOCGLIFCONF)
758 #if !defined(SYSV_SIOCGIFCONF) || defined(USE_SIOCGLIFCONF)
759 # define ifioctl ioctl
762 #ifdef USE_SIOCGLIFCONF
763 # define ifr_type struct lifreq
765 # define ifr_type struct ifreq
768 /* Handle variable length ifreq in BNR2 and later */
769 #ifdef VARIABLE_IFREQ
770 # define ifr_size(p) (sizeof(struct ifreq) + \
771 (p->ifr_addr.sa_len > sizeof(p->ifr_addr) ? \
772 p->ifr_addr.sa_len - sizeof(p->ifr_addr) : 0))
774 # define ifr_size(p) (sizeof(ifr_type))
777 #ifdef USE_SIOCGLIFCONF
778 # define IFC_IOCTL_REQ SIOCGLIFCONF
779 # define IFC_REQ(ifc) ifc.lifc_req
780 # define IFC_LEN(ifc) ifc.lifc_len
781 # define IFR_ADDR(ifr) ifr->lifr_addr
782 # define IFR_NAME(ifr) ifr->lifr_name
784 # define IFC_IOCTL_REQ SIOCGIFCONF
785 # define IFC_REQ(ifc) ifc.ifc_req
786 # define IFC_LEN(ifc) ifc.ifc_len
787 # define IFR_ADDR(ifr) ifr->ifr_addr
788 # define IFR_NAME(ifr) ifr->ifr_name
791 /* Define this host for access control. Find all the hosts the OS knows about
792 * for this fd and add them to the selfhosts list.
795 defineSelf( int fd
, FILE *file
, Xauth
*auth
, int *ok
)
797 char buf
[2048], *cp
, *cplim
;
802 #ifdef USE_SIOCGLIFCONF
805 size_t buflen
= sizeof(buf
);
814 #if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF)
815 ifn
.lifn_family
= AF_UNSPEC
;
817 if (ioctl( fd
, (int)SIOCGLIFNUM
, (char *)&ifn
) < 0)
818 logError( "Failed getting interface count\n" );
819 if (buflen
< (ifn
.lifn_count
* sizeof(struct lifreq
))) {
820 buflen
= ifn
.lifn_count
* sizeof(struct lifreq
);
821 bufptr
= Malloc( buflen
);
825 #ifdef USE_SIOCGLIFCONF
826 ifc
.lifc_family
= AF_UNSPEC
;
828 ifc
.lifc_len
= buflen
;
829 ifc
.lifc_buf
= bufptr
;
831 ifc
.ifc_len
= sizeof(buf
);
834 if (ifioctl (fd
, IFC_IOCTL_REQ
, (char *)&ifc
) < 0) {
835 logError( "Trouble getting network interface configuration\n" );
836 #if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF)
843 cplim
= (char *)IFC_REQ( ifc
) + IFC_LEN( ifc
);
845 for (cp
= (char *)IFC_REQ( ifc
); cp
< cplim
; cp
+= ifr_size (ifr
)) {
846 ifr
= (ifr_type
*) cp
;
849 * this is ugly but SIOCGIFCONF returns decnet addresses in
850 * a different form from other decnet calls
852 if (IFR_ADDR( ifr
).sa_family
== AF_DECnet
) {
853 len
= sizeof(struct dn_naddr
);
854 addr
= (CARD8
*)IFR_ADDR( ifr
).sa_data
;
855 family
= FamilyDECnet
;
859 family
= convertAddr( (char *)&IFR_ADDR( ifr
), &len
, &addr
);
864 debug( "skipping zero length address\n" );
868 * don't write out 'localhost' entries, as
869 * they may conflict with other local entries.
870 * defineLocal will always be called to add
871 * the local entry anyway, so this one can
874 if (family
== FamilyInternet
&&
875 addr
[0] == 127 && addr
[1] == 0 &&
876 addr
[2] == 0 && addr
[3] == 1)
878 debug( "skipping localhost address\n" );
881 #if defined(IPv6) && defined(AF_INET6)
882 if (family
== FamilyInternet6
) {
883 if (IN6_IS_ADDR_LOOPBACK( ((struct in6_addr
*)addr
) )) {
884 debug( "Skipping IPv6 localhost address\n" );
887 /* Also skip XDM-AUTHORIZATION-1 */
888 if (auth
->name_length
== 19 &&
889 !memcmp( auth
->name
, "XDM-AUTHORIZATION-1", 19 )) {
890 debug( "Skipping IPv6 XDM-AUTHORIZATION-1\n" );
896 debug( "defineSelf: write network address, length %d\n", len
);
897 writeAddr( family
, len
, addr
, file
, auth
, ok
);
899 #if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF)
905 #else /* SIOCGIFCONF */
907 /* Define this host for access control. Find all the hosts the OS knows about
908 * for this fd and add them to the selfhosts list.
911 defineSelf( int fd
, int file
, int auth
, int *ok
)
918 register struct hostent
*hp
;
922 struct sockaddr_in in
;
925 struct sockaddr_in
*inetaddr
;
928 * Why not use gethostname()? Well, at least on my system, I've had to
929 * make an ugly kernel patch to get a name longer than 8 characters, and
930 * uname() lets me access to the whole string (it smashes release, you
931 * see), whereas gethostname() kindly truncates it for me.
934 if ((hp
= gethostbyname( name
.nodename
))) {
935 saddr
.sa
.sa_family
= hp
->h_addrtype
;
936 inetaddr
= (struct sockaddr_in
*)(&(saddr
.sa
));
937 memmove( (char *)&(inetaddr
->sin_addr
), (char *)hp
->h_addr
,
939 if ((family
= convertAddr( &(saddr
.sa
), &len
, &addr
)) >= 0)
940 writeAddr( FamilyInternet
, sizeof(inetaddr
->sin_addr
),
941 (CARD8
*)(&inetaddr
->sin_addr
), file
, auth
, ok
);
945 #endif /* SIOCGIFCONF else */
946 #endif /* WINTCP else */
947 #endif /* STREAMSCONN && !SYSV_SIOCGIFCONF else */
948 #endif /* HAVE_GETIFADDRS */
951 setAuthNumber( Xauth
*auth
, const char *name
)
956 debug( "setAuthNumber %s\n", name
);
957 colon
= strrchr( name
, ':' );
960 dot
= strchr( colon
, '.' );
962 auth
->number_length
= dot
- colon
;
964 auth
->number_length
= strlen( colon
);
965 if (!strNDup( &auth
->number
, colon
, auth
->number_length
))
966 auth
->number_length
= 0;
967 debug( "setAuthNumber: %s\n", auth
->number
);
972 writeLocalAuth( FILE *file
, Xauth
*auth
, const char *name
, int *ok
)
974 #if defined(STREAMSCONN) || !defined(HAVE_GETIFADDRS)
978 debug( "writeLocalAuth: %s %.*s\n", name
, auth
->name_length
, auth
->name
);
979 setAuthNumber( auth
, name
);
981 fd
= t_open( "/dev/tcp", O_RDWR
, 0 );
982 t_bind( fd
, NULL
, NULL
);
983 defineSelf( fd
, file
, auth
, ok
);
986 # elif defined(HAVE_GETIFADDRS)
987 defineSelf( file
, auth
, ok
);
990 # if defined(IPv6) && defined(AF_INET6)
991 fd
= socket( AF_INET6
, SOCK_STREAM
, 0 );
994 fd
= socket( AF_INET
, SOCK_STREAM
, 0 );
995 defineSelf( fd
, file
, auth
, ok
);
999 fd
= socket( AF_DECnet
, SOCK_STREAM
, 0 );
1000 defineSelf( fd
, file
, auth
, ok
);
1003 # endif /* HAVE_GETIFADDRS */
1004 defineLocal( file
, auth
, ok
);
1010 * Call convertAddr(), and if it returns an IPv4 localhost, convert it
1011 * to a local display name. Meets the _XTransconvertAddress's localhost
1016 convertAuthAddr( char *saddr
, int *len
, CARD8
**addr
)
1018 int ret
= convertAddr( saddr
, len
, addr
);
1019 if (ret
== FamilyInternet
&&
1020 ((struct in_addr
*)*addr
)->s_addr
== htonl( 0x7F000001L
))
1026 writeRemoteAuth( FILE *file
, Xauth
*auth
, XdmcpNetaddr peer
, int peerlen
,
1027 const char *name
, int *ok
)
1029 int family
= FamilyLocal
;
1032 debug( "writeRemoteAuth: %s %.*s\n", name
, auth
->name_length
, auth
->name
);
1033 if (!peer
|| peerlen
< 2)
1035 setAuthNumber( auth
, name
);
1036 family
= convertAuthAddr( peer
, &peerlen
, &addr
);
1037 debug( "writeRemoteAuth: family %d\n", family
);
1038 if (family
!= FamilyLocal
) {
1039 debug( "writeRemoteAuth: %d, %02[*:hhx\n",
1040 family
, peerlen
, addr
);
1041 writeAddr( family
, peerlen
, addr
, file
, auth
, ok
);
1043 writeLocalAuth( file
, auth
, name
, ok
);
1051 startUserAuth( char *buf
, char *nbuf
, FILE **old
, FILE **new )
1058 if ((home
= getEnv( userEnviron
, "HOME" )) && strlen( home
) < NBSIZE
- 12) {
1059 sprintf( buf
, "%s/.Xauthority", home
);
1060 debug( "XauLockAuth %s\n", buf
);
1061 lockStatus
= XauLockAuth( buf
, 1, 2, 10 );
1062 debug( "lock is %d\n", lockStatus
);
1063 if (lockStatus
== LOCK_SUCCESS
)
1064 if (!openFiles( buf
, nbuf
, old
, new ))
1065 XauUnlockAuth( buf
);
1068 logWarn( "Cannot update authorization file in home dir %s\n", home
);
1072 endUserAuth( FILE *old
, FILE *new, const char *nname
, int ok
)
1078 if (fstat( fileno( old
), &statb
) != -1)
1079 chmod( nname
, (int)(statb
.st_mode
& 0777) );
1081 while ((entry
= XauReadAuth( old
))) {
1082 if (!checkEntry( entry
)) {
1083 debug( "writing an entry\n" );
1084 writeAuth( new, entry
, &ok
);
1086 XauDisposeAuth( entry
);
1090 if (fclose( new ) == EOF
)
1097 undoUserAuth( const char *name
, const char *new_name
)
1099 logWarn( "Cannot save user authorization in home dir\n" );
1101 XauUnlockAuth( name
);
1105 moveUserAuth( const char *name
, char *new_name
, char *envname
)
1108 debug( "unlink %s failed\n", name
);
1109 if (link( new_name
, name
)) {
1110 debug( "link failed %s %s\n", new_name
, name
);
1111 logError( "Cannot move user authorization into place\n" );
1114 debug( "new authorization moved into place\n" );
1117 XauUnlockAuth( name
);
1122 setUserAuthorization( struct display
*d
)
1131 char name_buf
[NBSIZE
], new_name
[NBSIZE
+ 2];
1133 debug( "setUserAuthorization\n" );
1134 auths
= d
->authorizations
;
1136 if (d
->forceUserAuthDir
)
1138 startUserAuth( name_buf
, new_name
, &old
, &new );
1143 /* 'old' is uninitialized here */
1146 if (strlen( d
->userAuthDir
) >= NBSIZE
- 13)
1149 * Note, that we don't lock the auth file here, as it's
1150 * temporary - we can assume, that we are the only ones
1151 * knowing about this file anyway.
1154 sprintf( name_buf
, "%s/.XauthXXXXXX", d
->userAuthDir
);
1155 new = fdOpenW( mkstemp( name_buf
) );
1157 for (i
= 0; i
< 100; i
++) {
1158 sprintf( name_buf
, "%s/.XauthXXXXXX", d
->userAuthDir
);
1159 (void)mktemp( name_buf
);
1161 fdOpenW( open( name_buf
, O_WRONLY
| O_CREAT
| O_EXCL
,
1167 logError( "Cannot create authorization file in %s\n",
1176 debug( "%d authorization protocols for %s\n", d
->authNum
, d
->name
);
1178 * Write MIT-MAGIC-COOKIE-1 authorization first, so that
1179 * R4 clients which only knew that, and used the first
1180 * matching entry will continue to function
1183 for (i
= 0; i
< d
->authNum
; i
++) {
1184 if (auths
[i
]->name_length
== 18 &&
1185 !memcmp( auths
[i
]->name
, "MIT-MAGIC-COOKIE-1", 18 ))
1188 if ((d
->displayType
& d_location
) == dLocal
)
1189 writeLocalAuth( new, auths
[i
], d
->name
, &ok
);
1192 writeRemoteAuth( new, auths
[i
], (XdmcpNetaddr
)d
->peer
.data
,
1193 d
->peer
.length
, d
->name
, &ok
);
1198 /* now write other authorizations */
1199 for (i
= 0; i
< d
->authNum
; i
++) {
1200 if (i
!= magicCookie
) {
1201 data_len
= auths
[i
]->data_length
;
1202 /* client will just use default Kerberos cache, so don't
1203 * even write cache info into the authority file.
1205 if (auths
[i
]->name_length
== 14 &&
1206 !strncmp( auths
[i
]->name
, "MIT-KERBEROS-5", 14 ))
1207 auths
[i
]->data_length
= 0;
1208 if ((d
->displayType
& d_location
) == dLocal
)
1209 writeLocalAuth( new, auths
[i
], d
->name
, &ok
);
1212 writeRemoteAuth( new, auths
[i
], (XdmcpNetaddr
)d
->peer
.data
,
1213 d
->peer
.length
, d
->name
, &ok
);
1215 auths
[i
]->data_length
= data_len
;
1218 if (!endUserAuth( old
, new, new_name
, ok
)) {
1220 logError( "Cannot save user authorization\n" );
1223 undoUserAuth( name
, new_name
);
1228 envname
= moveUserAuth( name
, new_name
, envname
);
1230 userEnviron
= setEnv( userEnviron
, "XAUTHORITY", envname
);
1231 systemEnviron
= setEnv( systemEnviron
, "XAUTHORITY", envname
);
1233 /* a chown() used to be here, but this code runs as user anyway */
1235 debug( "done setUserAuthorization\n" );
1239 removeUserAuthorization( struct display
*d
)
1244 char name
[NBSIZE
], new_name
[NBSIZE
+ 2];
1246 if (!(auths
= d
->authorizations
))
1248 debug( "removeUserAuthorization\n" );
1249 startUserAuth( name
, new_name
, &old
, &new );
1251 for (i
= 0; i
< d
->authNum
; i
++) {
1252 if ((d
->displayType
& d_location
) == dLocal
)
1253 writeLocalAuth( new, auths
[i
], d
->name
, 0 );
1256 writeRemoteAuth( new, auths
[i
], (XdmcpNetaddr
)d
->peer
.data
,
1257 d
->peer
.length
, d
->name
, 0 );
1260 if (endUserAuth( old
, new, new_name
, True
))
1261 (void)moveUserAuth( name
, new_name
, 0 );
1263 undoUserAuth( name
, new_name
);
1265 debug( "done removeUserAuthorization\n" );