process.c revision 9d794632
11.198Senami/* 21.147Simp * 31.1SchristosCopyright 1989, 1998 The Open Group 41.14Schristos 51.14SchristosPermission to use, copy, modify, distribute, and sell this software and its 61.1Schristosdocumentation for any purpose is hereby granted without fee, provided that 71.1Schristosthe above copyright notice appear in all copies and that both that 81.14Schristoscopyright notice and this permission notice appear in supporting 91.14Schristosdocumentation. 101.14Schristos 111.1SchristosThe above copyright notice and this permission notice shall be included in 121.1Schristosall copies or substantial portions of the Software. 131.1Schristos 141.1SchristosTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 151.1SchristosIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 161.1SchristosFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 171.1SchristosOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 181.1SchristosAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 191.1SchristosCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 201.1Schristos 211.14SchristosExcept as contained in this notice, the name of The Open Group shall not be 221.14Schristosused in advertising or otherwise to promote the sale, use or other dealings 231.14Schristosin this Software without prior written authorization from The Open Group. 241.14Schristos * * 251.14Schristos * Original Author of "xauth" : Jim Fulton, MIT X Consortium 261.1Schristos * Modified into "iceauth" : Ralph Mor, X Consortium 271.14Schristos */ 281.14Schristos 291.14Schristos#include "iceauth.h" 301.14Schristos#include <ctype.h> 311.14Schristos#include <errno.h> 321.14Schristos#include <sys/types.h> 331.14Schristos#include <sys/stat.h> 341.14Schristos#include <signal.h> 351.14Schristos 361.14Schristos#define SECURERPC "SUN-DES-1" 371.14Schristos#define K5AUTH "KERBEROS-V5-1" 381.1Schristos 391.1Schristos#define ICEAUTH_DEFAULT_RETRIES 10 /* number of competitors we expect */ 401.1Schristos#define ICEAUTH_DEFAULT_TIMEOUT 2 /* in seconds, be quick */ 411.140Simp#define ICEAUTH_DEFAULT_DEADTIME 600L /* 10 minutes in seconds */ 421.1Schristos 431.1Schristostypedef struct _AuthList { /* linked list of entries */ 441.31Snathanw struct _AuthList *next; 451.176Smason IceAuthFileEntry *auth; 461.83Smycroft} AuthList; 471.15Skenh 481.40Shwr#define add_to_list(h,t,e) {if (t) (t)->next = (e); else (h) = (e); (t) = (e);} 491.65Sjoda 501.1Schristostypedef int (*ProcessFunc)(const char *, int, int, char **); 511.183Sgmcgarrytypedef int (*DoFunc)(const char *, int, IceAuthFileEntry *, void *); 521.1Schristos 531.1Schristostypedef struct _CommandTable { /* commands that are understood */ 541.1Schristos const char *name; /* full name */ 551.1Schristos unsigned int minlen; /* unique prefix */ 561.65Sjoda unsigned int maxlen; /* strlen(name) */ 571.11Sthorpej ProcessFunc processfunc; /* handler */ 581.147Simp const char *helptext; /* what to print for help */ 591.128Sichiro} CommandTable; 601.1Schristos 611.140Simpstruct _extract_data { /* for iterating */ 621.147Simp FILE *fp; /* input source */ 631.1Schristos const char *filename; /* name of input */ 641.1Schristos Bool used_stdout; /* whether or not need to close */ 651.147Simp int nwritten; /* number of entries written */ 661.65Sjoda const char *cmd; /* for error messages */ 671.175Srjs}; 681.140Simp 691.171Sjonathanstruct _list_data { /* for iterating */ 701.1Schristos FILE *fp; /* output file */ 711.147Simp}; 721.4Sthorpej 731.147Simp 741.39Ssommerfe/* 751.66Sjlam * private data 761.158Sjoda */ 771.135Spookastatic const char *stdin_filename = "(stdin)"; /* for messages */ 781.65Sjodastatic const char *stdout_filename = "(stdout)"; /* for messages */ 791.111Simpstatic const char *Yes = "yes"; /* for messages */ 801.1Schristosstatic const char *No = "no"; /* for messages */ 811.67Schopps 821.98Simpstatic int binaryEqual ( const char *a, const char *b, unsigned len ); 831.55Ssommerfestatic void prefix ( const char *fn, int n ); 841.92Sonoestatic void badcommandline ( const char *cmd ); 851.99Smsaitohstatic char *skip_space ( char *s ); 861.85Smycroftstatic char *skip_nonspace ( char *s ); 871.97Sonoestatic char **split_into_words ( char *src, int *argcp ); 881.189Sichirostatic FILE *open_file ( const char **filenamep, const char *mode, Bool *usedstdp, const char *srcfn, int srcln, const char *cmd ); 891.196Smycroftstatic int read_auth_entries ( FILE *fp, AuthList **headp, AuthList **tailp ); 901.136Sichirostatic int cvthexkey ( const char *hexstr, char **ptrp ); 911.125Sichirostatic int dispatch_command ( const char *inputfilename, int lineno, int argc, char **argv, const CommandTable *tab, int *statusp ); 921.159Saymericstatic void die ( int sig ) _X_NORETURN; 931.122Sichirostatic void catchsig ( int sig ) _X_NORETURN; 941.147Simpstatic void register_signals ( void ); 951.147Simpstatic int write_auth_file ( char *tmp_nam, size_t tmp_nam_len ); 961.172Smartinstatic void fprintfhex ( FILE *fp, unsigned int len, const char *cp ); 971.38Smjlstatic int dump_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, void *data ); 981.72Ssorenstatic int extract_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, void *data ); 991.147Simpstatic int match_auth ( IceAuthFileEntry *a, IceAuthFileEntry *b, int *authDataSame ); 1001.147Simpstatic int merge_entries ( AuthList **firstp, AuthList *second, int *nnewp, int *nreplp, int *ndupp ); 1011.159Saymericstatic int search_and_do ( const char *inputfilename, int lineno, int start, int argc, char *argv[], DoFunc do_func, void *data ); 1021.25Sthorpejstatic int remove_entry ( const char *inputfilename, int lineno, IceAuthFileEntry *auth, void *data ); 1031.78Senamistatic int do_help ( const char *inputfilename, int lineno, int argc, char **argv ); 1041.134Schristosstatic int do_questionmark ( const char *inputfilename, int lineno, int argc, char **argv ); 1051.43Stronstatic int do_list ( const char *inputfilename, int lineno, int argc, char **argv ); 1061.99Smsaitohstatic int do_merge ( const char *inputfilename, int lineno, int argc, char **argv ); 1071.110Snonakastatic int do_extract ( const char *inputfilename, int lineno, int argc, char **argv ); 1081.22Sthorpejstatic int do_add ( const char *inputfilename, int lineno, int argc, char **argv ); 1091.43Stronstatic int do_remove ( const char *inputfilename, int lineno, int argc, char **argv ); 1101.15Skenhstatic int do_info ( const char *inputfilename, int lineno, int argc, char **argv ); 1111.89Sisstatic int do_exit ( const char *inputfilename, int lineno, int argc, char **argv ); 1121.195Smycroftstatic int do_quit ( const char *inputfilename, int lineno, int argc, char **argv ); 1131.108Sichirostatic int do_source ( const char *inputfilename, int lineno, int argc, char **argv ); 1141.191Sitohy 1151.1Schristosstatic const CommandTable command_table[] = { /* table of known commands */ 1161.1Schristos{ "add", 2, 3, do_add, 1171.140Simp"\ 1181.140Simpadd add an entry\n\ 1191.1Schristos add protoname protodata netid authname authdata" 1201.58Ssoren}, 1211.1Schristos 1221.94Sjoda{ "exit", 3, 4, do_exit, 1231.140Simp"\ 1241.140Simpexit save changes and exit program" 1251.140Simp}, 1261.140Simp 1271.1Schristos{ "extract", 3, 7, do_extract, 1281.1Schristos"\ 1291.13Sthorpejextract extract entries into file\n\ 1301.147Simp extract filename <protoname=$> <protodata=$> <netid=$> <authname=$>" 1311.132Sitojun}, 1321.172Smartin 1331.172Smartin{ "help", 1, 4, do_help, 1341.172Smartin"\ 1351.24Sthorpejhelp print help\n\ 1361.140Simp help <topic>" 1371.140Simp}, 1381.140Simp 1391.140Simp{ "info", 1, 4, do_info, 1401.140Simp"\ 1411.140Simpinfo print information about entries" 1421.140Simp}, 1431.140Simp 1441.140Simp{ "list", 1, 4, do_list, 1451.140Simp"\ 1461.140Simplist list entries\n\ 1471.189Sichiro list <protoname=$> <protodata=$> <netid=$> <authname=$>" 1481.189Sichiro}, 1491.189Sichiro 1501.189Sichiro{ "merge", 1, 5, do_merge, 1511.140Simp"\ 1521.147Simpmerge merge entries from files\n\ 1531.147Simp merge filename1 <filename2> <filename3> ..." 1541.147Simp}, 1551.196Smycroft 1561.196Smycroft{ "quit", 1, 4, do_quit, 1571.196Smycroft"\ 1581.140Simpquit abort changes and exit program" }, 1591.140Simp 1601.140Simp{ "remove", 1, 6, do_remove, 1611.140Simp"\ 1621.169Smycroftremove remove entries\n\ 1631.140Simp remove <protoname=$> <protodata=$> <netid=$> <authname=$>" 1641.147Simp}, 1651.147Simp 1661.147Simp{ "source", 1, 6, do_source, 1671.140Simp"\ 1681.140Simpsource read commands from file\n\ 1691.198Senami source filename" 1701.198Senami}, 1711.150Senami 1721.140Simp{ "?", 1, 1, do_questionmark, 1731.90Sgmcgarry"\ 1741.140Simp? list available commands" }, 1751.90Sgmcgarry 1761.90Sgmcgarry{ NULL, 0, 0, NULL, NULL }, 1771.24Sthorpej}; 1781.147Simp 1791.24Sthorpej#define COMMAND_NAMES_PADDED_WIDTH 10 /* wider than anything above */ 1801.37Smjl 1811.140Simp 1821.140Simpstatic Bool okay_to_use_stdin = True; /* set to false after using */ 1831.140Simp 1841.1Schristosstatic const char * const hex_table[] = { /* for printing hex digits */ 1851.1Schristos "00", "01", "02", "03", "04", "05", "06", "07", 1861.16Sdbj "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", 1871.16Sdbj "10", "11", "12", "13", "14", "15", "16", "17", 1881.1Schristos "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", 1891.15Skenh "20", "21", "22", "23", "24", "25", "26", "27", 1901.15Skenh "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", 1911.120Sthorpej "30", "31", "32", "33", "34", "35", "36", "37", 1921.120Sthorpej "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", 1931.120Sthorpej "40", "41", "42", "43", "44", "45", "46", "47", 1941.101Shubertf "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", 1951.147Simp "50", "51", "52", "53", "54", "55", "56", "57", 1961.147Simp "58", "59", "5a", "5b", "5c", "5d", "5e", "5f", 1971.157Saymeric "60", "61", "62", "63", "64", "65", "66", "67", 1981.157Saymeric "68", "69", "6a", "6b", "6c", "6d", "6e", "6f", 1991.157Saymeric "70", "71", "72", "73", "74", "75", "76", "77", 2001.147Simp "78", "79", "7a", "7b", "7c", "7d", "7e", "7f", 2011.101Shubertf "80", "81", "82", "83", "84", "85", "86", "87", 2021.101Shubertf "88", "89", "8a", "8b", "8c", "8d", "8e", "8f", 2031.101Shubertf "90", "91", "92", "93", "94", "95", "96", "97", 2041.144Sichiro "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", 2051.173Smartin "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", 2061.31Snathanw "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", 2071.140Simp "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", 2081.140Simp "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", 2091.158Sjoda "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", 2101.158Sjoda "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", 2111.158Sjoda "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 2121.140Simp "d8", "d9", "da", "db", "dc", "dd", "de", "df", 2131.140Simp "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", 2141.140Simp "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef", 2151.140Simp "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", 2161.31Snathanw "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff", 2171.32Snathanw}; 2181.140Simp 2191.34Sthorpejstatic unsigned int hexvalues[256]; /* for parsing hex input */ 2201.191Sitohy 2211.1Schristosstatic mode_t original_umask = 0; /* for restoring */ 2221.1Schristos 2231.103Sdrochner 2241.93Ssoren/* 2251.93Ssoren * private utility procedures 2261.93Ssoren */ 2271.93Ssoren 2281.149Syamt#define copystring(s) ( s != NULL ? strdup(s) : NULL ) 2291.93Ssoren 2301.1Schristosstatic int 2311.191SitohybinaryEqual ( 2321.155Sichiro register const char *a, 2331.59Ssoren register const char *b, 2341.1Schristos register unsigned len) 2351.90Sgmcgarry 2361.140Simp{ 2371.90Sgmcgarry while (len--) 2381.90Sgmcgarry if (*a++ != *b++) 2391.1Schristos return 0; 2401.56Senami return 1; 2411.122Sichiro} 2421.192Ssekiya 2431.92Sonoestatic void prefix (const char *fn, int n) 2441.140Simp{ 2451.140Simp fprintf (stderr, "%s: %s:%d: ", ProgramName, fn, n); 2461.140Simp} 2471.140Simp 2481.140Simpstatic void badcommandline (const char *cmd) 2491.72Ssoren{ 2501.72Ssoren fprintf (stderr, "bad \"%s\" command line\n", cmd); 2511.102Ssoren} 2521.1Schristos 2531.1Schristosstatic char *skip_space (register char *s) 2541.140Simp{ 2551.73Sthorpej if (!s) return NULL; 2561.21Sitohy 2571.1Schristos for ( ; *s && isascii(*s) && isspace(*s); s++) 2581.147Simp ; 2591.164Sichiro return s; 2601.167Sonoe} 2611.140Simp 2621.140Simp 2631.140Simpstatic char *skip_nonspace (register char *s) 2641.140Simp{ 2651.140Simp if (!s) return NULL; 2661.140Simp 2671.1Schristos /* put quoting into loop if need be */ 2681.1Schristos for ( ; *s && isascii(*s) && !isspace(*s); s++) 2691.191Sitohy ; 2701.1Schristos return s; 2711.58Ssoren} 2721.18Sthorpej 2731.147Simpstatic char **split_into_words ( /* argvify string */ 2741.1Schristos char *src, 2751.1Schristos int *argcp) 2761.78Senami{ 2771.191Sitohy char *jword; 2781.128Sichiro char savec; 2791.140Simp char **argv; 2801.140Simp int cur, total; 2811.140Simp 2821.147Simp *argcp = 0; 2831.140Simp#define WORDSTOALLOC 4 /* most lines are short */ 2841.140Simp argv = (char **) malloc (WORDSTOALLOC * sizeof (char *)); 2851.140Simp if (!argv) return NULL; 2861.147Simp cur = 0; 2871.147Simp total = WORDSTOALLOC; 2881.147Simp 2891.140Simp /* 2901.147Simp * split the line up into separate, nul-terminated tokens; the last 2911.147Simp * "token" will point to the empty string so that it can be bashed into 2921.147Simp * a null pointer. 2931.147Simp */ 2941.175Srjs 2951.147Simp do { 2961.166Schris jword = skip_space (src); 2971.176Smason src = skip_nonspace (jword); 2981.140Simp savec = *src; 2991.128Sichiro *src = '\0'; 3001.191Sitohy if (cur == total) { 3011.85Smycroft total += WORDSTOALLOC; 3021.195Smycroft argv = (char **) realloc (argv, total * sizeof (char *)); 3031.195Smycroft if (!argv) return NULL; 3041.195Smycroft } 3051.85Smycroft argv[cur++] = jword; 3061.85Smycroft if (savec) src++; /* if not last on line advance */ 3071.91Ssoren } while (jword != src); 3081.91Ssoren 3091.91Ssoren argv[--cur] = NULL; /* smash empty token to end list */ 3101.175Srjs *argcp = cur; 3111.175Srjs return argv; 3121.175Srjs} 3131.83Smycroft 3141.83Smycroft 3151.83Smycroftstatic FILE *open_file ( 3161.88Sjoda const char **filenamep, 3171.141Schristos const char *mode, 3181.147Simp Bool *usedstdp, 3191.147Simp const char *srcfn, 3201.147Simp int srcln, 3211.147Simp const char *cmd) 3221.147Simp{ 3231.135Spooka FILE *fp; 3241.135Spooka 3251.135Spooka if (strcmp (*filenamep, "-") == 0) { 3261.78Senami *usedstdp = True; 3271.147Simp /* select std descriptor to use */ 3281.185Sichiro if (mode[0] == 'r') { 3291.147Simp if (okay_to_use_stdin) { 3301.147Simp okay_to_use_stdin = False; 3311.140Simp *filenamep = stdin_filename; 3321.140Simp return stdin; 3331.140Simp } else { 3341.140Simp prefix (srcfn, srcln); 3351.140Simp fprintf (stderr, "%s: stdin already in use\n", cmd); 3361.140Simp return NULL; 3371.140Simp } 3381.140Simp } else { 3391.4Sthorpej *filenamep = stdout_filename; 3401.15Skenh return stdout; /* always okay to use stdout */ 3411.15Skenh } 3421.183Sgmcgarry } 3431.183Sgmcgarry 3441.183Sgmcgarry fp = fopen (*filenamep, mode); 3451.15Skenh if (!fp) { 3461.4Sthorpej prefix (srcfn, srcln); 3471.4Sthorpej fprintf (stderr, "%s: unable to open file %s\n", cmd, *filenamep); 3481.39Ssommerfe } 3491.39Ssommerfe return fp; 3501.1Schristos} 3511.140Simp 3521.140Simp 3531.140Simpstatic int read_auth_entries (FILE *fp, AuthList **headp, AuthList **tailp) 3541.140Simp{ 3551.1Schristos IceAuthFileEntry *auth; 3561.127Sjhawk AuthList *head, *tail; 3571.156Spooka int n; 3581.1Schristos 3591.19Sthorpej head = tail = NULL; 3601.140Simp n = 0; 3611.100Stoddpw /* put all records into linked list */ 3621.184Smartin while ((auth = IceReadAuthFileEntry (fp)) != NULL) { 3631.140Simp AuthList *l = (AuthList *) malloc (sizeof (AuthList)); 3641.140Simp if (!l) { 3651.140Simp fprintf (stderr, 3661.1Schristos "%s: unable to alloc entry reading auth file\n", 3671.1Schristos ProgramName); 3681.140Simp exit (1); 3691.1Schristos } 3701.140Simp l->next = NULL; 3711.163Smartin l->auth = auth; 3721.1Schristos if (tail) /* if not first time through append */ 3731.140Simp tail->next = l; 3741.140Simp else 3751.140Simp head = l; /* first time through, so assign */ 3761.140Simp tail = l; 3771.140Simp n++; 3781.140Simp } 3791.20Sthorpej *headp = head; 3801.90Sgmcgarry *tailp = tail; 3811.90Sgmcgarry return n; 3821.147Simp} 3831.90Sgmcgarry 3841.145Schristos 3851.140Simpstatic int cvthexkey ( /* turn hex key string into octets */ 3861.140Simp const char *hexstr, 3871.114Sthorpej char **ptrp) 3881.90Sgmcgarry{ 3891.140Simp unsigned int i; 3901.90Sgmcgarry unsigned int len = 0; 3911.96Sgmcgarry char *retval; 3921.96Sgmcgarry const char *s; 3931.134Schristos unsigned char *us; 3941.134Schristos char c; 3951.134Schristos char savec = '\0'; 3961.134Schristos 3971.140Simp /* count */ 3981.140Simp for (s = hexstr; *s; s++) { 3991.140Simp if (!isascii(*s)) return -1; 4001.195Smycroft if (isspace(*s)) continue; 4011.140Simp if (!isxdigit(*s)) return -1; 4021.140Simp len++; 4031.140Simp } 4041.140Simp 4051.191Sitohy /* if 0 or odd, then there was an error */ 4061.191Sitohy if (len == 0 || (len & 1) == 1) return -1; 4071.174Smjl 4081.140Simp 4091.62Sdanw /* now we know that the input is good */ 4101.64Saugustss len >>= 1; 4111.147Simp retval = malloc (len); 4121.196Smycroft if (!retval) { 4131.76Senami fprintf (stderr, "%s: unable to allocate %d bytes for hexkey\n", 4141.95Sonoe ProgramName, len); 4151.160Sis return -1; 4161.140Simp } 4171.147Simp 4181.191Sitohy for (us = (unsigned char *) retval, i = len; i > 0; hexstr++) { 4191.140Simp c = *hexstr; 4201.191Sitohy if (isspace(c)) continue; /* already know it is ascii */ 4211.191Sitohy if (isupper(c)) 4221.140Simp c = tolower(c); 4231.121Saymeric if (savec) { 4241.193Suwe#define atoh(c) ((c) - (((c) >= '0' && (c) <= '9') ? '0' : ('a'-10))) 4251.140Simp *us = (unsigned char)((atoh(savec) << 4) + atoh(c)); 4261.191Sitohy#undef atoh 4271.3Schristos savec = 0; /* ready for next character */ 4281.1Schristos us++; 4291.177Sbouyer i--; 4301.140Simp } else { 4311.197Smycroft savec = c; 4321.140Simp } 4331.182Schristos } 4341.140Simp *ptrp = retval; 4351.140Simp return (int) len; 4361.74Senami} 4371.143Smjl 4381.188Shamajimastatic int dispatch_command ( 4391.170Sitojun const char *inputfilename, 4401.74Senami int lineno, 4411.74Senami int argc, 4421.124Sichiro char **argv, 4431.130Sichiro const CommandTable *tab, 4441.194Sitohy int *statusp) 4451.86Sitojun{ 4461.118Sichiro const CommandTable *ct; 4471.142Smjl const char *cmd; 4481.181Sperry size_t n; 4491.190Snonaka /* scan table for command */ 4501.142Smjl cmd = argv[0]; 4511.140Simp n = strlen (cmd); 4521.140Simp for (ct = tab; ct->name; ct++) { 4531.140Simp /* look for unique prefix */ 4541.140Simp if (n >= ct->minlen && n <= ct->maxlen && 4551.171Sjonathan strncmp (cmd, ct->name, n) == 0) { 4561.178Sjdc *statusp = (*(ct->processfunc))(inputfilename, lineno, argc, argv); 4571.174Smjl return 1; 4581.174Smjl } 4591.70Smycroft } 4601.140Simp 4611.140Simp *statusp = 1; 4621.70Smycroft return 0; 4631.140Simp} 4641.62Sdanw 4651.64Saugustss 4661.193Suwestatic AuthList *iceauth_head = NULL; /* list of auth entries */ 4671.193Suwestatic Bool iceauth_existed = False; /* if was present at initialize */ 4681.193Suwestatic Bool iceauth_modified = False; /* if added, removed, or merged */ 4691.193Suwestatic Bool iceauth_allowed = True; /* if allowed to write auth file */ 4701.140Simpstatic char *iceauth_filename = NULL; 4711.196Smycroftstatic volatile Bool dieing = False; 4721.76Senami 4731.106Sjhawk/* poor man's puts(), for under signal handlers */ 4741.140Simp#define WRITES(fd, S) (void)write((fd), (S), strlen((S))) 4751.140Simp 4761.162Sis/* ARGSUSED */ 4771.140Simpstatic void die (_X_UNUSED int sig) 4781.191Sitohy{ 4791.99Smsaitoh dieing = True; 4801.191Sitohy _exit (auth_finalize ()); 4811.109Sichiro /* NOTREACHED */ 4821.140Simp} 4831.118Sichiro 4841.118Sichirostatic void catchsig (int sig) 4851.140Simp{ 4861.140Simp#ifdef SYSV 4871.140Simp if (sig > 0) signal (sig, die); /* re-establish signal handler */ 4881.140Simp#endif 4891.140Simp /* 4901.140Simp * fileno() might not be reentrant, avoid it if possible, and use 4911.140Simp * stderr instead of stdout 4921.168Stshiozak */ 4931.191Sitohy#ifdef STDERR_FILENO 4941.191Sitohy if (verbose && iceauth_modified) WRITES(STDERR_FILENO, "\r\n"); 4951.191Sitohy#else 4961.191Sitohy if (verbose && iceauth_modified) WRITES(fileno(stderr), "\r\n"); 4971.191Sitohy#endif 4981.191Sitohy die (sig); 4991.191Sitohy /* NOTREACHED */ 5001.191Sitohy} 5011.191Sitohy 5021.191Sitohystatic void register_signals (void) 5031.140Simp{ 5041.140Simp signal (SIGINT, catchsig); 5051.140Simp signal (SIGTERM, catchsig); 5061.151Schristos#ifdef SIGHUP 5071.140Simp signal (SIGHUP, catchsig); 5081.179Skanaoka#endif 5091.140Simp return; 5101.140Simp} 5111.139Saugustss 5121.140Simp 5131.140Simp/* 5141.139Saugustss * public procedures for parsing lines of input 5151.140Simp */ 5161.140Simp 5171.193Suweint auth_initialize ( char *authfilename ) 5181.140Simp{ 5191.193Suwe int n; 5201.140Simp AuthList *head, *tail; 5211.140Simp FILE *authfp; 5221.147Simp Bool exists; 523 524 register_signals (); 525 526 bzero ((char *) hexvalues, sizeof hexvalues); 527 hexvalues['0'] = 0; 528 hexvalues['1'] = 1; 529 hexvalues['2'] = 2; 530 hexvalues['3'] = 3; 531 hexvalues['4'] = 4; 532 hexvalues['5'] = 5; 533 hexvalues['6'] = 6; 534 hexvalues['7'] = 7; 535 hexvalues['8'] = 8; 536 hexvalues['9'] = 9; 537 hexvalues['a'] = hexvalues['A'] = 0xa; 538 hexvalues['b'] = hexvalues['B'] = 0xb; 539 hexvalues['c'] = hexvalues['C'] = 0xc; 540 hexvalues['d'] = hexvalues['D'] = 0xd; 541 hexvalues['e'] = hexvalues['E'] = 0xe; 542 hexvalues['f'] = hexvalues['F'] = 0xf; 543 544 if (break_locks && verbose) { 545 printf ("Attempting to break locks on authority file %s\n", 546 authfilename); 547 } 548 549 iceauth_filename = strdup(authfilename); 550 551 if (ignore_locks) { 552 if (break_locks) IceUnlockAuthFile (authfilename); 553 } else { 554 n = IceLockAuthFile (authfilename, ICEAUTH_DEFAULT_RETRIES, 555 ICEAUTH_DEFAULT_TIMEOUT, 556 (break_locks ? 0L : ICEAUTH_DEFAULT_DEADTIME)); 557 if (n != IceAuthLockSuccess) { 558 const char *reason = "unknown error"; 559 switch (n) { 560 case IceAuthLockError: 561 reason = "error"; 562 break; 563 case IceAuthLockTimeout: 564 reason = "timeout"; 565 break; 566 } 567 fprintf (stderr, "%s: %s in locking authority file %s\n", 568 ProgramName, reason, authfilename); 569 return -1; 570 } 571 } 572 573 /* these checks can only be done reliably after the file is locked */ 574 exists = (access (authfilename, F_OK) == 0); 575 if (exists && access (authfilename, W_OK) != 0) { 576 fprintf (stderr, 577 "%s: %s not writable, changes will be ignored\n", 578 ProgramName, authfilename); 579 iceauth_allowed = False; 580 } 581 582 original_umask = umask (0077); /* disallow non-owner access */ 583 584 authfp = fopen (authfilename, "rb"); 585 if (!authfp) { 586 int olderrno = errno; 587 588 /* if file there then error */ 589 if (access (authfilename, F_OK) == 0) { /* then file does exist! */ 590 errno = olderrno; 591 return -1; 592 } /* else ignore it */ 593 fprintf (stderr, 594 "%s: creating new authority file %s\n", 595 ProgramName, authfilename); 596 } else { 597 iceauth_existed = True; 598 n = read_auth_entries (authfp, &head, &tail); 599 (void) fclose (authfp); 600 if (n < 0) { 601 fprintf (stderr, 602 "%s: unable to read auth entries from file \"%s\"\n", 603 ProgramName, authfilename); 604 return -1; 605 } 606 iceauth_head = head; 607 } 608 609 iceauth_modified = False; 610 611 if (verbose) { 612 printf ("%s authority file %s\n", 613 ignore_locks ? "Ignoring locks on" : "Using", authfilename); 614 } 615 return 0; 616} 617 618static int write_auth_file (char *tmp_nam, size_t tmp_nam_len) 619{ 620 FILE *fp; 621 AuthList *list; 622 623 if ((strlen(iceauth_filename) + 3) > tmp_nam_len) { 624 strncpy(tmp_nam, "filename too long", tmp_nam_len); 625 tmp_nam[tmp_nam_len - 1] = '\0'; 626 return -1; 627 } 628 629 strcpy (tmp_nam, iceauth_filename); 630 strcat (tmp_nam, "-n"); /* for new */ 631 (void) unlink (tmp_nam); 632 fp = fopen (tmp_nam, "wb"); /* umask is still set to 0077 */ 633 if (!fp) { 634 fprintf (stderr, "%s: unable to open tmp file \"%s\"\n", 635 ProgramName, tmp_nam); 636 return -1; 637 } 638 639 for (list = iceauth_head; list; list = list->next) 640 IceWriteAuthFileEntry (fp, list->auth); 641 642 (void) fclose (fp); 643 return 0; 644} 645 646int auth_finalize (void) 647{ 648 char temp_name[1024]; /* large filename size */ 649 650 if (iceauth_modified) { 651 if (dieing) { 652 if (verbose) { 653 /* 654 * called from a signal handler -- printf is *not* reentrant; also 655 * fileno() might not be reentrant, avoid it if possible, and use 656 * stderr instead of stdout 657 */ 658#ifdef STDERR_FILENO 659 WRITES(STDERR_FILENO, "\nAborting changes to authority file "); 660 WRITES(STDERR_FILENO, iceauth_filename); 661 WRITES(STDERR_FILENO, "\n"); 662#else 663 WRITES(fileno(stderr), "\nAborting changes to authority file "); 664 WRITES(fileno(stderr), iceauth_filename); 665 WRITES(fileno(stderr), "\n"); 666#endif 667 } 668 } else if (!iceauth_allowed) { 669 fprintf (stderr, 670 "%s: %s not writable, changes ignored\n", 671 ProgramName, iceauth_filename); 672 } else { 673 if (verbose) { 674 printf ("%s authority file %s\n", 675 ignore_locks ? "Ignoring locks and writing" : 676 "Writing", iceauth_filename); 677 } 678 temp_name[0] = '\0'; 679 if (write_auth_file (temp_name, sizeof(temp_name)) == -1) { 680 fprintf (stderr, 681 "%s: unable to write authority file %s\n", 682 ProgramName, temp_name); 683 } else { 684 (void) unlink (iceauth_filename); 685#if defined(WIN32) || defined(__UNIXOS2__) 686 if (rename(temp_name, iceauth_filename) == -1) 687#else 688 /* Attempt to rename() if link() fails, since this may be on a FS that does not support hard links */ 689 if (link (temp_name, iceauth_filename) == -1 && rename(temp_name, iceauth_filename) == -1) 690#endif 691 { 692 fprintf (stderr, 693 "%s: unable to link authority file %s, use %s\n", 694 ProgramName, iceauth_filename, temp_name); 695 } else { 696 (void) unlink (temp_name); 697 } 698 } 699 } 700 } 701 702 if (!ignore_locks && (iceauth_filename != NULL)) { 703 IceUnlockAuthFile (iceauth_filename); 704 } 705 (void) umask (original_umask); 706 return 0; 707} 708 709int process_command ( 710 const char *inputfilename, 711 int lineno, 712 int argc, 713 char **argv) 714{ 715 int status; 716 717 if (argc < 1 || !argv || !argv[0]) return 1; 718 719 if (dispatch_command (inputfilename, lineno, argc, argv, 720 command_table, &status)) 721 return status; 722 723 prefix (inputfilename, lineno); 724 fprintf (stderr, "unknown command \"%s\"\n", argv[0]); 725 return 1; 726} 727 728 729/* 730 * utility routines 731 */ 732 733static void fprintfhex ( 734 register FILE *fp, 735 unsigned int len, 736 const char *cp) 737{ 738 const unsigned char *ucp = (const unsigned char *) cp; 739 740 for (; len > 0; len--, ucp++) { 741 register const char *s = hex_table[*ucp]; 742 putc (s[0], fp); 743 putc (s[1], fp); 744 } 745 return; 746} 747 748/* ARGSUSED */ 749static int dump_entry ( 750 const char *inputfilename _X_UNUSED, 751 int lineno _X_UNUSED, 752 IceAuthFileEntry *auth, 753 void *data) 754{ 755 struct _list_data *ld = (struct _list_data *) data; 756 FILE *fp = ld->fp; 757 758 fprintf (fp, "%s", auth->protocol_name); 759 putc (' ', fp); 760 if (auth->protocol_data_length > 0) 761 fprintfhex (fp, auth->protocol_data_length, auth->protocol_data); 762 else 763 fprintf (fp, "\"\""); 764 putc (' ', fp); 765 fprintf (fp, "%s", auth->network_id); 766 putc (' ', fp); 767 fprintf (fp, "%s", auth->auth_name); 768 putc (' ', fp); 769 770 if (auth->auth_data_length == 0) 771 fprintf (fp, "\"\""); 772 else if (!strcmp(auth->auth_name, SECURERPC) || 773 !strcmp(auth->auth_name, K5AUTH)) 774 fwrite (auth->auth_data, sizeof (char), auth->auth_data_length, fp); 775 else 776 fprintfhex (fp, auth->auth_data_length, auth->auth_data); 777 putc ('\n', fp); 778 779 return 0; 780} 781 782static int extract_entry ( 783 const char *inputfilename, 784 int lineno, 785 IceAuthFileEntry *auth, 786 void *data) 787{ 788 struct _extract_data *ed = (struct _extract_data *) data; 789 790 if (!ed->fp) { 791 ed->fp = open_file (&ed->filename, "wb", 792 &ed->used_stdout, 793 inputfilename, lineno, ed->cmd); 794 if (!ed->fp) { 795 prefix (inputfilename, lineno); 796 fprintf (stderr, 797 "unable to open extraction file \"%s\"\n", 798 ed->filename); 799 return -1; 800 } 801 } 802 IceWriteAuthFileEntry (ed->fp, auth); 803 ed->nwritten++; 804 805 return 0; 806} 807 808 809static int match_auth ( 810 register IceAuthFileEntry *a, 811 register IceAuthFileEntry *b, 812 int *authDataSame) 813{ 814 int match = strcmp (a->protocol_name, b->protocol_name) == 0 && 815 strcmp (a->network_id, b->network_id) == 0 && 816 strcmp (a->auth_name, b->auth_name) == 0; 817 818 if (match) 819 { 820 *authDataSame = (a->auth_data_length == b->auth_data_length && 821 binaryEqual (a->auth_data, b->auth_data, a->auth_data_length)); 822 } 823 else 824 *authDataSame = 0; 825 826 return (match); 827} 828 829 830static int merge_entries ( 831 AuthList **firstp, AuthList *second, 832 int *nnewp, int *nreplp, int *ndupp) 833{ 834 AuthList *a, *b, *first, *tail; 835 int n = 0, nnew = 0, nrepl = 0, ndup = 0; 836 837 if (!second) return 0; 838 839 if (!*firstp) { /* if nothing to merge into */ 840 *firstp = second; 841 for (tail = *firstp, n = 1; tail->next; n++, tail = tail->next) ; 842 *nnewp = n; 843 *nreplp = 0; 844 *ndupp = 0; 845 return n; 846 } 847 848 first = *firstp; 849 /* 850 * find end of first list and stick second list on it 851 */ 852 for (tail = first; tail->next; tail = tail->next) ; 853 tail->next = second; 854 855 /* 856 * run down list freeing duplicate entries; if an entry is okay, then 857 * bump the tail up to include it, otherwise, cut the entry out of 858 * the chain. 859 */ 860 for (b = second; b; ) { 861 AuthList *next = b->next; /* in case we free it */ 862 int duplicate; 863 864 duplicate = 0; 865 a = first; 866 for (;;) { 867 int authDataSame; 868 if (match_auth (a->auth, b->auth, &authDataSame)) { 869 if (authDataSame) 870 { 871 /* found a complete duplicate, ignore */ 872 duplicate = 1; 873 break; 874 } 875 else 876 { 877 /* found a duplicate, but auth data differs */ 878 879 AuthList tmp; /* swap it in for old one */ 880 tmp = *a; 881 *a = *b; 882 *b = tmp; 883 a->next = b->next; 884 IceFreeAuthFileEntry (b->auth); 885 free ((char *) b); 886 b = NULL; 887 tail->next = next; 888 nrepl++; 889 nnew--; 890 break; 891 } 892 } 893 if (a == tail) break; /* if have looked at left side */ 894 a = a->next; 895 } 896 if (!duplicate && b) { /* if we didn't remove it */ 897 tail = b; /* bump end of first list */ 898 } 899 b = next; 900 901 if (duplicate) 902 ndup++; 903 else 904 { 905 n++; 906 nnew++; 907 } 908 } 909 910 *nnewp = nnew; 911 *nreplp = nrepl; 912 *ndupp = ndup; 913 return n; 914 915} 916 917 918static int search_and_do ( 919 const char *inputfilename, 920 int lineno, 921 int start, 922 int argc, 923 char *argv[], 924 DoFunc do_func, 925 void *data) 926{ 927 int i; 928 int status = 0; 929 int errors = 0; 930 AuthList *l, *next; 931 char *protoname, *protodata, *netid, *authname; 932 933 for (l = iceauth_head; l; l = next) 934 { 935 next = l->next; 936 937 protoname = protodata = netid = authname = NULL; 938 939 for (i = start; i < argc; i++) 940 { 941 if (!strncmp ("protoname=", argv[i], 10)) 942 protoname = argv[i] + 10; 943 else if (!strncmp ("protodata=", argv[i], 10)) 944 protodata = argv[i] + 10; 945 else if (!strncmp ("netid=", argv[i], 6)) 946 netid = argv[i] + 6; 947 else if (!strncmp ("authname=", argv[i], 9)) 948 authname = argv[i] + 9; 949 } 950 951 status = 0; 952 953 if (protoname || protodata || netid || authname) 954 { 955 if (protoname && strcmp (protoname, l->auth->protocol_name)) 956 continue; 957 958 if (protodata && !binaryEqual (protodata, 959 l->auth->protocol_data, l->auth->protocol_data_length)) 960 continue; 961 962 if (netid && strcmp (netid, l->auth->network_id)) 963 continue; 964 965 if (authname && strcmp (authname, l->auth->auth_name)) 966 continue; 967 968 status = (*do_func) (inputfilename, lineno, l->auth, data); 969 970 if (status < 0) 971 break; 972 } 973 } 974 975 if (status < 0) 976 errors -= status; /* since status is negative */ 977 978 return (errors); 979} 980 981 982/* ARGSUSED */ 983static int remove_entry ( 984 const char *inputfilename _X_UNUSED, 985 int lineno _X_UNUSED, 986 IceAuthFileEntry *auth, 987 void *data) 988{ 989 int *nremovedp = (int *) data; 990 AuthList **listp = &iceauth_head; 991 AuthList *list; 992 993 /* 994 * unlink the auth we were asked to 995 */ 996 while ((list = *listp)->auth != auth) 997 listp = &list->next; 998 *listp = list->next; 999 IceFreeAuthFileEntry (list->auth); /* free the auth */ 1000 free (list); /* free the link */ 1001 iceauth_modified = True; 1002 (*nremovedp)++; 1003 return 1; 1004} 1005 1006/* 1007 * action routines 1008 */ 1009 1010/* 1011 * help 1012 */ 1013int print_help ( 1014 FILE *fp, 1015 const char *cmd) 1016{ 1017 const CommandTable *ct; 1018 int n = 0; 1019 1020 fprintf (fp, "\n"); 1021 if (!cmd) { /* if no cmd, print all help */ 1022 for (ct = command_table; ct->name; ct++) { 1023 fprintf (fp, "%s\n\n", ct->helptext); 1024 n++; 1025 } 1026 } else { 1027 size_t len = strlen (cmd); 1028 for (ct = command_table; ct->name; ct++) { 1029 if (strncmp (cmd, ct->name, len) == 0) { 1030 fprintf (fp, "%s\n\n", ct->helptext); 1031 n++; 1032 } 1033 } 1034 } 1035 1036 return n; 1037} 1038 1039static int do_help ( 1040 const char *inputfilename, 1041 int lineno, 1042 int argc, 1043 char **argv) 1044{ 1045 char *cmd = (argc > 1 ? argv[1] : NULL); 1046 int n; 1047 1048 n = print_help (stdout, cmd); 1049 1050 if (n < 0 || (n == 0 && !cmd)) { 1051 prefix (inputfilename, lineno); 1052 fprintf (stderr, "internal error with help"); 1053 if (cmd) { 1054 fprintf (stderr, " on command \"%s\"", cmd); 1055 } 1056 fprintf (stderr, "\n"); 1057 return 1; 1058 } 1059 1060 if (n == 0) { 1061 prefix (inputfilename, lineno); 1062 /* already know that cmd is set in this case */ 1063 fprintf (stderr, "no help for noexistent command \"%s\"\n", cmd); 1064 } 1065 1066 return 0; 1067} 1068 1069/* 1070 * questionmark 1071 */ 1072/* ARGSUSED */ 1073static int do_questionmark ( 1074 const char *inputfilename _X_UNUSED, 1075 int lineno _X_UNUSED, 1076 int argc _X_UNUSED, 1077 char **argv _X_UNUSED) 1078{ 1079 const CommandTable *ct; 1080 unsigned int i; 1081#define WIDEST_COLUMN 72 1082 unsigned int col = WIDEST_COLUMN; 1083 1084 printf ("Commands:\n"); 1085 for (ct = command_table; ct->name; ct++) { 1086 if ((col + ct->maxlen) > WIDEST_COLUMN) { 1087 if (ct != command_table) { 1088 putc ('\n', stdout); 1089 } 1090 fputs (" ", stdout); 1091 col = 8; /* length of string above */ 1092 } 1093 fputs (ct->name, stdout); 1094 col += ct->maxlen; 1095 for (i = ct->maxlen; i < COMMAND_NAMES_PADDED_WIDTH; i++) { 1096 putc (' ', stdout); 1097 col++; 1098 } 1099 } 1100 if (col != 0) { 1101 putc ('\n', stdout); 1102 } 1103 1104 /* allow bad lines since this is help */ 1105 return 0; 1106} 1107 1108/* 1109 * list [displayname ...] 1110 */ 1111static int do_list ( 1112 const char *inputfilename, 1113 int lineno, 1114 int argc, 1115 char **argv) 1116{ 1117 struct _list_data ld; 1118 1119 ld.fp = stdout; 1120 1121 if (argc == 1) { 1122 register AuthList *l; 1123 1124 if (iceauth_head) { 1125 for (l = iceauth_head; l; l = l->next) { 1126 dump_entry (inputfilename, lineno, l->auth, &ld); 1127 } 1128 } 1129 return 0; 1130 } 1131 else 1132 { 1133 return (search_and_do (inputfilename, lineno, 1, argc, argv, 1134 dump_entry, &ld)); 1135 } 1136} 1137 1138/* 1139 * merge filename [filename ...] 1140 */ 1141static int do_merge ( 1142 const char *inputfilename, 1143 int lineno, 1144 int argc, 1145 char **argv) 1146{ 1147 int i; 1148 int errors = 0; 1149 AuthList *head, *tail, *listhead, *listtail; 1150 int nentries, nnew, nrepl, ndup; 1151 1152 if (argc < 2) { 1153 prefix (inputfilename, lineno); 1154 badcommandline (argv[0]); 1155 return 1; 1156 } 1157 1158 listhead = listtail = NULL; 1159 1160 for (i = 1; i < argc; i++) { 1161 const char *filename = argv[i]; 1162 FILE *fp; 1163 Bool used_stdin = False; 1164 1165 fp = open_file (&filename, "rb", 1166 &used_stdin, inputfilename, lineno, 1167 argv[0]); 1168 if (!fp) { 1169 errors++; 1170 continue; 1171 } 1172 1173 head = tail = NULL; 1174 nentries = read_auth_entries (fp, &head, &tail); 1175 if (nentries == 0) { 1176 prefix (inputfilename, lineno); 1177 fprintf (stderr, "unable to read any entries from file \"%s\"\n", 1178 filename); 1179 errors++; 1180 } else { /* link it in */ 1181 add_to_list (listhead, listtail, head); 1182 } 1183 1184 if (!used_stdin) (void) fclose (fp); 1185 } 1186 1187 /* 1188 * if we have new entries, merge them in (freeing any duplicates) 1189 */ 1190 if (listhead) { 1191 nentries = merge_entries (&iceauth_head, listhead, 1192 &nnew, &nrepl, &ndup); 1193 if (verbose) 1194 printf ("%d entries read in: %d new, %d replacement%s\n", 1195 nentries, nnew, nrepl, nrepl != 1 ? "s" : ""); 1196 if (nentries > 0) iceauth_modified = True; 1197 } 1198 1199 return 0; 1200} 1201 1202/* 1203 * extract filename displayname [displayname ...] 1204 */ 1205static int do_extract ( 1206 const char *inputfilename, 1207 int lineno, 1208 int argc, 1209 char **argv) 1210{ 1211 int errors; 1212 struct _extract_data ed; 1213 1214 if (argc < 3) { 1215 prefix (inputfilename, lineno); 1216 badcommandline (argv[0]); 1217 return 1; 1218 } 1219 1220 ed.fp = NULL; 1221 ed.filename = argv[1]; 1222 ed.nwritten = 0; 1223 ed.cmd = argv[0]; 1224 1225 errors = search_and_do (inputfilename, lineno, 2, argc, argv, 1226 extract_entry, &ed); 1227 1228 if (!ed.fp) { 1229 fprintf (stderr, 1230 "No matches found, authority file \"%s\" not written\n", 1231 ed.filename); 1232 } else { 1233 if (verbose) { 1234 printf ("%d entries written to \"%s\"\n", 1235 ed.nwritten, ed.filename); 1236 } 1237 if (!ed.used_stdout) { 1238 (void) fclose (ed.fp); 1239 } 1240 } 1241 1242 return errors; 1243} 1244 1245 1246/* 1247 * add protoname protodata netid authname authdata 1248 */ 1249static int do_add ( 1250 const char *inputfilename, 1251 int lineno, 1252 int argc, 1253 char **argv) 1254{ 1255 int n, nnew, nrepl, ndup; 1256 char *protoname; 1257 char *protodata_hex; 1258 char *protodata = NULL; /* not required */ 1259 char *netid; 1260 char *authname; 1261 char *authdata_hex; 1262 char *authdata = NULL; 1263 int protodata_len, authdata_len; 1264 IceAuthFileEntry *auth = NULL; 1265 AuthList *list; 1266 int status = 0; 1267 1268 if (argc != 6 || !argv[1] || !argv[2] || 1269 !argv[3] || !argv[4] || !argv[5]) 1270 { 1271 prefix (inputfilename, lineno); 1272 badcommandline (argv[0]); 1273 return 1; 1274 } 1275 1276 protoname = argv[1]; 1277 protodata_hex = argv[2]; 1278 netid = argv[3]; 1279 authname = argv[4]; 1280 authdata_hex = argv[5]; 1281 1282 protodata_len = strlen (protodata_hex); 1283 if (protodata_len > 0) 1284 { 1285 if (protodata_hex[0] == '"' && protodata_hex[protodata_len - 1] == '"') 1286 { 1287 protodata = malloc (protodata_len - 1); 1288 if (protodata) 1289 { 1290 strncpy (protodata, protodata_hex + 1, protodata_len - 2); 1291 protodata_len -= 2; 1292 } 1293 else 1294 goto add_bad_malloc; 1295 } 1296 else 1297 { 1298 protodata_len = cvthexkey (protodata_hex, &protodata); 1299 if (protodata_len < 0) 1300 { 1301 prefix (inputfilename, lineno); 1302 fprintf (stderr, 1303 "protodata_hex contains odd number of or non-hex characters\n"); 1304 return (1); 1305 } 1306 } 1307 } 1308 1309 authdata_len = strlen (authdata_hex); 1310 if (authdata_hex[0] == '"' && authdata_hex[authdata_len - 1] == '"') 1311 { 1312 authdata = malloc (authdata_len - 1); 1313 if (authdata) 1314 { 1315 strncpy (authdata, authdata_hex + 1, authdata_len - 2); 1316 authdata_len -= 2; 1317 } 1318 else 1319 goto add_bad_malloc; 1320 } 1321 else if (!strcmp (protoname, SECURERPC) || !strcmp (protoname, K5AUTH)) 1322 { 1323 authdata = malloc (authdata_len + 1); 1324 if (authdata) 1325 strcpy (authdata, authdata_hex); 1326 else 1327 goto add_bad_malloc; 1328 } 1329 else 1330 { 1331 authdata_len = cvthexkey (authdata_hex, &authdata); 1332 if (authdata_len < 0) 1333 { 1334 prefix (inputfilename, lineno); 1335 fprintf (stderr, 1336 "authdata_hex contains odd number of or non-hex characters\n"); 1337 free (protodata); 1338 return (1); 1339 } 1340 } 1341 1342 auth = (IceAuthFileEntry *) malloc (sizeof (IceAuthFileEntry)); 1343 1344 if (!auth) 1345 goto add_bad_malloc; 1346 1347 auth->protocol_name = copystring (protoname); 1348 auth->protocol_data_length = protodata_len; 1349 auth->protocol_data = protodata; 1350 auth->network_id = copystring (netid); 1351 auth->auth_name = copystring (authname); 1352 auth->auth_data_length = authdata_len; 1353 auth->auth_data = authdata; 1354 1355 if (!auth->protocol_name || 1356 (!auth->protocol_data && auth->protocol_data_length > 0) || 1357 !auth->network_id || !auth->auth_name || 1358 (!auth->auth_data && auth->auth_data_length > 0)) 1359 { 1360 goto add_bad_malloc; 1361 } 1362 1363 list = (AuthList *) malloc (sizeof (AuthList)); 1364 1365 if (!list) 1366 goto add_bad_malloc; 1367 1368 list->next = NULL; 1369 list->auth = auth; 1370 1371 /* 1372 * merge it in; note that merge will deal with allocation 1373 */ 1374 1375 n = merge_entries (&iceauth_head, list, &nnew, &nrepl, &ndup); 1376 1377 if (n > 0) 1378 iceauth_modified = True; 1379 else 1380 { 1381 prefix (inputfilename, lineno); 1382 if (ndup > 0) 1383 { 1384 status = 0; 1385 fprintf (stderr, "no records added - all duplicate\n"); 1386 } 1387 else 1388 { 1389 status = 1; 1390 fprintf (stderr, "unable to merge in added record\n"); 1391 } 1392 goto cant_add; 1393 } 1394 1395 return 0; 1396 1397 1398add_bad_malloc: 1399 1400 status = 1; 1401 prefix (inputfilename, lineno); 1402 fprintf (stderr, "unable to allocate memory to add an entry\n"); 1403 1404cant_add: 1405 1406 if (protodata) 1407 free (protodata); 1408 if (authdata) 1409 free (authdata); 1410 if (auth) 1411 { 1412 if (auth->protocol_name) 1413 free (auth->protocol_name); 1414 /* auth->protocol_data already freed, 1415 since it's the same as protodata */ 1416 if (auth->network_id) 1417 free (auth->network_id); 1418 if (auth->auth_name) 1419 free (auth->auth_name); 1420 /* auth->auth_data already freed, 1421 since it's the same as authdata */ 1422 free ((char *) auth); 1423 } 1424 1425 return status; 1426} 1427 1428/* 1429 * remove displayname 1430 */ 1431static int do_remove ( 1432 const char *inputfilename, 1433 int lineno, 1434 int argc, 1435 char **argv) 1436{ 1437 int nremoved = 0; 1438 int errors; 1439 1440 if (argc < 2) { 1441 prefix (inputfilename, lineno); 1442 badcommandline (argv[0]); 1443 return 1; 1444 } 1445 1446 errors = search_and_do (inputfilename, lineno, 1, argc, argv, 1447 remove_entry, &nremoved); 1448 if (verbose) printf ("%d entries removed\n", nremoved); 1449 return errors; 1450} 1451 1452/* 1453 * info 1454 */ 1455static int do_info ( 1456 const char *inputfilename, 1457 int lineno, 1458 int argc, 1459 char **argv) 1460{ 1461 int n; 1462 AuthList *l; 1463 1464 if (argc != 1) { 1465 prefix (inputfilename, lineno); 1466 badcommandline (argv[0]); 1467 return 1; 1468 } 1469 1470 for (l = iceauth_head, n = 0; l; l = l->next, n++) ; 1471 1472 printf ("Authority file: %s\n", 1473 iceauth_filename ? iceauth_filename : "(none)"); 1474 printf ("File new: %s\n", iceauth_existed ? No : Yes); 1475 printf ("File locked: %s\n", ignore_locks ? No : Yes); 1476 printf ("Number of entries: %d\n", n); 1477 printf ("Changes honored: %s\n", iceauth_allowed ? Yes : No); 1478 printf ("Changes made: %s\n", iceauth_modified ? Yes : No); 1479 printf ("Current input: %s:%d\n", inputfilename, lineno); 1480 return 0; 1481} 1482 1483 1484/* 1485 * exit 1486 */ 1487static Bool alldone = False; 1488 1489/* ARGSUSED */ 1490static int do_exit ( 1491 const char *inputfilename _X_UNUSED, 1492 int lineno _X_UNUSED, 1493 int argc _X_UNUSED, 1494 char **argv _X_UNUSED) 1495{ 1496 /* allow bogus stuff */ 1497 alldone = True; 1498 return 0; 1499} 1500 1501/* 1502 * quit 1503 */ 1504/* ARGSUSED */ 1505static int do_quit ( 1506 const char *inputfilename _X_UNUSED, 1507 int lineno _X_UNUSED, 1508 int argc _X_UNUSED, 1509 char **argv _X_UNUSED) 1510{ 1511 /* allow bogus stuff */ 1512 die (0); 1513 /* NOTREACHED */ 1514 return -1; /* for picky compilers */ 1515} 1516 1517 1518/* 1519 * source filename 1520 */ 1521static int do_source ( 1522 const char *inputfilename, 1523 int lineno, 1524 int argc, 1525 char **argv) 1526{ 1527 const char *script; 1528 char buf[BUFSIZ]; 1529 FILE *fp; 1530 Bool used_stdin = False; 1531 size_t len; 1532 int errors = 0, status; 1533 int sublineno = 0; 1534 char **subargv; 1535 int subargc; 1536 Bool prompt = False; /* only true if reading from tty */ 1537 1538 if (argc != 2 || !argv[1]) { 1539 prefix (inputfilename, lineno); 1540 badcommandline (argv[0]); 1541 return 1; 1542 } 1543 1544 script = argv[1]; 1545 1546 fp = open_file (&script, "r", &used_stdin, inputfilename, lineno, argv[0]); 1547 if (!fp) { 1548 return 1; 1549 } 1550 1551 if (verbose && used_stdin && isatty (fileno (fp))) prompt = True; 1552 1553 while (!alldone) { 1554 buf[0] = '\0'; 1555 if (prompt) { 1556 printf ("iceauth> "); 1557 fflush (stdout); 1558 } 1559 if (fgets (buf, sizeof buf, fp) == NULL) break; 1560 sublineno++; 1561 len = strlen (buf); 1562 if (len == 0 || buf[0] == '#') continue; 1563 if (buf[len-1] != '\n') { 1564 prefix (script, sublineno); 1565 fprintf (stderr, "line too long\n"); 1566 errors++; 1567 break; 1568 } 1569 buf[--len] = '\0'; /* remove new line */ 1570 subargv = split_into_words (buf, &subargc); 1571 if (subargv) { 1572 status = process_command (script, sublineno, subargc, subargv); 1573 free ((char *) subargv); 1574 errors += status; 1575 } else { 1576 prefix (script, sublineno); 1577 fprintf (stderr, "unable to break line into words\n"); 1578 errors++; 1579 } 1580 } 1581 1582 if (!used_stdin) { 1583 (void) fclose (fp); 1584 } 1585 return errors; 1586} 1587