| File: | xdm/xdmauth.c |
| Location: | line 155, column 2 |
| Description: | Potential leak of memory pointed to by 'xdmcpauth' |
| 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 | * xdm - display manager daemon | |||
| 30 | * Author: Keith Packard, MIT X Consortium | |||
| 31 | * | |||
| 32 | * xdmauth | |||
| 33 | * | |||
| 34 | * generate authorization data for XDM-AUTHORIZATION-1 as per XDMCP spec | |||
| 35 | */ | |||
| 36 | ||||
| 37 | #include "dm.h" | |||
| 38 | #include "dm_auth.h" | |||
| 39 | #include "dm_error.h" | |||
| 40 | ||||
| 41 | #ifdef HASXDMAUTH1 | |||
| 42 | ||||
| 43 | static char auth_name[256]; | |||
| 44 | static int auth_name_len; | |||
| 45 | ||||
| 46 | static void | |||
| 47 | XdmPrintDataHex (const char *s, const char *a, int l) | |||
| 48 | { | |||
| 49 | int i; | |||
| 50 | ||||
| 51 | Debug ("%s", s); | |||
| 52 | for (i = 0; i < l; i++) | |||
| 53 | Debug (" %02x", a[i] & 0xff); | |||
| 54 | Debug ("\n"); | |||
| 55 | } | |||
| 56 | ||||
| 57 | # ifdef XDMCP | |||
| 58 | static void | |||
| 59 | XdmPrintArray8Hex (const char *s, ARRAY8Ptr a) | |||
| 60 | { | |||
| 61 | XdmPrintDataHex (s, (char *) a->data, a->length); | |||
| 62 | } | |||
| 63 | # endif | |||
| 64 | ||||
| 65 | void | |||
| 66 | XdmInitAuth (unsigned short name_len, char *name) | |||
| 67 | { | |||
| 68 | if (name_len > 256) | |||
| 69 | name_len = 256; | |||
| 70 | auth_name_len = name_len; | |||
| 71 | memmove( auth_name, name, name_len)__builtin___memmove_chk (auth_name, name, name_len, __builtin_object_size (auth_name, 0)); | |||
| 72 | } | |||
| 73 | ||||
| 74 | /* | |||
| 75 | * Generate authorization for XDM-AUTHORIZATION-1 | |||
| 76 | * | |||
| 77 | * When being used with XDMCP, 8 bytes are generated for the session key | |||
| 78 | * (sigma), as the random number (rho) is already shared between xdm and | |||
| 79 | * the server. Otherwise, we'll prepend a random number to pass in the file | |||
| 80 | * between xdm and the server (16 bytes total) | |||
| 81 | */ | |||
| 82 | ||||
| 83 | static Xauth * | |||
| 84 | XdmGetAuthHelper (unsigned short namelen, char *name, int includeRho) | |||
| 85 | { | |||
| 86 | Xauth *new; | |||
| 87 | new = malloc (sizeof (Xauth)); | |||
| 88 | ||||
| 89 | if (!new) | |||
| 90 | return (Xauth *) 0; | |||
| 91 | new->family = FamilyWild(65535); | |||
| 92 | new->address_length = 0; | |||
| 93 | new->address = NULL((void*)0); | |||
| 94 | new->number_length = 0; | |||
| 95 | new->number = NULL((void*)0); | |||
| 96 | if (includeRho) | |||
| 97 | new->data_length = 16; | |||
| 98 | else | |||
| 99 | new->data_length = 8; | |||
| 100 | ||||
| 101 | new->data = malloc (new->data_length); | |||
| 102 | if (!new->data) | |||
| 103 | { | |||
| 104 | free (new); | |||
| 105 | return (Xauth *) 0; | |||
| 106 | } | |||
| 107 | new->name = malloc (namelen); | |||
| 108 | if (!new->name) | |||
| 109 | { | |||
| 110 | free (new->data); | |||
| 111 | free (new); | |||
| 112 | return (Xauth *) 0; | |||
| 113 | } | |||
| 114 | memmove( (char *)new->name, name, namelen)__builtin___memmove_chk ((char *)new->name, name, namelen, __builtin_object_size ((char *)new->name, 0)); | |||
| 115 | new->name_length = namelen; | |||
| 116 | if (!GenerateAuthData ((char *)new->data, new->data_length)) | |||
| 117 | { | |||
| 118 | free (new->name); | |||
| 119 | free (new->data); | |||
| 120 | free (new); | |||
| 121 | return (Xauth *) 0; | |||
| 122 | } | |||
| 123 | /* | |||
| 124 | * set the first byte of the session key to zero as it | |||
| 125 | * is a DES key and only uses 56 bits | |||
| 126 | */ | |||
| 127 | ((char *)new->data)[new->data_length - 8] = '\0'; | |||
| 128 | XdmPrintDataHex ("Local server auth", (char *)new->data, new->data_length); | |||
| 129 | return new; | |||
| 130 | } | |||
| 131 | ||||
| 132 | Xauth * | |||
| 133 | XdmGetAuth (unsigned short namelen, char *name) | |||
| 134 | { | |||
| 135 | return XdmGetAuthHelper (namelen, name, TRUE1); | |||
| 136 | } | |||
| 137 | ||||
| 138 | # ifdef XDMCP | |||
| 139 | ||||
| 140 | void | |||
| 141 | XdmGetXdmcpAuth (struct protoDisplay *pdpy, | |||
| 142 | unsigned short authorizationNameLen, char *authorizationName) | |||
| 143 | { | |||
| 144 | Xauth *fileauth, *xdmcpauth; | |||
| 145 | ||||
| 146 | if (pdpy->fileAuthorization && pdpy->xdmcpAuthorization) | |||
| 147 | return; | |||
| 148 | xdmcpauth = XdmGetAuthHelper (authorizationNameLen, authorizationName, FALSE0); | |||
| ||||
| 149 | if (!xdmcpauth) | |||
| 150 | return; | |||
| 151 | fileauth = malloc (sizeof (Xauth)); | |||
| 152 | if (!fileauth) | |||
| 153 | { | |||
| 154 | XauDisposeAuth(xdmcpauth); | |||
| 155 | return; | |||
| ||||
| 156 | } | |||
| 157 | /* build the file auth from the XDMCP auth */ | |||
| 158 | *fileauth = *xdmcpauth; | |||
| 159 | fileauth->name = malloc (xdmcpauth->name_length); | |||
| 160 | fileauth->data = malloc (16); | |||
| 161 | fileauth->data_length = 16; | |||
| 162 | if (!fileauth->name || !fileauth->data) | |||
| 163 | { | |||
| 164 | XauDisposeAuth (xdmcpauth); | |||
| 165 | free (fileauth->name); | |||
| 166 | free (fileauth->data); | |||
| 167 | free (fileauth); | |||
| 168 | return; | |||
| 169 | } | |||
| 170 | /* | |||
| 171 | * for the file authorization, prepend the random number (rho) | |||
| 172 | * which is simply the number we've been passing back and | |||
| 173 | * forth via XDMCP | |||
| 174 | */ | |||
| 175 | memmove( fileauth->name, xdmcpauth->name, xdmcpauth->name_length)__builtin___memmove_chk (fileauth->name, xdmcpauth->name , xdmcpauth->name_length, __builtin_object_size (fileauth-> name, 0)); | |||
| 176 | memmove( fileauth->data, pdpy->authenticationData.data, 8)__builtin___memmove_chk (fileauth->data, pdpy->authenticationData .data, 8, __builtin_object_size (fileauth->data, 0)); | |||
| 177 | memmove( fileauth->data + 8, xdmcpauth->data, 8)__builtin___memmove_chk (fileauth->data + 8, xdmcpauth-> data, 8, __builtin_object_size (fileauth->data + 8, 0)); | |||
| 178 | XdmPrintDataHex ("Accept packet auth", xdmcpauth->data, xdmcpauth->data_length); | |||
| 179 | XdmPrintDataHex ("Auth file auth", fileauth->data, fileauth->data_length); | |||
| 180 | /* encrypt the session key for its trip back to the server */ | |||
| 181 | XdmcpWrap ((unsigned char *)xdmcpauth->data, (unsigned char *)&pdpy->key, | |||
| 182 | (unsigned char *)xdmcpauth->data, 8); | |||
| 183 | pdpy->fileAuthorization = fileauth; | |||
| 184 | pdpy->xdmcpAuthorization = xdmcpauth; | |||
| 185 | } | |||
| 186 | ||||
| 187 | # define atox(c)('0' <= c && c <= '9' ? c - '0' : 'a' <= c && c <= 'f' ? c - 'a' + 10 : 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1) ('0' <= c && c <= '9' ? c - '0' : \ | |||
| 188 | 'a' <= c && c <= 'f' ? c - 'a' + 10 : \ | |||
| 189 | 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1) | |||
| 190 | ||||
| 191 | static int | |||
| 192 | HexToBinary(char *key) | |||
| 193 | { | |||
| 194 | char *out, *in; | |||
| 195 | int top, bottom; | |||
| 196 | ||||
| 197 | in = key + 2; | |||
| 198 | out= key; | |||
| 199 | while (in[0] && in[1]) | |||
| 200 | { | |||
| 201 | top = atox(in[0])('0' <= in[0] && in[0] <= '9' ? in[0] - '0' : 'a' <= in[0] && in[0] <= 'f' ? in[0] - 'a' + 10 : 'A' <= in[0] && in[0] <= 'F' ? in[0] - 'A' + 10 : - 1); | |||
| 202 | if (top == -1) | |||
| 203 | return 0; | |||
| 204 | bottom = atox(in[1])('0' <= in[1] && in[1] <= '9' ? in[1] - '0' : 'a' <= in[1] && in[1] <= 'f' ? in[1] - 'a' + 10 : 'A' <= in[1] && in[1] <= 'F' ? in[1] - 'A' + 10 : - 1); | |||
| 205 | if (bottom == -1) | |||
| 206 | return 0; | |||
| 207 | *out++ = (top << 4) | bottom; | |||
| 208 | in += 2; | |||
| 209 | } | |||
| 210 | if (in[0]) | |||
| 211 | return 0; | |||
| 212 | *out++ = '\0'; | |||
| 213 | return 1; | |||
| 214 | } | |||
| 215 | ||||
| 216 | /* | |||
| 217 | * Search the Keys file for the entry matching this display. This | |||
| 218 | * routine accepts either plain ascii strings for keys, or hex-encoded numbers | |||
| 219 | */ | |||
| 220 | ||||
| 221 | static int | |||
| 222 | XdmGetKey(struct protoDisplay *pdpy, ARRAY8Ptr displayID) | |||
| 223 | { | |||
| 224 | FILE *keys; | |||
| 225 | char line[1024], id[1024], key[1024]; | |||
| 226 | int keylen; | |||
| 227 | ||||
| 228 | Debug ("Lookup key for %*.*s\n", displayID->length, displayID->length, displayID->data); | |||
| 229 | keys = fopen (keyFile, "r"); | |||
| 230 | if (!keys) | |||
| 231 | return FALSE0; | |||
| 232 | while (fgets (line, sizeof (line) - 1, keys)) | |||
| 233 | { | |||
| 234 | if (line[0] == '#' || sscanf (line, "%s %s", id, key) != 2) | |||
| 235 | continue; | |||
| 236 | bzero(line, sizeof(line))__builtin___memset_chk (line, 0, sizeof(line), __builtin_object_size (line, 0)); | |||
| 237 | Debug ("Key entry for \"%s\" %ld bytes\n", id, strlen(key)); | |||
| 238 | if (strlen (id) == displayID->length && | |||
| 239 | !strncmp (id, (char *)displayID->data, displayID->length)) | |||
| 240 | { | |||
| 241 | if (!strncmp (key, "0x", 2) || !strncmp (key, "0X", 2)) | |||
| 242 | if (!HexToBinary (key)) | |||
| 243 | break; | |||
| 244 | keylen = strlen (key); | |||
| 245 | while (keylen < 7) | |||
| 246 | key[keylen++] = '\0'; | |||
| 247 | pdpy->key.data[0] = '\0'; | |||
| 248 | memmove( pdpy->key.data + 1, key, 7)__builtin___memmove_chk (pdpy->key.data + 1, key, 7, __builtin_object_size (pdpy->key.data + 1, 0)); | |||
| 249 | bzero(key, sizeof(key))__builtin___memset_chk (key, 0, sizeof(key), __builtin_object_size (key, 0)); | |||
| 250 | fclose (keys); | |||
| 251 | return TRUE1; | |||
| 252 | } | |||
| 253 | } | |||
| 254 | bzero(line, sizeof(line))__builtin___memset_chk (line, 0, sizeof(line), __builtin_object_size (line, 0)); | |||
| 255 | bzero(key, sizeof(key))__builtin___memset_chk (key, 0, sizeof(key), __builtin_object_size (key, 0)); | |||
| 256 | fclose (keys); | |||
| 257 | return FALSE0; | |||
| 258 | } | |||
| 259 | ||||
| 260 | /*ARGSUSED*/ | |||
| 261 | int | |||
| 262 | XdmCheckAuthentication(struct protoDisplay *pdpy, ARRAY8Ptr displayID, | |||
| 263 | ARRAY8Ptr authenticationName, ARRAY8Ptr authenticationData) | |||
| 264 | { | |||
| 265 | XdmAuthKeyPtr incoming; | |||
| 266 | ||||
| 267 | if (!XdmGetKey (pdpy, displayID)) | |||
| 268 | return FALSE0; | |||
| 269 | if (authenticationData->length != 8) | |||
| 270 | return FALSE0; | |||
| 271 | XdmcpUnwrap (authenticationData->data, (unsigned char *)&pdpy->key, | |||
| 272 | authenticationData->data, 8); | |||
| 273 | XdmPrintArray8Hex ("Request packet auth", authenticationData); | |||
| 274 | if (!XdmcpCopyARRAY8(authenticationData, &pdpy->authenticationData)) | |||
| 275 | return FALSE0; | |||
| 276 | incoming = (XdmAuthKeyPtr) authenticationData->data; | |||
| 277 | XdmcpIncrementKey (incoming); | |||
| 278 | XdmcpWrap (authenticationData->data, (unsigned char *)&pdpy->key, | |||
| 279 | authenticationData->data, 8); | |||
| 280 | return TRUE1; | |||
| 281 | } | |||
| 282 | ||||
| 283 | # endif /* XDMCP */ | |||
| 284 | #endif /* HASXDMAUTH (covering the entire file) */ |