| File: | process.c |
| Location: | line 434, column 12 |
| Description: | Potential leak of memory pointed to by 'auth' |
| 1 | /* | |||||
| 2 | ||||||
| 3 | Copyright 1989, 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 | * Author: Jim Fulton, MIT X Consortium | |||||
| 31 | */ | |||||
| 32 | ||||||
| 33 | #ifdef HAVE_CONFIG_H1 | |||||
| 34 | #include "config.h" | |||||
| 35 | #endif | |||||
| 36 | ||||||
| 37 | #include "xauth.h" | |||||
| 38 | #include <ctype.h> | |||||
| 39 | #include <errno(*__error()).h> | |||||
| 40 | #include <sys/stat.h> | |||||
| 41 | #ifndef WIN32 | |||||
| 42 | #include <sys/socket.h> | |||||
| 43 | #else | |||||
| 44 | #include <X11/Xwinsock.h> | |||||
| 45 | #endif | |||||
| 46 | ||||||
| 47 | #include <signal.h> | |||||
| 48 | #include <X11/X.h> /* for Family constants */ | |||||
| 49 | ||||||
| 50 | #include <X11/Xlib.h> | |||||
| 51 | #include <X11/extensions/security.h> | |||||
| 52 | ||||||
| 53 | #ifndef DEFAULT_PROTOCOL_ABBREV"." /* to make add command easier */ | |||||
| 54 | #define DEFAULT_PROTOCOL_ABBREV"." "." | |||||
| 55 | #endif | |||||
| 56 | #ifndef DEFAULT_PROTOCOL"MIT-MAGIC-COOKIE-1" /* for protocol abbreviation */ | |||||
| 57 | #define DEFAULT_PROTOCOL"MIT-MAGIC-COOKIE-1" "MIT-MAGIC-COOKIE-1" | |||||
| 58 | #endif | |||||
| 59 | ||||||
| 60 | #define SECURERPC"SUN-DES-1" "SUN-DES-1" | |||||
| 61 | #define K5AUTH"MIT-KERBEROS-5" "MIT-KERBEROS-5" | |||||
| 62 | ||||||
| 63 | #define XAUTH_DEFAULT_RETRIES10 10 /* number of competitors we expect */ | |||||
| 64 | #define XAUTH_DEFAULT_TIMEOUT2 2 /* in seconds, be quick */ | |||||
| 65 | #define XAUTH_DEFAULT_DEADTIME600L 600L /* 10 minutes in seconds */ | |||||
| 66 | ||||||
| 67 | typedef struct _AuthList { /* linked list of entries */ | |||||
| 68 | struct _AuthList *next; | |||||
| 69 | Xauth *auth; | |||||
| 70 | } AuthList; | |||||
| 71 | ||||||
| 72 | typedef int (*ProcessFunc)(const char *, int, int, const char**); | |||||
| 73 | ||||||
| 74 | #define add_to_list(h,t,e){if (t) (t)->next = (e); else (h) = (e); (t) = (e);} {if (t) (t)->next = (e); else (h) = (e); (t) = (e);} | |||||
| 75 | ||||||
| 76 | typedef struct _CommandTable { /* commands that are understood */ | |||||
| 77 | const char *name; /* full name */ | |||||
| 78 | int minlen; /* unique prefix */ | |||||
| 79 | int maxlen; /* strlen(name) */ | |||||
| 80 | ProcessFunc processfunc; /* handler */ | |||||
| 81 | const char *helptext; /* what to print for help */ | |||||
| 82 | } CommandTable; | |||||
| 83 | ||||||
| 84 | struct _extract_data { /* for iterating */ | |||||
| 85 | FILE *fp; /* input source */ | |||||
| 86 | const char *filename; /* name of input */ | |||||
| 87 | Boolint used_stdout; /* whether or not need to close */ | |||||
| 88 | Boolint numeric; /* format in which to write */ | |||||
| 89 | int nwritten; /* number of entries written */ | |||||
| 90 | const char *cmd; /* for error messages */ | |||||
| 91 | }; | |||||
| 92 | ||||||
| 93 | struct _list_data { /* for iterating */ | |||||
| 94 | FILE *fp; /* output file */ | |||||
| 95 | Boolint numeric; /* format in which to write */ | |||||
| 96 | }; | |||||
| 97 | ||||||
| 98 | ||||||
| 99 | /* | |||||
| 100 | * private data | |||||
| 101 | */ | |||||
| 102 | static const char *stdin_filename = "(stdin)"; /* for messages */ | |||||
| 103 | static const char *stdout_filename = "(stdout)"; /* for messages */ | |||||
| 104 | static const char *Yes = "yes"; /* for messages */ | |||||
| 105 | static const char *No = "no"; /* for messages */ | |||||
| 106 | ||||||
| 107 | static int do_help ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 108 | static int do_questionmark ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 109 | static int do_list ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 110 | static int do_merge ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 111 | static int do_extract ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 112 | static int do_add ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 113 | static int do_remove ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 114 | static int do_info ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 115 | static int do_exit ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 116 | static int do_quit ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 117 | static int do_source ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 118 | static int do_generate ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 119 | static int do_version ( const char *inputfilename, int lineno, int argc, const char **argv ); | |||||
| 120 | ||||||
| 121 | static CommandTable command_table[] = { /* table of known commands */ | |||||
| 122 | { "add", 2, 3, do_add, | |||||
| 123 | "add dpyname protoname hexkey add entry" }, | |||||
| 124 | { "exit", 3, 4, do_exit, | |||||
| 125 | "exit save changes and exit program" }, | |||||
| 126 | { "extract", 3, 7, do_extract, | |||||
| 127 | "extract filename dpyname... extract entries into file" }, | |||||
| 128 | { "help", 1, 4, do_help, | |||||
| 129 | "help [topic] print help" }, | |||||
| 130 | { "info", 1, 4, do_info, | |||||
| 131 | "info print information about entries" }, | |||||
| 132 | { "list", 1, 4, do_list, | |||||
| 133 | "list [dpyname...] list entries" }, | |||||
| 134 | { "merge", 1, 5, do_merge, | |||||
| 135 | "merge filename... merge entries from files" }, | |||||
| 136 | { "nextract", 2, 8, do_extract, | |||||
| 137 | "nextract filename dpyname... numerically extract entries" }, | |||||
| 138 | { "nlist", 2, 5, do_list, | |||||
| 139 | "nlist [dpyname...] numerically list entries" }, | |||||
| 140 | { "nmerge", 2, 6, do_merge, | |||||
| 141 | "nmerge filename... numerically merge entries" }, | |||||
| 142 | { "quit", 1, 4, do_quit, | |||||
| 143 | "quit abort changes and exit program" }, | |||||
| 144 | { "remove", 1, 6, do_remove, | |||||
| 145 | "remove dpyname... remove entries" }, | |||||
| 146 | { "source", 1, 6, do_source, | |||||
| 147 | "source filename read commands from file" }, | |||||
| 148 | { "version", 1, 7, do_version, | |||||
| 149 | "version show version number of xauth" }, | |||||
| 150 | { "?", 1, 1, do_questionmark, | |||||
| 151 | "? list available commands" }, | |||||
| 152 | { "generate", 1, 8, do_generate, | |||||
| 153 | "generate dpyname protoname [options] use server to generate entry\n" | |||||
| 154 | " options are:\n" | |||||
| 155 | " timeout n authorization expiration time in seconds\n" | |||||
| 156 | " trusted clients using this entry are trusted\n" | |||||
| 157 | " untrusted clients using this entry are untrusted\n" | |||||
| 158 | " group n clients using this entry belong to application group n\n" | |||||
| 159 | " data hexkey auth protocol specific data needed to generate the entry\n" | |||||
| 160 | }, | |||||
| 161 | { NULL((void*)0), 0, 0, NULL((void*)0), NULL((void*)0) }, | |||||
| 162 | }; | |||||
| 163 | ||||||
| 164 | #define COMMAND_NAMES_PADDED_WIDTH10 10 /* wider than anything above */ | |||||
| 165 | ||||||
| 166 | ||||||
| 167 | static Boolint okay_to_use_stdin = True1; /* set to false after using */ | |||||
| 168 | ||||||
| 169 | static const char *hex_table[] = { /* for printing hex digits */ | |||||
| 170 | "00", "01", "02", "03", "04", "05", "06", "07", | |||||
| 171 | "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", | |||||
| 172 | "10", "11", "12", "13", "14", "15", "16", "17", | |||||
| 173 | "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", | |||||
| 174 | "20", "21", "22", "23", "24", "25", "26", "27", | |||||
| 175 | "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", | |||||
| 176 | "30", "31", "32", "33", "34", "35", "36", "37", | |||||
| 177 | "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", | |||||
| 178 | "40", "41", "42", "43", "44", "45", "46", "47", | |||||
| 179 | "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", | |||||
| 180 | "50", "51", "52", "53", "54", "55", "56", "57", | |||||
| 181 | "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", | |||||
| 182 | "60", "61", "62", "63", "64", "65", "66", "67", | |||||
| 183 | "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", | |||||
| 184 | "70", "71", "72", "73", "74", "75", "76", "77", | |||||
| 185 | "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", | |||||
| 186 | "80", "81", "82", "83", "84", "85", "86", "87", | |||||
| 187 | "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", | |||||
| 188 | "90", "91", "92", "93", "94", "95", "96", "97", | |||||
| 189 | "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", | |||||
| 190 | "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", | |||||
| 191 | "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", | |||||
| 192 | "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", | |||||
| 193 | "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", | |||||
| 194 | "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", | |||||
| 195 | "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", | |||||
| 196 | "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", | |||||
| 197 | "d8", "d9", "da", "db", "dc", "dd", "de", "df", | |||||
| 198 | "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", | |||||
| 199 | "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", | |||||
| 200 | "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", | |||||
| 201 | "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", | |||||
| 202 | }; | |||||
| 203 | ||||||
| 204 | static unsigned int hexvalues[256]; /* for parsing hex input */ | |||||
| 205 | ||||||
| 206 | static int original_umask = 0; /* for restoring */ | |||||
| 207 | ||||||
| 208 | ||||||
| 209 | /* | |||||
| 210 | * private utility procedures | |||||
| 211 | */ | |||||
| 212 | ||||||
| 213 | static void | |||||
| 214 | prefix(const char *fn, int n) | |||||
| 215 | { | |||||
| 216 | fprintf (stderr__stderrp, "%s: %s:%d: ", ProgramName, fn, n); | |||||
| 217 | } | |||||
| 218 | ||||||
| 219 | static void | |||||
| 220 | baddisplayname(const char *dpy, const char *cmd) | |||||
| 221 | { | |||||
| 222 | fprintf (stderr__stderrp, "bad display name \"%s\" in \"%s\" command\n", | |||||
| 223 | dpy, cmd); | |||||
| 224 | } | |||||
| 225 | ||||||
| 226 | static void | |||||
| 227 | badcommandline(const char *cmd) | |||||
| 228 | { | |||||
| 229 | fprintf (stderr__stderrp, "bad \"%s\" command line\n", cmd); | |||||
| 230 | } | |||||
| 231 | ||||||
| 232 | static char * | |||||
| 233 | skip_space(register char *s) | |||||
| 234 | { | |||||
| 235 | if (!s) return NULL((void*)0); | |||||
| 236 | ||||||
| 237 | for ( ; *s && isascii(*s) && isspace(*s); s++) | |||||
| 238 | ; | |||||
| 239 | return s; | |||||
| 240 | } | |||||
| 241 | ||||||
| 242 | ||||||
| 243 | static char * | |||||
| 244 | skip_nonspace(register char *s) | |||||
| 245 | { | |||||
| 246 | if (!s) return NULL((void*)0); | |||||
| 247 | ||||||
| 248 | /* put quoting into loop if need be */ | |||||
| 249 | for ( ; *s && isascii(*s) && !isspace(*s); s++) | |||||
| 250 | ; | |||||
| 251 | return s; | |||||
| 252 | } | |||||
| 253 | ||||||
| 254 | static const char ** | |||||
| 255 | split_into_words(char *src, int *argcp) /* argvify string */ | |||||
| 256 | { | |||||
| 257 | char *jword; | |||||
| 258 | char savec; | |||||
| 259 | const char **argv; | |||||
| 260 | int cur, total; | |||||
| 261 | ||||||
| 262 | *argcp = 0; | |||||
| 263 | #define WORDSTOALLOC4 4 /* most lines are short */ | |||||
| 264 | argv = malloc (WORDSTOALLOC4 * sizeof (char *)); | |||||
| 265 | if (!argv) return NULL((void*)0); | |||||
| 266 | cur = 0; | |||||
| 267 | total = WORDSTOALLOC4; | |||||
| 268 | ||||||
| 269 | /* | |||||
| 270 | * split the line up into separate, nul-terminated tokens; the last | |||||
| 271 | * "token" will point to the empty string so that it can be bashed into | |||||
| 272 | * a null pointer. | |||||
| 273 | */ | |||||
| 274 | ||||||
| 275 | do { | |||||
| 276 | jword = skip_space (src); | |||||
| 277 | src = skip_nonspace (jword); | |||||
| 278 | savec = *src; | |||||
| 279 | *src = '\0'; | |||||
| 280 | if (cur == total) { | |||||
| 281 | total += WORDSTOALLOC4; | |||||
| 282 | argv = realloc (argv, total * sizeof (char *)); | |||||
| 283 | if (!argv) return NULL((void*)0); | |||||
| 284 | } | |||||
| 285 | argv[cur++] = jword; | |||||
| 286 | if (savec) src++; /* if not last on line advance */ | |||||
| 287 | } while (jword != src); | |||||
| 288 | ||||||
| 289 | argv[--cur] = NULL((void*)0); /* smash empty token to end list */ | |||||
| 290 | *argcp = cur; | |||||
| 291 | return argv; | |||||
| 292 | } | |||||
| 293 | ||||||
| 294 | ||||||
| 295 | static FILE * | |||||
| 296 | open_file(const char **filenamep, | |||||
| 297 | const char *mode, | |||||
| 298 | Boolint *usedstdp, | |||||
| 299 | const char *srcfn, | |||||
| 300 | int srcln, | |||||
| 301 | const char *cmd) | |||||
| 302 | { | |||||
| 303 | FILE *fp; | |||||
| 304 | ||||||
| 305 | if (strcmp (*filenamep, "-") == 0) { | |||||
| 306 | *usedstdp = True1; | |||||
| 307 | /* select std descriptor to use */ | |||||
| 308 | if (mode[0] == 'r') { | |||||
| 309 | if (okay_to_use_stdin) { | |||||
| 310 | okay_to_use_stdin = False0; | |||||
| 311 | *filenamep = stdin_filename; | |||||
| 312 | return stdin__stdinp; | |||||
| 313 | } else { | |||||
| 314 | prefix (srcfn, srcln); | |||||
| 315 | fprintf (stderr__stderrp, "%s: stdin already in use\n", cmd); | |||||
| 316 | return NULL((void*)0); | |||||
| 317 | } | |||||
| 318 | } else { | |||||
| 319 | *filenamep = stdout_filename; | |||||
| 320 | return stdout__stdoutp; /* always okay to use stdout */ | |||||
| 321 | } | |||||
| 322 | } | |||||
| 323 | ||||||
| 324 | fp = fopen (*filenamep, mode); | |||||
| 325 | if (!fp) { | |||||
| 326 | prefix (srcfn, srcln); | |||||
| 327 | fprintf (stderr__stderrp, "%s: unable to open file %s\n", cmd, *filenamep); | |||||
| 328 | } | |||||
| 329 | return fp; | |||||
| 330 | } | |||||
| 331 | ||||||
| 332 | static int | |||||
| 333 | getinput(FILE *fp) | |||||
| 334 | { | |||||
| 335 | register int c; | |||||
| 336 | ||||||
| 337 | while ((c = getc (fp)) != EOF(-1) && isascii(c) && c != '\n' && isspace(c)) ; | |||||
| 338 | return c; | |||||
| 339 | } | |||||
| 340 | ||||||
| 341 | static int | |||||
| 342 | get_short(FILE *fp, unsigned short *sp) /* for reading numeric input */ | |||||
| 343 | { | |||||
| 344 | int c; | |||||
| 345 | int i; | |||||
| 346 | unsigned short us = 0; | |||||
| 347 | ||||||
| 348 | /* | |||||
| 349 | * read family: written with %04x | |||||
| 350 | */ | |||||
| 351 | for (i = 0; i < 4; i++) { | |||||
| 352 | switch (c = getinput (fp)) { | |||||
| 353 | case EOF(-1): | |||||
| 354 | case '\n': | |||||
| 355 | return 0; | |||||
| 356 | } | |||||
| 357 | if (c < 0 || c > 255) return 0; | |||||
| 358 | us = (us * 16) + hexvalues[c]; /* since msb */ | |||||
| 359 | } | |||||
| 360 | *sp = us; | |||||
| 361 | return 1; | |||||
| 362 | } | |||||
| 363 | ||||||
| 364 | static int | |||||
| 365 | get_bytes(FILE *fp, unsigned int n, char **ptr) /* for reading numeric input */ | |||||
| 366 | { | |||||
| 367 | char *s; | |||||
| 368 | register char *cp; | |||||
| 369 | int c1, c2; | |||||
| 370 | ||||||
| 371 | cp = s = malloc (n); | |||||
| 372 | if (!cp) return 0; | |||||
| 373 | ||||||
| 374 | while (n > 0) { | |||||
| 375 | if ((c1 = getinput (fp)) == EOF(-1) || c1 == '\n' || | |||||
| 376 | (c2 = getinput (fp)) == EOF(-1) || c2 == '\n') { | |||||
| 377 | free (s); | |||||
| 378 | return 0; | |||||
| 379 | } | |||||
| 380 | *cp = (char) ((hexvalues[c1] * 16) + hexvalues[c2]); | |||||
| 381 | cp++; | |||||
| 382 | n--; | |||||
| 383 | } | |||||
| 384 | ||||||
| 385 | *ptr = s; | |||||
| 386 | return 1; | |||||
| 387 | } | |||||
| 388 | ||||||
| 389 | ||||||
| 390 | static Xauth * | |||||
| 391 | read_numeric(FILE *fp) | |||||
| 392 | { | |||||
| 393 | Xauth *auth; | |||||
| 394 | ||||||
| 395 | auth = (Xauth *) malloc (sizeof (Xauth)); | |||||
| ||||||
| 396 | if (!auth) goto bad; | |||||
| 397 | auth->family = 0; | |||||
| 398 | auth->address = NULL((void*)0); | |||||
| 399 | auth->address_length = 0; | |||||
| 400 | auth->number = NULL((void*)0); | |||||
| 401 | auth->number_length = 0; | |||||
| 402 | auth->name = NULL((void*)0); | |||||
| 403 | auth->name_length = 0; | |||||
| 404 | auth->data = NULL((void*)0); | |||||
| 405 | auth->data_length = 0; | |||||
| 406 | ||||||
| 407 | if (!get_short (fp, (unsigned short *) &auth->family)) | |||||
| 408 | goto bad; | |||||
| 409 | if (!get_short (fp, (unsigned short *) &auth->address_length)) | |||||
| 410 | goto bad; | |||||
| 411 | if (!get_bytes (fp, (unsigned int) auth->address_length, &auth->address)) | |||||
| 412 | goto bad; | |||||
| 413 | if (!get_short (fp, (unsigned short *) &auth->number_length)) | |||||
| 414 | goto bad; | |||||
| 415 | if (!get_bytes (fp, (unsigned int) auth->number_length, &auth->number)) | |||||
| 416 | goto bad; | |||||
| 417 | if (!get_short (fp, (unsigned short *) &auth->name_length)) | |||||
| 418 | goto bad; | |||||
| 419 | if (!get_bytes (fp, (unsigned int) auth->name_length, &auth->name)) | |||||
| 420 | goto bad; | |||||
| 421 | if (!get_short (fp, (unsigned short *) &auth->data_length)) | |||||
| 422 | goto bad; | |||||
| 423 | if (!get_bytes (fp, (unsigned int) auth->data_length, &auth->data)) | |||||
| 424 | goto bad; | |||||
| 425 | ||||||
| 426 | switch (getinput (fp)) { /* get end of line */ | |||||
| 427 | case EOF(-1): | |||||
| 428 | case '\n': | |||||
| 429 | return auth; | |||||
| 430 | } | |||||
| 431 | ||||||
| 432 | bad: | |||||
| 433 | if (auth) XauDisposeAuth (auth); /* won't free null pointers */ | |||||
| 434 | return NULL((void*)0); | |||||
| ||||||
| 435 | } | |||||
| 436 | ||||||
| 437 | typedef Xauth *(*ReadFunc)(FILE *); | |||||
| 438 | ||||||
| 439 | static int | |||||
| 440 | read_auth_entries(FILE *fp, Boolint numeric, AuthList **headp, AuthList **tailp) | |||||
| 441 | { | |||||
| 442 | ReadFunc readfunc = (numeric ? read_numeric : XauReadAuth); | |||||
| 443 | Xauth *auth; | |||||
| 444 | AuthList *head, *tail; | |||||
| 445 | int n; | |||||
| 446 | ||||||
| 447 | head = tail = NULL((void*)0); | |||||
| 448 | n = 0; | |||||
| 449 | /* put all records into linked list */ | |||||
| 450 | while ((auth = ((*readfunc) (fp))) != NULL((void*)0)) { | |||||
| 451 | AuthList *l = (AuthList *) malloc (sizeof (AuthList)); | |||||
| 452 | if (!l) { | |||||
| 453 | fprintf (stderr__stderrp, | |||||
| 454 | "%s: unable to alloc entry reading auth file\n", | |||||
| 455 | ProgramName); | |||||
| 456 | exit (1); | |||||
| 457 | } | |||||
| 458 | l->next = NULL((void*)0); | |||||
| 459 | l->auth = auth; | |||||
| 460 | if (tail) /* if not first time through append */ | |||||
| 461 | tail->next = l; | |||||
| 462 | else | |||||
| 463 | head = l; /* first time through, so assign */ | |||||
| 464 | tail = l; | |||||
| 465 | n++; | |||||
| 466 | } | |||||
| 467 | *headp = head; | |||||
| 468 | *tailp = tail; | |||||
| 469 | return n; | |||||
| 470 | } | |||||
| 471 | ||||||
| 472 | static Boolint | |||||
| 473 | get_displayname_auth(const char *displayname, AuthList **authl) | |||||
| 474 | { | |||||
| 475 | int family; | |||||
| 476 | char *host = NULL((void*)0), *rest = NULL((void*)0); | |||||
| 477 | int dpynum, scrnum; | |||||
| 478 | char *cp; | |||||
| 479 | int prelen = 0; | |||||
| 480 | struct addrlist *addrlist_head, *addrlist_cur; | |||||
| 481 | AuthList *authl_cur = NULL((void*)0); | |||||
| 482 | ||||||
| 483 | *authl = NULL((void*)0); | |||||
| 484 | /* | |||||
| 485 | * check to see if the display name is of the form "host/unix:" | |||||
| 486 | * which is how the list routine prints out local connections | |||||
| 487 | */ | |||||
| 488 | cp = strchr(displayname, '/'); | |||||
| 489 | if (cp && strncmp (cp, "/unix:", 6) == 0) | |||||
| 490 | prelen = (cp - displayname); | |||||
| 491 | ||||||
| 492 | if (!parse_displayname (displayname + ((prelen > 0) ? prelen + 1 : 0), | |||||
| 493 | &family, &host, &dpynum, &scrnum, &rest)) { | |||||
| 494 | return False0; | |||||
| 495 | } | |||||
| 496 | ||||||
| 497 | addrlist_head = get_address_info(family, displayname, prelen, host); | |||||
| 498 | if (addrlist_head) { | |||||
| 499 | char buf[40]; /* want to hold largest display num */ | |||||
| 500 | unsigned short dpylen; | |||||
| 501 | ||||||
| 502 | buf[0] = '\0'; | |||||
| 503 | sprintf (buf, "%d", dpynum)__builtin___sprintf_chk (buf, 0, __builtin_object_size (buf, 2 > 1 ? 1 : 0), "%d", dpynum); | |||||
| 504 | dpylen = strlen (buf); | |||||
| 505 | if (dpylen > 0) { | |||||
| 506 | for (addrlist_cur = addrlist_head; addrlist_cur != NULL((void*)0); | |||||
| 507 | addrlist_cur = addrlist_cur->next) { | |||||
| 508 | AuthList *newal = malloc(sizeof(AuthList)); | |||||
| 509 | Xauth *auth = malloc(sizeof(Xauth)); | |||||
| 510 | ||||||
| 511 | if ((newal == NULL((void*)0)) || (auth == NULL((void*)0))) { | |||||
| 512 | if (newal != NULL((void*)0)) free(newal); | |||||
| 513 | if (auth != NULL((void*)0)) free(auth); | |||||
| 514 | break; | |||||
| 515 | } | |||||
| 516 | ||||||
| 517 | if (authl_cur == NULL((void*)0)) { | |||||
| 518 | *authl = authl_cur = newal; | |||||
| 519 | } else { | |||||
| 520 | authl_cur->next = newal; | |||||
| 521 | authl_cur = newal; | |||||
| 522 | } | |||||
| 523 | ||||||
| 524 | newal->next = NULL((void*)0); | |||||
| 525 | newal->auth = auth; | |||||
| 526 | ||||||
| 527 | auth->family = addrlist_cur->family; | |||||
| 528 | auth->address = addrlist_cur->address; | |||||
| 529 | auth->address_length = addrlist_cur->len; | |||||
| 530 | auth->number = copystring(buf, dpylen); | |||||
| 531 | auth->number_length = dpylen; | |||||
| 532 | auth->name = NULL((void*)0); | |||||
| 533 | auth->name_length = 0; | |||||
| 534 | auth->data = NULL((void*)0); | |||||
| 535 | auth->data_length = 0; | |||||
| 536 | } | |||||
| 537 | } | |||||
| 538 | } | |||||
| 539 | ||||||
| 540 | if (host) free (host); | |||||
| 541 | if (rest) free (rest); | |||||
| 542 | ||||||
| 543 | if (*authl != NULL((void*)0)) { | |||||
| 544 | return True1; | |||||
| 545 | } else { | |||||
| 546 | return False0; | |||||
| 547 | } | |||||
| 548 | } | |||||
| 549 | ||||||
| 550 | static int | |||||
| 551 | cvthexkey(const char *hexstr, char **ptrp) /* turn hex key string into octets */ | |||||
| 552 | { | |||||
| 553 | int i; | |||||
| 554 | int len = 0; | |||||
| 555 | char *retval; | |||||
| 556 | const char *s; | |||||
| 557 | unsigned char *us; | |||||
| 558 | char c; | |||||
| 559 | char savec = '\0'; | |||||
| 560 | ||||||
| 561 | /* count */ | |||||
| 562 | for (s = hexstr; *s; s++) { | |||||
| 563 | if (!isascii(*s)) return -1; | |||||
| 564 | if (isspace(*s)) continue; | |||||
| 565 | if (!isxdigit(*s)) return -1; | |||||
| 566 | len++; | |||||
| 567 | } | |||||
| 568 | ||||||
| 569 | /* if 0 or odd, then there was an error */ | |||||
| 570 | if (len == 0 || (len & 1) == 1) return -1; | |||||
| 571 | ||||||
| 572 | ||||||
| 573 | /* now we know that the input is good */ | |||||
| 574 | len >>= 1; | |||||
| 575 | retval = malloc (len); | |||||
| 576 | if (!retval) { | |||||
| 577 | fprintf (stderr__stderrp, "%s: unable to allocate %d bytes for hexkey\n", | |||||
| 578 | ProgramName, len); | |||||
| 579 | return -1; | |||||
| 580 | } | |||||
| 581 | ||||||
| 582 | for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) { | |||||
| 583 | c = *hexstr; | |||||
| 584 | if (isspace(c)) continue; /* already know it is ascii */ | |||||
| 585 | if (isupper(c)) | |||||
| 586 | c = tolower(c); | |||||
| 587 | if (savec) { | |||||
| 588 | #define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10))) | |||||
| 589 | *us = (unsigned char)((atoh(savec) << 4) + atoh(c)); | |||||
| 590 | #undef atoh | |||||
| 591 | savec = 0; /* ready for next character */ | |||||
| 592 | us++; | |||||
| 593 | i--; | |||||
| 594 | } else { | |||||
| 595 | savec = c; | |||||
| 596 | } | |||||
| 597 | } | |||||
| 598 | *ptrp = retval; | |||||
| 599 | return len; | |||||
| 600 | } | |||||
| 601 | ||||||
| 602 | static int | |||||
| 603 | dispatch_command(const char *inputfilename, | |||||
| 604 | int lineno, | |||||
| 605 | int argc, | |||||
| 606 | const char **argv, | |||||
| 607 | CommandTable *tab, | |||||
| 608 | int *statusp) | |||||
| 609 | { | |||||
| 610 | CommandTable *ct; | |||||
| 611 | const char *cmd; | |||||
| 612 | int n; | |||||
| 613 | /* scan table for command */ | |||||
| 614 | cmd = argv[0]; | |||||
| 615 | n = strlen (cmd); | |||||
| 616 | for (ct = tab; ct->name; ct++) { | |||||
| 617 | /* look for unique prefix */ | |||||
| 618 | if (n >= ct->minlen && n <= ct->maxlen && | |||||
| 619 | strncmp (cmd, ct->name, n) == 0) { | |||||
| 620 | *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv); | |||||
| 621 | return 1; | |||||
| 622 | } | |||||
| 623 | } | |||||
| 624 | ||||||
| 625 | *statusp = 1; | |||||
| 626 | return 0; | |||||
| 627 | } | |||||
| 628 | ||||||
| 629 | ||||||
| 630 | static AuthList *xauth_head = NULL((void*)0); /* list of auth entries */ | |||||
| 631 | static Boolint xauth_existed = False0; /* if was present at initialize */ | |||||
| 632 | static Boolint xauth_modified = False0; /* if added, removed, or merged */ | |||||
| 633 | static Boolint xauth_allowed = True1; /* if allowed to write auth file */ | |||||
| 634 | static Boolint xauth_locked = False0; /* if has been locked */ | |||||
| 635 | static const char *xauth_filename = NULL((void*)0); | |||||
| 636 | static volatile Boolint dieing = False0; | |||||
| 637 | ||||||
| 638 | ||||||
| 639 | /* poor man's puts(), for under signal handlers, | |||||
| 640 | extended to ignore warn_unused_result */ | |||||
| 641 | #define WRITES(fd, S){if(write((fd), (S), strlen((S))));} {if(write((fd), (S), strlen((S))));} | |||||
| 642 | ||||||
| 643 | /* ARGSUSED */ | |||||
| 644 | _X_NORETURN__attribute((noreturn)) | |||||
| 645 | static void | |||||
| 646 | die(int sig) | |||||
| 647 | { | |||||
| 648 | dieing = True1; | |||||
| 649 | _exit (auth_finalize ()); | |||||
| 650 | /* NOTREACHED */ | |||||
| 651 | } | |||||
| 652 | ||||||
| 653 | _X_NORETURN__attribute((noreturn)) | |||||
| 654 | static void | |||||
| 655 | catchsig(int sig) | |||||
| 656 | { | |||||
| 657 | #ifdef SYSV | |||||
| 658 | if (sig > 0) signal (sig, die); /* re-establish signal handler */ | |||||
| 659 | #endif | |||||
| 660 | /* | |||||
| 661 | * fileno() might not be reentrant, avoid it if possible, and use | |||||
| 662 | * stderr instead of stdout | |||||
| 663 | */ | |||||
| 664 | #ifdef STDERR_FILENO2 | |||||
| 665 | if (verbose && xauth_modified) WRITES(STDERR_FILENO, "\r\n"){if(write((2), ("\r\n"), strlen(("\r\n"))));}; | |||||
| 666 | #else | |||||
| 667 | if (verbose && xauth_modified) WRITES(fileno(stderr), "\r\n"){if(write((fileno(__stderrp)), ("\r\n"), strlen(("\r\n"))));}; | |||||
| 668 | #endif | |||||
| 669 | die (sig); | |||||
| 670 | /* NOTREACHED */ | |||||
| 671 | } | |||||
| 672 | ||||||
| 673 | static void | |||||
| 674 | register_signals(void) | |||||
| 675 | { | |||||
| 676 | signal (SIGINT2, catchsig); | |||||
| 677 | signal (SIGTERM15, catchsig); | |||||
| 678 | #ifdef SIGHUP1 | |||||
| 679 | signal (SIGHUP1, catchsig); | |||||
| 680 | #endif | |||||
| 681 | #ifdef SIGPIPE13 | |||||
| 682 | signal (SIGPIPE13, catchsig); | |||||
| 683 | #endif | |||||
| 684 | return; | |||||
| 685 | } | |||||
| 686 | ||||||
| 687 | ||||||
| 688 | /* | |||||
| 689 | * public procedures for parsing lines of input | |||||
| 690 | */ | |||||
| 691 | ||||||
| 692 | int | |||||
| 693 | auth_initialize(const char *authfilename) | |||||
| 694 | { | |||||
| 695 | int n; | |||||
| 696 | AuthList *head, *tail; | |||||
| 697 | FILE *authfp; | |||||
| 698 | Boolint exists; | |||||
| 699 | ||||||
| 700 | xauth_filename = authfilename; /* used in cleanup, prevent race with | |||||
| 701 | signals */ | |||||
| 702 | register_signals (); | |||||
| 703 | ||||||
| 704 | bzero ((char *) hexvalues, sizeof hexvalues)__builtin___memset_chk ((char *) hexvalues, 0, sizeof hexvalues , __builtin_object_size ((char *) hexvalues, 0)); | |||||
| 705 | hexvalues['0'] = 0; | |||||
| 706 | hexvalues['1'] = 1; | |||||
| 707 | hexvalues['2'] = 2; | |||||
| 708 | hexvalues['3'] = 3; | |||||
| 709 | hexvalues['4'] = 4; | |||||
| 710 | hexvalues['5'] = 5; | |||||
| 711 | hexvalues['6'] = 6; | |||||
| 712 | hexvalues['7'] = 7; | |||||
| 713 | hexvalues['8'] = 8; | |||||
| 714 | hexvalues['9'] = 9; | |||||
| 715 | hexvalues['a'] = hexvalues['A'] = 0xa; | |||||
| 716 | hexvalues['b'] = hexvalues['B'] = 0xb; | |||||
| 717 | hexvalues['c'] = hexvalues['C'] = 0xc; | |||||
| 718 | hexvalues['d'] = hexvalues['D'] = 0xd; | |||||
| 719 | hexvalues['e'] = hexvalues['E'] = 0xe; | |||||
| 720 | hexvalues['f'] = hexvalues['F'] = 0xf; | |||||
| 721 | ||||||
| 722 | if (break_locks && verbose) { | |||||
| 723 | printf ("Attempting to break locks on authority file %s\n", | |||||
| 724 | authfilename); | |||||
| 725 | } | |||||
| 726 | ||||||
| 727 | if (ignore_locks) { | |||||
| 728 | if (break_locks) XauUnlockAuth (authfilename); | |||||
| 729 | } else { | |||||
| 730 | n = XauLockAuth (authfilename, XAUTH_DEFAULT_RETRIES10, | |||||
| 731 | XAUTH_DEFAULT_TIMEOUT2, | |||||
| 732 | (break_locks ? 0L : XAUTH_DEFAULT_DEADTIME600L)); | |||||
| 733 | if (n != LOCK_SUCCESS0) { | |||||
| 734 | const char *reason = "unknown error"; | |||||
| 735 | switch (n) { | |||||
| 736 | case LOCK_ERROR1: | |||||
| 737 | reason = "error"; | |||||
| 738 | break; | |||||
| 739 | case LOCK_TIMEOUT2: | |||||
| 740 | reason = "timeout"; | |||||
| 741 | break; | |||||
| 742 | } | |||||
| 743 | fprintf (stderr__stderrp, "%s: %s in locking authority file %s\n", | |||||
| 744 | ProgramName, reason, authfilename); | |||||
| 745 | return -1; | |||||
| 746 | } else | |||||
| 747 | xauth_locked = True1; | |||||
| 748 | } | |||||
| 749 | ||||||
| 750 | /* these checks can only be done reliably after the file is locked */ | |||||
| 751 | exists = (access (authfilename, F_OK0) == 0); | |||||
| 752 | if (exists && access (authfilename, W_OK(1<<1)) != 0) { | |||||
| 753 | fprintf (stderr__stderrp, | |||||
| 754 | "%s: %s not writable, changes will be ignored\n", | |||||
| 755 | ProgramName, authfilename); | |||||
| 756 | xauth_allowed = False0; | |||||
| 757 | } | |||||
| 758 | ||||||
| 759 | original_umask = umask (0077); /* disallow non-owner access */ | |||||
| 760 | ||||||
| 761 | authfp = fopen (authfilename, "rb"); | |||||
| 762 | if (!authfp) { | |||||
| 763 | int olderrno = errno(*__error()); | |||||
| 764 | ||||||
| 765 | /* if file there then error */ | |||||
| 766 | if (access (authfilename, F_OK0) == 0) { /* then file does exist! */ | |||||
| 767 | errno(*__error()) = olderrno; | |||||
| 768 | return -1; | |||||
| 769 | } /* else ignore it */ | |||||
| 770 | fprintf (stderr__stderrp, | |||||
| 771 | "%s: file %s does not exist\n", | |||||
| 772 | ProgramName, authfilename); | |||||
| 773 | } else { | |||||
| 774 | xauth_existed = True1; | |||||
| 775 | n = read_auth_entries (authfp, False0, &head, &tail); | |||||
| 776 | (void) fclose (authfp); | |||||
| 777 | if (n < 0) { | |||||
| 778 | fprintf (stderr__stderrp, | |||||
| 779 | "%s: unable to read auth entries from file \"%s\"\n", | |||||
| 780 | ProgramName, authfilename); | |||||
| 781 | return -1; | |||||
| 782 | } | |||||
| 783 | xauth_head = head; | |||||
| 784 | } | |||||
| 785 | ||||||
| 786 | xauth_filename = strdup(authfilename); | |||||
| 787 | if (!xauth_filename) { | |||||
| 788 | fprintf(stderr__stderrp,"cannot allocate memory\n"); | |||||
| 789 | return -1; | |||||
| 790 | } | |||||
| 791 | ||||||
| 792 | xauth_modified = False0; | |||||
| 793 | ||||||
| 794 | if (verbose) { | |||||
| 795 | printf ("%s authority file %s\n", | |||||
| 796 | ignore_locks ? "Ignoring locks on" : "Using", authfilename); | |||||
| 797 | } | |||||
| 798 | return 0; | |||||
| 799 | } | |||||
| 800 | ||||||
| 801 | static int | |||||
| 802 | write_auth_file(char *tmp_nam) | |||||
| 803 | { | |||||
| 804 | FILE *fp = NULL((void*)0); | |||||
| 805 | int fd; | |||||
| 806 | AuthList *list; | |||||
| 807 | ||||||
| 808 | /* | |||||
| 809 | * xdm and auth spec assumes auth file is 12 or fewer characters | |||||
| 810 | */ | |||||
| 811 | strcpy (tmp_nam, xauth_filename)__builtin___strcpy_chk (tmp_nam, xauth_filename, __builtin_object_size (tmp_nam, 2 > 1 ? 1 : 0)); | |||||
| 812 | strcat (tmp_nam, "-n")__builtin___strcat_chk (tmp_nam, "-n", __builtin_object_size ( tmp_nam, 2 > 1 ? 1 : 0)); /* for new */ | |||||
| 813 | (void) unlink (tmp_nam); | |||||
| 814 | /* CPhipps 2000/02/12 - fix file unlink/fopen race */ | |||||
| 815 | fd = open(tmp_nam, O_WRONLY0x0001 | O_CREAT0x0200 | O_EXCL0x0800, 0600); | |||||
| 816 | if (fd != -1) fp = fdopen (fd, "wb"); | |||||
| 817 | if (!fp) { | |||||
| 818 | if (fd != -1) close(fd); | |||||
| 819 | fprintf (stderr__stderrp, "%s: unable to open tmp file \"%s\"\n", | |||||
| 820 | ProgramName, tmp_nam); | |||||
| 821 | return -1; | |||||
| 822 | } | |||||
| 823 | ||||||
| 824 | /* | |||||
| 825 | * Write MIT-MAGIC-COOKIE-1 first, because R4 Xlib knows | |||||
| 826 | * only that and uses the first authorization it finds. | |||||
| 827 | */ | |||||
| 828 | for (list = xauth_head; list; list = list->next) { | |||||
| 829 | if (list->auth->name_length == 18 | |||||
| 830 | && strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) == 0) { | |||||
| 831 | if (!XauWriteAuth(fp, list->auth)) { | |||||
| 832 | (void) fclose(fp); | |||||
| 833 | return -1; | |||||
| 834 | } | |||||
| 835 | } | |||||
| 836 | } | |||||
| 837 | for (list = xauth_head; list; list = list->next) { | |||||
| 838 | if (list->auth->name_length != 18 | |||||
| 839 | || strncmp(list->auth->name, "MIT-MAGIC-COOKIE-1", 18) != 0) { | |||||
| 840 | if (!XauWriteAuth(fp, list->auth)) { | |||||
| 841 | (void) fclose(fp); | |||||
| 842 | return -1; | |||||
| 843 | } | |||||
| 844 | } | |||||
| 845 | } | |||||
| 846 | ||||||
| 847 | if (fclose(fp)) { | |||||
| 848 | return -1; | |||||
| 849 | } | |||||
| 850 | ||||||
| 851 | return 0; | |||||
| 852 | } | |||||
| 853 | ||||||
| 854 | int | |||||
| 855 | auth_finalize(void) | |||||
| 856 | { | |||||
| 857 | char temp_name[1024]; /* large filename size */ | |||||
| 858 | ||||||
| 859 | if (xauth_modified) { | |||||
| 860 | if (dieing) { | |||||
| 861 | if (verbose) { | |||||
| 862 | /* | |||||
| 863 | * called from a signal handler -- printf is *not* reentrant; also | |||||
| 864 | * fileno() might not be reentrant, avoid it if possible, and use | |||||
| 865 | * stderr instead of stdout | |||||
| 866 | */ | |||||
| 867 | #ifdef STDERR_FILENO2 | |||||
| 868 | WRITES(STDERR_FILENO, "\nAborting changes to authority file "){if(write((2), ("\nAborting changes to authority file "), strlen (("\nAborting changes to authority file "))));}; | |||||
| 869 | WRITES(STDERR_FILENO, xauth_filename){if(write((2), (xauth_filename), strlen((xauth_filename))));}; | |||||
| 870 | WRITES(STDERR_FILENO, "\n"){if(write((2), ("\n"), strlen(("\n"))));}; | |||||
| 871 | #else | |||||
| 872 | WRITES(fileno(stderr), "\nAborting changes to authority file "){if(write((fileno(__stderrp)), ("\nAborting changes to authority file " ), strlen(("\nAborting changes to authority file "))));}; | |||||
| 873 | WRITES(fileno(stderr), xauth_filename){if(write((fileno(__stderrp)), (xauth_filename), strlen((xauth_filename ))));}; | |||||
| 874 | WRITES(fileno(stderr), "\n"){if(write((fileno(__stderrp)), ("\n"), strlen(("\n"))));}; | |||||
| 875 | #endif | |||||
| 876 | } | |||||
| 877 | } else if (!xauth_allowed) { | |||||
| 878 | fprintf (stderr__stderrp, | |||||
| 879 | "%s: %s not writable, changes ignored\n", | |||||
| 880 | ProgramName, xauth_filename); | |||||
| 881 | } else { | |||||
| 882 | if (verbose) { | |||||
| 883 | printf ("%s authority file %s\n", | |||||
| 884 | ignore_locks ? "Ignoring locks and writing" : | |||||
| 885 | "Writing", xauth_filename); | |||||
| 886 | } | |||||
| 887 | temp_name[0] = '\0'; | |||||
| 888 | if (write_auth_file (temp_name) == -1) { | |||||
| 889 | fprintf (stderr__stderrp, | |||||
| 890 | "%s: unable to write authority file %s\n", | |||||
| 891 | ProgramName, temp_name); | |||||
| 892 | } else { | |||||
| 893 | (void) unlink (xauth_filename); | |||||
| 894 | #if defined(WIN32) || defined(__UNIXOS2__) | |||||
| 895 | if (rename(temp_name, xauth_filename) == -1) | |||||
| 896 | #else | |||||
| 897 | /* Attempt to rename() if link() fails, since this may be on a FS that does not support hard links */ | |||||
| 898 | if (link (temp_name, xauth_filename) == -1 && rename(temp_name, xauth_filename) == -1) | |||||
| 899 | #endif | |||||
| 900 | { | |||||
| 901 | fprintf (stderr__stderrp, | |||||
| 902 | "%s: unable to link authority file %s, use %s\n", | |||||
| 903 | ProgramName, xauth_filename, temp_name); | |||||
| 904 | } else { | |||||
| 905 | (void) unlink (temp_name); | |||||
| 906 | } | |||||
| 907 | } | |||||
| 908 | } | |||||
| 909 | } | |||||
| 910 | ||||||
| 911 | if (xauth_locked) { | |||||
| 912 | XauUnlockAuth (xauth_filename); | |||||
| 913 | } | |||||
| 914 | (void) umask (original_umask); | |||||
| 915 | return 0; | |||||
| 916 | } | |||||
| 917 | ||||||
| 918 | int | |||||
| 919 | process_command(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 920 | { | |||||
| 921 | int status; | |||||
| 922 | ||||||
| 923 | if (argc < 1 || !argv || !argv[0]) return 1; | |||||
| 924 | ||||||
| 925 | if (dispatch_command (inputfilename, lineno, argc, argv, | |||||
| 926 | command_table, &status)) | |||||
| 927 | return status; | |||||
| 928 | ||||||
| 929 | prefix (inputfilename, lineno); | |||||
| 930 | fprintf (stderr__stderrp, "unknown command \"%s\"\n", argv[0]); | |||||
| 931 | return 1; | |||||
| 932 | } | |||||
| 933 | ||||||
| 934 | ||||||
| 935 | /* | |||||
| 936 | * utility routines | |||||
| 937 | */ | |||||
| 938 | ||||||
| 939 | static char * | |||||
| 940 | bintohex(unsigned int len, const char *bindata) | |||||
| 941 | { | |||||
| 942 | char *hexdata, *starthex; | |||||
| 943 | ||||||
| 944 | /* two chars per byte, plus null termination */ | |||||
| 945 | starthex = hexdata = (char *)malloc(2*len + 1); | |||||
| 946 | if (!hexdata) | |||||
| 947 | return NULL((void*)0); | |||||
| 948 | ||||||
| 949 | for (; len > 0; len--, bindata++) { | |||||
| 950 | register const char *s = hex_table[(unsigned char)*bindata]; | |||||
| 951 | *hexdata++ = s[0]; | |||||
| 952 | *hexdata++ = s[1]; | |||||
| 953 | } | |||||
| 954 | *hexdata = '\0'; | |||||
| 955 | return starthex; | |||||
| 956 | } | |||||
| 957 | ||||||
| 958 | static void | |||||
| 959 | fprintfhex(register FILE *fp, int len, char *cp) | |||||
| 960 | { | |||||
| 961 | char *hex; | |||||
| 962 | ||||||
| 963 | hex = bintohex(len, cp); | |||||
| 964 | fprintf(fp, "%s", hex); | |||||
| 965 | free(hex); | |||||
| 966 | } | |||||
| 967 | ||||||
| 968 | static int | |||||
| 969 | dump_numeric(register FILE *fp, register Xauth *auth) | |||||
| 970 | { | |||||
| 971 | fprintf (fp, "%04x", auth->family); /* unsigned short */ | |||||
| 972 | fprintf (fp, " %04x ", auth->address_length); /* short */ | |||||
| 973 | fprintfhex (fp, auth->address_length, auth->address); | |||||
| 974 | fprintf (fp, " %04x ", auth->number_length); /* short */ | |||||
| 975 | fprintfhex (fp, auth->number_length, auth->number); | |||||
| 976 | fprintf (fp, " %04x ", auth->name_length); /* short */ | |||||
| 977 | fprintfhex (fp, auth->name_length, auth->name); | |||||
| 978 | fprintf (fp, " %04x ", auth->data_length); /* short */ | |||||
| 979 | fprintfhex (fp, auth->data_length, auth->data); | |||||
| 980 | putc ('\n', fp); | |||||
| 981 | return 1; | |||||
| 982 | } | |||||
| 983 | ||||||
| 984 | /* ARGSUSED */ | |||||
| 985 | static int | |||||
| 986 | dump_entry(const char *inputfilename, int lineno, Xauth *auth, char *data) | |||||
| 987 | { | |||||
| 988 | struct _list_data *ld = (struct _list_data *) data; | |||||
| 989 | FILE *fp = ld->fp; | |||||
| 990 | ||||||
| 991 | if (ld->numeric) { | |||||
| 992 | dump_numeric (fp, auth); | |||||
| 993 | } else { | |||||
| 994 | const char *dpyname = NULL((void*)0); | |||||
| 995 | ||||||
| 996 | switch (auth->family) { | |||||
| 997 | case FamilyLocal(256): | |||||
| 998 | fwrite (auth->address, sizeof (char), auth->address_length, fp); | |||||
| 999 | fprintf (fp, "/unix"); | |||||
| 1000 | break; | |||||
| 1001 | case FamilyInternet0: | |||||
| 1002 | #if defined(IPv61) && defined(AF_INET630) | |||||
| 1003 | case FamilyInternet66: | |||||
| 1004 | #endif | |||||
| 1005 | case FamilyDECnet1: | |||||
| 1006 | dpyname = get_hostname (auth); | |||||
| 1007 | if (dpyname) { | |||||
| 1008 | fprintf (fp, "%s", dpyname); | |||||
| 1009 | break; | |||||
| 1010 | } | |||||
| 1011 | /* else fall through to default */ | |||||
| 1012 | default: | |||||
| 1013 | fprintf (fp, "#%04x#", auth->family); | |||||
| 1014 | fprintfhex (fp, auth->address_length, auth->address); | |||||
| 1015 | putc ('#', fp); | |||||
| 1016 | } | |||||
| 1017 | putc (':', fp); | |||||
| 1018 | fwrite (auth->number, sizeof (char), auth->number_length, fp); | |||||
| 1019 | putc (' ', fp); | |||||
| 1020 | putc (' ', fp); | |||||
| 1021 | fwrite (auth->name, sizeof (char), auth->name_length, fp); | |||||
| 1022 | putc (' ', fp); | |||||
| 1023 | putc (' ', fp); | |||||
| 1024 | if (!strncmp(auth->name, SECURERPC"SUN-DES-1", auth->name_length) || | |||||
| 1025 | !strncmp(auth->name, K5AUTH"MIT-KERBEROS-5", auth->name_length)) | |||||
| 1026 | fwrite (auth->data, sizeof (char), auth->data_length, fp); | |||||
| 1027 | else | |||||
| 1028 | fprintfhex (fp, auth->data_length, auth->data); | |||||
| 1029 | putc ('\n', fp); | |||||
| 1030 | } | |||||
| 1031 | return 0; | |||||
| 1032 | } | |||||
| 1033 | ||||||
| 1034 | static int | |||||
| 1035 | extract_entry(const char *inputfilename, int lineno, Xauth *auth, char *data) | |||||
| 1036 | { | |||||
| 1037 | struct _extract_data *ed = (struct _extract_data *) data; | |||||
| 1038 | ||||||
| 1039 | if (!ed->fp) { | |||||
| 1040 | ed->fp = open_file (&ed->filename, | |||||
| 1041 | ed->numeric ? "w" : "wb", | |||||
| 1042 | &ed->used_stdout, | |||||
| 1043 | inputfilename, lineno, ed->cmd); | |||||
| 1044 | if (!ed->fp) { | |||||
| 1045 | prefix (inputfilename, lineno); | |||||
| 1046 | fprintf (stderr__stderrp, | |||||
| 1047 | "unable to open extraction file \"%s\"\n", | |||||
| 1048 | ed->filename); | |||||
| 1049 | return -1; | |||||
| 1050 | } | |||||
| 1051 | } | |||||
| 1052 | (*(ed->numeric ? dump_numeric : XauWriteAuth)) (ed->fp, auth); | |||||
| 1053 | ed->nwritten++; | |||||
| 1054 | ||||||
| 1055 | return 0; | |||||
| 1056 | } | |||||
| 1057 | ||||||
| 1058 | ||||||
| 1059 | static int | |||||
| 1060 | eq_auth(Xauth *a, Xauth *b) | |||||
| 1061 | { | |||||
| 1062 | return((a->family == b->family && | |||||
| 1063 | a->address_length == b->address_length && | |||||
| 1064 | a->number_length == b->number_length && | |||||
| 1065 | a->name_length == b->name_length && | |||||
| 1066 | a->data_length == b->data_length && | |||||
| 1067 | memcmp(a->address, b->address, a->address_length) == 0 && | |||||
| 1068 | memcmp(a->number, b->number, a->number_length) == 0 && | |||||
| 1069 | memcmp(a->name, b->name, a->name_length) == 0 && | |||||
| 1070 | memcmp(a->data, b->data, a->data_length) == 0) ? 1 : 0); | |||||
| 1071 | } | |||||
| 1072 | ||||||
| 1073 | static int | |||||
| 1074 | match_auth_dpy(register Xauth *a, register Xauth *b) | |||||
| 1075 | { | |||||
| 1076 | if (a->family != FamilyWild(65535) && b->family != FamilyWild(65535)) { | |||||
| 1077 | /* Both "a" and "b" are not FamilyWild, they are "normal" families. */ | |||||
| 1078 | ||||||
| 1079 | /* Make sure, that both families match: */ | |||||
| 1080 | if (a->family != b->family) | |||||
| 1081 | return 0; | |||||
| 1082 | ||||||
| 1083 | /* By looking at 'man Xsecurity' and the code in | |||||
| 1084 | * GetAuthByAddr() and XauGetBestAuthByAddr() in libXau, we | |||||
| 1085 | * decided, that the address is only relevant for "normal" | |||||
| 1086 | * families and therefore should be ignored for | |||||
| 1087 | * "FamilyWild". */ | |||||
| 1088 | if (a->address_length != b->address_length || | |||||
| 1089 | memcmp(a->address, b->address, a->address_length) != 0) | |||||
| 1090 | return 0; | |||||
| 1091 | } | |||||
| 1092 | ||||||
| 1093 | if (a->number_length != 0 && b->number_length != 0) { | |||||
| 1094 | /* Both "a" and "b" have a number, make sure they match: */ | |||||
| 1095 | if (a->number_length != b->number_length || | |||||
| 1096 | memcmp(a->number, b->number, a->number_length) != 0) | |||||
| 1097 | return 0; | |||||
| 1098 | } | |||||
| 1099 | ||||||
| 1100 | return 1; | |||||
| 1101 | } | |||||
| 1102 | ||||||
| 1103 | /* return non-zero iff display and authorization type are the same */ | |||||
| 1104 | ||||||
| 1105 | static int | |||||
| 1106 | match_auth(register Xauth *a, register Xauth *b) | |||||
| 1107 | { | |||||
| 1108 | return ((match_auth_dpy(a, b) | |||||
| 1109 | && a->name_length == b->name_length | |||||
| 1110 | && memcmp(a->name, b->name, a->name_length) == 0) ? 1 : 0); | |||||
| 1111 | } | |||||
| 1112 | ||||||
| 1113 | ||||||
| 1114 | static int | |||||
| 1115 | merge_entries(AuthList **firstp, AuthList *second, int *nnewp, int *nreplp) | |||||
| 1116 | { | |||||
| 1117 | AuthList *a, *b, *first, *tail; | |||||
| 1118 | int n = 0, nnew = 0, nrepl = 0; | |||||
| 1119 | ||||||
| 1120 | if (!second) return 0; | |||||
| 1121 | ||||||
| 1122 | if (!*firstp) { /* if nothing to merge into */ | |||||
| 1123 | *firstp = second; | |||||
| 1124 | for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ; | |||||
| 1125 | *nnewp = n; | |||||
| 1126 | *nreplp = 0; | |||||
| 1127 | return n; | |||||
| 1128 | } | |||||
| 1129 | ||||||
| 1130 | first = *firstp; | |||||
| 1131 | /* | |||||
| 1132 | * find end of first list and stick second list on it | |||||
| 1133 | */ | |||||
| 1134 | for (tail = first; tail->next; tail = tail->next) ; | |||||
| 1135 | tail->next = second; | |||||
| 1136 | ||||||
| 1137 | /* | |||||
| 1138 | * run down list freeing duplicate entries; if an entry is okay, then | |||||
| 1139 | * bump the tail up to include it, otherwise, cut the entry out of | |||||
| 1140 | * the chain. | |||||
| 1141 | */ | |||||
| 1142 | for (b = second; b; ) { | |||||
| 1143 | AuthList *next = b->next; /* in case we free it */ | |||||
| 1144 | ||||||
| 1145 | a = first; | |||||
| 1146 | for (;;) { | |||||
| 1147 | if (match_auth (a->auth, b->auth)) { /* found a duplicate */ | |||||
| 1148 | AuthList tmp; /* swap it in for old one */ | |||||
| 1149 | tmp = *a; | |||||
| 1150 | *a = *b; | |||||
| 1151 | *b = tmp; | |||||
| 1152 | a->next = b->next; | |||||
| 1153 | XauDisposeAuth (b->auth); | |||||
| 1154 | free ((char *) b); | |||||
| 1155 | b = NULL((void*)0); | |||||
| 1156 | tail->next = next; | |||||
| 1157 | nrepl++; | |||||
| 1158 | nnew--; | |||||
| 1159 | break; | |||||
| 1160 | } | |||||
| 1161 | if (a == tail) break; /* if have looked at left side */ | |||||
| 1162 | a = a->next; | |||||
| 1163 | } | |||||
| 1164 | if (b) { /* if we didn't remove it */ | |||||
| 1165 | tail = b; /* bump end of first list */ | |||||
| 1166 | } | |||||
| 1167 | b = next; | |||||
| 1168 | n++; | |||||
| 1169 | nnew++; | |||||
| 1170 | } | |||||
| 1171 | ||||||
| 1172 | *nnewp = nnew; | |||||
| 1173 | *nreplp = nrepl; | |||||
| 1174 | return n; | |||||
| 1175 | ||||||
| 1176 | } | |||||
| 1177 | ||||||
| 1178 | static Xauth * | |||||
| 1179 | copyAuth(Xauth *auth) | |||||
| 1180 | { | |||||
| 1181 | Xauth *a; | |||||
| 1182 | ||||||
| 1183 | a = (Xauth *)malloc(sizeof(Xauth)); | |||||
| 1184 | if (a == NULL((void*)0)) { | |||||
| 1185 | return NULL((void*)0); | |||||
| 1186 | } | |||||
| 1187 | memset(a, 0, sizeof(Xauth))__builtin___memset_chk (a, 0, sizeof(Xauth), __builtin_object_size (a, 0)); | |||||
| 1188 | a->family = auth->family; | |||||
| 1189 | if (auth->address_length != 0) { | |||||
| 1190 | a->address = malloc(auth->address_length); | |||||
| 1191 | if (a->address == NULL((void*)0)) { | |||||
| 1192 | free(a); | |||||
| 1193 | return NULL((void*)0); | |||||
| 1194 | } | |||||
| 1195 | memcpy(a->address, auth->address, auth->address_length)__builtin___memcpy_chk (a->address, auth->address, auth ->address_length, __builtin_object_size (a->address, 0) ); | |||||
| 1196 | a->address_length = auth->address_length; | |||||
| 1197 | } | |||||
| 1198 | if (auth->number_length != 0) { | |||||
| 1199 | a->number = malloc(auth->number_length); | |||||
| 1200 | if (a->number == NULL((void*)0)) { | |||||
| 1201 | free(a->address); | |||||
| 1202 | free(a); | |||||
| 1203 | return NULL((void*)0); | |||||
| 1204 | } | |||||
| 1205 | memcpy(a->number, auth->number, auth->number_length)__builtin___memcpy_chk (a->number, auth->number, auth-> number_length, __builtin_object_size (a->number, 0)); | |||||
| 1206 | a->number_length = auth->number_length; | |||||
| 1207 | } | |||||
| 1208 | if (auth->name_length != 0) { | |||||
| 1209 | a->name = malloc(auth->name_length); | |||||
| 1210 | if (a->name == NULL((void*)0)) { | |||||
| 1211 | free(a->address); | |||||
| 1212 | free(a->number); | |||||
| 1213 | free(a); | |||||
| 1214 | return NULL((void*)0); | |||||
| 1215 | } | |||||
| 1216 | memcpy(a->name, auth->name, auth->name_length)__builtin___memcpy_chk (a->name, auth->name, auth->name_length , __builtin_object_size (a->name, 0)); | |||||
| 1217 | a->name_length = auth->name_length; | |||||
| 1218 | } | |||||
| 1219 | if (auth->data_length != 0) { | |||||
| 1220 | a->data = malloc(auth->data_length); | |||||
| 1221 | if (a->data == NULL((void*)0)) { | |||||
| 1222 | free(a->address); | |||||
| 1223 | free(a->number); | |||||
| 1224 | free(a->name); | |||||
| 1225 | free(a); | |||||
| 1226 | return NULL((void*)0); | |||||
| 1227 | } | |||||
| 1228 | memcpy(a->data, auth->data, auth->data_length)__builtin___memcpy_chk (a->data, auth->data, auth->data_length , __builtin_object_size (a->data, 0)); | |||||
| 1229 | a->data_length = auth->data_length; | |||||
| 1230 | } | |||||
| 1231 | return a; | |||||
| 1232 | } | |||||
| 1233 | ||||||
| 1234 | typedef int (*YesNoFunc)(const char *, int, Xauth *, char *); | |||||
| 1235 | ||||||
| 1236 | static int | |||||
| 1237 | iterdpy (const char *inputfilename, int lineno, int start, | |||||
| 1238 | int argc, const char *argv[], | |||||
| 1239 | YesNoFunc yfunc, YesNoFunc nfunc, char *data) | |||||
| 1240 | { | |||||
| 1241 | int i; | |||||
| 1242 | int status; | |||||
| 1243 | int errors = 0; | |||||
| 1244 | Xauth *tmp_auth; | |||||
| 1245 | AuthList *proto_head, *proto; | |||||
| 1246 | AuthList *l, *next; | |||||
| 1247 | ||||||
| 1248 | /* | |||||
| 1249 | * iterate | |||||
| 1250 | */ | |||||
| 1251 | for (i = start; i < argc; i++) { | |||||
| 1252 | const char *displayname = argv[i]; | |||||
| 1253 | if (!get_displayname_auth (displayname, &proto_head)) { | |||||
| 1254 | prefix (inputfilename, lineno); | |||||
| 1255 | baddisplayname (displayname, argv[0]); | |||||
| 1256 | errors++; | |||||
| 1257 | continue; | |||||
| 1258 | } | |||||
| 1259 | status = 0; | |||||
| 1260 | for (l = xauth_head; l; l = next) { | |||||
| 1261 | Boolint matched = False0; | |||||
| 1262 | ||||||
| 1263 | /* l may be freed by remove_entry below. so save its contents */ | |||||
| 1264 | next = l->next; | |||||
| 1265 | tmp_auth = copyAuth(l->auth); | |||||
| 1266 | for (proto = proto_head; proto; proto = proto->next) { | |||||
| 1267 | if (match_auth_dpy (proto->auth, tmp_auth)) { | |||||
| 1268 | matched = True1; | |||||
| 1269 | if (yfunc) { | |||||
| 1270 | status = (*yfunc) (inputfilename, lineno, | |||||
| 1271 | tmp_auth, data); | |||||
| 1272 | if (status < 0) break; | |||||
| 1273 | } | |||||
| 1274 | } | |||||
| 1275 | } | |||||
| 1276 | XauDisposeAuth(tmp_auth); | |||||
| 1277 | if (matched == False0) { | |||||
| 1278 | if (nfunc) { | |||||
| 1279 | status = (*nfunc) (inputfilename, lineno, | |||||
| 1280 | l->auth, data); | |||||
| 1281 | } | |||||
| 1282 | } | |||||
| 1283 | if (status < 0) break; | |||||
| 1284 | } | |||||
| 1285 | for (proto = proto_head; proto ; proto = next) { | |||||
| 1286 | next = proto->next; | |||||
| 1287 | if (proto->auth->address) free (proto->auth->address); | |||||
| 1288 | if (proto->auth->number) free (proto->auth->number); | |||||
| 1289 | free (proto->auth); | |||||
| 1290 | free (proto); | |||||
| 1291 | } | |||||
| 1292 | if (status < 0) { | |||||
| 1293 | errors -= status; /* since status is negative */ | |||||
| 1294 | break; | |||||
| 1295 | } | |||||
| 1296 | } | |||||
| 1297 | ||||||
| 1298 | return errors; | |||||
| 1299 | } | |||||
| 1300 | ||||||
| 1301 | /* ARGSUSED */ | |||||
| 1302 | static int | |||||
| 1303 | remove_entry(const char *inputfilename, int lineno, Xauth *auth, char *data) | |||||
| 1304 | { | |||||
| 1305 | int *nremovedp = (int *) data; | |||||
| 1306 | AuthList **listp = &xauth_head; | |||||
| 1307 | AuthList *list; | |||||
| 1308 | ||||||
| 1309 | /* | |||||
| 1310 | * unlink the auth we were asked to | |||||
| 1311 | */ | |||||
| 1312 | while (!eq_auth((list = *listp)->auth, auth)) { | |||||
| 1313 | listp = &list->next; | |||||
| 1314 | if (!*listp) | |||||
| 1315 | return 0; | |||||
| 1316 | } | |||||
| 1317 | *listp = list->next; | |||||
| 1318 | XauDisposeAuth (list->auth); /* free the auth */ | |||||
| 1319 | free (list); /* free the link */ | |||||
| 1320 | xauth_modified = True1; | |||||
| 1321 | (*nremovedp)++; | |||||
| 1322 | return 1; | |||||
| 1323 | } | |||||
| 1324 | ||||||
| 1325 | /* | |||||
| 1326 | * action routines | |||||
| 1327 | */ | |||||
| 1328 | ||||||
| 1329 | /* | |||||
| 1330 | * help | |||||
| 1331 | */ | |||||
| 1332 | int | |||||
| 1333 | print_help(FILE *fp, const char *cmd, const char *line_prefix) | |||||
| 1334 | { | |||||
| 1335 | CommandTable *ct; | |||||
| 1336 | int n = 0; | |||||
| 1337 | ||||||
| 1338 | if (!line_prefix) line_prefix = ""; | |||||
| 1339 | ||||||
| 1340 | if (!cmd) { /* if no cmd, print all help */ | |||||
| 1341 | for (ct = command_table; ct->name; ct++) { | |||||
| 1342 | fprintf (fp, "%s%s\n", line_prefix, ct->helptext); | |||||
| 1343 | n++; | |||||
| 1344 | } | |||||
| 1345 | } else { | |||||
| 1346 | int len = strlen (cmd); | |||||
| 1347 | for (ct = command_table; ct->name; ct++) { | |||||
| 1348 | if (strncmp (cmd, ct->name, len) == 0) { | |||||
| 1349 | fprintf (fp, "%s%s\n", line_prefix, ct->helptext); | |||||
| 1350 | n++; | |||||
| 1351 | } | |||||
| 1352 | } | |||||
| 1353 | } | |||||
| 1354 | ||||||
| 1355 | return n; | |||||
| 1356 | } | |||||
| 1357 | ||||||
| 1358 | static int | |||||
| 1359 | do_help(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1360 | { | |||||
| 1361 | const char *cmd = (argc > 1 ? argv[1] : NULL((void*)0)); | |||||
| 1362 | int n; | |||||
| 1363 | ||||||
| 1364 | n = print_help (stdout__stdoutp, cmd, " "); /* a nice amount */ | |||||
| 1365 | ||||||
| 1366 | if (n < 0 || (n == 0 && !cmd)) { | |||||
| 1367 | prefix (inputfilename, lineno); | |||||
| 1368 | fprintf (stderr__stderrp, "internal error with help"); | |||||
| 1369 | if (cmd) { | |||||
| 1370 | fprintf (stderr__stderrp, " on command \"%s\"", cmd); | |||||
| 1371 | } | |||||
| 1372 | fprintf (stderr__stderrp, "\n"); | |||||
| 1373 | return 1; | |||||
| 1374 | } | |||||
| 1375 | ||||||
| 1376 | if (n == 0) { | |||||
| 1377 | prefix (inputfilename, lineno); | |||||
| 1378 | /* already know that cmd is set in this case */ | |||||
| 1379 | fprintf (stderr__stderrp, "no help for noexistent command \"%s\"\n", cmd); | |||||
| 1380 | } | |||||
| 1381 | ||||||
| 1382 | return 0; | |||||
| 1383 | } | |||||
| 1384 | ||||||
| 1385 | /* | |||||
| 1386 | * questionmark | |||||
| 1387 | */ | |||||
| 1388 | /* ARGSUSED */ | |||||
| 1389 | static int | |||||
| 1390 | do_questionmark(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1391 | { | |||||
| 1392 | CommandTable *ct; | |||||
| 1393 | int i; | |||||
| 1394 | #define WIDEST_COLUMN72 72 | |||||
| 1395 | int col = WIDEST_COLUMN72; | |||||
| 1396 | ||||||
| 1397 | printf ("Commands:\n"); | |||||
| 1398 | for (ct = command_table; ct->name; ct++) { | |||||
| 1399 | if ((col + ct->maxlen) > WIDEST_COLUMN72) { | |||||
| 1400 | if (ct != command_table) { | |||||
| 1401 | putc ('\n', stdout__stdoutp); | |||||
| 1402 | } | |||||
| 1403 | fputs (" ", stdout__stdoutp); | |||||
| 1404 | col = 8; /* length of string above */ | |||||
| 1405 | } | |||||
| 1406 | fputs (ct->name, stdout__stdoutp); | |||||
| 1407 | col += ct->maxlen; | |||||
| 1408 | for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH10; i++) { | |||||
| 1409 | putc (' ', stdout__stdoutp); | |||||
| 1410 | col++; | |||||
| 1411 | } | |||||
| 1412 | } | |||||
| 1413 | if (col != 0) { | |||||
| 1414 | putc ('\n', stdout__stdoutp); | |||||
| 1415 | } | |||||
| 1416 | ||||||
| 1417 | /* allow bad lines since this is help */ | |||||
| 1418 | return 0; | |||||
| 1419 | } | |||||
| 1420 | ||||||
| 1421 | /* | |||||
| 1422 | * version | |||||
| 1423 | */ | |||||
| 1424 | /* ARGSUSED */ | |||||
| 1425 | static int | |||||
| 1426 | do_version(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1427 | { | |||||
| 1428 | puts (PACKAGE_VERSION"1.0.9"); | |||||
| 1429 | return 0; | |||||
| 1430 | } | |||||
| 1431 | ||||||
| 1432 | /* | |||||
| 1433 | * list [displayname ...] | |||||
| 1434 | */ | |||||
| 1435 | static int | |||||
| 1436 | do_list (const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1437 | { | |||||
| 1438 | struct _list_data ld; | |||||
| 1439 | ||||||
| 1440 | ld.fp = stdout__stdoutp; | |||||
| 1441 | ld.numeric = (argv[0][0] == 'n'); | |||||
| 1442 | ||||||
| 1443 | if (argc == 1) { | |||||
| 1444 | register AuthList *l; | |||||
| 1445 | ||||||
| 1446 | if (xauth_head) { | |||||
| 1447 | for (l = xauth_head; l; l = l->next) { | |||||
| 1448 | dump_entry (inputfilename, lineno, l->auth, (char *) &ld); | |||||
| 1449 | } | |||||
| 1450 | } | |||||
| 1451 | return 0; | |||||
| 1452 | } | |||||
| 1453 | ||||||
| 1454 | return iterdpy (inputfilename, lineno, 1, argc, argv, | |||||
| 1455 | dump_entry, NULL((void*)0), (char *) &ld); | |||||
| 1456 | } | |||||
| 1457 | ||||||
| 1458 | /* | |||||
| 1459 | * merge filename [filename ...] | |||||
| 1460 | */ | |||||
| 1461 | static int | |||||
| 1462 | do_merge(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1463 | { | |||||
| 1464 | int i; | |||||
| 1465 | int errors = 0; | |||||
| 1466 | AuthList *head, *tail, *listhead, *listtail; | |||||
| 1467 | int nentries, nnew, nrepl; | |||||
| 1468 | Boolint numeric = False0; | |||||
| 1469 | ||||||
| 1470 | if (argc < 2) { | |||||
| 1471 | prefix (inputfilename, lineno); | |||||
| 1472 | badcommandline (argv[0]); | |||||
| 1473 | return 1; | |||||
| 1474 | } | |||||
| 1475 | ||||||
| 1476 | if (argv[0][0] == 'n') numeric = True1; | |||||
| 1477 | listhead = listtail = NULL((void*)0); | |||||
| 1478 | ||||||
| 1479 | for (i = 1; i < argc; i++) { | |||||
| 1480 | const char *filename = argv[i]; | |||||
| 1481 | FILE *fp; | |||||
| 1482 | Boolint used_stdin = False0; | |||||
| 1483 | ||||||
| 1484 | fp = open_file (&filename, | |||||
| 1485 | numeric ? "r" : "rb", | |||||
| 1486 | &used_stdin, inputfilename, lineno, | |||||
| 1487 | argv[0]); | |||||
| 1488 | if (!fp) { | |||||
| 1489 | errors++; | |||||
| 1490 | continue; | |||||
| 1491 | } | |||||
| 1492 | ||||||
| 1493 | head = tail = NULL((void*)0); | |||||
| 1494 | nentries = read_auth_entries (fp, numeric, &head, &tail); | |||||
| 1495 | if (nentries == 0) { | |||||
| 1496 | prefix (inputfilename, lineno); | |||||
| 1497 | fprintf (stderr__stderrp, "unable to read any entries from file \"%s\"\n", | |||||
| 1498 | filename); | |||||
| 1499 | errors++; | |||||
| 1500 | } else { /* link it in */ | |||||
| 1501 | add_to_list (listhead, listtail, head){if (listtail) (listtail)->next = (head); else (listhead) = (head); (listtail) = (head);}; | |||||
| 1502 | } | |||||
| 1503 | ||||||
| 1504 | if (!used_stdin) (void) fclose (fp); | |||||
| 1505 | } | |||||
| 1506 | ||||||
| 1507 | /* | |||||
| 1508 | * if we have new entries, merge them in (freeing any duplicates) | |||||
| 1509 | */ | |||||
| 1510 | if (listhead) { | |||||
| 1511 | nentries = merge_entries (&xauth_head, listhead, &nnew, &nrepl); | |||||
| 1512 | if (verbose) | |||||
| 1513 | printf ("%d entries read in: %d new, %d replacement%s\n", | |||||
| 1514 | nentries, nnew, nrepl, nrepl != 1 ? "s" : ""); | |||||
| 1515 | if (nentries > 0) xauth_modified = True1; | |||||
| 1516 | } | |||||
| 1517 | ||||||
| 1518 | return 0; | |||||
| 1519 | } | |||||
| 1520 | ||||||
| 1521 | /* | |||||
| 1522 | * extract filename displayname [displayname ...] | |||||
| 1523 | */ | |||||
| 1524 | static int | |||||
| 1525 | do_extract(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1526 | { | |||||
| 1527 | int errors; | |||||
| 1528 | struct _extract_data ed; | |||||
| 1529 | ||||||
| 1530 | if (argc < 3) { | |||||
| 1531 | prefix (inputfilename, lineno); | |||||
| 1532 | badcommandline (argv[0]); | |||||
| 1533 | return 1; | |||||
| 1534 | } | |||||
| 1535 | ||||||
| 1536 | ed.fp = NULL((void*)0); | |||||
| 1537 | ed.filename = argv[1]; | |||||
| 1538 | ed.used_stdout = False0; | |||||
| 1539 | ed.numeric = (argv[0][0] == 'n'); | |||||
| 1540 | ed.nwritten = 0; | |||||
| 1541 | ed.cmd = argv[0]; | |||||
| 1542 | ||||||
| 1543 | errors = iterdpy (inputfilename, lineno, 2, argc, argv, | |||||
| 1544 | extract_entry, NULL((void*)0), (char *) &ed); | |||||
| 1545 | ||||||
| 1546 | if (!ed.fp) { | |||||
| 1547 | fprintf (stderr__stderrp, | |||||
| 1548 | "No matches found, authority file \"%s\" not written\n", | |||||
| 1549 | ed.filename); | |||||
| 1550 | } else { | |||||
| 1551 | if (verbose) { | |||||
| 1552 | printf ("%d entries written to \"%s\"\n", | |||||
| 1553 | ed.nwritten, ed.filename); | |||||
| 1554 | } | |||||
| 1555 | if (!ed.used_stdout) { | |||||
| 1556 | (void) fclose (ed.fp); | |||||
| 1557 | } | |||||
| 1558 | } | |||||
| 1559 | ||||||
| 1560 | return errors; | |||||
| 1561 | } | |||||
| 1562 | ||||||
| 1563 | ||||||
| 1564 | /* | |||||
| 1565 | * add displayname protocolname hexkey | |||||
| 1566 | */ | |||||
| 1567 | ||||||
| 1568 | static int | |||||
| 1569 | do_add(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1570 | { | |||||
| 1571 | int n, nnew, nrepl; | |||||
| 1572 | int len; | |||||
| 1573 | const char *dpyname; | |||||
| 1574 | const char *protoname; | |||||
| 1575 | const char *hexkey; | |||||
| 1576 | char *key; | |||||
| 1577 | AuthList *list, *list_cur, *list_next; | |||||
| 1578 | ||||||
| 1579 | if (argc != 4 || !argv[1] || !argv[2] || !argv[3]) { | |||||
| 1580 | prefix (inputfilename, lineno); | |||||
| 1581 | badcommandline (argv[0]); | |||||
| 1582 | return 1; | |||||
| 1583 | } | |||||
| 1584 | ||||||
| 1585 | dpyname = argv[1]; | |||||
| 1586 | protoname = argv[2]; | |||||
| 1587 | hexkey = argv[3]; | |||||
| 1588 | ||||||
| 1589 | len = strlen(hexkey); | |||||
| 1590 | if (hexkey[0] == '"' && hexkey[len-1] == '"') { | |||||
| 1591 | key = malloc(len-1); | |||||
| 1592 | strncpy(key, hexkey+1, len-2)__builtin___strncpy_chk (key, hexkey+1, len-2, __builtin_object_size (key, 2 > 1 ? 1 : 0)); | |||||
| 1593 | len -= 2; | |||||
| 1594 | } else if (!strcmp(protoname, SECURERPC"SUN-DES-1") || | |||||
| 1595 | !strcmp(protoname, K5AUTH"MIT-KERBEROS-5")) { | |||||
| 1596 | key = malloc(len+1); | |||||
| 1597 | strcpy(key, hexkey)__builtin___strcpy_chk (key, hexkey, __builtin_object_size (key , 2 > 1 ? 1 : 0)); | |||||
| 1598 | } else { | |||||
| 1599 | len = cvthexkey (hexkey, &key); | |||||
| 1600 | if (len < 0) { | |||||
| 1601 | prefix (inputfilename, lineno); | |||||
| 1602 | fprintf (stderr__stderrp, | |||||
| 1603 | "key contains odd number of or non-hex characters\n"); | |||||
| 1604 | return 1; | |||||
| 1605 | } | |||||
| 1606 | } | |||||
| 1607 | ||||||
| 1608 | if (!get_displayname_auth (dpyname, &list)) { | |||||
| 1609 | prefix (inputfilename, lineno); | |||||
| 1610 | baddisplayname (dpyname, argv[0]); | |||||
| 1611 | free (key); | |||||
| 1612 | return 1; | |||||
| 1613 | } | |||||
| 1614 | ||||||
| 1615 | /* | |||||
| 1616 | * allow an abbreviation for common protocol names | |||||
| 1617 | */ | |||||
| 1618 | if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV".") == 0) { | |||||
| 1619 | protoname = DEFAULT_PROTOCOL"MIT-MAGIC-COOKIE-1"; | |||||
| 1620 | } | |||||
| 1621 | ||||||
| 1622 | for (list_cur = list; list_cur != NULL((void*)0); list_cur = list_cur->next) { | |||||
| 1623 | Xauth *auth = list_cur->auth; | |||||
| 1624 | ||||||
| 1625 | auth->name_length = strlen (protoname); | |||||
| 1626 | auth->name = copystring (protoname, auth->name_length); | |||||
| 1627 | if (!auth->name) { | |||||
| 1628 | prefix (inputfilename, lineno); | |||||
| 1629 | fprintf (stderr__stderrp, "unable to allocate %d character protocol name\n", | |||||
| 1630 | auth->name_length); | |||||
| 1631 | for (list_cur = list; list_cur != NULL((void*)0); list_cur = list_next) { | |||||
| 1632 | list_next = list_cur->next; | |||||
| 1633 | XauDisposeAuth(list_cur->auth); | |||||
| 1634 | free(list_cur); | |||||
| 1635 | } | |||||
| 1636 | free (key); | |||||
| 1637 | return 1; | |||||
| 1638 | } | |||||
| 1639 | auth->data_length = len; | |||||
| 1640 | auth->data = malloc(len); | |||||
| 1641 | if (!auth->data) { | |||||
| 1642 | prefix(inputfilename, lineno); | |||||
| 1643 | fprintf(stderr__stderrp, "unable to allocate %d bytes for key\n", len); | |||||
| 1644 | for (list_cur = list; list_cur != NULL((void*)0); list_cur = list_next) { | |||||
| 1645 | list_next = list_cur->next; | |||||
| 1646 | XauDisposeAuth(list_cur->auth); | |||||
| 1647 | free(list_cur); | |||||
| 1648 | } | |||||
| 1649 | free(key); | |||||
| 1650 | return 1; | |||||
| 1651 | } | |||||
| 1652 | memcpy(auth->data, key, len)__builtin___memcpy_chk (auth->data, key, len, __builtin_object_size (auth->data, 0)); | |||||
| 1653 | } | |||||
| 1654 | free(key); | |||||
| 1655 | /* | |||||
| 1656 | * merge it in; note that merge will deal with allocation | |||||
| 1657 | */ | |||||
| 1658 | n = merge_entries (&xauth_head, list, &nnew, &nrepl); | |||||
| 1659 | if (n <= 0) { | |||||
| 1660 | prefix (inputfilename, lineno); | |||||
| 1661 | fprintf (stderr__stderrp, "unable to merge in added record\n"); | |||||
| 1662 | return 1; | |||||
| 1663 | } | |||||
| 1664 | ||||||
| 1665 | xauth_modified = True1; | |||||
| 1666 | return 0; | |||||
| 1667 | } | |||||
| 1668 | ||||||
| 1669 | /* | |||||
| 1670 | * remove displayname | |||||
| 1671 | */ | |||||
| 1672 | static int | |||||
| 1673 | do_remove(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1674 | { | |||||
| 1675 | int nremoved = 0; | |||||
| 1676 | int errors; | |||||
| 1677 | ||||||
| 1678 | if (argc < 2) { | |||||
| 1679 | prefix (inputfilename, lineno); | |||||
| 1680 | badcommandline (argv[0]); | |||||
| 1681 | return 1; | |||||
| 1682 | } | |||||
| 1683 | ||||||
| 1684 | errors = iterdpy (inputfilename, lineno, 1, argc, argv, | |||||
| 1685 | remove_entry, NULL((void*)0), (char *) &nremoved); | |||||
| 1686 | if (verbose) printf ("%d entries removed\n", nremoved); | |||||
| 1687 | return errors; | |||||
| 1688 | } | |||||
| 1689 | ||||||
| 1690 | /* | |||||
| 1691 | * info | |||||
| 1692 | */ | |||||
| 1693 | static int | |||||
| 1694 | do_info(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1695 | { | |||||
| 1696 | int n; | |||||
| 1697 | AuthList *l; | |||||
| 1698 | ||||||
| 1699 | if (argc != 1) { | |||||
| 1700 | prefix (inputfilename, lineno); | |||||
| 1701 | badcommandline (argv[0]); | |||||
| 1702 | return 1; | |||||
| 1703 | } | |||||
| 1704 | ||||||
| 1705 | for (l = xauth_head, n = 0; l; l = l->next, n++) ; | |||||
| 1706 | ||||||
| 1707 | printf ("Authority file: %s\n", | |||||
| 1708 | xauth_filename ? xauth_filename : "(none)"); | |||||
| 1709 | printf ("File new: %s\n", xauth_existed ? No : Yes); | |||||
| 1710 | printf ("File locked: %s\n", xauth_locked ? No : Yes); | |||||
| 1711 | printf ("Number of entries: %d\n", n); | |||||
| 1712 | printf ("Changes honored: %s\n", xauth_allowed ? Yes : No); | |||||
| 1713 | printf ("Changes made: %s\n", xauth_modified ? Yes : No); | |||||
| 1714 | printf ("Current input: %s:%d\n", inputfilename, lineno); | |||||
| 1715 | return 0; | |||||
| 1716 | } | |||||
| 1717 | ||||||
| 1718 | ||||||
| 1719 | /* | |||||
| 1720 | * exit | |||||
| 1721 | */ | |||||
| 1722 | static Boolint alldone = False0; | |||||
| 1723 | ||||||
| 1724 | /* ARGSUSED */ | |||||
| 1725 | static int | |||||
| 1726 | do_exit(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1727 | { | |||||
| 1728 | /* allow bogus stuff */ | |||||
| 1729 | alldone = True1; | |||||
| 1730 | return 0; | |||||
| 1731 | } | |||||
| 1732 | ||||||
| 1733 | /* | |||||
| 1734 | * quit | |||||
| 1735 | */ | |||||
| 1736 | /* ARGSUSED */ | |||||
| 1737 | static int | |||||
| 1738 | do_quit(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1739 | { | |||||
| 1740 | /* allow bogus stuff */ | |||||
| 1741 | die (0); | |||||
| 1742 | /* NOTREACHED */ | |||||
| 1743 | return -1; /* for picky compilers */ | |||||
| 1744 | } | |||||
| 1745 | ||||||
| 1746 | ||||||
| 1747 | /* | |||||
| 1748 | * source filename | |||||
| 1749 | */ | |||||
| 1750 | static int | |||||
| 1751 | do_source(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1752 | { | |||||
| 1753 | const char *script; | |||||
| 1754 | char buf[BUFSIZ1024]; | |||||
| 1755 | FILE *fp; | |||||
| 1756 | Boolint used_stdin = False0; | |||||
| 1757 | int len; | |||||
| 1758 | int errors = 0, status; | |||||
| 1759 | int sublineno = 0; | |||||
| 1760 | const char **subargv; | |||||
| 1761 | int subargc; | |||||
| 1762 | Boolint prompt = False0; /* only true if reading from tty */ | |||||
| 1763 | ||||||
| 1764 | if (argc != 2 || !argv[1]) { | |||||
| 1765 | prefix (inputfilename, lineno); | |||||
| 1766 | badcommandline (argv[0]); | |||||
| 1767 | return 1; | |||||
| 1768 | } | |||||
| 1769 | ||||||
| 1770 | script = argv[1]; | |||||
| 1771 | ||||||
| 1772 | fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]); | |||||
| 1773 | if (!fp) { | |||||
| 1774 | return 1; | |||||
| 1775 | } | |||||
| 1776 | ||||||
| 1777 | if (verbose && used_stdin && isatty (fileno (fp))) prompt = True1; | |||||
| 1778 | ||||||
| 1779 | while (!alldone) { | |||||
| 1780 | buf[0] = '\0'; | |||||
| 1781 | if (prompt) { | |||||
| 1782 | printf ("xauth> "); | |||||
| 1783 | fflush (stdout__stdoutp); | |||||
| 1784 | } | |||||
| 1785 | if (fgets (buf, sizeof buf, fp) == NULL((void*)0)) break; | |||||
| 1786 | sublineno++; | |||||
| 1787 | len = strlen (buf); | |||||
| 1788 | if (len == 0 || buf[0] == '#') continue; | |||||
| 1789 | if (buf[len-1] != '\n') { | |||||
| 1790 | prefix (script, sublineno); | |||||
| 1791 | fprintf (stderr__stderrp, "line too long\n"); | |||||
| 1792 | errors++; | |||||
| 1793 | break; | |||||
| 1794 | } | |||||
| 1795 | buf[--len] = '\0'; /* remove new line */ | |||||
| 1796 | subargv = (const char **) split_into_words (buf, &subargc); | |||||
| 1797 | if (subargv) { | |||||
| 1798 | status = process_command (script, sublineno, subargc, subargv); | |||||
| 1799 | free (subargv); | |||||
| 1800 | errors += status; | |||||
| 1801 | } else { | |||||
| 1802 | prefix (script, sublineno); | |||||
| 1803 | fprintf (stderr__stderrp, "unable to break line into words\n"); | |||||
| 1804 | errors++; | |||||
| 1805 | } | |||||
| 1806 | } | |||||
| 1807 | ||||||
| 1808 | if (!used_stdin) { | |||||
| 1809 | (void) fclose (fp); | |||||
| 1810 | } | |||||
| 1811 | return errors; | |||||
| 1812 | } | |||||
| 1813 | ||||||
| 1814 | static int x_protocol_error; | |||||
| 1815 | static int | |||||
| 1816 | catch_x_protocol_error(Display *dpy, XErrorEvent *errevent) | |||||
| 1817 | { | |||||
| 1818 | char buf[80]; | |||||
| 1819 | XGetErrorText(dpy, errevent->error_code, buf, sizeof (buf)); | |||||
| 1820 | fprintf(stderr__stderrp, "%s\n", buf); | |||||
| 1821 | x_protocol_error = errevent->error_code; | |||||
| 1822 | return 1; | |||||
| 1823 | } | |||||
| 1824 | ||||||
| 1825 | /* | |||||
| 1826 | * generate | |||||
| 1827 | */ | |||||
| 1828 | static int | |||||
| 1829 | do_generate(const char *inputfilename, int lineno, int argc, const char **argv) | |||||
| 1830 | { | |||||
| 1831 | const char *displayname; | |||||
| 1832 | int major_version, minor_version; | |||||
| 1833 | XSecurityAuthorization id_return; | |||||
| 1834 | Xauth *auth_in, *auth_return; | |||||
| 1835 | XSecurityAuthorizationAttributes attributes; | |||||
| 1836 | unsigned long attrmask = 0; | |||||
| 1837 | Display *dpy; | |||||
| 1838 | int status; | |||||
| 1839 | const char *args[4]; | |||||
| 1840 | const char *protoname = "."; | |||||
| 1841 | int i; | |||||
| 1842 | int authdatalen = 0; | |||||
| 1843 | const char *hexdata; | |||||
| 1844 | char *authdata = NULL((void*)0); | |||||
| 1845 | char *hex; | |||||
| 1846 | ||||||
| 1847 | if (argc < 2 || !argv[1]) { | |||||
| 1848 | prefix (inputfilename, lineno); | |||||
| 1849 | badcommandline (argv[0]); | |||||
| 1850 | return 1; | |||||
| 1851 | } | |||||
| 1852 | ||||||
| 1853 | displayname = argv[1]; | |||||
| 1854 | ||||||
| 1855 | if (argc > 2) { | |||||
| 1856 | protoname = argv[2]; | |||||
| 1857 | } | |||||
| 1858 | ||||||
| 1859 | for (i = 3; i < argc; i++) { | |||||
| 1860 | if (0 == strcmp(argv[i], "timeout")) { | |||||
| 1861 | if (++i == argc) { | |||||
| 1862 | prefix (inputfilename, lineno); | |||||
| 1863 | badcommandline (argv[i-1]); | |||||
| 1864 | return 1; | |||||
| 1865 | } | |||||
| 1866 | attributes.timeout = atoi(argv[i]); | |||||
| 1867 | attrmask |= XSecurityTimeout(1<<0); | |||||
| 1868 | ||||||
| 1869 | } else if (0 == strcmp(argv[i], "trusted")) { | |||||
| 1870 | attributes.trust_level = XSecurityClientTrusted0; | |||||
| 1871 | attrmask |= XSecurityTrustLevel(1<<1); | |||||
| 1872 | ||||||
| 1873 | } else if (0 == strcmp(argv[i], "untrusted")) { | |||||
| 1874 | attributes.trust_level = XSecurityClientUntrusted1; | |||||
| 1875 | attrmask |= XSecurityTrustLevel(1<<1); | |||||
| 1876 | ||||||
| 1877 | } else if (0 == strcmp(argv[i], "group")) { | |||||
| 1878 | if (++i == argc) { | |||||
| 1879 | prefix (inputfilename, lineno); | |||||
| 1880 | badcommandline (argv[i-1]); | |||||
| 1881 | return 1; | |||||
| 1882 | } | |||||
| 1883 | attributes.group = atoi(argv[i]); | |||||
| 1884 | attrmask |= XSecurityGroup(1<<2); | |||||
| 1885 | ||||||
| 1886 | } else if (0 == strcmp(argv[i], "data")) { | |||||
| 1887 | if (++i == argc) { | |||||
| 1888 | prefix (inputfilename, lineno); | |||||
| 1889 | badcommandline (argv[i-1]); | |||||
| 1890 | return 1; | |||||
| 1891 | } | |||||
| 1892 | hexdata = argv[i]; | |||||
| 1893 | authdatalen = strlen(hexdata); | |||||
| 1894 | if (hexdata[0] == '"' && hexdata[authdatalen-1] == '"') { | |||||
| 1895 | authdata = malloc(authdatalen-1); | |||||
| 1896 | strncpy(authdata, hexdata+1, authdatalen-2)__builtin___strncpy_chk (authdata, hexdata+1, authdatalen-2, __builtin_object_size (authdata, 2 > 1 ? 1 : 0)); | |||||
| 1897 | authdatalen -= 2; | |||||
| 1898 | } else { | |||||
| 1899 | authdatalen = cvthexkey (hexdata, &authdata); | |||||
| 1900 | if (authdatalen < 0) { | |||||
| 1901 | prefix (inputfilename, lineno); | |||||
| 1902 | fprintf (stderr__stderrp, | |||||
| 1903 | "data contains odd number of or non-hex characters\n"); | |||||
| 1904 | return 1; | |||||
| 1905 | } | |||||
| 1906 | } | |||||
| 1907 | } else { | |||||
| 1908 | prefix (inputfilename, lineno); | |||||
| 1909 | badcommandline (argv[i]); | |||||
| 1910 | return 1; | |||||
| 1911 | } | |||||
| 1912 | } | |||||
| 1913 | ||||||
| 1914 | /* generate authorization using the Security extension */ | |||||
| 1915 | ||||||
| 1916 | dpy = XOpenDisplay (displayname); | |||||
| 1917 | if (!dpy) { | |||||
| 1918 | prefix (inputfilename, lineno); | |||||
| 1919 | fprintf (stderr__stderrp, "unable to open display \"%s\".\n", displayname); | |||||
| 1920 | return 1; | |||||
| 1921 | } | |||||
| 1922 | ||||||
| 1923 | status = XSecurityQueryExtension(dpy, &major_version, &minor_version); | |||||
| 1924 | if (!status) | |||||
| 1925 | { | |||||
| 1926 | prefix (inputfilename, lineno); | |||||
| 1927 | fprintf (stderr__stderrp, "couldn't query Security extension on display \"%s\"\n", | |||||
| 1928 | displayname); | |||||
| 1929 | return 1; | |||||
| 1930 | } | |||||
| 1931 | ||||||
| 1932 | /* fill in input Xauth struct */ | |||||
| 1933 | ||||||
| 1934 | auth_in = XSecurityAllocXauth(); | |||||
| 1935 | if (strcmp (protoname, DEFAULT_PROTOCOL_ABBREV".") == 0) { | |||||
| 1936 | auth_in->name = copystring(DEFAULT_PROTOCOL"MIT-MAGIC-COOKIE-1", strlen(DEFAULT_PROTOCOL"MIT-MAGIC-COOKIE-1")); | |||||
| 1937 | } | |||||
| 1938 | else | |||||
| 1939 | auth_in->name = copystring (protoname, strlen(protoname)); | |||||
| 1940 | auth_in->name_length = strlen(auth_in->name); | |||||
| 1941 | auth_in->data = authdata; | |||||
| 1942 | auth_in->data_length = authdatalen; | |||||
| 1943 | ||||||
| 1944 | x_protocol_error = 0; | |||||
| 1945 | XSetErrorHandler(catch_x_protocol_error); | |||||
| 1946 | auth_return = XSecurityGenerateAuthorization(dpy, auth_in, attrmask, | |||||
| 1947 | &attributes, &id_return); | |||||
| 1948 | XSync(dpy, False0); | |||||
| 1949 | ||||||
| 1950 | if (!auth_return || x_protocol_error) | |||||
| 1951 | { | |||||
| 1952 | prefix (inputfilename, lineno); | |||||
| 1953 | fprintf (stderr__stderrp, "couldn't generate authorization\n"); | |||||
| 1954 | return 1; | |||||
| 1955 | } | |||||
| 1956 | ||||||
| 1957 | if (verbose) | |||||
| 1958 | printf("authorization id is %ld\n", id_return); | |||||
| 1959 | ||||||
| 1960 | /* create a fake input line to give to do_add */ | |||||
| 1961 | hex = bintohex(auth_return->data_length, auth_return->data); | |||||
| 1962 | args[0] = "add"; | |||||
| 1963 | args[1] = displayname; | |||||
| 1964 | args[2] = auth_in->name; | |||||
| 1965 | args[3] = hex; | |||||
| 1966 | ||||||
| 1967 | status = do_add(inputfilename, lineno, 4, args); | |||||
| 1968 | ||||||
| 1969 | if (authdata) free(authdata); | |||||
| 1970 | XSecurityFreeXauth(auth_in); | |||||
| 1971 | XSecurityFreeXauth(auth_return); | |||||
| 1972 | free(hex); | |||||
| 1973 | XCloseDisplay(dpy); | |||||
| 1974 | return status; | |||||
| 1975 | } |