1 /******************************************************************************
2
3
4 Copyright 1993, 1998 The Open Group
5
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
10 documentation.
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
25
26 Author: 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_LIBBSD
39 #include <bsd/stdlib.h> /* for arc4random_buf() */
40 #endif
41
42 #include <unistd.h>
43
44 static int was_called_state;
45
46 #ifndef HAVE_ARC4RANDOM_BUF
47
48 static void
emulate_getrandom_buf(char * auth,int len)49 emulate_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
82 static void
arc4random_buf(char * auth,int len)83 arc4random_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
108 char *
IceGenerateMagicCookie(int len)109 IceGenerateMagicCookie (
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
126 IcePoAuthStatus
_IcePoMagicCookie1Proc(IceConn iceConn,IcePointer * authStatePtr,Bool cleanUp,Bool swap,int authDataLen,IcePointer authData,int * replyDataLenRet,IcePointer * replyDataRet,char ** errorStringRet)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 occurence 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
199 IcePoAuthProc _IcePoAuthProcs[] = {_IcePoMagicCookie1Proc};
200
201
202 IcePaAuthStatus
_IcePaMagicCookie1Proc(IceConn iceConn,IcePointer * authStatePtr,Bool swap,int authDataLen,IcePointer authData,int * replyDataLenRet,IcePointer * replyDataRet,char ** errorStringRet)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 occurence 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
282 IcePaAuthProc _IcePaAuthProcs[] = {_IcePaMagicCookie1Proc};
283