iceauth.c revision 1009a292
1/******************************************************************************
2
3
4Copyright 1993, 1998  The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25
26Author: Ralph Mor, X Consortium
27******************************************************************************/
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include <X11/ICE/ICElib.h>
33#include "ICElibint.h"
34#include <X11/ICE/ICEutil.h>
35
36#include <time.h>
37
38#ifdef HAVE_ARC4RANDOM_BUF
39#include <stdlib.h>	/* for arc4random_buf() */
40#endif
41
42#include <unistd.h>
43
44static int was_called_state;
45
46#ifndef HAVE_ARC4RANDOM_BUF
47
48static void
49emulate_getrandom_buf (
50	char *auth,
51	int len
52)
53{
54    long    ldata[2];
55    int	    seed;
56    int	    value;
57    int	    i;
58
59#ifdef ITIMER_REAL
60    {
61	struct timeval  now;
62	X_GETTIMEOFDAY (&now);
63	ldata[0] = now.tv_sec;
64	ldata[1] = now.tv_usec;
65    }
66#else /* ITIMER_REAL */
67    {
68	long    time ();
69	ldata[0] = time ((long *) 0);
70	ldata[1] = getpid ();
71    }
72#endif /* ITIMER_REAL */
73    seed = (ldata[0]) + (ldata[1] << 16);
74    srand (seed);
75    for (i = 0; i < len; i++)
76    {
77	value = rand ();
78	auth[i] = value & 0xff;
79    }
80}
81
82static void
83arc4random_buf (
84	char *auth,
85	int len
86)
87{
88#if HAVE_GETENTROPY
89    int	    ret;
90
91    /* weak emulation of arc4random through the entropy libc */
92    ret = getentropy (auth, len);
93    if (ret == 0)
94	return;
95#endif /* HAVE_GETENTROPY */
96
97    emulate_getrandom_buf (auth, len);
98}
99
100#endif /* !defined(HAVE_ARC4RANDOM_BUF) */
101
102/*
103 * MIT-MAGIC-COOKIE-1 is a sample authentication method implemented by
104 * the SI.  It is not part of standard ICElib.
105 */
106
107
108char *
109IceGenerateMagicCookie (
110	int len
111)
112{
113    char    *auth;
114
115    if ((auth = malloc (len + 1)) == NULL)
116	return (NULL);
117
118    arc4random_buf (auth, len);
119
120    auth[len] = '\0';
121    return (auth);
122}
123
124
125
126IcePoAuthStatus
127_IcePoMagicCookie1Proc (
128	IceConn		iceConn,
129	IcePointer	*authStatePtr,
130	Bool 		cleanUp,
131	Bool		swap,
132	int     	authDataLen,
133	IcePointer	authData,
134	int 		*replyDataLenRet,
135	IcePointer	*replyDataRet,
136	char    	**errorStringRet
137)
138{
139    if (cleanUp)
140    {
141	/*
142	 * We didn't allocate any state.  We're done.
143	 */
144
145	return (IcePoAuthDoneCleanup);
146    }
147
148    *errorStringRet = NULL;
149
150    if (*authStatePtr == NULL)
151    {
152	/*
153	 * This is the first time we're being called.  Search the
154	 * authentication data for the first occurrence of
155	 * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
156	 */
157
158	unsigned short  length;
159	char		*data;
160
161	_IceGetPoAuthData ("ICE", iceConn->connection_string,
162	    "MIT-MAGIC-COOKIE-1", &length, &data);
163
164	if (!data)
165	{
166	    const char *tempstr =
167		"Could not find correct MIT-MAGIC-COOKIE-1 authentication";
168
169	    *errorStringRet = strdup(tempstr);
170
171	    return (IcePoAuthFailed);
172	}
173	else
174	{
175	    *authStatePtr = (IcePointer) &was_called_state;
176
177	    *replyDataLenRet = length;
178	    *replyDataRet = data;
179
180	    return (IcePoAuthHaveReply);
181	}
182    }
183    else
184    {
185	/*
186	 * We should never get here for MIT-MAGIC-COOKIE-1 since it is
187	 * a single pass authentication method.
188	 */
189
190	const char *tempstr =
191	    "MIT-MAGIC-COOKIE-1 authentication internal error";
192
193	*errorStringRet = strdup(tempstr);
194
195	return (IcePoAuthFailed);
196    }
197}
198
199IcePoAuthProc	_IcePoAuthProcs[] = {_IcePoMagicCookie1Proc};
200
201
202IcePaAuthStatus
203_IcePaMagicCookie1Proc (
204	IceConn		iceConn,
205	IcePointer	*authStatePtr,
206	Bool		swap,
207	int     	authDataLen,
208	IcePointer	authData,
209	int 		*replyDataLenRet,
210	IcePointer	*replyDataRet,
211	char    	**errorStringRet
212)
213{
214    *errorStringRet = NULL;
215    *replyDataLenRet = 0;
216    *replyDataRet = NULL;
217
218    if (*authStatePtr == NULL)
219    {
220	/*
221	 * This is the first time we're being called.  We don't have
222	 * any data to pass to the other client.
223	 */
224
225	*authStatePtr = (IcePointer) &was_called_state;
226
227	return (IcePaAuthContinue);
228    }
229    else
230    {
231	/*
232	 * Search the authentication data for the first occurrence of
233	 * MIT-MAGIC-COOKIE-1 that matches iceConn->connection_string.
234	 */
235
236	unsigned short  length;
237	char		*data;
238
239	_IceGetPaAuthData ("ICE", iceConn->connection_string,
240	    "MIT-MAGIC-COOKIE-1", &length, &data);
241
242	if (data)
243	{
244	    IcePaAuthStatus stat;
245
246	    if (authDataLen == length &&
247	        memcmp (authData, data, authDataLen) == 0)
248	    {
249		stat = IcePaAuthAccepted;
250	    }
251	    else
252	    {
253		const char *tempstr
254		    = "MIT-MAGIC-COOKIE-1 authentication rejected";
255
256		*errorStringRet = strdup(tempstr);
257
258		stat = IcePaAuthRejected;
259	    }
260
261	    free (data);
262	    return (stat);
263	}
264	else
265	{
266	    /*
267	     * We should never get here because in the ConnectionReply
268	     * we should have passed all the valid methods.  So we should
269	     * always find a valid entry.
270	     */
271
272	    const char *tempstr =
273		"MIT-MAGIC-COOKIE-1 authentication internal error";
274
275	    *errorStringRet = strdup(tempstr);
276
277	    return (IcePaAuthFailed);
278	}
279    }
280}
281
282IcePaAuthProc	_IcePaAuthProcs[] = {_IcePaMagicCookie1Proc};
283