auth.c (9066B)
1 /* 2 3 Copyright 1988, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 /* 30 * authorization hooks for the server 31 * Author: Keith Packard, MIT X Consortium 32 */ 33 34 #ifdef HAVE_DIX_CONFIG_H 35 #include <dix-config.h> 36 #endif 37 38 #include <X11/X.h> 39 #include <X11/Xauth.h> 40 #include "misc.h" 41 #include "osdep.h" 42 #include "dixstruct.h" 43 #include <sys/types.h> 44 #include <sys/stat.h> 45 #include <errno.h> 46 #ifdef WIN32 47 #include <X11/Xw32defs.h> 48 #endif 49 #ifdef HAVE_LIBBSD 50 #include <bsd/stdlib.h> /* for arc4random_buf() */ 51 #endif 52 53 struct protocol { 54 unsigned short name_length; 55 const char *name; 56 AuthAddCFunc Add; /* new authorization data */ 57 AuthCheckFunc Check; /* verify client authorization data */ 58 AuthRstCFunc Reset; /* delete all authorization data entries */ 59 AuthFromIDFunc FromID; /* convert ID to cookie */ 60 AuthRemCFunc Remove; /* remove a specific cookie */ 61 #ifdef XCSECURITY 62 AuthGenCFunc Generate; 63 #endif 64 }; 65 66 static struct protocol protocols[] = { 67 {(unsigned short) 18, "MIT-MAGIC-COOKIE-1", 68 MitAddCookie, MitCheckCookie, MitResetCookie, 69 MitFromID, MitRemoveCookie, 70 #ifdef XCSECURITY 71 MitGenerateCookie 72 #endif 73 }, 74 #ifdef HASXDMAUTH 75 {(unsigned short) 19, "XDM-AUTHORIZATION-1", 76 XdmAddCookie, XdmCheckCookie, XdmResetCookie, 77 XdmFromID, XdmRemoveCookie, 78 #ifdef XCSECURITY 79 NULL 80 #endif 81 }, 82 #endif 83 #ifdef SECURE_RPC 84 {(unsigned short) 9, "SUN-DES-1", 85 SecureRPCAdd, SecureRPCCheck, SecureRPCReset, 86 SecureRPCFromID, SecureRPCRemove, 87 #ifdef XCSECURITY 88 NULL 89 #endif 90 }, 91 #endif 92 }; 93 94 #define NUM_AUTHORIZATION ARRAY_SIZE(protocols) 95 96 /* 97 * Initialize all classes of authorization by reading the 98 * specified authorization file 99 */ 100 101 static const char *authorization_file = NULL; 102 103 static Bool ShouldLoadAuth = TRUE; 104 105 void 106 InitAuthorization(const char *file_name) 107 { 108 authorization_file = file_name; 109 } 110 111 static int 112 LoadAuthorization(void) 113 { 114 FILE *f; 115 Xauth *auth; 116 int i; 117 int count = 0; 118 119 ShouldLoadAuth = FALSE; 120 if (!authorization_file) 121 return 0; 122 123 errno = 0; 124 f = Fopen(authorization_file, "r"); 125 if (!f) { 126 LogMessageVerb(X_ERROR, 0, 127 "Failed to open authorization file \"%s\": %s\n", 128 authorization_file, 129 errno != 0 ? strerror(errno) : "Unknown error"); 130 return -1; 131 } 132 133 while ((auth = XauReadAuth(f)) != 0) { 134 for (i = 0; i < NUM_AUTHORIZATION; i++) { 135 if (protocols[i].name_length == auth->name_length && 136 memcmp(protocols[i].name, auth->name, 137 (int) auth->name_length) == 0 && protocols[i].Add) { 138 ++count; 139 (*protocols[i].Add) (auth->data_length, auth->data, 140 FakeClientID(0)); 141 } 142 } 143 XauDisposeAuth(auth); 144 } 145 146 Fclose(f); 147 return count; 148 } 149 150 #ifdef XDMCP 151 /* 152 * XdmcpInit calls this function to discover all authorization 153 * schemes supported by the display 154 */ 155 void 156 RegisterAuthorizations(void) 157 { 158 int i; 159 160 for (i = 0; i < NUM_AUTHORIZATION; i++) 161 XdmcpRegisterAuthorization(protocols[i].name, 162 (int) protocols[i].name_length); 163 } 164 #endif 165 166 XID 167 CheckAuthorization(unsigned int name_length, 168 const char *name, 169 unsigned int data_length, 170 const char *data, ClientPtr client, const char **reason) 171 { /* failure message. NULL for default msg */ 172 int i; 173 struct stat buf; 174 static time_t lastmod = 0; 175 static Bool loaded = FALSE; 176 177 if (!authorization_file || stat(authorization_file, &buf)) { 178 if (lastmod != 0) { 179 lastmod = 0; 180 ShouldLoadAuth = TRUE; /* stat lost, so force reload */ 181 } 182 } 183 else if (buf.st_mtime > lastmod) { 184 lastmod = buf.st_mtime; 185 ShouldLoadAuth = TRUE; 186 } 187 if (ShouldLoadAuth) { 188 int loadauth = LoadAuthorization(); 189 190 /* 191 * If the authorization file has at least one entry for this server, 192 * disable local access. (loadauth > 0) 193 * 194 * If there are zero entries (either initially or when the 195 * authorization file is later reloaded), or if a valid 196 * authorization file was never loaded, enable local access. 197 * (loadauth == 0 || !loaded) 198 * 199 * If the authorization file was loaded initially (with valid 200 * entries for this server), and reloading it later fails, don't 201 * change anything. (loadauth == -1 && loaded) 202 */ 203 204 if (loadauth > 0) { 205 DisableLocalAccess(); /* got at least one */ 206 loaded = TRUE; 207 } 208 else if (loadauth == 0 || !loaded) 209 EnableLocalAccess(); 210 } 211 if (name_length) { 212 for (i = 0; i < NUM_AUTHORIZATION; i++) { 213 if (protocols[i].name_length == name_length && 214 memcmp(protocols[i].name, name, (int) name_length) == 0) { 215 return (*protocols[i].Check) (data_length, data, client, 216 reason); 217 } 218 *reason = "Authorization protocol not supported by server\n"; 219 } 220 } 221 else 222 *reason = "Authorization required, but no authorization protocol specified\n"; 223 return (XID) ~0L; 224 } 225 226 void 227 ResetAuthorization(void) 228 { 229 int i; 230 231 for (i = 0; i < NUM_AUTHORIZATION; i++) 232 if (protocols[i].Reset) 233 (*protocols[i].Reset) (); 234 ShouldLoadAuth = TRUE; 235 } 236 237 int 238 AuthorizationFromID(XID id, 239 unsigned short *name_lenp, 240 const char **namep, unsigned short *data_lenp, char **datap) 241 { 242 int i; 243 244 for (i = 0; i < NUM_AUTHORIZATION; i++) { 245 if (protocols[i].FromID && 246 (*protocols[i].FromID) (id, data_lenp, datap)) { 247 *name_lenp = protocols[i].name_length; 248 *namep = protocols[i].name; 249 return 1; 250 } 251 } 252 return 0; 253 } 254 255 int 256 RemoveAuthorization(unsigned short name_length, 257 const char *name, 258 unsigned short data_length, const char *data) 259 { 260 int i; 261 262 for (i = 0; i < NUM_AUTHORIZATION; i++) { 263 if (protocols[i].name_length == name_length && 264 memcmp(protocols[i].name, name, (int) name_length) == 0 && 265 protocols[i].Remove) { 266 return (*protocols[i].Remove) (data_length, data); 267 } 268 } 269 return 0; 270 } 271 272 int 273 AddAuthorization(unsigned name_length, const char *name, 274 unsigned data_length, char *data) 275 { 276 int i; 277 278 for (i = 0; i < NUM_AUTHORIZATION; i++) { 279 if (protocols[i].name_length == name_length && 280 memcmp(protocols[i].name, name, (int) name_length) == 0 && 281 protocols[i].Add) { 282 return (*protocols[i].Add) (data_length, data, FakeClientID(0)); 283 } 284 } 285 return 0; 286 } 287 288 #ifdef XCSECURITY 289 290 XID 291 GenerateAuthorization(unsigned name_length, 292 const char *name, 293 unsigned data_length, 294 const char *data, 295 unsigned *data_length_return, char **data_return) 296 { 297 int i; 298 299 for (i = 0; i < NUM_AUTHORIZATION; i++) { 300 if (protocols[i].name_length == name_length && 301 memcmp(protocols[i].name, name, (int) name_length) == 0 && 302 protocols[i].Generate) { 303 return (*protocols[i].Generate) (data_length, data, 304 FakeClientID(0), 305 data_length_return, data_return); 306 } 307 } 308 return -1; 309 } 310 311 #endif /* XCSECURITY */ 312 313 void 314 GenerateRandomData(int len, char *buf) 315 { 316 #ifdef HAVE_ARC4RANDOM_BUF 317 arc4random_buf(buf, len); 318 #else 319 int fd; 320 321 fd = open("/dev/urandom", O_RDONLY); 322 read(fd, buf, len); 323 close(fd); 324 #endif 325 }