auth.c revision 629baa8c
1629baa8cSmrg/*
2629baa8cSmrg
3629baa8cSmrgCopyright 1988, 1998  The Open Group
4629baa8cSmrg
5629baa8cSmrgPermission to use, copy, modify, distribute, and sell this software and its
6629baa8cSmrgdocumentation for any purpose is hereby granted without fee, provided that
7629baa8cSmrgthe above copyright notice appear in all copies and that both that
8629baa8cSmrgcopyright notice and this permission notice appear in supporting
9629baa8cSmrgdocumentation.
10629baa8cSmrg
11629baa8cSmrgThe above copyright notice and this permission notice shall be included
12629baa8cSmrgin all copies or substantial portions of the Software.
13629baa8cSmrg
14629baa8cSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15629baa8cSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16629baa8cSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17629baa8cSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18629baa8cSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19629baa8cSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20629baa8cSmrgOTHER DEALINGS IN THE SOFTWARE.
21629baa8cSmrg
22629baa8cSmrgExcept as contained in this notice, the name of The Open Group shall
23629baa8cSmrgnot be used in advertising or otherwise to promote the sale, use or
24629baa8cSmrgother dealings in this Software without prior written authorization
25629baa8cSmrgfrom The Open Group.
26629baa8cSmrg
27629baa8cSmrg*/
28629baa8cSmrg
29629baa8cSmrg/*
30629baa8cSmrg * xdm - display manager daemon
31629baa8cSmrg * Author:  Keith Packard, MIT X Consortium
32629baa8cSmrg *
33629baa8cSmrg * auth.c
34629baa8cSmrg *
35629baa8cSmrg * maintain the authorization generation daemon
36629baa8cSmrg */
37629baa8cSmrg
38629baa8cSmrg#include <X11/X.h>
39629baa8cSmrg#include <X11/Xlibint.h>
40629baa8cSmrg#include <sys/types.h>
41629baa8cSmrg#include <sys/stat.h>
42629baa8cSmrg
43629baa8cSmrg#include "dm.h"
44629baa8cSmrg#include "dm_auth.h"
45629baa8cSmrg#include "dm_error.h"
46629baa8cSmrg
47629baa8cSmrg#include <errno.h>
48629baa8cSmrg
49629baa8cSmrg#include <sys/ioctl.h>
50629baa8cSmrg
51629baa8cSmrg#if defined(TCPCONN) || defined(STREAMSCONN)
52629baa8cSmrg# include "dm_socket.h"
53629baa8cSmrg#endif
54629baa8cSmrg#ifdef DNETCONN
55629baa8cSmrg# include <netdnet/dn.h>
56629baa8cSmrg# include <netdnet/dnetdb.h>
57629baa8cSmrg#endif
58629baa8cSmrg
59629baa8cSmrg#if defined(hpux)
60629baa8cSmrg# include <sys/utsname.h>
61629baa8cSmrg#endif
62629baa8cSmrg
63629baa8cSmrg#if defined(SYSV) && defined(i386)
64629baa8cSmrg# include <sys/stream.h>
65629baa8cSmrg# ifdef ISC
66629baa8cSmrg#  include <stropts.h>
67629baa8cSmrg#  include <sys/sioctl.h>
68629baa8cSmrg# endif /* ISC */
69629baa8cSmrg#endif /* i386 */
70629baa8cSmrg
71629baa8cSmrg#ifdef SVR4
72629baa8cSmrg# include <netdb.h>
73629baa8cSmrg# include <sys/sockio.h>
74629baa8cSmrg# include <sys/stropts.h>
75629baa8cSmrg#endif
76629baa8cSmrg#ifdef __convex__
77629baa8cSmrg# include <sync/queue.h>
78629baa8cSmrg# include <sync/sema.h>
79629baa8cSmrg#endif
80629baa8cSmrg#ifdef __GNU__
81629baa8cSmrg# include <netdb.h>
82629baa8cSmrg# undef SIOCGIFCONF
83629baa8cSmrg#else /* __GNU__ */
84629baa8cSmrg# include <net/if.h>
85629baa8cSmrg#endif /* __GNU__ */
86629baa8cSmrg
87629baa8cSmrg#if defined(TCPCONN) && !defined(WIN32)
88629baa8cSmrg# include <netinet/in.h>
89629baa8cSmrg#endif
90629baa8cSmrg
91629baa8cSmrg/* Solaris provides an extended interface SIOCGLIFCONF for IPv6 support.
92629baa8cSmrg */
93629baa8cSmrg#ifdef SIOCGLIFCONF
94629baa8cSmrg# define USE_SIOCGLIFCONF
95629baa8cSmrg#endif
96629baa8cSmrg
97629baa8cSmrg#if ((defined(SVR4) && !defined(sun)) || defined(ISC)) && \
98629baa8cSmrg    defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
99629baa8cSmrg# define SYSV_SIOCGIFCONF
100629baa8cSmrg#endif
101629baa8cSmrg
102629baa8cSmrg#ifdef HAVE_SYS_PARAM_H
103629baa8cSmrg#include <sys/param.h>
104629baa8cSmrg# ifdef BSD
105629baa8cSmrg#  if (BSD >= 199103)
106629baa8cSmrg#   define VARIABLE_IFREQ
107629baa8cSmrg#  endif
108629baa8cSmrg# endif
109629baa8cSmrg#endif
110629baa8cSmrg
111629baa8cSmrg#ifdef __UNIXOS2__
112629baa8cSmrg# define link rename
113629baa8cSmrgint chown(int a,int b,int c) {}
114629baa8cSmrg# include <io.h>
115629baa8cSmrg#endif
116629baa8cSmrg
117629baa8cSmrgstruct AuthProtocol {
118629baa8cSmrg    unsigned short  name_length;
119629baa8cSmrg    char	    *name;
120629baa8cSmrg    void	    (*InitAuth)(unsigned short len, char *name);
121629baa8cSmrg    Xauth	    *(*GetAuth)(unsigned short len, char *name);
122629baa8cSmrg    void	    (*GetXdmcpAuth)(
123629baa8cSmrg			struct protoDisplay	*pdpy,
124629baa8cSmrg			unsigned short	authorizationNameLen,
125629baa8cSmrg			char		*authorizationName);
126629baa8cSmrg    int		    inited;
127629baa8cSmrg};
128629baa8cSmrg
129629baa8cSmrgstatic struct AuthProtocol AuthProtocols[] = {
130629baa8cSmrg{ (unsigned short) 18,	"MIT-MAGIC-COOKIE-1",
131629baa8cSmrg    MitInitAuth, MitGetAuth, NULL
132629baa8cSmrg},
133629baa8cSmrg#ifdef HASXDMAUTH
134629baa8cSmrg{ (unsigned short) 19,	"XDM-AUTHORIZATION-1",
135629baa8cSmrg    XdmInitAuth, XdmGetAuth, XdmGetXdmcpAuth,
136629baa8cSmrg},
137629baa8cSmrg#endif
138629baa8cSmrg#ifdef SECURE_RPC
139629baa8cSmrg{ (unsigned short) 9, "SUN-DES-1",
140629baa8cSmrg    SecureRPCInitAuth, SecureRPCGetAuth, NULL,
141629baa8cSmrg},
142629baa8cSmrg#endif
143629baa8cSmrg#ifdef K5AUTH
144629baa8cSmrg{ (unsigned short) 14, "MIT-KERBEROS-5",
145629baa8cSmrg    Krb5InitAuth, Krb5GetAuth, NULL,
146629baa8cSmrg},
147629baa8cSmrg#endif
148629baa8cSmrg};
149629baa8cSmrg
150629baa8cSmrg#define NUM_AUTHORIZATION (sizeof (AuthProtocols) / sizeof (AuthProtocols[0]))
151629baa8cSmrg
152629baa8cSmrgstatic struct AuthProtocol *
153629baa8cSmrgfindProtocol (unsigned short name_length, char *name)
154629baa8cSmrg{
155629baa8cSmrg    int	i;
156629baa8cSmrg
157629baa8cSmrg    for (i = 0; i < NUM_AUTHORIZATION; i++)
158629baa8cSmrg	if (AuthProtocols[i].name_length == name_length &&
159629baa8cSmrg	    memcmp(AuthProtocols[i].name, name, name_length) == 0)
160629baa8cSmrg	{
161629baa8cSmrg	    return &AuthProtocols[i];
162629baa8cSmrg	}
163629baa8cSmrg    return (struct AuthProtocol *) 0;
164629baa8cSmrg}
165629baa8cSmrg
166629baa8cSmrgint
167629baa8cSmrgValidAuthorization (unsigned short name_length, char *name)
168629baa8cSmrg{
169629baa8cSmrg    if (findProtocol (name_length, name))
170629baa8cSmrg	return TRUE;
171629baa8cSmrg    return FALSE;
172629baa8cSmrg}
173629baa8cSmrg
174629baa8cSmrgstatic Xauth *
175629baa8cSmrgGenerateAuthorization (unsigned short name_length, char *name)
176629baa8cSmrg{
177629baa8cSmrg    struct AuthProtocol	*a;
178629baa8cSmrg    Xauth   *auth = NULL;
179629baa8cSmrg    int	    i;
180629baa8cSmrg
181629baa8cSmrg    Debug ("GenerateAuthorization %*.*s\n",
182629baa8cSmrg	    name_length, name_length, name);
183629baa8cSmrg    a = findProtocol (name_length, name);
184629baa8cSmrg    if (a)
185629baa8cSmrg    {
186629baa8cSmrg	if (!a->inited)
187629baa8cSmrg	{
188629baa8cSmrg	    (*a->InitAuth) (name_length, name);
189629baa8cSmrg	    a->inited = TRUE;
190629baa8cSmrg	}
191629baa8cSmrg	auth = (*a->GetAuth) (name_length, name);
192629baa8cSmrg	if (auth)
193629baa8cSmrg	{
194629baa8cSmrg	    Debug ("Got %p (%d %*.*s) ", auth,
195629baa8cSmrg		auth->name_length, auth->name_length,
196629baa8cSmrg		auth->name_length, auth->name);
197629baa8cSmrg	    for (i = 0; i < (int)auth->data_length; i++)
198629baa8cSmrg		Debug (" %02x", auth->data[i] & 0xff);
199629baa8cSmrg	    Debug ("\n");
200629baa8cSmrg	}
201629baa8cSmrg	else
202629baa8cSmrg	    Debug ("Got (null)\n");
203629baa8cSmrg    }
204629baa8cSmrg    else
205629baa8cSmrg    {
206629baa8cSmrg	Debug ("Unknown authorization %*.*s\n", name_length, name_length, name);
207629baa8cSmrg    }
208629baa8cSmrg    return auth;
209629baa8cSmrg}
210629baa8cSmrg
211629baa8cSmrg#ifdef XDMCP
212629baa8cSmrg
213629baa8cSmrgvoid
214629baa8cSmrgSetProtoDisplayAuthorization (
215629baa8cSmrg    struct protoDisplay	*pdpy,
216629baa8cSmrg    unsigned short	authorizationNameLen,
217629baa8cSmrg    char		*authorizationName)
218629baa8cSmrg{
219629baa8cSmrg    struct AuthProtocol	*a;
220629baa8cSmrg    Xauth   *auth;
221629baa8cSmrg
222629baa8cSmrg    a = findProtocol (authorizationNameLen, authorizationName);
223629baa8cSmrg    pdpy->xdmcpAuthorization = pdpy->fileAuthorization = NULL;
224629baa8cSmrg    if (a)
225629baa8cSmrg    {
226629baa8cSmrg	if (!a->inited)
227629baa8cSmrg	{
228629baa8cSmrg	    (*a->InitAuth) (authorizationNameLen, authorizationName);
229629baa8cSmrg	    a->inited = TRUE;
230629baa8cSmrg	}
231629baa8cSmrg	if (a->GetXdmcpAuth)
232629baa8cSmrg	{
233629baa8cSmrg	    (*a->GetXdmcpAuth) (pdpy, authorizationNameLen, authorizationName);
234629baa8cSmrg	    auth = pdpy->xdmcpAuthorization;
235629baa8cSmrg	}
236629baa8cSmrg	else
237629baa8cSmrg	{
238629baa8cSmrg	    auth = (*a->GetAuth) (authorizationNameLen, authorizationName);
239629baa8cSmrg	    pdpy->fileAuthorization = auth;
240629baa8cSmrg	    pdpy->xdmcpAuthorization = NULL;
241629baa8cSmrg	}
242629baa8cSmrg	if (auth)
243629baa8cSmrg	    Debug ("Got %p (%d %*.*s)\n", auth,
244629baa8cSmrg		auth->name_length, auth->name_length,
245629baa8cSmrg		auth->name_length, auth->name);
246629baa8cSmrg	else
247629baa8cSmrg	    Debug ("Got (null)\n");
248629baa8cSmrg    }
249629baa8cSmrg}
250629baa8cSmrg
251629baa8cSmrg#endif /* XDMCP */
252629baa8cSmrg
253629baa8cSmrgvoid
254629baa8cSmrgCleanUpFileName (char *src, char *dst, int len)
255629baa8cSmrg{
256629baa8cSmrg    while (*src) {
257629baa8cSmrg	if (--len <= 0)
258629baa8cSmrg		break;
259629baa8cSmrg	switch (*src & 0x7f)
260629baa8cSmrg	{
261629baa8cSmrg	case '/':
262629baa8cSmrg	    *dst++ = '_';
263629baa8cSmrg	    break;
264629baa8cSmrg	case '-':
265629baa8cSmrg	    *dst++ = '.';
266629baa8cSmrg	    break;
267629baa8cSmrg	default:
268629baa8cSmrg	    *dst++ = (*src & 0x7f);
269629baa8cSmrg	}
270629baa8cSmrg	++src;
271629baa8cSmrg    }
272629baa8cSmrg    *dst = '\0';
273629baa8cSmrg}
274629baa8cSmrg
275629baa8cSmrg/* Checks to see if specified directory exists, makes it if not
276629baa8cSmrg * Returns: 0 if already exists, 1 if created, < 0 if error occured
277629baa8cSmrg */
278629baa8cSmrgstatic int
279629baa8cSmrgCheckServerAuthDir (const char *path, struct stat *statb, int mode)
280629baa8cSmrg{
281629baa8cSmrg    int r = stat(path, statb);
282629baa8cSmrg
283629baa8cSmrg    if (r != 0) {
284629baa8cSmrg	if (errno == ENOENT) {
285629baa8cSmrg	    r = mkdir(path, mode);
286629baa8cSmrg	    if (r < 0) {
287629baa8cSmrg		LogError ("cannot make authentication directory %s: %s\n",
288629baa8cSmrg			  path, _SysErrorMsg (errno));
289629baa8cSmrg	    } else {
290629baa8cSmrg		r = 1;
291629baa8cSmrg	    }
292629baa8cSmrg	} else {
293629baa8cSmrg	    LogError ("cannot access authentication directory %s: %s\n",
294629baa8cSmrg		      path, _SysErrorMsg (errno));
295629baa8cSmrg	}
296629baa8cSmrg    } else { /* Directory already exists */
297629baa8cSmrg	if (!S_ISDIR(statb->st_mode)) {
298629baa8cSmrg	    LogError ("cannot make authentication directory %s: %s\n",
299629baa8cSmrg		      path, "file with that name already exists");
300629baa8cSmrg	    return -1;
301629baa8cSmrg	}
302629baa8cSmrg    }
303629baa8cSmrg
304629baa8cSmrg    return r;
305629baa8cSmrg}
306629baa8cSmrg
307629baa8cSmrgstatic char authdir1[] = "authdir";
308629baa8cSmrgstatic char authdir2[] = "authfiles";
309629baa8cSmrg
310629baa8cSmrgstatic int
311629baa8cSmrgMakeServerAuthFile (struct display *d, FILE ** file)
312629baa8cSmrg{
313629baa8cSmrg    int len;
314629baa8cSmrg#ifdef MAXNAMELEN
315629baa8cSmrg# define NAMELEN	MAXNAMELEN
316629baa8cSmrg#else
317629baa8cSmrg# define NAMELEN	255
318629baa8cSmrg#endif
319629baa8cSmrg    char    cleanname[NAMELEN];
320629baa8cSmrg    int r;
321629baa8cSmrg#ifdef HAVE_MKSTEMP
322629baa8cSmrg    int fd;
323629baa8cSmrg#endif
324629baa8cSmrg    struct stat	statb;
325629baa8cSmrg
326629baa8cSmrg    *file = NULL;
327629baa8cSmrg
328629baa8cSmrg    if (!d->authFile) {
329629baa8cSmrg	if (d->clientAuthFile && *d->clientAuthFile) {
330629baa8cSmrg	    d->authFile = strdup(d->clientAuthFile);
331629baa8cSmrg	    if (!d->authFile)
332629baa8cSmrg		return FALSE;
333629baa8cSmrg	} else {
334629baa8cSmrg	    CleanUpFileName (d->name, cleanname, NAMELEN - 8);
335629baa8cSmrg
336629baa8cSmrg	    /* Make authDir if it doesn't already exist */
337629baa8cSmrg	    r = CheckServerAuthDir(authDir, &statb, 0755);
338629baa8cSmrg	    if (r < 0) {
339629baa8cSmrg		return FALSE;
340629baa8cSmrg	    }
341629baa8cSmrg
342629baa8cSmrg	    len = strlen (authDir) + strlen (authdir1) + strlen (authdir2)
343629baa8cSmrg		+ strlen (cleanname) + 14;
344629baa8cSmrg	    d->authFile = malloc (len);
345629baa8cSmrg	    if (!d->authFile)
346629baa8cSmrg		return FALSE;
347629baa8cSmrg
348629baa8cSmrg	    snprintf (d->authFile, len, "%s/%s", authDir, authdir1);
349629baa8cSmrg	    r = CheckServerAuthDir(d->authFile, &statb, 0700);
350629baa8cSmrg	    if (r == 0) {
351629baa8cSmrg		if (statb.st_uid != 0)
352629baa8cSmrg		    (void) chown(d->authFile, 0, statb.st_gid);
353629baa8cSmrg		if ((statb.st_mode & 0077) != 0)
354629baa8cSmrg		    (void) chmod(d->authFile, statb.st_mode & 0700);
355629baa8cSmrg	    } else if (r < 0) {
356629baa8cSmrg		free (d->authFile);
357629baa8cSmrg		d->authFile = NULL;
358629baa8cSmrg		return FALSE;
359629baa8cSmrg	    }
360629baa8cSmrg
361629baa8cSmrg	    snprintf (d->authFile, len, "%s/%s/%s",
362629baa8cSmrg		      authDir, authdir1, authdir2);
363629baa8cSmrg	    r = CheckServerAuthDir(d->authFile, &statb, 0700);
364629baa8cSmrg	    if (r < 0) {
365629baa8cSmrg		free (d->authFile);
366629baa8cSmrg		d->authFile = NULL;
367629baa8cSmrg		return FALSE;
368629baa8cSmrg	    }
369629baa8cSmrg	    snprintf (d->authFile, len, "%s/%s/%s/A%s-XXXXXX",
370629baa8cSmrg		      authDir, authdir1, authdir2, cleanname);
371629baa8cSmrg#ifdef HAVE_MKSTEMP
372629baa8cSmrg	    fd = mkstemp (d->authFile);
373629baa8cSmrg	    if (fd < 0) {
374629baa8cSmrg		LogError ("cannot make authentication file %s: %s\n",
375629baa8cSmrg			  d->authFile, _SysErrorMsg (errno));
376629baa8cSmrg		free (d->authFile);
377629baa8cSmrg		d->authFile = NULL;
378629baa8cSmrg		return FALSE;
379629baa8cSmrg	    }
380629baa8cSmrg
381629baa8cSmrg	    *file = fdopen(fd, "w");
382629baa8cSmrg	    if (!*file)
383629baa8cSmrg		(void) close (fd);
384629baa8cSmrg	    return TRUE;
385629baa8cSmrg#else
386629baa8cSmrg	    (void) mktemp (d->authFile);
387629baa8cSmrg#endif
388629baa8cSmrg	}
389629baa8cSmrg    }
390629baa8cSmrg
391629baa8cSmrg    (void) unlink (d->authFile);
392629baa8cSmrg    *file = fopen (d->authFile, "w");
393629baa8cSmrg    return TRUE;
394629baa8cSmrg}
395629baa8cSmrg
396629baa8cSmrgint
397629baa8cSmrgSaveServerAuthorizations (
398629baa8cSmrg    struct display  *d,
399629baa8cSmrg    Xauth	    **auths,
400629baa8cSmrg    int		    count)
401629baa8cSmrg{
402629baa8cSmrg    FILE	*auth_file;
403629baa8cSmrg    mode_t	mask;
404629baa8cSmrg    int		ret;
405629baa8cSmrg    int		i;
406629baa8cSmrg    const char	dummy_auth[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
407629baa8cSmrg		               "XXXXXXXXXXXXXXXXX"; /* 64 "X"s */
408629baa8cSmrg    int		err = 0;
409629baa8cSmrg
410629baa8cSmrg    mask = umask (0077);
411629baa8cSmrg    ret = MakeServerAuthFile(d, &auth_file);
412629baa8cSmrg    umask (mask);
413629baa8cSmrg    if (!ret)
414629baa8cSmrg	return FALSE;
415629baa8cSmrg    if (!auth_file) {
416629baa8cSmrg	LogError ("cannot open server authorization file %s: %s\n",
417629baa8cSmrg		  d->authFile, _SysErrorMsg (errno));
418629baa8cSmrg	ret = FALSE;
419629baa8cSmrg    }
420629baa8cSmrg    else
421629baa8cSmrg    {
422629baa8cSmrg	Debug ("File: %s auth: %p\n", d->authFile, auths);
423629baa8cSmrg	ret = TRUE;
424629baa8cSmrg	if (count == 0)
425629baa8cSmrg	{
426629baa8cSmrg		/*
427629baa8cSmrg		 * This is a crude hack to determine whether we really can
428629baa8cSmrg		 * write to the auth file even if we don't have real data
429629baa8cSmrg		 * to write right now.
430629baa8cSmrg		 */
431629baa8cSmrg
432629baa8cSmrg		/*
433629baa8cSmrg		 * Write garbage data to file to provoke ENOSPC and other
434629baa8cSmrg		 * errors.
435629baa8cSmrg		 */
436629baa8cSmrg		(void) fprintf (auth_file, "%s", dummy_auth);
437629baa8cSmrg		(void) fflush (auth_file);
438629baa8cSmrg		if (ferror (auth_file))
439629baa8cSmrg		{
440629baa8cSmrg		    err = errno;
441629baa8cSmrg		    ret = FALSE;
442629baa8cSmrg		}
443629baa8cSmrg		/*
444629baa8cSmrg		 * Rewind so that the garbage data is overwritten later.
445629baa8cSmrg		 */
446629baa8cSmrg		rewind(auth_file);
447629baa8cSmrg	}
448629baa8cSmrg	for (i = 0; i < count; i++)
449629baa8cSmrg	{
450629baa8cSmrg	    /*
451629baa8cSmrg	     * User-based auths may not have data until
452629baa8cSmrg	     * a user logs in.  In which case don't write
453629baa8cSmrg	     * to the auth file so xrdb and setup programs don't fail.
454629baa8cSmrg	     */
455629baa8cSmrg	    if (auths[i]->data_length > 0)
456629baa8cSmrg		if (!XauWriteAuth (auth_file, auths[i]))
457629baa8cSmrg		{
458629baa8cSmrg		    Debug ("XauWriteAuth() failed\n");
459629baa8cSmrg		}
460629baa8cSmrg		(void) fflush (auth_file);
461629baa8cSmrg		if (ferror (auth_file))
462629baa8cSmrg		{
463629baa8cSmrg		    err = errno;
464629baa8cSmrg		    ret = FALSE;
465629baa8cSmrg		}
466629baa8cSmrg	}
467629baa8cSmrg	/*
468629baa8cSmrg	 * XXX: This is not elegant, but stdio has no truncation function.
469629baa8cSmrg	 */
470629baa8cSmrg	if (ftruncate(fileno(auth_file), ftell(auth_file)))
471629baa8cSmrg	{
472629baa8cSmrg		Debug ("ftruncate() failed\n");
473629baa8cSmrg	}
474629baa8cSmrg	fclose (auth_file);
475629baa8cSmrg
476629baa8cSmrg    }
477629baa8cSmrg    if (ret == FALSE)
478629baa8cSmrg    {
479629baa8cSmrg	LogError ("Cannot write to server authorization file %s%s%s\n",
480629baa8cSmrg		  d->authFile,
481629baa8cSmrg		  err ? ": " : "",
482629baa8cSmrg		  err ? _SysErrorMsg (errno) : "");
483629baa8cSmrg	free (d->authFile);
484629baa8cSmrg	d->authFile = NULL;
485629baa8cSmrg    }
486629baa8cSmrg    return ret;
487629baa8cSmrg}
488629baa8cSmrg
489629baa8cSmrgvoid
490629baa8cSmrgSetLocalAuthorization (struct display *d)
491629baa8cSmrg{
492629baa8cSmrg    Xauth	*auth, **auths;
493629baa8cSmrg    int		i, j;
494629baa8cSmrg
495629baa8cSmrg    if (d->authorizations)
496629baa8cSmrg    {
497629baa8cSmrg	for (i = 0; i < d->authNum; i++)
498629baa8cSmrg	    XauDisposeAuth (d->authorizations[i]);
499629baa8cSmrg	free (d->authorizations);
500629baa8cSmrg	d->authorizations = (Xauth **) NULL;
501629baa8cSmrg	d->authNum = 0;
502629baa8cSmrg    }
503629baa8cSmrg    if (!d->authNames)
504629baa8cSmrg	return;
505629baa8cSmrg    for (i = 0; d->authNames[i]; i++)
506629baa8cSmrg	;
507629baa8cSmrg    d->authNameNum = i;
508629baa8cSmrg    free (d->authNameLens);
509629baa8cSmrg    d->authNameLens = malloc (d->authNameNum * sizeof (unsigned short));
510629baa8cSmrg    if (!d->authNameLens)
511629baa8cSmrg	return;
512629baa8cSmrg    for (i = 0; i < d->authNameNum; i++)
513629baa8cSmrg	d->authNameLens[i] = strlen (d->authNames[i]);
514629baa8cSmrg    auths = malloc (d->authNameNum * sizeof (Xauth *));
515629baa8cSmrg    if (!auths)
516629baa8cSmrg	return;
517629baa8cSmrg    j = 0;
518629baa8cSmrg    for (i = 0; i < d->authNameNum; i++)
519629baa8cSmrg    {
520629baa8cSmrg	auth = GenerateAuthorization (d->authNameLens[i], d->authNames[i]);
521629baa8cSmrg	if (auth)
522629baa8cSmrg	    auths[j++] = auth;
523629baa8cSmrg    }
524629baa8cSmrg    if (SaveServerAuthorizations (d, auths, j))
525629baa8cSmrg    {
526629baa8cSmrg	d->authorizations = auths;
527629baa8cSmrg	d->authNum = j;
528629baa8cSmrg    }
529629baa8cSmrg    else
530629baa8cSmrg    {
531629baa8cSmrg	for (i = 0; i < j; i++)
532629baa8cSmrg	    XauDisposeAuth (auths[i]);
533629baa8cSmrg	free (auths);
534629baa8cSmrg    }
535629baa8cSmrg}
536629baa8cSmrg
537629baa8cSmrg/*
538629baa8cSmrg * Set the authorization to use for xdm's initial connection
539629baa8cSmrg * to the X server.  Cannot use user-based authorizations
540629baa8cSmrg * because no one has logged in yet, so we don't have any
541629baa8cSmrg * user credentials.
542629baa8cSmrg * Well, actually we could use SUN-DES-1 because we tell the server
543629baa8cSmrg * to allow root in.  This is bogus and should be fixed.
544629baa8cSmrg */
545629baa8cSmrgvoid
546629baa8cSmrgSetAuthorization (struct display *d)
547629baa8cSmrg{
548629baa8cSmrg    register Xauth **auth = d->authorizations;
549629baa8cSmrg    int i;
550629baa8cSmrg
551629baa8cSmrg    for (i = 0; i < d->authNum; i++)
552629baa8cSmrg    {
553629baa8cSmrg	if (auth[i]->name_length == 9 &&
554629baa8cSmrg	    memcmp(auth[i]->name, "SUN-DES-1", 9) == 0)
555629baa8cSmrg	    continue;
556629baa8cSmrg	if (auth[i]->name_length == 14 &&
557629baa8cSmrg	    memcmp(auth[i]->name, "MIT-KERBEROS-5", 14) == 0)
558629baa8cSmrg	    continue;
559629baa8cSmrg	XSetAuthorization (auth[i]->name, (int) auth[i]->name_length,
560629baa8cSmrg			   auth[i]->data, (int) auth[i]->data_length);
561629baa8cSmrg    }
562629baa8cSmrg}
563629baa8cSmrg
564629baa8cSmrgstatic int
565629baa8cSmrgopenFiles (char *name, char *new_name, FILE **oldp, FILE **newp)
566629baa8cSmrg{
567629baa8cSmrg	mode_t	mask;
568629baa8cSmrg	int newfd;
569629baa8cSmrg
570629baa8cSmrg	strcpy (new_name, name);
571629baa8cSmrg	strcat (new_name, "-n");
572629baa8cSmrg	/*
573629baa8cSmrg	 * Set safe umask for file creation operations.
574629baa8cSmrg	 */
575629baa8cSmrg	mask = umask (0077);
576629baa8cSmrg	/*
577629baa8cSmrg	 * Unlink the authorization file we intend to create, and then open
578629baa8cSmrg	 * it with O_CREAT | O_EXCL to avoid race-based symlink attacks.
579629baa8cSmrg	 */
580629baa8cSmrg	(void) unlink (new_name);
581629baa8cSmrg	newfd = open (new_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
582629baa8cSmrg	if (newfd >= 0)
583629baa8cSmrg	    *newp = fdopen (newfd, "w");
584629baa8cSmrg	else
585629baa8cSmrg	{
586629baa8cSmrg	    LogError ("Cannot create file %s: %s\n", new_name,
587629baa8cSmrg		      _SysErrorMsg (errno));
588629baa8cSmrg	    *newp = NULL;
589629baa8cSmrg	}
590629baa8cSmrg	/*
591629baa8cSmrg	 * There are no more attempts to create files after this point;
592629baa8cSmrg	 * restore the original umask.
593629baa8cSmrg	 */
594629baa8cSmrg	(void) umask (mask);
595629baa8cSmrg	if (!*newp) {
596629baa8cSmrg		Debug ("can't open new file %s\n", new_name);
597629baa8cSmrg		return 0;
598629baa8cSmrg	}
599629baa8cSmrg	if (!*oldp)
600629baa8cSmrg	    *oldp = fopen (name, "r");
601629baa8cSmrg	Debug ("opens succeeded %s %s\n", name, new_name);
602629baa8cSmrg	return 1;
603629baa8cSmrg}
604629baa8cSmrg
605629baa8cSmrgstatic int
606629baa8cSmrgbinaryEqual (char *a, char *b, unsigned short len)
607629baa8cSmrg{
608629baa8cSmrg	while (len-- > 0)
609629baa8cSmrg		if (*a++ != *b++)
610629baa8cSmrg			return FALSE;
611629baa8cSmrg	return TRUE;
612629baa8cSmrg}
613629baa8cSmrg
614629baa8cSmrgstatic void
615629baa8cSmrgdumpBytes (unsigned short len, char *data)
616629baa8cSmrg{
617629baa8cSmrg	unsigned short	i;
618629baa8cSmrg
619629baa8cSmrg	Debug ("%d: ", len);
620629baa8cSmrg	for (i = 0; i < len; i++)
621629baa8cSmrg		Debug ("%02x ", data[i] & 0377);
622629baa8cSmrg	Debug ("\n");
623629baa8cSmrg}
624629baa8cSmrg
625629baa8cSmrgstatic void
626629baa8cSmrgdumpAuth (Xauth *auth)
627629baa8cSmrg{
628629baa8cSmrg	Debug ("family: %d\n", auth->family);
629629baa8cSmrg	Debug ("addr:   ");
630629baa8cSmrg	dumpBytes (auth->address_length, auth->address);
631629baa8cSmrg	Debug ("number: ");
632629baa8cSmrg	dumpBytes (auth->number_length, auth->number);
633629baa8cSmrg	Debug ("name:   ");
634629baa8cSmrg	dumpBytes (auth->name_length, auth->name);
635629baa8cSmrg	Debug ("data:   ");
636629baa8cSmrg	dumpBytes (auth->data_length, auth->data);
637629baa8cSmrg}
638629baa8cSmrg
639629baa8cSmrgstruct addrList {
640629baa8cSmrg	unsigned short	family;
641629baa8cSmrg	unsigned short	address_length;
642629baa8cSmrg	char	*address;
643629baa8cSmrg	unsigned short	number_length;
644629baa8cSmrg	char	*number;
645629baa8cSmrg	unsigned short	name_length;
646629baa8cSmrg	char	*name;
647629baa8cSmrg	struct addrList	*next;
648629baa8cSmrg};
649629baa8cSmrg
650629baa8cSmrgstatic struct addrList	*addrs;
651629baa8cSmrg
652629baa8cSmrgstatic void
653629baa8cSmrginitAddrs (void)
654629baa8cSmrg{
655629baa8cSmrg	addrs = NULL;
656629baa8cSmrg}
657629baa8cSmrg
658629baa8cSmrgstatic void
659629baa8cSmrgdoneAddrs (void)
660629baa8cSmrg{
661629baa8cSmrg	struct addrList	*a, *n;
662629baa8cSmrg	for (a = addrs; a; a = n) {
663629baa8cSmrg		n = a->next;
664629baa8cSmrg		free (a->address);
665629baa8cSmrg		free (a->number);
666629baa8cSmrg		free (a);
667629baa8cSmrg	}
668629baa8cSmrg}
669629baa8cSmrg
670629baa8cSmrgstatic int checkEntry (Xauth *auth);
671629baa8cSmrg
672629baa8cSmrgstatic void
673629baa8cSmrgsaveEntry (Xauth *auth)
674629baa8cSmrg{
675629baa8cSmrg	struct addrList	*new;
676629baa8cSmrg
677629baa8cSmrg	new = malloc (sizeof (struct addrList));
678629baa8cSmrg	if (!new) {
679629baa8cSmrg		LogOutOfMem ("saveEntry");
680629baa8cSmrg		return;
681629baa8cSmrg	}
682629baa8cSmrg	if ((new->address_length = auth->address_length) > 0) {
683629baa8cSmrg		new->address = malloc (auth->address_length);
684629baa8cSmrg		if (!new->address) {
685629baa8cSmrg			LogOutOfMem ("saveEntry");
686629baa8cSmrg			free (new);
687629baa8cSmrg			return;
688629baa8cSmrg		}
689629baa8cSmrg		memmove( new->address, auth->address, (int) auth->address_length);
690629baa8cSmrg	} else
691629baa8cSmrg		new->address = NULL;
692629baa8cSmrg	if ((new->number_length = auth->number_length) > 0) {
693629baa8cSmrg		new->number = malloc (auth->number_length);
694629baa8cSmrg		if (!new->number) {
695629baa8cSmrg			LogOutOfMem ("saveEntry");
696629baa8cSmrg			free (new->address);
697629baa8cSmrg			free (new);
698629baa8cSmrg			return;
699629baa8cSmrg		}
700629baa8cSmrg		memmove( new->number, auth->number, (int) auth->number_length);
701629baa8cSmrg	} else
702629baa8cSmrg		new->number = NULL;
703629baa8cSmrg	if ((new->name_length = auth->name_length) > 0) {
704629baa8cSmrg		new->name = malloc (auth->name_length);
705629baa8cSmrg		if (!new->name) {
706629baa8cSmrg			LogOutOfMem ("saveEntry");
707629baa8cSmrg			free (new->number);
708629baa8cSmrg			free (new->address);
709629baa8cSmrg			free (new);
710629baa8cSmrg			return;
711629baa8cSmrg		}
712629baa8cSmrg		memmove( new->name, auth->name, (int) auth->name_length);
713629baa8cSmrg	} else
714629baa8cSmrg		new->name = NULL;
715629baa8cSmrg	new->family = auth->family;
716629baa8cSmrg	new->next = addrs;
717629baa8cSmrg	addrs = new;
718629baa8cSmrg}
719629baa8cSmrg
720629baa8cSmrgstatic int
721629baa8cSmrgcheckEntry (Xauth *auth)
722629baa8cSmrg{
723629baa8cSmrg	struct addrList	*a;
724629baa8cSmrg
725629baa8cSmrg	for (a = addrs; a; a = a->next) {
726629baa8cSmrg		if (a->family == auth->family &&
727629baa8cSmrg		    a->address_length == auth->address_length &&
728629baa8cSmrg		    binaryEqual (a->address, auth->address, auth->address_length) &&
729629baa8cSmrg		    a->number_length == auth->number_length &&
730629baa8cSmrg		    binaryEqual (a->number, auth->number, auth->number_length) &&
731629baa8cSmrg		    a->name_length == auth->name_length &&
732629baa8cSmrg		    binaryEqual (a->name, auth->name, auth->name_length))
733629baa8cSmrg		{
734629baa8cSmrg			return 1;
735629baa8cSmrg		}
736629baa8cSmrg	}
737629baa8cSmrg	return 0;
738629baa8cSmrg}
739629baa8cSmrg
740629baa8cSmrgstatic int  doWrite;
741629baa8cSmrg
742629baa8cSmrgstatic void
743629baa8cSmrgwriteAuth (FILE *file, Xauth *auth)
744629baa8cSmrg{
745629baa8cSmrg    if (debugLevel >= 15) {	/* normally too verbose */
746629baa8cSmrg        Debug ("writeAuth: doWrite = %d\n", doWrite);
747629baa8cSmrg	dumpAuth (auth);	/* does Debug only */
748629baa8cSmrg    }
749629baa8cSmrg	if (doWrite)
750629baa8cSmrg	    XauWriteAuth (file, auth);
751629baa8cSmrg}
752629baa8cSmrg
753629baa8cSmrgstatic void
754629baa8cSmrgwriteAddr (
755629baa8cSmrg    int		family,
756629baa8cSmrg    int		addr_length,
757629baa8cSmrg    char	*addr,
758629baa8cSmrg    FILE	*file,
759629baa8cSmrg    Xauth	*auth)
760629baa8cSmrg{
761629baa8cSmrg	auth->family = (unsigned short) family;
762629baa8cSmrg	auth->address_length = addr_length;
763629baa8cSmrg	auth->address = addr;
764629baa8cSmrg	Debug ("writeAddr: writing and saving an entry\n");
765629baa8cSmrg	writeAuth (file, auth);
766629baa8cSmrg	saveEntry (auth);
767629baa8cSmrg}
768629baa8cSmrg
769629baa8cSmrgstatic void
770629baa8cSmrgDefineLocal (FILE *file, Xauth *auth)
771629baa8cSmrg{
772629baa8cSmrg	char	displayname[100];
773629baa8cSmrg	int	len = _XGetHostname (displayname, sizeof(displayname));
774629baa8cSmrg
775629baa8cSmrg/* Make sure this produces the same string as _XGetHostname in lib/X/XlibInt.c.
776629baa8cSmrg * Otherwise, Xau will not be able to find your cookies in the Xauthority file.
777629baa8cSmrg *
778629baa8cSmrg * Note: POSIX says that the ``nodename'' member of utsname does _not_ have
779629baa8cSmrg *       to have sufficient information for interfacing to the network,
780629baa8cSmrg *       and so, you may be better off using gethostname (if it exists).
781629baa8cSmrg */
782629baa8cSmrg
783629baa8cSmrg#if defined(hpux)
784629baa8cSmrg	/*
785629baa8cSmrg	 * For HP-UX, HP's Xlib expects a fully-qualified domain name, which
786629baa8cSmrg	 * is achieved by using gethostname().  For compatability, we must
787629baa8cSmrg	 * also still create the entry using uname().
788629baa8cSmrg	 */
789629baa8cSmrg	char	tmp_displayname[100];
790629baa8cSmrg	struct utsname name;
791629baa8cSmrg
792629baa8cSmrg	tmp_displayname[0] = 0;
793629baa8cSmrg	uname(&name);
794629baa8cSmrg	snprintf(tmp_displayname, sizeof(tmp_displayname), "%s", name.nodename);
795629baa8cSmrg	writeAddr (FamilyLocal, strlen (tmp_displayname), tmp_displayname,
796629baa8cSmrg		   file, auth);
797629baa8cSmrg
798629baa8cSmrg	/*
799629baa8cSmrg	 * If _XGetHostname() returned the same value as uname(), don't
800629baa8cSmrg	 * write a duplicate entry.
801629baa8cSmrg	 */
802629baa8cSmrg	if (strcmp (displayname, tmp_displayname))
803629baa8cSmrg#endif
804629baa8cSmrg
805629baa8cSmrg	writeAddr (FamilyLocal, len, displayname, file, auth);
806629baa8cSmrg}
807629baa8cSmrg
808629baa8cSmrg#ifdef HAVE_GETIFADDRS
809629baa8cSmrg# include <ifaddrs.h>
810629baa8cSmrg
811629baa8cSmrgstatic void
812629baa8cSmrgDefineSelf(int fd, FILE *file, Xauth *auth)
813629baa8cSmrg{
814629baa8cSmrg    struct ifaddrs *ifap, *ifr;
815629baa8cSmrg    char *addr;
816629baa8cSmrg    int family, len;
817629baa8cSmrg
818629baa8cSmrg    Debug("DefineSelf\n");
819629baa8cSmrg    if (getifaddrs(&ifap) < 0)
820629baa8cSmrg	return;
821629baa8cSmrg    for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
822629baa8cSmrg	len = sizeof(*(ifr->ifa_addr));
823629baa8cSmrg	family = ConvertAddr((XdmcpNetaddr)(ifr->ifa_addr), &len, &addr);
824629baa8cSmrg	if (family == -1 || family == FamilyLocal)
825629baa8cSmrg	    continue;
826629baa8cSmrg	/*
827629baa8cSmrg	 * don't write out 'localhost' entries, as
828629baa8cSmrg	 * they may conflict with other local entries.
829629baa8cSmrg	 * DefineLocal will always be called to add
830629baa8cSmrg	 * the local entry anyway, so this one can
831629baa8cSmrg	 * be tossed.
832629baa8cSmrg	 */
833629baa8cSmrg	if (family == FamilyInternet && len == 4 && addr[0] == 127)
834629baa8cSmrg	{
835629baa8cSmrg	    Debug ("Skipping localhost address\n");
836629baa8cSmrg	    continue;
837629baa8cSmrg	}
838629baa8cSmrg# if defined(IPv6) && defined(AF_INET6)
839629baa8cSmrg	if(family == FamilyInternet6) {
840629baa8cSmrg	    if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) {
841629baa8cSmrg		Debug ("Skipping IPv6 localhost address\n");
842629baa8cSmrg		continue;
843629baa8cSmrg	    }
844629baa8cSmrg	    /* Also skip XDM-AUTHORIZATION-1 */
845629baa8cSmrg	    if (auth->name_length == 19 &&
846629baa8cSmrg		strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) {
847629baa8cSmrg		Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n");
848629baa8cSmrg		continue;
849629baa8cSmrg	    }
850629baa8cSmrg	}
851629baa8cSmrg# endif
852629baa8cSmrg	writeAddr(family, len, addr, file, auth);
853629baa8cSmrg    }
854629baa8cSmrg    freeifaddrs(ifap);
855629baa8cSmrg    Debug("DefineSelf done\n");
856629baa8cSmrg}
857629baa8cSmrg#else  /* GETIFADDRS */
858629baa8cSmrg
859629baa8cSmrg# ifdef SYSV_SIOCGIFCONF
860629baa8cSmrg
861629baa8cSmrg/* Deal with different SIOCGIFCONF ioctl semantics on SYSV, SVR4 */
862629baa8cSmrg
863629baa8cSmrgstatic int
864629baa8cSmrgifioctl (int fd, int cmd, char *arg)
865629baa8cSmrg{
866629baa8cSmrg    struct strioctl ioc;
867629baa8cSmrg    int ret;
868629baa8cSmrg
869629baa8cSmrg    bzero((char *) &ioc, sizeof(ioc));
870629baa8cSmrg    ioc.ic_cmd = cmd;
871629baa8cSmrg    ioc.ic_timout = 0;
872629baa8cSmrg    if (cmd == SIOCGIFCONF)
873629baa8cSmrg    {
874629baa8cSmrg	ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
875629baa8cSmrg	ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
876629baa8cSmrg#  ifdef ISC
877629baa8cSmrg	/* SIOCGIFCONF is somewhat brain damaged on ISC. The argument
878629baa8cSmrg	 * buffer must contain the ifconf structure as header. Ifc_req
879629baa8cSmrg	 * is also not a pointer but a one element array of ifreq
880629baa8cSmrg	 * structures. On return this array is extended by enough
881629baa8cSmrg	 * ifreq fields to hold all interfaces. The return buffer length
882629baa8cSmrg	 * is placed in the buffer header.
883629baa8cSmrg	 */
884629baa8cSmrg        ((struct ifconf *) ioc.ic_dp)->ifc_len =
885629baa8cSmrg                                         ioc.ic_len - sizeof(struct ifconf);
886629baa8cSmrg#  endif
887629baa8cSmrg    }
888629baa8cSmrg    else
889629baa8cSmrg    {
890629baa8cSmrg	ioc.ic_len = sizeof(struct ifreq);
891629baa8cSmrg	ioc.ic_dp = arg;
892629baa8cSmrg    }
893629baa8cSmrg    ret = ioctl(fd, I_STR, (char *) &ioc);
894629baa8cSmrg    if (ret >= 0 && cmd == SIOCGIFCONF)
895629baa8cSmrg#  ifdef SVR4
896629baa8cSmrg	((struct ifconf *) arg)->ifc_len = ioc.ic_len;
897629baa8cSmrg#  endif
898629baa8cSmrg#  ifdef ISC
899629baa8cSmrg    {
900629baa8cSmrg	((struct ifconf *) arg)->ifc_len =
901629baa8cSmrg				 ((struct ifconf *)ioc.ic_dp)->ifc_len;
902629baa8cSmrg	((struct ifconf *) arg)->ifc_buf =
903629baa8cSmrg			(caddr_t)((struct ifconf *)ioc.ic_dp)->ifc_req;
904629baa8cSmrg    }
905629baa8cSmrg#  endif
906629baa8cSmrg    return(ret);
907629baa8cSmrg}
908629baa8cSmrg# else /* SYSV_SIOCGIFCONF */
909629baa8cSmrg#  define ifioctl ioctl
910629baa8cSmrg# endif /* SYSV_SIOCGIFCONF */
911629baa8cSmrg
912629baa8cSmrg# if defined(STREAMSCONN) && !defined(SYSV_SIOCGIFCONF) && !defined(NCR)
913629baa8cSmrg
914629baa8cSmrg#  include <tiuser.h>
915629baa8cSmrg
916629baa8cSmrg/* Define this host for access control.  Find all the hosts the OS knows about
917629baa8cSmrg * for this fd and add them to the selfhosts list.
918629baa8cSmrg * TLI version, written without sufficient documentation.
919629baa8cSmrg */
920629baa8cSmrgstatic void
921629baa8cSmrgDefineSelf (int fd, FILE *file, Xauth *auth)
922629baa8cSmrg{
923629baa8cSmrg    struct netbuf	netb;
924629baa8cSmrg    char		addrret[1024]; /* easier than t_alloc */
925629baa8cSmrg
926629baa8cSmrg    netb.maxlen = sizeof(addrret);
927629baa8cSmrg    netb.buf = addrret;
928629baa8cSmrg    if (t_getname (fd, &netb, LOCALNAME) == -1)
929629baa8cSmrg	t_error ("t_getname");
930629baa8cSmrg    /* what a kludge */
931629baa8cSmrg    writeAddr (FamilyInternet, 4, netb.buf+4, file, auth);
932629baa8cSmrg}
933629baa8cSmrg
934629baa8cSmrg# else
935629baa8cSmrg
936629baa8cSmrg#  ifdef WINTCP /* NCR with Wollongong TCP */
937629baa8cSmrg
938629baa8cSmrg#   include <sys/un.h>
939629baa8cSmrg#   include <stropts.h>
940629baa8cSmrg#   include <tiuser.h>
941629baa8cSmrg
942629baa8cSmrg#   include <sys/stream.h>
943629baa8cSmrg#   include <net/if.h>
944629baa8cSmrg#   include <netinet/ip.h>
945629baa8cSmrg#   include <netinet/ip_var.h>
946629baa8cSmrg#   include <netinet/in.h>
947629baa8cSmrg#   include <netinet/in_var.h>
948629baa8cSmrg
949629baa8cSmrgstatic void
950629baa8cSmrgDefineSelf (int fd, FILE *file, Xauth *auth)
951629baa8cSmrg{
952629baa8cSmrg    /*
953629baa8cSmrg     * The Wollongong drivers used by NCR SVR4/MP-RAS don't understand the
954629baa8cSmrg     * socket IO calls that most other drivers seem to like. Because of
955629baa8cSmrg     * this, this routine must be special cased for NCR. Eventually,
956629baa8cSmrg     * this will be cleared up.
957629baa8cSmrg     */
958629baa8cSmrg
959629baa8cSmrg    struct ipb ifnet;
960629baa8cSmrg    struct in_ifaddr ifaddr;
961629baa8cSmrg    struct strioctl str;
962629baa8cSmrg    unsigned char *addr;
963629baa8cSmrg    int	len, ipfd;
964629baa8cSmrg
965629baa8cSmrg    if ((ipfd = open ("/dev/ip", O_RDWR, 0 )) < 0)
966629baa8cSmrg        LogError ("cannot get interface configuration; cannot open /dev/ip: "
967629baa8cSmrg		  "%s\n", _SysErrorMsg (errno));
968629baa8cSmrg
969629baa8cSmrg    /* Indicate that we want to start at the begining */
970629baa8cSmrg    ifnet.ib_next = (struct ipb *) 1;
971629baa8cSmrg
972629baa8cSmrg    while (ifnet.ib_next)
973629baa8cSmrg    {
974629baa8cSmrg	str.ic_cmd = IPIOC_GETIPB;
975629baa8cSmrg	str.ic_timout = 0;
976629baa8cSmrg	str.ic_len = sizeof (struct ipb);
977629baa8cSmrg	str.ic_dp = (char *) &ifnet;
978629baa8cSmrg
979629baa8cSmrg	if (ioctl (ipfd, (int) I_STR, (char *) &str) < 0)
980629baa8cSmrg	{
981629baa8cSmrg	    LogError ("cannot get interface configuration; ioctl failed: %s\n",
982629baa8cSmrg		      _SysErrorMsg (errno));
983629baa8cSmrg	    close (ipfd);
984629baa8cSmrg	}
985629baa8cSmrg
986629baa8cSmrg	ifaddr.ia_next = (struct in_ifaddr *) ifnet.if_addrlist;
987629baa8cSmrg	str.ic_cmd = IPIOC_GETINADDR;
988629baa8cSmrg	str.ic_timout = 0;
989629baa8cSmrg	str.ic_len = sizeof (struct in_ifaddr);
990629baa8cSmrg	str.ic_dp = (char *) &ifaddr;
991629baa8cSmrg
992629baa8cSmrg	if (ioctl (ipfd, (int) I_STR, (char *) &str) < 0)
993629baa8cSmrg	{
994629baa8cSmrg	    LogError ("cannot get interface configuration; ioctl failed: %s\n",
995629baa8cSmrg		      _SysErrorMsg (errno));
996629baa8cSmrg	    close (ipfd);
997629baa8cSmrg	}
998629baa8cSmrg
999629baa8cSmrg	/*
1000629baa8cSmrg	 * Ignore the 127.0.0.1 entry.
1001629baa8cSmrg	 */
1002629baa8cSmrg	if (IA_SIN(&ifaddr)->sin_addr.s_addr == htonl(0x7f000001) )
1003629baa8cSmrg		continue;
1004629baa8cSmrg
1005629baa8cSmrg	writeAddr (FamilyInternet, 4, (char *)&(IA_SIN(&ifaddr)->sin_addr), file, auth);
1006629baa8cSmrg
1007629baa8cSmrg    }
1008629baa8cSmrg    close(ipfd);
1009629baa8cSmrg}
1010629baa8cSmrg
1011629baa8cSmrg#  else /* WINTCP */
1012629baa8cSmrg
1013629baa8cSmrg#   if defined(SIOCGIFCONF) || defined (USE_SIOCGLIFCONF)
1014629baa8cSmrg
1015629baa8cSmrg#    ifdef USE_SIOCGLIFCONF
1016629baa8cSmrg#     define ifr_type    struct lifreq
1017629baa8cSmrg#    else
1018629baa8cSmrg#     define ifr_type    struct ifreq
1019629baa8cSmrg#    endif
1020629baa8cSmrg
1021629baa8cSmrg/* Handle variable length ifreq in BNR2 and later */
1022629baa8cSmrg#    ifdef VARIABLE_IFREQ
1023629baa8cSmrg#     define ifr_size(p) (sizeof (struct ifreq) + \
1024629baa8cSmrg		     (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
1025629baa8cSmrg		      p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
1026629baa8cSmrg#    else
1027629baa8cSmrg#     define ifr_size(p) (sizeof (ifr_type))
1028629baa8cSmrg#    endif
1029629baa8cSmrg
1030629baa8cSmrg/* Define this host for access control.  Find all the hosts the OS knows about
1031629baa8cSmrg * for this fd and add them to the selfhosts list.
1032629baa8cSmrg */
1033629baa8cSmrgstatic void
1034629baa8cSmrgDefineSelf (int fd, FILE *file, Xauth *auth)
1035629baa8cSmrg{
1036629baa8cSmrg    char		buf[2048], *cp, *cplim;
1037629baa8cSmrg    int 		len;
1038629baa8cSmrg    char 		*addr;
1039629baa8cSmrg    int 		family;
1040629baa8cSmrg    register ifr_type  *ifr;
1041629baa8cSmrg#    ifdef USE_SIOCGLIFCONF
1042629baa8cSmrg    void *		bufptr = buf;
1043629baa8cSmrg    size_t		buflen = sizeof(buf);
1044629baa8cSmrg    struct lifconf	ifc;
1045629baa8cSmrg#     ifdef SIOCGLIFNUM
1046629baa8cSmrg    struct lifnum	ifn;
1047629baa8cSmrg#     endif
1048629baa8cSmrg#    else
1049629baa8cSmrg    struct ifconf	ifc;
1050629baa8cSmrg#    endif
1051629baa8cSmrg
1052629baa8cSmrg#    if defined(SIOCGLIFNUM) && defined(SIOCGLIFCONF)
1053629baa8cSmrg    ifn.lifn_family = AF_UNSPEC;
1054629baa8cSmrg    ifn.lifn_flags = 0;
1055629baa8cSmrg    if (ioctl (fd, (int) SIOCGLIFNUM, (char *) &ifn) < 0)
1056629baa8cSmrg	LogError ("Failed getting interface count");
1057629baa8cSmrg    if (buflen < (ifn.lifn_count * sizeof(struct lifreq))) {
1058629baa8cSmrg	buflen = ifn.lifn_count * sizeof(struct lifreq);
1059629baa8cSmrg	bufptr = malloc(buflen);
1060629baa8cSmrg    }
1061629baa8cSmrg#    endif
1062629baa8cSmrg
1063629baa8cSmrg#    ifdef USE_SIOCGLIFCONF
1064629baa8cSmrg    ifc.lifc_family = AF_UNSPEC;
1065629baa8cSmrg    ifc.lifc_flags = 0;
1066629baa8cSmrg    ifc.lifc_len = buflen;
1067629baa8cSmrg    ifc.lifc_buf = bufptr;
1068629baa8cSmrg
1069629baa8cSmrg#     define IFC_IOCTL_REQ SIOCGLIFCONF
1070629baa8cSmrg#     define IFC_IFC_REQ ifc.lifc_req
1071629baa8cSmrg#     define IFC_IFC_LEN ifc.lifc_len
1072629baa8cSmrg#     define IFR_IFR_ADDR ifr->lifr_addr
1073629baa8cSmrg#     define IFR_IFR_NAME ifr->lifr_name
1074629baa8cSmrg
1075629baa8cSmrg#    else
1076629baa8cSmrg    ifc.ifc_len = sizeof (buf);
1077629baa8cSmrg    ifc.ifc_buf = buf;
1078629baa8cSmrg
1079629baa8cSmrg#     define IFC_IOCTL_REQ SIOCGIFCONF
1080629baa8cSmrg#     ifdef ISC
1081629baa8cSmrg#      define IFC_IFC_REQ (struct ifreq *) ifc.ifc_buf
1082629baa8cSmrg#     else
1083629baa8cSmrg#      define IFC_IFC_REQ ifc.ifc_req
1084629baa8cSmrg#     endif
1085629baa8cSmrg#     define IFC_IFC_LEN ifc.ifc_len
1086629baa8cSmrg#     define IFR_IFR_ADDR ifr->ifr_addr
1087629baa8cSmrg#     define IFR_IFR_NAME ifr->ifr_name
1088629baa8cSmrg#    endif
1089629baa8cSmrg
1090629baa8cSmrg    if (ifioctl (fd, IFC_IOCTL_REQ, (char *) &ifc) < 0) {
1091629baa8cSmrg        LogError ("Trouble getting network interface configuration");
1092629baa8cSmrg
1093629baa8cSmrg#    ifdef USE_SIOCGLIFCONF
1094629baa8cSmrg	if (bufptr != buf) {
1095629baa8cSmrg	    free(bufptr);
1096629baa8cSmrg	}
1097629baa8cSmrg#    endif
1098629baa8cSmrg	return;
1099629baa8cSmrg    }
1100629baa8cSmrg
1101629baa8cSmrg    cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
1102629baa8cSmrg
1103629baa8cSmrg    for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
1104629baa8cSmrg    {
1105629baa8cSmrg	ifr = (ifr_type *) cp;
1106629baa8cSmrg#    ifdef DNETCONN
1107629baa8cSmrg	/*
1108629baa8cSmrg	 * this is ugly but SIOCGIFCONF returns decnet addresses in
1109629baa8cSmrg	 * a different form from other decnet calls
1110629baa8cSmrg	 */
1111629baa8cSmrg	if (IFR_IFR_ADDR.sa_family == AF_DECnet) {
1112629baa8cSmrg		len = sizeof (struct dn_naddr);
1113629baa8cSmrg		addr = (char *)ifr->ifr_addr.sa_data;
1114629baa8cSmrg		family = FamilyDECnet;
1115629baa8cSmrg	} else
1116629baa8cSmrg#    endif
1117629baa8cSmrg	{
1118629baa8cSmrg	    family = ConvertAddr ((XdmcpNetaddr) &IFR_IFR_ADDR, &len, &addr);
1119629baa8cSmrg	    if (family < 0)
1120629baa8cSmrg		continue;
1121629baa8cSmrg
1122629baa8cSmrg	    if (len == 0)
1123629baa8cSmrg	    {
1124629baa8cSmrg		Debug ("Skipping zero length address\n");
1125629baa8cSmrg		continue;
1126629baa8cSmrg	    }
1127629baa8cSmrg	    /*
1128629baa8cSmrg	     * don't write out 'localhost' entries, as
1129629baa8cSmrg	     * they may conflict with other local entries.
1130629baa8cSmrg	     * DefineLocal will always be called to add
1131629baa8cSmrg	     * the local entry anyway, so this one can
1132629baa8cSmrg	     * be tossed.
1133629baa8cSmrg	     */
1134629baa8cSmrg	    if (family == FamilyInternet && len == 4 &&
1135629baa8cSmrg		addr[0] == 127 && addr[1] == 0 &&
1136629baa8cSmrg		addr[2] == 0 && addr[3] == 1)
1137629baa8cSmrg	    {
1138629baa8cSmrg		    Debug ("Skipping localhost address\n");
1139629baa8cSmrg		    continue;
1140629baa8cSmrg	    }
1141629baa8cSmrg#    if defined(IPv6) && defined(AF_INET6)
1142629baa8cSmrg	    if(family == FamilyInternet6) {
1143629baa8cSmrg		if (IN6_IS_ADDR_LOOPBACK(((struct in6_addr *)addr))) {
1144629baa8cSmrg		    Debug ("Skipping IPv6 localhost address\n");
1145629baa8cSmrg		    continue;
1146629baa8cSmrg		}
1147629baa8cSmrg		/* Also skip XDM-AUTHORIZATION-1 */
1148629baa8cSmrg		if (auth->name_length == 19 &&
1149629baa8cSmrg		    strcmp(auth->name, "XDM-AUTHORIZATION-1") == 0) {
1150629baa8cSmrg		    Debug ("Skipping IPv6 XDM-AUTHORIZATION-1\n");
1151629baa8cSmrg		    continue;
1152629baa8cSmrg		}
1153629baa8cSmrg	    }
1154629baa8cSmrg#    endif
1155629baa8cSmrg	}
1156629baa8cSmrg	Debug ("DefineSelf: write network address, length %d\n", len);
1157629baa8cSmrg	writeAddr (family, len, addr, file, auth);
1158629baa8cSmrg    }
1159629baa8cSmrg}
1160629baa8cSmrg
1161629baa8cSmrg#   else /* SIOCGIFCONF */
1162629baa8cSmrg
1163629baa8cSmrg/* Define this host for access control.  Find all the hosts the OS knows about
1164629baa8cSmrg * for this fd and add them to the selfhosts list.
1165629baa8cSmrg */
1166629baa8cSmrgstatic void
1167629baa8cSmrgDefineSelf (int fd, int file, int auth)
1168629baa8cSmrg{
1169629baa8cSmrg    register int n;
1170629baa8cSmrg    int	len;
1171629baa8cSmrg    caddr_t	addr;
1172629baa8cSmrg    int		family;
1173629baa8cSmrg
1174629baa8cSmrg    struct utsname name;
1175629baa8cSmrg    register struct hostent  *hp;
1176629baa8cSmrg
1177629baa8cSmrg    union {
1178629baa8cSmrg	struct  sockaddr   sa;
1179629baa8cSmrg	struct  sockaddr_in  in;
1180629baa8cSmrg    } saddr;
1181629baa8cSmrg
1182629baa8cSmrg    struct	sockaddr_in	*inetaddr;
1183629baa8cSmrg
1184629baa8cSmrg    /* hpux:
1185629baa8cSmrg     * Why not use gethostname()?  Well, at least on my system, I've had to
1186629baa8cSmrg     * make an ugly kernel patch to get a name longer than 8 characters, and
1187629baa8cSmrg     * uname() lets me access to the whole string (it smashes release, you
1188629baa8cSmrg     * see), whereas gethostname() kindly truncates it for me.
1189629baa8cSmrg     */
1190629baa8cSmrg    uname(&name);
1191629baa8cSmrg    hp = gethostbyname (name.nodename);
1192629baa8cSmrg    if (hp != NULL) {
1193629baa8cSmrg	saddr.sa.sa_family = hp->h_addrtype;
1194629baa8cSmrg	inetaddr = (struct sockaddr_in *) (&(saddr.sa));
1195629baa8cSmrg	memmove( (char *) &(inetaddr->sin_addr), (char *) hp->h_addr, (int) hp->h_length);
1196629baa8cSmrg	family = ConvertAddr ( &(saddr.sa), &len, &addr);
1197629baa8cSmrg	if ( family >= 0) {
1198629baa8cSmrg	    writeAddr (FamilyInternet, sizeof (inetaddr->sin_addr),
1199629baa8cSmrg			(char *) (&inetaddr->sin_addr), file, auth);
1200629baa8cSmrg	}
1201629baa8cSmrg    }
1202629baa8cSmrg}
1203629baa8cSmrg
1204629baa8cSmrg
1205629baa8cSmrg#   endif /* SIOCGIFCONF else */
1206629baa8cSmrg#  endif /* WINTCP else */
1207629baa8cSmrg# endif /* STREAMSCONN && !SYSV_SIOCGIFCONF else */
1208629baa8cSmrg#endif /* HAVE_GETIFADDRS */
1209629baa8cSmrg
1210629baa8cSmrgstatic void
1211629baa8cSmrgsetAuthNumber (Xauth *auth, char *name)
1212629baa8cSmrg{
1213629baa8cSmrg    char	*colon;
1214629baa8cSmrg    char	*dot, *number;
1215629baa8cSmrg
1216629baa8cSmrg    Debug ("setAuthNumber %s\n", name);
1217629baa8cSmrg    colon = strrchr(name, ':');
1218629baa8cSmrg    if (colon) {
1219629baa8cSmrg	++colon;
1220629baa8cSmrg	dot = strchr(colon, '.');
1221629baa8cSmrg	if (dot)
1222629baa8cSmrg	    auth->number_length = dot - colon;
1223629baa8cSmrg	else
1224629baa8cSmrg	    auth->number_length = strlen (colon);
1225629baa8cSmrg	number = malloc (auth->number_length + 1);
1226629baa8cSmrg	if (number) {
1227629baa8cSmrg	    strncpy (number, colon, auth->number_length);
1228629baa8cSmrg	    number[auth->number_length] = '\0';
1229629baa8cSmrg	} else {
1230629baa8cSmrg	    LogOutOfMem ("setAuthNumber");
1231629baa8cSmrg	    auth->number_length = 0;
1232629baa8cSmrg	}
1233629baa8cSmrg	auth->number = number;
1234629baa8cSmrg	Debug ("setAuthNumber: %s\n", number);
1235629baa8cSmrg    }
1236629baa8cSmrg}
1237629baa8cSmrg
1238629baa8cSmrgstatic void
1239629baa8cSmrgwriteLocalAuth (FILE *file, Xauth *auth, char *name)
1240629baa8cSmrg{
1241629baa8cSmrg    int	fd;
1242629baa8cSmrg
1243629baa8cSmrg    Debug ("writeLocalAuth: %s %.*s\n", name, auth->name_length, auth->name);
1244629baa8cSmrg    setAuthNumber (auth, name);
1245629baa8cSmrg#ifdef STREAMSCONN
1246629baa8cSmrg    fd = t_open ("/dev/tcp", O_RDWR, 0);
1247629baa8cSmrg    t_bind(fd, NULL, NULL);
1248629baa8cSmrg    DefineSelf (fd, file, auth);
1249629baa8cSmrg    t_unbind (fd);
1250629baa8cSmrg    t_close (fd);
1251629baa8cSmrg#endif
1252629baa8cSmrg#ifdef TCPCONN
1253629baa8cSmrg# if defined(IPv6) && defined(AF_INET6)
1254629baa8cSmrg    fd = socket (AF_INET6, SOCK_STREAM, 0);
1255629baa8cSmrg    if (fd < 0)
1256629baa8cSmrg# endif
1257629baa8cSmrg    fd = socket (AF_INET, SOCK_STREAM, 0);
1258629baa8cSmrg    DefineSelf (fd, file, auth);
1259629baa8cSmrg    close (fd);
1260629baa8cSmrg#endif
1261629baa8cSmrg#ifdef DNETCONN
1262629baa8cSmrg    fd = socket (AF_DECnet, SOCK_STREAM, 0);
1263629baa8cSmrg    DefineSelf (fd, file, auth);
1264629baa8cSmrg    close (fd);
1265629baa8cSmrg#endif
1266629baa8cSmrg    DefineLocal (file, auth);
1267629baa8cSmrg}
1268629baa8cSmrg
1269629baa8cSmrg#ifdef XDMCP
1270629baa8cSmrg
1271629baa8cSmrgstatic void
1272629baa8cSmrgwriteRemoteAuth (FILE *file, Xauth *auth, XdmcpNetaddr peer, int peerlen, char *name)
1273629baa8cSmrg{
1274629baa8cSmrg    int	    family = FamilyLocal;
1275629baa8cSmrg    char    *addr;
1276629baa8cSmrg
1277629baa8cSmrg    Debug ("writeRemoteAuth: %s %.*s\n", name, auth->name_length, auth->name);
1278629baa8cSmrg    if (!peer || peerlen < 2)
1279629baa8cSmrg	return;
1280629baa8cSmrg    setAuthNumber (auth, name);
1281629baa8cSmrg    family = ConvertAddr (peer, &peerlen, &addr);
1282629baa8cSmrg    Debug ("writeRemoteAuth: family %d\n", family);
1283629baa8cSmrg    if (family != FamilyLocal)
1284629baa8cSmrg    {
1285629baa8cSmrg	Debug ("writeRemoteAuth: %d, %d, %x\n",
1286629baa8cSmrg		family, peerlen, *(int *)addr);
1287629baa8cSmrg	writeAddr (family, peerlen, addr, file, auth);
1288629baa8cSmrg    }
1289629baa8cSmrg    else
1290629baa8cSmrg    {
1291629baa8cSmrg	writeLocalAuth (file, auth, name);
1292629baa8cSmrg    }
1293629baa8cSmrg}
1294629baa8cSmrg
1295629baa8cSmrg#endif /* XDMCP */
1296629baa8cSmrg
1297629baa8cSmrgvoid
1298629baa8cSmrgSetUserAuthorization (struct display *d, struct verify_info *verify)
1299629baa8cSmrg{
1300629baa8cSmrg    FILE	*old = NULL, *new;
1301629baa8cSmrg    char	home_name[1024], backup_name[1024], new_name[1024];
1302629baa8cSmrg    char	*name = NULL;
1303629baa8cSmrg    char	*home;
1304629baa8cSmrg    char	*envname = NULL;
1305629baa8cSmrg    int	lockStatus;
1306629baa8cSmrg    Xauth	*entry, **auths;
1307629baa8cSmrg    int		setenv = 0;
1308629baa8cSmrg    struct stat	statb;
1309629baa8cSmrg    int		i;
1310629baa8cSmrg    int		magicCookie;
1311629baa8cSmrg    int		data_len;
1312629baa8cSmrg#ifdef HAVE_MKSTEMP
1313629baa8cSmrg    int		fd;
1314629baa8cSmrg#endif
1315629baa8cSmrg
1316629baa8cSmrg    Debug ("SetUserAuthorization\n");
1317629baa8cSmrg    auths = d->authorizations;
1318629baa8cSmrg    if (auths) {
1319629baa8cSmrg	home = getEnv (verify->userEnviron, "HOME");
1320629baa8cSmrg	lockStatus = LOCK_ERROR;
1321629baa8cSmrg	if (home) {
1322629baa8cSmrg	    snprintf (home_name, sizeof(home_name), "%s/.Xauthority", home);
1323629baa8cSmrg	    Debug ("XauLockAuth %s\n", home_name);
1324629baa8cSmrg	    lockStatus = XauLockAuth (home_name, 1, 2, 10);
1325629baa8cSmrg	    Debug ("Lock is %d\n", lockStatus);
1326629baa8cSmrg	    if (lockStatus == LOCK_SUCCESS) {
1327629baa8cSmrg		if (openFiles (home_name, new_name, &old, &new)
1328629baa8cSmrg		    && (old != NULL) && (new != NULL)) {
1329629baa8cSmrg		    name = home_name;
1330629baa8cSmrg		    setenv = 0;
1331629baa8cSmrg		} else {
1332629baa8cSmrg		    Debug ("openFiles failed\n");
1333629baa8cSmrg		    XauUnlockAuth (home_name);
1334629baa8cSmrg		    lockStatus = LOCK_ERROR;
1335629baa8cSmrg		    if (old != NULL) {
1336629baa8cSmrg			(void) fclose (old);
1337629baa8cSmrg			old = NULL;
1338629baa8cSmrg		    }
1339629baa8cSmrg		    if (new != NULL)
1340629baa8cSmrg			(void) fclose (new);
1341629baa8cSmrg		}
1342629baa8cSmrg	    }
1343629baa8cSmrg	}
1344629baa8cSmrg	if (lockStatus != LOCK_SUCCESS) {
1345629baa8cSmrg	    snprintf (backup_name, sizeof(backup_name),
1346629baa8cSmrg		      "%s/.XauthXXXXXX", d->userAuthDir);
1347629baa8cSmrg#ifdef HAVE_MKSTEMP
1348629baa8cSmrg	    fd = mkstemp (backup_name);
1349629baa8cSmrg	    if (fd >= 0) {
1350629baa8cSmrg		old = fdopen (fd, "r");
1351629baa8cSmrg		if (old == NULL)
1352629baa8cSmrg		    (void) close(fd);
1353629baa8cSmrg	    }
1354629baa8cSmrg
1355629baa8cSmrg	    if (old != NULL)
1356629baa8cSmrg#else
1357629baa8cSmrg	    (void) mktemp (backup_name);
1358629baa8cSmrg#endif
1359629baa8cSmrg	    {
1360629baa8cSmrg		lockStatus = XauLockAuth (backup_name, 1, 2, 10);
1361629baa8cSmrg		Debug ("backup lock is %d\n", lockStatus);
1362629baa8cSmrg		if (lockStatus == LOCK_SUCCESS) {
1363629baa8cSmrg		    if (openFiles (backup_name, new_name, &old, &new)
1364629baa8cSmrg			&& (old != NULL) && (new != NULL)) {
1365629baa8cSmrg			name = backup_name;
1366629baa8cSmrg			setenv = 1;
1367629baa8cSmrg		    } else {
1368629baa8cSmrg			XauUnlockAuth (backup_name);
1369629baa8cSmrg			lockStatus = LOCK_ERROR;
1370629baa8cSmrg			if (old != NULL) {
1371629baa8cSmrg			    (void) fclose (old);
1372629baa8cSmrg			    old = NULL;
1373629baa8cSmrg			}
1374629baa8cSmrg			if (new != NULL)
1375629baa8cSmrg			    (void) fclose (new);
1376629baa8cSmrg		    }
1377629baa8cSmrg#ifdef HAVE_MKSTEMP
1378629baa8cSmrg		} else {
1379629baa8cSmrg		    (void) fclose (old);
1380629baa8cSmrg#endif
1381629baa8cSmrg		}
1382629baa8cSmrg	    }
1383629baa8cSmrg	}
1384629baa8cSmrg	if (lockStatus != LOCK_SUCCESS) {
1385629baa8cSmrg	    Debug ("can't lock auth file %s or backup %s\n",
1386629baa8cSmrg			    home_name, backup_name);
1387629baa8cSmrg	    LogError ("can't lock authorization file %s or backup %s\n",
1388629baa8cSmrg			    home_name, backup_name);
1389629baa8cSmrg	    return;
1390629baa8cSmrg	}
1391629baa8cSmrg	initAddrs ();
1392629baa8cSmrg	doWrite = 1;
1393629baa8cSmrg	Debug ("%d authorization protocols for %s\n", d->authNum, d->name);
1394629baa8cSmrg	/*
1395629baa8cSmrg	 * Write MIT-MAGIC-COOKIE-1 authorization first, so that
1396629baa8cSmrg	 * R4 clients which only knew that, and used the first
1397629baa8cSmrg	 * matching entry will continue to function
1398629baa8cSmrg	 */
1399629baa8cSmrg	magicCookie = -1;
1400629baa8cSmrg	for (i = 0; i < d->authNum; i++)
1401629baa8cSmrg	{
1402629baa8cSmrg	    if (auths[i]->name_length == 18 &&
1403629baa8cSmrg		!strncmp (auths[i]->name, "MIT-MAGIC-COOKIE-1", 18))
1404629baa8cSmrg	    {
1405629baa8cSmrg		magicCookie = i;
1406629baa8cSmrg		if (d->displayType.location == Local)
1407629baa8cSmrg		    writeLocalAuth (new, auths[i], d->name);
1408629baa8cSmrg#ifdef XDMCP
1409629baa8cSmrg		else
1410629baa8cSmrg		    writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
1411629baa8cSmrg#endif
1412629baa8cSmrg		break;
1413629baa8cSmrg	    }
1414629baa8cSmrg	}
1415629baa8cSmrg	/* now write other authorizations */
1416629baa8cSmrg	for (i = 0; i < d->authNum; i++)
1417629baa8cSmrg	{
1418629baa8cSmrg	    if (i != magicCookie)
1419629baa8cSmrg	    {
1420629baa8cSmrg		data_len = auths[i]->data_length;
1421629baa8cSmrg		/* client will just use default Kerberos cache, so don't
1422629baa8cSmrg		 * even write cache info into the authority file.
1423629baa8cSmrg		 */
1424629baa8cSmrg		if (auths[i]->name_length == 14 &&
1425629baa8cSmrg		    !strncmp (auths[i]->name, "MIT-KERBEROS-5", 14))
1426629baa8cSmrg		    auths[i]->data_length = 0;
1427629baa8cSmrg		if (d->displayType.location == Local)
1428629baa8cSmrg		    writeLocalAuth (new, auths[i], d->name);
1429629baa8cSmrg#ifdef XDMCP
1430629baa8cSmrg		else
1431629baa8cSmrg		    writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
1432629baa8cSmrg#endif
1433629baa8cSmrg		auths[i]->data_length = data_len;
1434629baa8cSmrg	    }
1435629baa8cSmrg	}
1436629baa8cSmrg	if (old) {
1437629baa8cSmrg	    if (fstat (fileno (old), &statb) != -1)
1438629baa8cSmrg		chmod (new_name, (int) (statb.st_mode & 0777));
1439629baa8cSmrg	    /*SUPPRESS 560*/
1440629baa8cSmrg	    while ((entry = XauReadAuth (old))) {
1441629baa8cSmrg		if (!checkEntry (entry))
1442629baa8cSmrg		{
1443629baa8cSmrg		    Debug ("Writing an entry\n");
1444629baa8cSmrg		    writeAuth (new, entry);
1445629baa8cSmrg		}
1446629baa8cSmrg		XauDisposeAuth (entry);
1447629baa8cSmrg	    }
1448629baa8cSmrg	    fclose (old);
1449629baa8cSmrg	}
1450629baa8cSmrg	doneAddrs ();
1451629baa8cSmrg	fclose (new);
1452629baa8cSmrg	if (unlink (name) == -1)
1453629baa8cSmrg	    if (errno != ENOENT)
1454629baa8cSmrg		LogError ("cannot remove old authorization file %s: %s\n",
1455629baa8cSmrg			  name, _SysErrorMsg (errno));
1456629baa8cSmrg	envname = name;
1457629baa8cSmrg	if (link (new_name, name) == -1) {
1458629baa8cSmrg	    LogError ("cannot link temporary authorization file %s to old "
1459629baa8cSmrg		      "location %s: %s\n", new_name, name,
1460629baa8cSmrg		      _SysErrorMsg (errno));
1461629baa8cSmrg	    setenv = 1;
1462629baa8cSmrg	    envname = new_name;
1463629baa8cSmrg	} else {
1464629baa8cSmrg	    Debug ("authorization file %s successfully updated\n", name);
1465629baa8cSmrg	    if (unlink (new_name))
1466629baa8cSmrg		if (errno != ENOENT)
1467629baa8cSmrg		    LogError ("cannot remove new authorization file %s:"
1468629baa8cSmrg			      " %s\n", new_name, _SysErrorMsg (errno));
1469629baa8cSmrg	}
1470629baa8cSmrg	if (setenv) {
1471629baa8cSmrg	    verify->userEnviron = setEnv (verify->userEnviron,
1472629baa8cSmrg				    "XAUTHORITY", envname);
1473629baa8cSmrg	    verify->systemEnviron = setEnv (verify->systemEnviron,
1474629baa8cSmrg				    "XAUTHORITY", envname);
1475629baa8cSmrg	}
1476629baa8cSmrg	XauUnlockAuth (name);
1477629baa8cSmrg	if (envname)
1478629baa8cSmrg	    chown (envname, verify->uid, verify->gid);
1479629baa8cSmrg    }
1480629baa8cSmrg    Debug ("done SetUserAuthorization\n");
1481629baa8cSmrg}
1482629baa8cSmrg
1483629baa8cSmrgvoid
1484629baa8cSmrgRemoveUserAuthorization (struct display *d, struct verify_info *verify)
1485629baa8cSmrg{
1486629baa8cSmrg    char    *home;
1487629baa8cSmrg    Xauth   **auths, *entry;
1488629baa8cSmrg    char    name[1024], new_name[1024];
1489629baa8cSmrg    int	    lockStatus;
1490629baa8cSmrg    FILE    *old, *new;
1491629baa8cSmrg    struct stat	statb;
1492629baa8cSmrg    int	    i;
1493629baa8cSmrg
1494629baa8cSmrg    if (!(auths = d->authorizations))
1495629baa8cSmrg	return;
1496629baa8cSmrg    home = getEnv (verify->userEnviron, "HOME");
1497629baa8cSmrg    if (!home)
1498629baa8cSmrg	return;
1499629baa8cSmrg    Debug ("RemoveUserAuthorization\n");
1500629baa8cSmrg    snprintf(name, sizeof(name), "%s/.Xauthority", home);
1501629baa8cSmrg    Debug ("XauLockAuth %s\n", name);
1502629baa8cSmrg    lockStatus = XauLockAuth (name, 1, 2, 10);
1503629baa8cSmrg    Debug ("Lock is %d\n", lockStatus);
1504629baa8cSmrg    if (lockStatus != LOCK_SUCCESS)
1505629baa8cSmrg	return;
1506629baa8cSmrg    old = NULL;
1507629baa8cSmrg    if (openFiles (name, new_name, &old, &new))
1508629baa8cSmrg    {
1509629baa8cSmrg	initAddrs ();
1510629baa8cSmrg	doWrite = 0;
1511629baa8cSmrg	for (i = 0; i < d->authNum; i++)
1512629baa8cSmrg	{
1513629baa8cSmrg	    if (d->displayType.location == Local)
1514629baa8cSmrg		writeLocalAuth (new, auths[i], d->name);
1515629baa8cSmrg#ifdef XDMCP
1516629baa8cSmrg	    else
1517629baa8cSmrg		writeRemoteAuth (new, auths[i], d->peer, d->peerlen, d->name);
1518629baa8cSmrg#endif
1519629baa8cSmrg	}
1520629baa8cSmrg	doWrite = 1;
1521629baa8cSmrg	if (old) {
1522629baa8cSmrg	    if (fstat (fileno (old), &statb) != -1)
1523629baa8cSmrg		chmod (new_name, (int) (statb.st_mode & 0777));
1524629baa8cSmrg	    /*SUPPRESS 560*/
1525629baa8cSmrg	    while ((entry = XauReadAuth (old))) {
1526629baa8cSmrg		if (!checkEntry (entry))
1527629baa8cSmrg		{
1528629baa8cSmrg		    Debug ("Writing an entry\n");
1529629baa8cSmrg		    writeAuth (new, entry);
1530629baa8cSmrg		}
1531629baa8cSmrg		XauDisposeAuth (entry);
1532629baa8cSmrg	    }
1533629baa8cSmrg	    fclose (old);
1534629baa8cSmrg	}
1535629baa8cSmrg	doneAddrs ();
1536629baa8cSmrg	fclose (new);
1537629baa8cSmrg	if (unlink (name) == -1)
1538629baa8cSmrg	    if (errno != ENOENT)
1539629baa8cSmrg		LogError ("cannot remove new authorization file %s: %s\n",
1540629baa8cSmrg			  name, _SysErrorMsg (errno));
1541629baa8cSmrg	if (link (new_name, name) == -1) {
1542629baa8cSmrg	    LogError ("cannot link temporary authorization file %s to old "
1543629baa8cSmrg		      "location %s: %s\n", new_name, name,
1544629baa8cSmrg		      _SysErrorMsg (errno));
1545629baa8cSmrg	} else {
1546629baa8cSmrg	    Debug ("authorization file %s successfully updated\n", name);
1547629baa8cSmrg	    if (unlink (new_name))
1548629baa8cSmrg		if (errno != ENOENT)
1549629baa8cSmrg		    LogError ("cannot remove new authorization file %s:"
1550629baa8cSmrg			      " %s\n", new_name, _SysErrorMsg (errno));
1551629baa8cSmrg	}
1552629baa8cSmrg    }
1553629baa8cSmrg    XauUnlockAuth (name);
1554629baa8cSmrg}
1555