3 Copyright 1989, 1998 The Open Group
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
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 * Original Author of "xauth" : Jim Fulton, MIT X Consortium
26 * Modified into "iceauth" : Ralph Mor, X Consortium
32 #include <sys/types.h>
36 #define SECURERPC "SUN-DES-1"
37 #define K5AUTH "KERBEROS-V5-1"
39 #define ICEAUTH_DEFAULT_RETRIES 10 /* number of competitors we expect */
40 #define ICEAUTH_DEFAULT_TIMEOUT 2 /* in seconds, be quick */
41 #define ICEAUTH_DEFAULT_DEADTIME 600L /* 10 minutes in seconds */
43 typedef struct _AuthList { /* linked list of entries */
44 struct _AuthList *next;
45 IceAuthFileEntry *auth;
48 #define add_to_list(h,t,e) {if (t) (t)->next = (e); else (h) = (e); (t) = (e);}
50 typedef int (*ProcessFunc)(const char *, int, int, char **);
51 typedef int (*DoFunc)(const char *, int, IceAuthFileEntry *, char *);
53 typedef struct _CommandTable { /* commands that are understood */
54 char *name; /* full name */
55 int minlen; /* unique prefix */
56 int maxlen; /* strlen(name) */
57 ProcessFunc processfunc; /* handler */
58 char *helptext; /* what to print for help */
61 struct _extract_data { /* for iterating */
62 FILE *fp; /* input source */
63 char *filename; /* name of input */
64 Bool used_stdout; /* whether or not need to close */
65 int nwritten; /* number of entries written */
66 char *cmd; /* for error messages */
69 struct _list_data { /* for iterating */
70 FILE *fp; /* output file */
77 static char *stdin_filename = "(stdin)"; /* for messages */
78 static char *stdout_filename = "(stdout)"; /* for messages */
79 static const char *Yes = "yes"; /* for messages */
80 static const char *No = "no"; /* for messages */
82 static int binaryEqual ( const char *a, const char *b, unsigned len );
83 static void prefix ( const char *fn, int n );
84 static void badcommandline ( const char *cmd );
85 static char *skip_space ( char *s );
86 static char *skip_nonspace ( char *s );
87 static char **split_into_words ( char *src, int *argcp );
88 static FILE *open_file ( char **filenamep, const char *mode, Bool *usedstdp, const char *srcfn, int srcln, const char *cmd );
89 static int read_auth_entries ( FILE *fp, AuthList **headp, AuthList **tailp );
90 static int cvthexkey ( char *hexstr, char **ptrp );
91 static int dispatch_command ( const char *inputfilename, int lineno, int argc, char **argv, const CommandTable *tab, int *statusp );
92 static void die ( int sig );
93 static void catchsig ( int sig );
94 static void register_signals ( void );
95 static int write_auth_file ( char *tmp_nam, size_t tmp_nam_len );
96 static void fprintfhex ( FILE *fp, unsigned int len, const char *cp );
97 static int dump_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, char *data );
98 static int extract_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, char *data );
99 static int match_auth ( IceAuthFileEntry *a, IceAuthFileEntry *b, int *authDataSame );
100 static int merge_entries ( AuthList **firstp, AuthList *second, int *nnewp, int *nreplp, int *ndupp );
101 static int search_and_do ( const char *inputfilename, int lineno, int start, int argc, char *argv[], DoFunc do_func, char *data );
102 static int remove_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, char *data );
103 static int do_help ( const char *inputfilename, int lineno, int argc, char **argv );
104 static int do_questionmark ( const char *inputfilename, int lineno, int argc, char **argv );
105 static int do_list ( const char *inputfilename, int lineno, int argc, char **argv );
106 static int do_merge ( const char *inputfilename, int lineno, int argc, char **argv );
107 static int do_extract ( const char *inputfilename, int lineno, int argc, char **argv );
108 static int do_add ( const char *inputfilename, int lineno, int argc, char **argv );
109 static int do_remove ( const char *inputfilename, int lineno, int argc, char **argv );
110 static int do_info ( const char *inputfilename, int lineno, int argc, char **argv );
111 static int do_exit ( const char *inputfilename, int lineno, int argc, char **argv );
112 static int do_quit ( const char *inputfilename, int lineno, int argc, char **argv );
113 static int do_source ( const char *inputfilename, int lineno, int argc, char **argv );
115 static const CommandTable command_table[] = { /* table of known commands */
116 { "add", 2, 3, do_add,
119 add protoname protodata netid authname authdata"
122 { "exit", 3, 4, do_exit,
124 exit save changes and exit program"
127 { "extract", 3, 7, do_extract,
129 extract extract entries into file\n\
130 extract filename <protoname=$> <protodata=$> <netid=$> <authname=$>"
133 { "help", 1, 4, do_help,
139 { "info", 1, 4, do_info,
141 info print information about entries"
144 { "list", 1, 4, do_list,
147 list <protoname=$> <protodata=$> <netid=$> <authname=$>"
150 { "merge", 1, 5, do_merge,
152 merge merge entries from files\n\
153 merge filename1 <filename2> <filename3> ..."
156 { "quit", 1, 4, do_quit,
158 quit abort changes and exit program" },
160 { "remove", 1, 6, do_remove,
162 remove remove entries\n\
163 remove <protoname=$> <protodata=$> <netid=$> <authname=$>"
166 { "source", 1, 6, do_source,
168 source read commands from file\n\
172 { "?", 1, 1, do_questionmark,
174 ? list available commands" },
176 { NULL, 0, 0, NULL, NULL },
179 #define COMMAND_NAMES_PADDED_WIDTH 10 /* wider than anything above */
182 static Bool okay_to_use_stdin = True; /* set to false after using */
184 static const char * const hex_table[] = { /* for printing hex digits */
185 "00", "01", "02", "03", "04", "05", "06", "07",
186 "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
187 "10", "11", "12", "13", "14", "15", "16", "17",
188 "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
189 "20", "21", "22", "23", "24", "25", "26", "27",
190 "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
191 "30", "31", "32", "33", "34", "35", "36", "37",
192 "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
193 "40", "41", "42", "43", "44", "45", "46", "47",
194 "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
195 "50", "51", "52", "53", "54", "55", "56", "57",
196 "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
197 "60", "61", "62", "63", "64", "65", "66", "67",
198 "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
199 "70", "71", "72", "73", "74", "75", "76", "77",
200 "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
201 "80", "81", "82", "83", "84", "85", "86", "87",
202 "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
203 "90", "91", "92", "93", "94", "95", "96", "97",
204 "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
205 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
206 "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
207 "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7",
208 "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
209 "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7",
210 "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
211 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
212 "d8", "d9", "da", "db", "dc", "dd", "de", "df",
213 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7",
214 "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
215 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
216 "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff",
219 static unsigned int hexvalues[256]; /* for parsing hex input */
221 static mode_t original_umask = 0; /* for restoring */
225 * private utility procedures
228 #define copystring(s) ( s != NULL ? strdup(s) : NULL )
232 register const char *a,
233 register const char *b,
234 register unsigned len)
243 static void prefix (const char *fn, int n)
245 fprintf (stderr, "%s: %s:%d: ", ProgramName, fn, n);
248 static void badcommandline (const char *cmd)
250 fprintf (stderr, "bad \"%s\" command line\n", cmd);
253 static char *skip_space (register char *s)
257 for ( ; *s && isascii(*s) && isspace(*s); s++)
263 static char *skip_nonspace (register char *s)
267 /* put quoting into loop if need be */
268 for ( ; *s && isascii(*s) && !isspace(*s); s++)
273 static char **split_into_words ( /* argvify string */
283 #define WORDSTOALLOC 4 /* most lines are short */
284 argv = (char **) malloc (WORDSTOALLOC * sizeof (char *));
285 if (!argv) return NULL;
287 total = WORDSTOALLOC;
290 * split the line up into separate, nul-terminated tokens; the last
291 * "token" will point to the empty string so that it can be bashed into
296 jword = skip_space (src);
297 src = skip_nonspace (jword);
301 total += WORDSTOALLOC;
302 argv = (char **) realloc (argv, total * sizeof (char *));
303 if (!argv) return NULL;
306 if (savec) src++; /* if not last on line advance */
307 } while (jword != src);
309 argv[--cur] = NULL; /* smash empty token to end list */
315 static FILE *open_file (
325 if (strcmp (*filenamep, "-") == 0) {
327 /* select std descriptor to use */
328 if (mode[0] == 'r') {
329 if (okay_to_use_stdin) {
330 okay_to_use_stdin = False;
331 *filenamep = stdin_filename;
334 prefix (srcfn, srcln);
335 fprintf (stderr, "%s: stdin already in use\n", cmd);
339 *filenamep = stdout_filename;
340 return stdout; /* always okay to use stdout */
344 fp = fopen (*filenamep, mode);
346 prefix (srcfn, srcln);
347 fprintf (stderr, "%s: unable to open file %s\n", cmd, *filenamep);
353 static int read_auth_entries (FILE *fp, AuthList **headp, AuthList **tailp)
355 IceAuthFileEntry *auth;
356 AuthList *head, *tail;
361 /* put all records into linked list */
362 while ((auth = IceReadAuthFileEntry (fp)) != NULL) {
363 AuthList *l = (AuthList *) malloc (sizeof (AuthList));
366 "%s: unable to alloc entry reading auth file\n",
372 if (tail) /* if not first time through append */
375 head = l; /* first time through, so assign */
385 static int cvthexkey ( /* turn hex key string into octets */
397 for (s = hexstr; *s; s++) {
398 if (!isascii(*s)) return -1;
399 if (isspace(*s)) continue;
400 if (!isxdigit(*s)) return -1;
404 /* if 0 or odd, then there was an error */
405 if (len == 0 || (len & 1) == 1) return -1;
408 /* now we know that the input is good */
410 retval = malloc (len);
412 fprintf (stderr, "%s: unable to allocate %d bytes for hexkey\n",
417 for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) {
419 if (isspace(c)) continue; /* already know it is ascii */
423 #define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10)))
424 *us = (unsigned char)((atoh(savec) << 4) + atoh(c));
426 savec = 0; /* ready for next character */
437 static int dispatch_command (
438 const char *inputfilename,
442 const CommandTable *tab,
445 const CommandTable *ct;
448 /* scan table for command */
451 for (ct = tab; ct->name; ct++) {
452 /* look for unique prefix */
453 if (n >= ct->minlen && n <= ct->maxlen &&
454 strncmp (cmd, ct->name, n) == 0) {
455 *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv);
465 static AuthList *iceauth_head = NULL; /* list of auth entries */
466 static Bool iceauth_existed = False; /* if was present at initialize */
467 static Bool iceauth_modified = False; /* if added, removed, or merged */
468 static Bool iceauth_allowed = True; /* if allowed to write auth file */
469 static char *iceauth_filename = NULL;
470 static volatile Bool dieing = False;
472 #ifdef RETSIGTYPE /* autoconf AC_TYPE_SIGNAL */
473 # define _signal_t RETSIGTYPE
475 #ifdef SIGNALRETURNSINT
476 #define _signal_t int
478 #define _signal_t void
480 #endif /* RETSIGTYPE */
482 /* poor man's puts(), for under signal handlers */
483 #define WRITES(fd, S) (void)write((fd), (S), strlen((S)))
486 static _signal_t die (int sig)
489 _exit (auth_finalize ());
491 #ifdef SIGNALRETURNSINT
492 return -1; /* for picky compilers */
496 static _signal_t catchsig (int sig)
499 if (sig > 0) signal (sig, die); /* re-establish signal handler */
502 * fileno() might not be reentrant, avoid it if possible, and use
503 * stderr instead of stdout
506 if (verbose && iceauth_modified) WRITES(STDERR_FILENO, "\r\n");
508 if (verbose && iceauth_modified) WRITES(fileno(stderr), "\r\n");
512 #ifdef SIGNALRETURNSINT
513 return -1; /* for picky compilers */
517 static void register_signals (void)
519 signal (SIGINT, catchsig);
520 signal (SIGTERM, catchsig);
522 signal (SIGHUP, catchsig);
529 * public procedures for parsing lines of input
532 int auth_initialize ( char *authfilename )
535 AuthList *head, *tail;
541 bzero ((char *) hexvalues, sizeof hexvalues);
552 hexvalues['a'] = hexvalues['A'] = 0xa;
553 hexvalues['b'] = hexvalues['B'] = 0xb;
554 hexvalues['c'] = hexvalues['C'] = 0xc;
555 hexvalues['d'] = hexvalues['D'] = 0xd;
556 hexvalues['e'] = hexvalues['E'] = 0xe;
557 hexvalues['f'] = hexvalues['F'] = 0xf;
559 if (break_locks && verbose) {
560 printf ("Attempting to break locks on authority file %s\n",
564 iceauth_filename = strdup(authfilename);
567 if (break_locks) IceUnlockAuthFile (authfilename);
569 n = IceLockAuthFile (authfilename, ICEAUTH_DEFAULT_RETRIES,
570 ICEAUTH_DEFAULT_TIMEOUT,
571 (break_locks ? 0L : ICEAUTH_DEFAULT_DEADTIME));
572 if (n != IceAuthLockSuccess) {
573 char *reason = "unknown error";
575 case IceAuthLockError:
578 case IceAuthLockTimeout:
582 fprintf (stderr, "%s: %s in locking authority file %s\n",
583 ProgramName, reason, authfilename);
588 /* these checks can only be done reliably after the file is locked */
589 exists = (access (authfilename, F_OK) == 0);
590 if (exists && access (authfilename, W_OK) != 0) {
592 "%s: %s not writable, changes will be ignored\n",
593 ProgramName, authfilename);
594 iceauth_allowed = False;
597 original_umask = umask (0077); /* disallow non-owner access */
599 authfp = fopen (authfilename, "rb");
601 int olderrno = errno;
603 /* if file there then error */
604 if (access (authfilename, F_OK) == 0) { /* then file does exist! */
607 } /* else ignore it */
609 "%s: creating new authority file %s\n",
610 ProgramName, authfilename);
612 iceauth_existed = True;
613 n = read_auth_entries (authfp, &head, &tail);
614 (void) fclose (authfp);
617 "%s: unable to read auth entries from file \"%s\"\n",
618 ProgramName, authfilename);
624 iceauth_modified = False;
627 printf ("%s authority file %s\n",
628 ignore_locks ? "Ignoring locks on" : "Using", authfilename);
633 static int write_auth_file (char *tmp_nam, size_t tmp_nam_len)
638 if ((strlen(iceauth_filename) + 3) > tmp_nam_len) {
639 strncpy(tmp_nam, "filename too long", tmp_nam_len);
640 tmp_nam[tmp_nam_len - 1] = '\0';
644 strcpy (tmp_nam, iceauth_filename);
645 strcat (tmp_nam, "-n"); /* for new */
646 (void) unlink (tmp_nam);
647 fp = fopen (tmp_nam, "wb"); /* umask is still set to 0077 */
649 fprintf (stderr, "%s: unable to open tmp file \"%s\"\n",
650 ProgramName, tmp_nam);
654 for (list = iceauth_head; list; list = list->next)
655 IceWriteAuthFileEntry (fp, list->auth);
661 int auth_finalize (void)
663 char temp_name[1024]; /* large filename size */
665 if (iceauth_modified) {
669 * called from a signal handler -- printf is *not* reentrant; also
670 * fileno() might not be reentrant, avoid it if possible, and use
671 * stderr instead of stdout
674 WRITES(STDERR_FILENO, "\nAborting changes to authority file ");
675 WRITES(STDERR_FILENO, iceauth_filename);
676 WRITES(STDERR_FILENO, "\n");
678 WRITES(fileno(stderr), "\nAborting changes to authority file ");
679 WRITES(fileno(stderr), iceauth_filename);
680 WRITES(fileno(stderr), "\n");
683 } else if (!iceauth_allowed) {
685 "%s: %s not writable, changes ignored\n",
686 ProgramName, iceauth_filename);
689 printf ("%s authority file %s\n",
690 ignore_locks ? "Ignoring locks and writing" :
691 "Writing", iceauth_filename);
694 if (write_auth_file (temp_name, sizeof(temp_name)) == -1) {
696 "%s: unable to write authority file %s\n",
697 ProgramName, temp_name);
699 (void) unlink (iceauth_filename);
700 #if defined(WIN32) || defined(__UNIXOS2__)
701 if (rename(temp_name, iceauth_filename) == -1)
703 /* Attempt to rename() if link() fails, since this may be on a FS that does not support hard links */
704 if (link (temp_name, iceauth_filename) == -1 && rename(temp_name, iceauth_filename) == -1)
708 "%s: unable to link authority file %s, use %s\n",
709 ProgramName, iceauth_filename, temp_name);
711 (void) unlink (temp_name);
717 if (!ignore_locks && (iceauth_filename != NULL)) {
718 IceUnlockAuthFile (iceauth_filename);
720 (void) umask (original_umask);
724 int process_command (
725 const char *inputfilename,
732 if (argc < 1 || !argv || !argv[0]) return 1;
734 if (dispatch_command (inputfilename, lineno, argc, argv,
735 command_table, &status))
738 prefix (inputfilename, lineno);
739 fprintf (stderr, "unknown command \"%s\"\n", argv[0]);
748 static void fprintfhex (
753 const unsigned char *ucp = (const unsigned char *) cp;
755 for (; len > 0; len--, ucp++) {
756 register const char *s = hex_table[*ucp];
764 static int dump_entry (
765 const char *inputfilename,
767 IceAuthFileEntry *auth,
770 struct _list_data *ld = (struct _list_data *) data;
773 fprintf (fp, "%s", auth->protocol_name);
775 if (auth->protocol_data_length > 0)
776 fprintfhex (fp, auth->protocol_data_length, auth->protocol_data);
778 fprintf (fp, "\"\"");
780 fprintf (fp, "%s", auth->network_id);
782 fprintf (fp, "%s", auth->auth_name);
785 if (auth->auth_data_length == 0)
786 fprintf (fp, "\"\"");
787 else if (!strcmp(auth->auth_name, SECURERPC) ||
788 !strcmp(auth->auth_name, K5AUTH))
789 fwrite (auth->auth_data, sizeof (char), auth->auth_data_length, fp);
791 fprintfhex (fp, auth->auth_data_length, auth->auth_data);
797 static int extract_entry (
798 const char *inputfilename,
800 IceAuthFileEntry *auth,
803 struct _extract_data *ed = (struct _extract_data *) data;
806 ed->fp = open_file (&ed->filename, "wb",
808 inputfilename, lineno, ed->cmd);
810 prefix (inputfilename, lineno);
812 "unable to open extraction file \"%s\"\n",
817 IceWriteAuthFileEntry (ed->fp, auth);
824 static int match_auth (
825 register IceAuthFileEntry *a,
826 register IceAuthFileEntry *b,
829 int match = strcmp (a->protocol_name, b->protocol_name) == 0 &&
830 strcmp (a->network_id, b->network_id) == 0 &&
831 strcmp (a->auth_name, b->auth_name) == 0;
835 *authDataSame = (a->auth_data_length == b->auth_data_length &&
836 binaryEqual (a->auth_data, b->auth_data, a->auth_data_length));
845 static int merge_entries (
846 AuthList **firstp, AuthList *second,
847 int *nnewp, int *nreplp, int *ndupp)
849 AuthList *a, *b, *first, *tail;
850 int n = 0, nnew = 0, nrepl = 0, ndup = 0;
852 if (!second) return 0;
854 if (!*firstp) { /* if nothing to merge into */
856 for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ;
865 * find end of first list and stick second list on it
867 for (tail = first; tail->next; tail = tail->next) ;
871 * run down list freeing duplicate entries; if an entry is okay, then
872 * bump the tail up to include it, otherwise, cut the entry out of
875 for (b = second; b; ) {
876 AuthList *next = b->next; /* in case we free it */
883 if (match_auth (a->auth, b->auth, &authDataSame)) {
886 /* found a complete duplicate, ignore */
892 /* found a duplicate, but auth data differs */
894 AuthList tmp; /* swap it in for old one */
899 IceFreeAuthFileEntry (b->auth);
908 if (a == tail) break; /* if have looked at left side */
911 if (!duplicate && b) { /* if we didn't remove it */
912 tail = b; /* bump end of first list */
933 static int search_and_do (
934 const char *inputfilename,
946 char *protoname, *protodata, *netid, *authname;
948 for (l = iceauth_head; l; l = next)
952 protoname = protodata = netid = authname = NULL;
954 for (i = start; i < argc; i++)
956 if (!strncmp ("protoname=", argv[i], 10))
957 protoname = argv[i] + 10;
958 else if (!strncmp ("protodata=", argv[i], 10))
959 protodata = argv[i] + 10;
960 else if (!strncmp ("netid=", argv[i], 6))
962 else if (!strncmp ("authname=", argv[i], 9))
963 authname = argv[i] + 9;
968 if (protoname || protodata || netid || authname)
970 if (protoname && strcmp (protoname, l->auth->protocol_name))
973 if (protodata && !binaryEqual (protodata,
974 l->auth->protocol_data, l->auth->protocol_data_length))
977 if (netid && strcmp (netid, l->auth->network_id))
980 if (authname && strcmp (authname, l->auth->auth_name))
983 status = (*do_func) (inputfilename, lineno, l->auth, data);
991 errors -= status; /* since status is negative */
998 static int remove_entry (
999 const char *inputfilename,
1001 IceAuthFileEntry *auth,
1004 int *nremovedp = (int *) data;
1005 AuthList **listp = &iceauth_head;
1009 * unlink the auth we were asked to
1011 while ((list = *listp)->auth != auth)
1012 listp = &list->next;
1013 *listp = list->next;
1014 IceFreeAuthFileEntry (list->auth); /* free the auth */
1015 free (list); /* free the link */
1016 iceauth_modified = True;
1032 const CommandTable *ct;
1036 if (!cmd) { /* if no cmd, print all help */
1037 for (ct = command_table; ct->name; ct++) {
1038 fprintf (fp, "%s\n\n", ct->helptext);
1042 int len = strlen (cmd);
1043 for (ct = command_table; ct->name; ct++) {
1044 if (strncmp (cmd, ct->name, len) == 0) {
1045 fprintf (fp, "%s\n\n", ct->helptext);
1054 static int do_help (
1055 const char *inputfilename,
1060 char *cmd = (argc > 1 ? argv[1] : NULL);
1063 n = print_help (stdout, cmd);
1065 if (n < 0 || (n == 0 && !cmd)) {
1066 prefix (inputfilename, lineno);
1067 fprintf (stderr, "internal error with help");
1069 fprintf (stderr, " on command \"%s\"", cmd);
1071 fprintf (stderr, "\n");
1076 prefix (inputfilename, lineno);
1077 /* already know that cmd is set in this case */
1078 fprintf (stderr, "no help for noexistent command \"%s\"\n", cmd);
1088 static int do_questionmark (
1089 const char *inputfilename,
1094 const CommandTable *ct;
1096 #define WIDEST_COLUMN 72
1097 int col = WIDEST_COLUMN;
1099 printf ("Commands:\n");
1100 for (ct = command_table; ct->name; ct++) {
1101 if ((col + ct->maxlen) > WIDEST_COLUMN) {
1102 if (ct != command_table) {
1103 putc ('\n', stdout);
1105 fputs (" ", stdout);
1106 col = 8; /* length of string above */
1108 fputs (ct->name, stdout);
1110 for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH; i++) {
1116 putc ('\n', stdout);
1119 /* allow bad lines since this is help */
1124 * list [displayname ...]
1126 static int do_list (
1127 const char *inputfilename,
1132 struct _list_data ld;
1137 register AuthList *l;
1140 for (l = iceauth_head; l; l = l->next) {
1141 dump_entry (inputfilename, lineno, l->auth, (char *) &ld);
1148 return (search_and_do (inputfilename, lineno, 1, argc, argv,
1149 dump_entry, (char *) &ld));
1154 * merge filename [filename ...]
1156 static int do_merge (
1157 const char *inputfilename,
1164 AuthList *head, *tail, *listhead, *listtail;
1165 int nentries, nnew, nrepl, ndup;
1168 prefix (inputfilename, lineno);
1169 badcommandline (argv[0]);
1173 listhead = listtail = NULL;
1175 for (i = 1; i < argc; i++) {
1176 char *filename = argv[i];
1178 Bool used_stdin = False;
1180 fp = open_file (&filename, "rb",
1181 &used_stdin, inputfilename, lineno,
1189 nentries = read_auth_entries (fp, &head, &tail);
1190 if (nentries == 0) {
1191 prefix (inputfilename, lineno);
1192 fprintf (stderr, "unable to read any entries from file \"%s\"\n",
1195 } else { /* link it in */
1196 add_to_list (listhead, listtail, head);
1199 if (!used_stdin) (void) fclose (fp);
1203 * if we have new entries, merge them in (freeing any duplicates)
1206 nentries = merge_entries (&iceauth_head, listhead,
1207 &nnew, &nrepl, &ndup);
1209 printf ("%d entries read in: %d new, %d replacement%s\n",
1210 nentries, nnew, nrepl, nrepl != 1 ? "s" : "");
1211 if (nentries > 0) iceauth_modified = True;
1218 * extract filename displayname [displayname ...]
1220 static int do_extract (
1221 const char *inputfilename,
1227 struct _extract_data ed;
1230 prefix (inputfilename, lineno);
1231 badcommandline (argv[0]);
1236 ed.filename = argv[1];
1240 errors = search_and_do (inputfilename, lineno, 2, argc, argv,
1241 extract_entry, (char *) &ed);
1245 "No matches found, authority file \"%s\" not written\n",
1249 printf ("%d entries written to \"%s\"\n",
1250 ed.nwritten, ed.filename);
1252 if (!ed.used_stdout) {
1253 (void) fclose (ed.fp);
1262 * add protoname protodata netid authname authdata
1265 const char *inputfilename,
1270 int n, nnew, nrepl, ndup;
1272 char *protodata_hex;
1273 char *protodata = NULL; /* not required */
1277 char *authdata = NULL;
1278 int protodata_len, authdata_len;
1279 IceAuthFileEntry *auth = NULL;
1283 if (argc != 6 || !argv[1] || !argv[2] ||
1284 !argv[3] || !argv[4] || !argv[5])
1286 prefix (inputfilename, lineno);
1287 badcommandline (argv[0]);
1291 protoname = argv[1];
1292 protodata_hex = argv[2];
1295 authdata_hex = argv[5];
1297 protodata_len = strlen (protodata_hex);
1298 if (protodata_len > 0)
1300 if (protodata_hex[0] == '"' && protodata_hex[protodata_len - 1] == '"')
1302 protodata = malloc (protodata_len - 1);
1305 strncpy (protodata, protodata_hex + 1, protodata_len - 2);
1309 goto add_bad_malloc;
1313 protodata_len = cvthexkey (protodata_hex, &protodata);
1314 if (protodata_len < 0)
1316 prefix (inputfilename, lineno);
1318 "protodata_hex contains odd number of or non-hex characters\n");
1324 authdata_len = strlen (authdata_hex);
1325 if (authdata_hex[0] == '"' && authdata_hex[authdata_len - 1] == '"')
1327 authdata = malloc (authdata_len - 1);
1330 strncpy (authdata, authdata_hex + 1, authdata_len - 2);
1334 goto add_bad_malloc;
1336 else if (!strcmp (protoname, SECURERPC) || !strcmp (protoname, K5AUTH))
1338 authdata = malloc (authdata_len + 1);
1340 strcpy (authdata, authdata_hex);
1342 goto add_bad_malloc;
1346 authdata_len = cvthexkey (authdata_hex, &authdata);
1347 if (authdata_len < 0)
1349 prefix (inputfilename, lineno);
1351 "authdata_hex contains odd number of or non-hex characters\n");
1357 auth = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry));
1360 goto add_bad_malloc;
1362 auth->protocol_name = copystring (protoname);
1363 auth->protocol_data_length = protodata_len;
1364 auth->protocol_data = protodata;
1365 auth->network_id = copystring (netid);
1366 auth->auth_name = copystring (authname);
1367 auth->auth_data_length = authdata_len;
1368 auth->auth_data = authdata;
1370 if (!auth->protocol_name ||
1371 (!auth->protocol_data && auth->protocol_data_length > 0) ||
1372 !auth->network_id || !auth->auth_name ||
1373 (!auth->auth_data && auth->auth_data_length > 0))
1375 goto add_bad_malloc;
1378 list = (AuthList *) malloc (sizeof (AuthList));
1381 goto add_bad_malloc;
1387 * merge it in; note that merge will deal with allocation
1390 n = merge_entries (&iceauth_head, list, &nnew, &nrepl, &ndup);
1393 iceauth_modified = True;
1396 prefix (inputfilename, lineno);
1400 fprintf (stderr, "no records added - all duplicate\n");
1405 fprintf (stderr, "unable to merge in added record\n");
1416 prefix (inputfilename, lineno);
1417 fprintf (stderr, "unable to allocate memory to add an entry\n");
1427 if (auth->protocol_name)
1428 free (auth->protocol_name);
1429 /* auth->protocol_data already freed,
1430 since it's the same as protodata */
1431 if (auth->network_id)
1432 free (auth->network_id);
1433 if (auth->auth_name)
1434 free (auth->auth_name);
1435 /* auth->auth_data already freed,
1436 since it's the same as authdata */
1437 free ((char *) auth);
1444 * remove displayname
1446 static int do_remove (
1447 const char *inputfilename,
1456 prefix (inputfilename, lineno);
1457 badcommandline (argv[0]);
1461 errors = search_and_do (inputfilename, lineno, 1, argc, argv,
1462 remove_entry, (char *) &nremoved);
1463 if (verbose) printf ("%d entries removed\n", nremoved);
1470 static int do_info (
1471 const char *inputfilename,
1480 prefix (inputfilename, lineno);
1481 badcommandline (argv[0]);
1485 for (l = iceauth_head, n = 0; l; l = l->next, n++) ;
1487 printf ("Authority file: %s\n",
1488 iceauth_filename ? iceauth_filename : "(none)");
1489 printf ("File new: %s\n", iceauth_existed ? No : Yes);
1490 printf ("File locked: %s\n", ignore_locks ? No : Yes);
1491 printf ("Number of entries: %d\n", n);
1492 printf ("Changes honored: %s\n", iceauth_allowed ? Yes : No);
1493 printf ("Changes made: %s\n", iceauth_modified ? Yes : No);
1494 printf ("Current input: %s:%d\n", inputfilename, lineno);
1502 static Bool alldone = False;
1505 static int do_exit (
1506 const char *inputfilename,
1511 /* allow bogus stuff */
1520 static int do_quit (
1521 const char *inputfilename,
1526 /* allow bogus stuff */
1529 return -1; /* for picky compilers */
1536 static int do_source (
1537 const char *inputfilename,
1545 Bool used_stdin = False;
1547 int errors = 0, status;
1551 Bool prompt = False; /* only true if reading from tty */
1553 if (argc != 2 || !argv[1]) {
1554 prefix (inputfilename, lineno);
1555 badcommandline (argv[0]);
1561 fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]);
1566 if (verbose && used_stdin && isatty (fileno (fp))) prompt = True;
1571 printf ("iceauth> ");
1574 if (fgets (buf, sizeof buf, fp) == NULL) break;
1577 if (len == 0 || buf[0] == '#') continue;
1578 if (buf[len-1] != '\n') {
1579 prefix (script, sublineno);
1580 fprintf (stderr, "line too long\n");
1584 buf[--len] = '\0'; /* remove new line */
1585 subargv = split_into_words (buf, &subargc);
1587 status = process_command (script, sublineno, subargc, subargv);
1588 free ((char *) subargv);
1591 prefix (script, sublineno);
1592 fprintf (stderr, "unable to break line into words\n");