1/*
2
3Copyright 1988, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include <X11/Xauth.h>
31#include <X11/Xos.h>
32#ifdef XTHREADS
33#include <X11/Xthreads.h>
34#endif
35
36#ifdef O_CLOEXEC
37#define FOPEN_CLOEXEC "e"
38#else
39#define FOPEN_CLOEXEC ""
40#endif
41
42#define binaryEqual(a, b, len) (memcmp(a, b, len) == 0)
43
44Xauth *
45XauGetBestAuthByAddr (
46#if NeedWidePrototypes
47    unsigned int	family,
48    unsigned int	address_length,
49#else
50    unsigned short	family,
51    unsigned short	address_length,
52#endif
53    _Xconst char*	address,
54#if NeedWidePrototypes
55    unsigned int	number_length,
56#else
57    unsigned short	number_length,
58#endif
59    _Xconst char*	number,
60    int			types_length,
61    char**		types,
62    _Xconst int*	type_lengths)
63{
64    FILE    *auth_file;
65    char    *auth_name;
66    Xauth   *entry;
67    Xauth   *best;
68    int	    best_type;
69    int	    type;
70
71    auth_name = XauFileName ();
72    if (!auth_name)
73	return NULL;
74    if (access (auth_name, R_OK) != 0)		/* checks REAL id */
75	return NULL;
76    auth_file = fopen (auth_name, "rb" FOPEN_CLOEXEC);
77    if (!auth_file)
78	return NULL;
79
80    best = NULL;
81    best_type = types_length;
82    for (;;) {
83	entry = XauReadAuth (auth_file);
84	if (!entry)
85	    break;
86	/*
87	 * Match when:
88	 *   either family or entry->family are FamilyWild or
89	 *    family and entry->family are the same and
90	 *     address and entry->address are the same
91	 *  and
92	 *   either number or entry->number are empty or
93	 *    number and entry->number are the same
94	 *  and
95	 *   either name or entry->name are empty or
96	 *    name and entry->name are the same
97	 */
98
99	if ((family == FamilyWild || entry->family == FamilyWild ||
100	     (entry->family == family &&
101	     ((address_length == entry->address_length &&
102	      binaryEqual (entry->address, address, address_length))
103	    ))) &&
104	    (number_length == 0 || entry->number_length == 0 ||
105	     (number_length == entry->number_length &&
106	      binaryEqual (entry->number, number, number_length))))
107	{
108	    if (best_type == 0)
109	    {
110		best = entry;
111		break;
112	    }
113	    for (type = 0; type < best_type; type++)
114		if (type_lengths[type] == entry->name_length &&
115		    !(strncmp (types[type], entry->name, entry->name_length)))
116		{
117		    break;
118		}
119	    if (type < best_type)
120	    {
121		if (best)
122		    XauDisposeAuth (best);
123		best = entry;
124		best_type = type;
125		if (type == 0)
126		    break;
127		continue;
128	    }
129	}
130	XauDisposeAuth (entry);
131    }
132    (void) fclose (auth_file);
133    return best;
134}
135