1266e564dSmrg/******************************************************************************
2266e564dSmrg
3266e564dSmrg
4266e564dSmrgCopyright 1993, 1998  The Open Group
5266e564dSmrg
6266e564dSmrgPermission to use, copy, modify, distribute, and sell this software and its
7266e564dSmrgdocumentation for any purpose is hereby granted without fee, provided that
8266e564dSmrgthe above copyright notice appear in all copies and that both that
9266e564dSmrgcopyright notice and this permission notice appear in supporting
10266e564dSmrgdocumentation.
11266e564dSmrg
12266e564dSmrgThe above copyright notice and this permission notice shall be included in
13266e564dSmrgall copies or substantial portions of the Software.
14266e564dSmrg
15266e564dSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16266e564dSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17266e564dSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18266e564dSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19266e564dSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20266e564dSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21266e564dSmrg
22266e564dSmrgExcept as contained in this notice, the name of The Open Group shall not be
23266e564dSmrgused in advertising or otherwise to promote the sale, use or other dealings
24266e564dSmrgin this Software without prior written authorization from The Open Group.
25266e564dSmrg
26266e564dSmrgAuthor: Ralph Mor, X Consortium
27266e564dSmrg******************************************************************************/
28266e564dSmrg
29266e564dSmrg#ifdef HAVE_CONFIG_H
30266e564dSmrg#include <config.h>
31266e564dSmrg#endif
32266e564dSmrg#include <X11/ICE/ICElib.h>
33266e564dSmrg#include "ICElibint.h"
34266e564dSmrg#include <X11/ICE/ICEutil.h>
35266e564dSmrg
36266e564dSmrg#include <time.h>
37266e564dSmrg
381009a292Smrg#ifdef HAVE_ARC4RANDOM_BUF
391009a292Smrg#include <stdlib.h>	/* for arc4random_buf() */
40fb5e8d76Smrg#endif
41fb5e8d76Smrg
42a3129944Smrg#include <unistd.h>
43a3129944Smrg
44266e564dSmrgstatic int was_called_state;
45266e564dSmrg
46a3129944Smrg#ifndef HAVE_ARC4RANDOM_BUF
47266e564dSmrg
48a3129944Smrgstatic void
49a3129944Smrgemulate_getrandom_buf (
50a3129944Smrg	char *auth,
51c5629e66Smrg	int len
52c5629e66Smrg)
53266e564dSmrg{
54266e564dSmrg    long    ldata[2];
55266e564dSmrg    int	    seed;
56266e564dSmrg    int	    value;
57266e564dSmrg    int	    i;
589ef0b394Smrg
59266e564dSmrg#ifdef ITIMER_REAL
60266e564dSmrg    {
61266e564dSmrg	struct timeval  now;
62266e564dSmrg	X_GETTIMEOFDAY (&now);
63266e564dSmrg	ldata[0] = now.tv_sec;
64266e564dSmrg	ldata[1] = now.tv_usec;
65266e564dSmrg    }
66a3129944Smrg#else /* ITIMER_REAL */
67266e564dSmrg    {
68266e564dSmrg	long    time ();
69266e564dSmrg	ldata[0] = time ((long *) 0);
70266e564dSmrg	ldata[1] = getpid ();
71266e564dSmrg    }
72a3129944Smrg#endif /* ITIMER_REAL */
73266e564dSmrg    seed = (ldata[0]) + (ldata[1] << 16);
74266e564dSmrg    srand (seed);
75266e564dSmrg    for (i = 0; i < len; i++)
76266e564dSmrg    {
77266e564dSmrg	value = rand ();
78266e564dSmrg	auth[i] = value & 0xff;
79266e564dSmrg    }
80a3129944Smrg}
81a3129944Smrg
82a3129944Smrgstatic void
83a3129944Smrgarc4random_buf (
84a3129944Smrg	char *auth,
85a3129944Smrg	int len
86a3129944Smrg)
87a3129944Smrg{
88a3129944Smrg#if HAVE_GETENTROPY
89a3129944Smrg    int	    ret;
90a3129944Smrg
91a3129944Smrg    /* weak emulation of arc4random through the entropy libc */
92a3129944Smrg    ret = getentropy (auth, len);
93a3129944Smrg    if (ret == 0)
94a3129944Smrg	return;
95a3129944Smrg#endif /* HAVE_GETENTROPY */
96a3129944Smrg
97a3129944Smrg    emulate_getrandom_buf (auth, len);
98a3129944Smrg}
99a3129944Smrg
100a3129944Smrg#endif /* !defined(HAVE_ARC4RANDOM_BUF) */
101a3129944Smrg
102a3129944Smrg/*
103a3129944Smrg * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by
104a3129944Smrg * the SI.  It is not part of standard ICElib.
105a3129944Smrg */
106a3129944Smrg
107a3129944Smrg
108a3129944Smrgchar *
109a3129944SmrgIceGenerateMagicCookie (
110a3129944Smrg	int len
111a3129944Smrg)
112a3129944Smrg{
113a3129944Smrg    char    *auth;
114a3129944Smrg
115a3129944Smrg    if ((auth = malloc (len + 1)) == NULL)
116a3129944Smrg	return (NULL);
117a3129944Smrg
118a3129944Smrg    arc4random_buf (auth, len);
119a3129944Smrg
120266e564dSmrg    auth[len] = '\0';
121266e564dSmrg    return (auth);
122266e564dSmrg}
123266e564dSmrg
124266e564dSmrg
125a3129944Smrg
126266e564dSmrgIcePoAuthStatus
127c5629e66Smrg_IcePoMagicCookie1Proc (
128c5629e66Smrg	IceConn		iceConn,
129c5629e66Smrg	IcePointer	*authStatePtr,
130c5629e66Smrg	Bool 		cleanUp,
131c5629e66Smrg	Bool		swap,
132c5629e66Smrg	int     	authDataLen,
133c5629e66Smrg	IcePointer	authData,
134c5629e66Smrg	int 		*replyDataLenRet,
135c5629e66Smrg	IcePointer	*replyDataRet,
136c5629e66Smrg	char    	**errorStringRet
137c5629e66Smrg)
138266e564dSmrg{
139266e564dSmrg    if (cleanUp)
140266e564dSmrg    {
141266e564dSmrg	/*
142266e564dSmrg	 * We didn't allocate any state.  We're done.
143266e564dSmrg	 */
144266e564dSmrg
145266e564dSmrg	return (IcePoAuthDoneCleanup);
146266e564dSmrg    }
147266e564dSmrg
148266e564dSmrg    *errorStringRet = NULL;
149266e564dSmrg
150266e564dSmrg    if (*authStatePtr == NULL)
151266e564dSmrg    {
152266e564dSmrg	/*
153266e564dSmrg	 * This is the first time we're being called.  Search the
1541009a292Smrg	 * authentication data for the first occurrence of
155266e564dSmrg	 * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
156266e564dSmrg	 */
157266e564dSmrg
158266e564dSmrg	unsigned short  length;
159266e564dSmrg	char		*data;
160266e564dSmrg
161266e564dSmrg	_IceGetPoAuthData ("ICE", iceConn->connection_string,
162266e564dSmrg	    "MIT-MAGIC-COOKIE-1", &length, &data);
163266e564dSmrg
164266e564dSmrg	if (!data)
165266e564dSmrg	{
166266e564dSmrg	    const char *tempstr =
167266e564dSmrg		"Could not find correct MIT-MAGIC-COOKIE-1 authentication";
168266e564dSmrg
169266e564dSmrg	    *errorStringRet = strdup(tempstr);
170266e564dSmrg
171266e564dSmrg	    return (IcePoAuthFailed);
172266e564dSmrg	}
173266e564dSmrg	else
174266e564dSmrg	{
175266e564dSmrg	    *authStatePtr = (IcePointer) &was_called_state;
176266e564dSmrg
177266e564dSmrg	    *replyDataLenRet = length;
178266e564dSmrg	    *replyDataRet = data;
179266e564dSmrg
180266e564dSmrg	    return (IcePoAuthHaveReply);
181266e564dSmrg	}
182266e564dSmrg    }
183266e564dSmrg    else
184266e564dSmrg    {
185266e564dSmrg	/*
186266e564dSmrg	 * We should never get here for MIT-MAGIC-COOKIE-1 since it is
187266e564dSmrg	 * a single pass authentication method.
188266e564dSmrg	 */
189266e564dSmrg
190266e564dSmrg	const char *tempstr =
191266e564dSmrg	    "MIT-MAGIC-COOKIE-1 authentication internal error";
192266e564dSmrg
193266e564dSmrg	*errorStringRet = strdup(tempstr);
194266e564dSmrg
195266e564dSmrg	return (IcePoAuthFailed);
196266e564dSmrg    }
197266e564dSmrg}
198266e564dSmrg
199c5629e66SmrgIcePoAuthProc	_IcePoAuthProcs[] = {_IcePoMagicCookie1Proc};
200266e564dSmrg
201266e564dSmrg
202266e564dSmrgIcePaAuthStatus
203c5629e66Smrg_IcePaMagicCookie1Proc (
204c5629e66Smrg	IceConn		iceConn,
205c5629e66Smrg	IcePointer	*authStatePtr,
206c5629e66Smrg	Bool		swap,
207c5629e66Smrg	int     	authDataLen,
208c5629e66Smrg	IcePointer	authData,
209c5629e66Smrg	int 		*replyDataLenRet,
210c5629e66Smrg	IcePointer	*replyDataRet,
211c5629e66Smrg	char    	**errorStringRet
212c5629e66Smrg)
213266e564dSmrg{
214266e564dSmrg    *errorStringRet = NULL;
215266e564dSmrg    *replyDataLenRet = 0;
216266e564dSmrg    *replyDataRet = NULL;
217266e564dSmrg
218266e564dSmrg    if (*authStatePtr == NULL)
219266e564dSmrg    {
220266e564dSmrg	/*
221266e564dSmrg	 * This is the first time we're being called.  We don't have
222266e564dSmrg	 * any data to pass to the other client.
223266e564dSmrg	 */
224266e564dSmrg
225266e564dSmrg	*authStatePtr = (IcePointer) &was_called_state;
226266e564dSmrg
227266e564dSmrg	return (IcePaAuthContinue);
228266e564dSmrg    }
229266e564dSmrg    else
230266e564dSmrg    {
231266e564dSmrg	/*
2321009a292Smrg	 * Search the authentication data for the first occurrence of
233266e564dSmrg	 * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
234266e564dSmrg	 */
235266e564dSmrg
236266e564dSmrg	unsigned short  length;
237266e564dSmrg	char		*data;
238266e564dSmrg
239266e564dSmrg	_IceGetPaAuthData ("ICE", iceConn->connection_string,
240266e564dSmrg	    "MIT-MAGIC-COOKIE-1", &length, &data);
241266e564dSmrg
242266e564dSmrg	if (data)
243266e564dSmrg	{
244266e564dSmrg	    IcePaAuthStatus stat;
245266e564dSmrg
246266e564dSmrg	    if (authDataLen == length &&
247c5629e66Smrg	        memcmp (authData, data, authDataLen) == 0)
248266e564dSmrg	    {
249266e564dSmrg		stat = IcePaAuthAccepted;
250266e564dSmrg	    }
251266e564dSmrg	    else
252266e564dSmrg	    {
253266e564dSmrg		const char *tempstr
254266e564dSmrg		    = "MIT-MAGIC-COOKIE-1 authentication rejected";
255266e564dSmrg
256266e564dSmrg		*errorStringRet = strdup(tempstr);
257266e564dSmrg
258266e564dSmrg		stat = IcePaAuthRejected;
259266e564dSmrg	    }
260266e564dSmrg
261266e564dSmrg	    free (data);
262266e564dSmrg	    return (stat);
263266e564dSmrg	}
264266e564dSmrg	else
265266e564dSmrg	{
266266e564dSmrg	    /*
267266e564dSmrg	     * We should never get here because in the ConnectionReply
268266e564dSmrg	     * we should have passed all the valid methods.  So we should
269266e564dSmrg	     * always find a valid entry.
270266e564dSmrg	     */
271266e564dSmrg
272266e564dSmrg	    const char *tempstr =
273266e564dSmrg		"MIT-MAGIC-COOKIE-1 authentication internal error";
274266e564dSmrg
275266e564dSmrg	    *errorStringRet = strdup(tempstr);
276266e564dSmrg
277266e564dSmrg	    return (IcePaAuthFailed);
278266e564dSmrg	}
279266e564dSmrg    }
280266e564dSmrg}
281266e564dSmrg
282c5629e66SmrgIcePaAuthProc	_IcePaAuthProcs[] = {_IcePaMagicCookie1Proc};
283