auth: Refactor CellServDB path creation
[openafs.git] / src / auth / cellconfig.c
index f20173f..b15408c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Copyright 2000, International Business Machines Corporation and others.
  * All Rights Reserved.
- * 
+ *
  * This software has been released under the terms of the IBM Public
  * License.  For details, see the LICENSE file in the top-level source
  * directory or online at http://www.openafs.org/dl/license10.html
 #include <afsconfig.h>
 #include <afs/param.h>
 
+#include <roken.h>
 
 #include <afs/stds.h>
 #include <afs/pthread_glock.h>
-#ifdef UKERNEL
-#include "afs/sysincludes.h"
-#include "afsincludes.h"
-#include "des/des.h"
-#include "rx/rxkad.h"
-#include <netdb.h>
-#include <ctype.h>
-#else /* UKERNEL */
 #include <sys/types.h>
 #ifdef AFS_NT40_ENV
 #include <winsock2.h>
 #endif
 #include <rx/rxkad.h>
 #include <rx/rx.h>
-#endif /* UKERNEL */
+
 #include <afs/afsutil.h>
-#include "cellconfig.h"
 #include "keys.h"
+#include "cellconfig.h"
+#include "internal.h"
+
 #ifdef AFS_NT40_ENV
 #include <cm.h>
 #include <cm_config.h>
@@ -92,22 +87,18 @@ static struct afsconf_servPair serviceTable[] = {
 
 /* Prototypes */
 static int TrimLine(char *abuffer, int abufsize);
-static int IsClientConfigDirectory(const char *path);
 #ifdef AFS_NT40_ENV
 static int GetCellNT(struct afsconf_dir *adir);
 #endif
-static int afsconf_Check(register struct afsconf_dir *adir);
-static int afsconf_Touch(register struct afsconf_dir *adir);
 static int GetCellUnix(struct afsconf_dir *adir);
-static int afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
+static int afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
                                char clones[]);
-static int ParseHostLine(char *aline, register struct sockaddr_in *addr,
+static int ParseHostLine(char *aline, struct sockaddr_in *addr,
                         char *aname, char *aclone);
-static int ParseCellLine(register char *aline, register char *aname,
-                        register char *alname);
-static int afsconf_CloseInternal(register struct afsconf_dir *adir);
-static int afsconf_Reopen(register struct afsconf_dir *adir);
-static int SaveKeys(struct afsconf_dir *adir);
+static int ParseCellLine(char *aline, char *aname,
+                        char *alname);
+static int afsconf_CloseInternal(struct afsconf_dir *adir);
+static int afsconf_Reopen(struct afsconf_dir *adir);
 
 #ifndef T_AFSDB
 #define T_AFSDB 18             /* per RFC1183 section 1 */
@@ -127,7 +118,7 @@ static int SaveKeys(struct afsconf_dir *adir);
 /* Solaris through 10 in 32 bit mode will return EMFILE if fopen can't
    get an fd <= 255. We allow the fileserver to claim more fds than that.
    This has always been a problem since pr_Initialize would have the same
-   issue, but hpr_Initialize makes it more likely that we would see this. 
+   issue, but hpr_Initialize makes it more likely that we would see this.
    Work around it. This is not generic. It's coded with the needs of
    afsconf_* in mind only.
 
@@ -150,11 +141,11 @@ afsconf_fopen(const char *fname, const char *fmode)
 {
     int fd;
     afsconf_FILE *iop;
-    
+
     if ((fd = open(fname, O_RDONLY)) == -1) {
        return NULL;
     }
-    
+
     iop = malloc(sizeof(struct afsconf_iobuffer));
     if (iop == NULL) {
        (void) close(fd);
@@ -190,14 +181,14 @@ static char *
 afsconf_fgets(char *s, int n, afsconf_FILE *iop)
 {
     char *p;
-    
+
     p = s;
     for (;;) {
        char c;
-       
+
        if (iop->ptr == iop->endptr) {
            ssize_t len;
-           
+
            if ((len = read(iop->_file, (void *)iop->buffer, BUFFER)) == -1) {
                return NULL;
            }
@@ -241,7 +232,7 @@ afsconf_FindService(const char *aname)
     if (aname == NULL || aname[0] == '\0')
        return -1;
 
-#if     defined(AFS_OSF_ENV) 
+#if     defined(AFS_OSF_ENV)
     ts = getservbyname(aname, "");
 #else
     ts = (struct servent *) getservbyname(aname, NULL);
@@ -282,8 +273,8 @@ static int
 TrimLine(char *abuffer, int abufsize)
 {
     char tbuffer[256];
-    register char *tp;
-    register int tc;
+    char *tp;
+    int tc;
 
     tp = abuffer;
     while ((tc = *tp)) {
@@ -305,8 +296,8 @@ TrimLine(char *abuffer, int abufsize)
 #else /* AFS_NT40_ENV */
 #define IS_SEP(x) ((x) == '/')
 #endif /* AFS_NT40_ENV */
-static int
-IsClientConfigDirectory(const char *path)
+int
+_afsconf_IsClientConfigDirectory(const char *path)
 {
     const char *cdir = AFSDIR_CLIENT_ETC_DIRPATH;
     int i, cc, pc;
@@ -345,105 +336,113 @@ IsClientConfigDirectory(const char *path)
     return 1;
 }
 
-
-static int
-afsconf_Check(register struct afsconf_dir *adir)
-{
-    char tbuffer[256];
 #ifdef AFS_NT40_ENV
+static void
+_afsconf_CellServDBPath(struct afsconf_dir *adir, char **path)
+{
     char *p;
-#endif
-    struct stat tstat;
-    register afs_int32 code;
 
-#ifdef AFS_NT40_ENV
     /* NT client CellServDB has different file name than NT server or Unix */
-    if (IsClientConfigDirectory(adir->name)) {
+    if (_afsconf_IsClientConfigDirectory(adir->name)) {
        if (!afssw_GetClientCellServDBDir(&p)) {
-           strcompose(tbuffer, sizeof(tbuffer), p, "/",
-                      AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
+           asprintf(path, "%s/%s", p, AFSDIR_CELLSERVDB_FILE_NTCLIENT);
            free(p);
        } else {
-           int len;
-           strncpy(tbuffer, adir->name, sizeof(tbuffer));
-           len = (int)strlen(tbuffer);
-           if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
-               strncat(tbuffer, "\\", sizeof(tbuffer));
-           }
-           strncat(tbuffer, AFSDIR_CELLSERVDB_FILE_NTCLIENT,
-                   sizeof(tbuffer));
-           tbuffer[sizeof(tbuffer) - 1] = '\0';
+           asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE_NTCLIENT);
        }
     } else {
-       strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE,
-                  NULL);
+       asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE);
     }
+    return;
+}
 #else
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
+static void
+_afsconf_CellServDBPath(struct afsconf_dir *adir, char **path)
+{
+    asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE);
+}
 #endif /* AFS_NT40_ENV */
 
-    code = stat(tbuffer, &tstat);
-    if (code < 0) {
-       return code;
-    }
+int
+_afsconf_UpToDate(struct afsconf_dir *adir)
+{
+    char *cellservDB;
+    struct stat tstat;
+    int code;
+
+    _afsconf_CellServDBPath(adir, &cellservDB);
+    if (cellservDB == NULL)
+       return 0;
+
+    code = stat(cellservDB, &tstat);
+    free(cellservDB);
+    if (code < 0)
+       return 0; /* Can't throw the error, so just say we're not up to date */
+
     /* did file change? */
-    if (tstat.st_mtime == adir->timeRead) {
+    if (tstat.st_mtime == adir->timeRead)
+       return 1;
+
+    /* otherwise file has changed */
+    return 0;
+}
+
+int
+afsconf_UpToDate(void *rock)
+{
+    int code;
+
+    LOCK_GLOBAL_MUTEX;
+    code = _afsconf_UpToDate(rock);
+    UNLOCK_GLOBAL_MUTEX;
+
+    return code;
+}
+
+int
+_afsconf_Check(struct afsconf_dir *adir)
+{
+    /* did configuration change? */
+    if (_afsconf_UpToDate(adir))
        return 0;
-    }
+
     /* otherwise file has changed, so reopen it */
     return afsconf_Reopen(adir);
 }
 
 /* set modtime on file */
-static int
-afsconf_Touch(register struct afsconf_dir *adir)
+int
+_afsconf_Touch(struct afsconf_dir *adir)
 {
-    char tbuffer[256];
+    char *cellservDB;
+    int code;
 #ifndef AFS_NT40_ENV
     struct timeval tvp[2];
-#else
-    char *p;
 #endif
 
     adir->timeRead = 0;                /* just in case */
 
-#ifdef AFS_NT40_ENV
-    /* NT client CellServDB has different file name than NT server or Unix */
-
-    if (IsClientConfigDirectory(adir->name)) {
-       if (!afssw_GetClientCellServDBDir(&p)) {
-           strcompose(tbuffer, sizeof(tbuffer), p, "/",
-                      AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
-           free(p);
-       } else {
-           int len = (int)strlen(tbuffer);
-           if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
-               strncat(tbuffer, "\\", sizeof(tbuffer));
-           }
-           strncat(tbuffer, AFSDIR_CELLSERVDB_FILE_NTCLIENT,
-                   sizeof(tbuffer));
-           tbuffer[sizeof(tbuffer) - 1] = '\0';
-       }
-    } else {
-       strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE,
-                  NULL);
-    }
-
-    return _utime(tbuffer, NULL);
+    _afsconf_CellServDBPath(adir, &cellservDB);
+    if (cellservDB == NULL)
+       return ENOMEM;
 
+#ifdef AFS_NT40_ENV
+    code = _utime(cellservDB, NULL);
 #else
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
     gettimeofday(&tvp[0], NULL);
     tvp[1] = tvp[0];
-    return utimes(tbuffer, tvp);
+    code = utimes(cellservDB, tvp);
 #endif /* AFS_NT40_ENV */
+    free(cellservDB);
+
+    return code;
 }
 
 struct afsconf_dir *
-afsconf_Open(register const char *adir)
+afsconf_Open(const char *adir)
 {
-    register struct afsconf_dir *tdir;
-    register afs_int32 code;
+    struct afsconf_dir *tdir;
+    afs_int32 code;
 
     LOCK_GLOBAL_MUTEX;
     /* zero structure and fill in name; rest is done by internal routine */
@@ -521,7 +520,7 @@ GetCellUnix(struct afsconf_dir *adir)
     char tbuffer[256];
     char *start, *p;
     afsconf_FILE *fp;
-    
+
     strcompose(tbuffer, 256, adir->name, "/", AFSDIR_THISCELL_FILE, NULL);
     fp = fopen(tbuffer, "r");
     if (fp == 0) {
@@ -551,7 +550,7 @@ GetCellUnix(struct afsconf_dir *adir)
 static int
 GetCellNT(struct afsconf_dir *adir)
 {
-    if (IsClientConfigDirectory(adir->name)) {
+    if (_afsconf_IsClientConfigDirectory(adir->name)) {
        /* NT client config dir; ThisCell is in registry (no file). */
        return afssw_GetClientCellName(&adir->cellName);
     } else {
@@ -561,7 +560,7 @@ GetCellNT(struct afsconf_dir *adir)
 }
 
 /* The following procedures and structs are used on Windows only
- * to enumerate the Cell information distributed within the 
+ * to enumerate the Cell information distributed within the
  * Windows registry.  (See src/WINNT/afsd/cm_config.c)
  */
 typedef struct _cm_enumCellRegistry {
@@ -570,7 +569,7 @@ typedef struct _cm_enumCellRegistry {
 } cm_enumCellRegistry_t;
 
 static long
-cm_serverConfigProc(void *rockp, struct sockaddr_in *addrp, 
+cm_serverConfigProc(void *rockp, struct sockaddr_in *addrp,
                     char *hostNamep, unsigned short rank)
 {
     struct afsconf_cell *cellInfop = (struct afsconf_cell *)rockp;
@@ -621,22 +620,24 @@ cm_enumCellRegistryProc(void *rockp, char * cellNamep)
         free(newEntry);
     }
     return code;
-}       
+}
 #endif /* AFS_NT40_ENV */
 
 
 static int
-afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
+afsconf_OpenInternal(struct afsconf_dir *adir, char *cell,
                     char clones[])
 {
     afsconf_FILE *tf;
-    register char *tp, *bp;
-    register struct afsconf_entry *curEntry;
+    char *tp, *bp;
+    struct afsconf_entry *curEntry;
     struct afsconf_aliasentry *curAlias;
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 i;
-    char tbuffer[256], tbuf1[256];
+    char tbuffer[256];
     struct stat tstat;
+    char *cellservDB;
+
 #ifdef AFS_NT40_ENV
     cm_enumCellRegistry_t enumCellRegistry = {0, 0};
 #endif /* AFS_NT40_ENV */
@@ -658,61 +659,33 @@ afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
     /* now parse the individual lines */
     curEntry = 0;
 
-#ifdef AFS_NT40_ENV
-    /* NT client/server have a CellServDB that is the same format as Unix.
-     * However, the NT client uses a different file name
-     */
-    if (IsClientConfigDirectory(adir->name)) {
-       /* NT client config dir */
-       char *p;
+    _afsconf_CellServDBPath(adir, &cellservDB);
 
+#ifdef AFS_NT40_ENV
+    if (_afsconf_IsClientConfigDirectory(adir->name))
         enumCellRegistry.client = 1;
-
-       if (!afssw_GetClientCellServDBDir(&p)) {
-           strcompose(tbuffer, sizeof(tbuffer), p, "/",
-                      AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
-           free(p);
-       } else {
-           int len;
-           strncpy(tbuffer, adir->name, sizeof(tbuffer));
-           len = (int)strlen(tbuffer);
-           if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
-               strncat(tbuffer, "\\", sizeof(tbuffer));
-           }
-           strncat(tbuffer, AFSDIR_CELLSERVDB_FILE_NTCLIENT,
-                   sizeof(tbuffer));
-           tbuffer[sizeof(tbuffer) - 1] = '\0';
-       }
-    } else {
-       /* NT server config dir */
-       strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE,
-                  NULL);
-    }
-#else
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLSERVDB_FILE, NULL);
 #endif /* AFS_NT40_ENV */
 
-    if (!stat(tbuffer, &tstat)) {
+    if (!stat(cellservDB, &tstat)) {
        adir->timeRead = tstat.st_mtime;
     } else {
        adir->timeRead = 0;
     }
 
-    strlcpy(tbuf1, tbuffer, sizeof tbuf1);
-    tf = fopen(tbuffer, "r");
+    tf = fopen(cellservDB, "r");
     if (!tf) {
        return -1;
     }
 
-    /* The CellServDB file is now open.  
-     * The following code parses the contents of the 
+    /* The CellServDB file is now open.
+     * The following code parses the contents of the
      * file and creates a list with the first cell entry
      * in the CellServDB file at the end of the list.
-     * 
+     *
      * No checking is performed for duplicates.
      * The side effects of this process are that duplicate
      * entries appended to the end of the CellServDB file
-     * take precedence and are found in a shorter period 
+     * take precedence and are found in a shorter period
      * of time.
      */
 
@@ -756,13 +729,13 @@ afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
            if (i < MAXHOSTSPERCELL) {
                if (cell && !strcmp(cell, curEntry->cellInfo.name))
                    code =
-                       ParseHostLine(tbuffer, 
+                       ParseHostLine(tbuffer,
                                      &curEntry->cellInfo.hostAddr[i],
-                                     curEntry->cellInfo.hostName[i], 
+                                     curEntry->cellInfo.hostName[i],
                                      &clones[i]);
                else
                    code =
-                       ParseHostLine(tbuffer, 
+                       ParseHostLine(tbuffer,
                                      &curEntry->cellInfo.hostAddr[i],
                                      curEntry->cellInfo.hostName[i], 0);
 
@@ -775,7 +748,7 @@ afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
                        *bp = '\0';
                        fprintf(stderr,
                                "Can't properly parse host line \"%s\" in configuration file %s\n",
-                               tbuffer, tbuf1);
+                               tbuffer, cellservDB);
                    }
                    free(curEntry);
                    fclose(tf);
@@ -785,12 +758,13 @@ afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
                curEntry->cellInfo.numServers = ++i;
            } else {
                fprintf(stderr,
-                       "Too many hosts for cell %s in configuration file %s\n", 
-                       curEntry->cellInfo.name, tbuf1);
+                       "Too many hosts for cell %s in configuration file %s\n",
+                       curEntry->cellInfo.name, cellservDB);
            }
        }
     }
     fclose(tf);                        /* close the file now */
+    free(cellservDB);
 
     /* end the last partially-completed cell */
     if (curEntry) {
@@ -799,10 +773,10 @@ afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
     }
 
 #ifdef AFS_NT40_ENV
-     /* 
+     /*
       * Windows maintains a CellServDB list in the Registry
       * that supercedes the contents of the CellServDB file.
-      * Prepending these entries to the head of the list 
+      * Prepending these entries to the head of the list
       * is sufficient to enforce the precedence.
       */
      cm_EnumerateCellRegistry( enumCellRegistry.client,
@@ -855,24 +829,25 @@ afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
     if (tf != NULL)
        fclose(tf);
     /* now read the fs keys, if possible */
-    adir->keystr = (struct afsconf_keys *)0;
-    afsconf_IntGetKeys(adir);
 
-    return 0;
+    _afsconf_InitKeys(adir);
+    code = _afsconf_LoadKeys(adir);
+
+    return code;
 }
 
 /* parse a line of the form
  *"128.2.1.3   #hostname" or
  *"[128.2.1.3]  #hostname" for clones
- * into the appropriate pieces.  
+ * into the appropriate pieces.
  */
 static int
-ParseHostLine(char *aline, register struct sockaddr_in *addr, char *aname,
+ParseHostLine(char *aline, struct sockaddr_in *addr, char *aname,
              char *aclone)
 {
     int c1, c2, c3, c4;
-    register afs_int32 code;
-    register char *tp;
+    afs_int32 code;
+    char *tp;
 
     if (*aline == '[') {
        if (aclone)
@@ -905,10 +880,10 @@ ParseHostLine(char *aline, register struct sockaddr_in *addr, char *aname,
  * into the appropriate pieces.
  */
 static int
-ParseCellLine(register char *aline, register char *aname,
-             register char *alname)
+ParseCellLine(char *aline, char *aname,
+             char *alname)
 {
-    register int code;
+    int code;
     /* FIXME: length of aname, alname unknown here */
     code = sscanf(aline, ">%s %s", aname, alname);
     if (code == 1)
@@ -927,8 +902,8 @@ afsconf_CellApply(struct afsconf_dir *adir,
                  int (*aproc) (struct afsconf_cell * cell, void *arock,
                                struct afsconf_dir * dir), void *arock)
 {
-    register struct afsconf_entry *tde;
-    register afs_int32 code;
+    struct afsconf_entry *tde;
+    afs_int32 code;
     LOCK_GLOBAL_MUTEX;
     for (tde = adir->entries; tde; tde = tde->next) {
        code = (*aproc) (&tde->cellInfo, arock, adir);
@@ -950,8 +925,8 @@ afsconf_CellAliasApply(struct afsconf_dir *adir,
                                     void *arock, struct afsconf_dir * dir),
                       void *arock)
 {
-    register struct afsconf_aliasentry *tde;
-    register afs_int32 code;
+    struct afsconf_aliasentry *tde;
+    afs_int32 code;
     LOCK_GLOBAL_MUTEX;
     for (tde = adir->alias_entries; tde; tde = tde->next) {
        code = (*aproc) (&tde->aliasInfo, arock, adir);
@@ -1170,7 +1145,7 @@ afsconf_LookupServer(const char *service, const char *protocol,
                memcpy(&ipaddr, he->h_addr, he->h_length);
                cellHostAddrs[server_num] = ipaddr;
                ipRanks[server_num] = (p[0] << 8) | p[1];
-               ports[server_num] = (p[4] << 8) | p[5];
+               ports[server_num] = htons((p[4] << 8) | p[5]);
                /* weight = (p[2] << 8) | p[3]; */
                strncpy(cellHostNames[server_num], host,
                        sizeof(cellHostNames[server_num]));
@@ -1335,10 +1310,10 @@ int
 afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
                    struct afsconf_cell *acellInfo)
 {
-    register struct afsconf_entry *tce;
+    struct afsconf_entry *tce;
     struct afsconf_aliasentry *tcae;
     struct afsconf_entry *bestce;
-    register afs_int32 i;
+    afs_int32 i;
     int tservice;
     char *tcell;
     int cnLen;
@@ -1347,7 +1322,7 @@ afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
 
     LOCK_GLOBAL_MUTEX;
     if (adir)
-       afsconf_Check(adir);
+       _afsconf_Check(adir);
     if (acellName) {
        tcell = acellName;
        cnLen = (int)(strlen(tcell) + 1);
@@ -1407,12 +1382,12 @@ afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
        }
        acellInfo->timeout = 0;
 
-        /* 
+        /*
          * Until we figure out how to separate out ubik server
          * queries from other server queries, only perform gethostbyname()
          * lookup on the specified hostnames for the client CellServDB files.
          */
-        if (IsClientConfigDirectory(adir->name) && 
+        if (_afsconf_IsClientConfigDirectory(adir->name) &&
             !(acellInfo->flags & AFSCONF_CELL_FLAG_DNS_QUERIED)) {
             int j;
             short numServers=0;                                        /*Num active servers for the cell */
@@ -1473,7 +1448,7 @@ afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice,
 }
 
 int
-afsconf_GetLocalCell(register struct afsconf_dir *adir, char *aname,
+afsconf_GetLocalCell(struct afsconf_dir *adir, char *aname,
                     afs_int32 alen)
 {
     static int afsconf_showcell = 0;
@@ -1482,7 +1457,7 @@ afsconf_GetLocalCell(register struct afsconf_dir *adir, char *aname,
 
     LOCK_GLOBAL_MUTEX;
     /*
-     * If a cell switch was specified in a command, then it should override the 
+     * If a cell switch was specified in a command, then it should override the
      * AFSCELL variable.  If a cell was specified, then the afsconf_SawCell flag
      * is set and the cell name in the adir structure is used.
      * Read the AFSCELL var each time: in case it changes (unsetenv AFSCELL).
@@ -1495,7 +1470,7 @@ afsconf_GetLocalCell(register struct afsconf_dir *adir, char *aname,
        }
        strncpy(aname, afscell_path, alen);
     } else {
-       afsconf_Check(adir);
+       _afsconf_Check(adir);
        if (adir->cellName) {
            strncpy(aname, adir->cellName, alen);
        } else
@@ -1519,11 +1494,11 @@ afsconf_Close(struct afsconf_dir *adir)
 }
 
 static int
-afsconf_CloseInternal(register struct afsconf_dir *adir)
+afsconf_CloseInternal(struct afsconf_dir *adir)
 {
-    register struct afsconf_entry *td, *nd;
+    struct afsconf_entry *td, *nd;
     struct afsconf_aliasentry *ta, *na;
-    register char *tname;
+    char *tname;
 
     tname = adir->name;                /* remember name, since that's all we preserve */
 
@@ -1540,8 +1515,8 @@ afsconf_CloseInternal(register struct afsconf_dir *adir)
        na = ta->next;
        free(ta);
     }
-    if (adir->keystr)
-       free(adir->keystr);
+
+    _afsconf_FreeAllKeys(adir);
 
     /* reinit */
     memset(adir, 0, sizeof(struct afsconf_dir));
@@ -1550,270 +1525,12 @@ afsconf_CloseInternal(register struct afsconf_dir *adir)
 }
 
 static int
-afsconf_Reopen(register struct afsconf_dir *adir)
+afsconf_Reopen(struct afsconf_dir *adir)
 {
-    register afs_int32 code;
+    afs_int32 code;
     code = afsconf_CloseInternal(adir);
     if (code)
        return code;
     code = afsconf_OpenInternal(adir, 0, 0);
     return code;
 }
-
-/* called during opening of config file */
-int
-afsconf_IntGetKeys(struct afsconf_dir *adir)
-{
-    char tbuffer[256];
-    register int fd;
-    struct afsconf_keys *tstr;
-    register afs_int32 code;
-
-#ifdef AFS_NT40_ENV
-    /* NT client config dir has no KeyFile; don't risk attempting open
-     * because there might be a random file of this name if dir is shared.
-     */
-    if (IsClientConfigDirectory(adir->name)) {
-       adir->keystr = ((struct afsconf_keys *)
-                       malloc(sizeof(struct afsconf_keys)));
-       adir->keystr->nkeys = 0;
-       return 0;
-    }
-#endif /* AFS_NT40_ENV */
-
-    LOCK_GLOBAL_MUTEX;
-    /* compute the key name and other setup */
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_KEY_FILE, NULL);
-    tstr = (struct afsconf_keys *)malloc(sizeof(struct afsconf_keys));
-    adir->keystr = tstr;
-
-    /* read key file */
-    fd = open(tbuffer, O_RDONLY);
-    if (fd < 0) {
-       tstr->nkeys = 0;
-       UNLOCK_GLOBAL_MUTEX;
-       return 0;
-    }
-    code = read(fd, tstr, sizeof(struct afsconf_keys));
-    close(fd);
-    if (code < sizeof(afs_int32)) {
-       tstr->nkeys = 0;
-       UNLOCK_GLOBAL_MUTEX;
-       return 0;
-    }
-
-    /* convert key structure to host order */
-    tstr->nkeys = ntohl(tstr->nkeys);
-
-    if (code < sizeof(afs_int32) + (tstr->nkeys*sizeof(struct afsconf_key))) {
-       tstr->nkeys = 0;
-       UNLOCK_GLOBAL_MUTEX;
-       return 0;
-    }
-
-    for (fd = 0; fd < tstr->nkeys; fd++)
-       tstr->key[fd].kvno = ntohl(tstr->key[fd].kvno);
-
-    UNLOCK_GLOBAL_MUTEX;
-    return 0;
-}
-
-/* get keys structure */
-int
-afsconf_GetKeys(struct afsconf_dir *adir, struct afsconf_keys *astr)
-{
-    register afs_int32 code;
-
-    LOCK_GLOBAL_MUTEX;
-    code = afsconf_Check(adir);
-    if (code) {
-       UNLOCK_GLOBAL_MUTEX;
-       return AFSCONF_FAILURE;
-    }
-    memcpy(astr, adir->keystr, sizeof(struct afsconf_keys));
-    UNLOCK_GLOBAL_MUTEX;
-    return 0;
-}
-
-/* get latest key */
-afs_int32
-afsconf_GetLatestKey(struct afsconf_dir * adir, afs_int32 * avno, 
-                    struct ktc_encryptionKey *akey)
-{
-    register int i;
-    int maxa;
-    register struct afsconf_key *tk;
-    register afs_int32 best;
-    struct afsconf_key *bestk;
-    register afs_int32 code;
-
-    LOCK_GLOBAL_MUTEX;
-    code = afsconf_Check(adir);
-    if (code) {
-       UNLOCK_GLOBAL_MUTEX;
-       return AFSCONF_FAILURE;
-    }
-    maxa = adir->keystr->nkeys;
-
-    best = -1;                 /* highest kvno we've seen yet */
-    bestk = (struct afsconf_key *)0;   /* ptr to structure providing best */
-    for (tk = adir->keystr->key, i = 0; i < maxa; i++, tk++) {
-       if (tk->kvno == 999)
-           continue;           /* skip bcrypt keys */
-       if (tk->kvno > best) {
-           best = tk->kvno;
-           bestk = tk;
-       }
-    }
-    if (bestk) {               /* found any  */
-       if (akey)
-           memcpy(akey, bestk->key, 8);        /* copy out latest key */
-       if (avno)
-           *avno = bestk->kvno;        /* and kvno to caller */
-       UNLOCK_GLOBAL_MUTEX;
-       return 0;
-    }
-    UNLOCK_GLOBAL_MUTEX;
-    return AFSCONF_NOTFOUND;   /* didn't find any keys */
-}
-
-/* get a particular key */
-int
-afsconf_GetKey(void *rock, int avno, struct ktc_encryptionKey *akey)
-{
-    struct afsconf_dir *adir = (struct afsconf_dir *) rock;
-    register int i, maxa;
-    register struct afsconf_key *tk;
-    register afs_int32 code;
-
-    LOCK_GLOBAL_MUTEX;
-    code = afsconf_Check(adir);
-    if (code) {
-       UNLOCK_GLOBAL_MUTEX;
-       return AFSCONF_FAILURE;
-    }
-    maxa = adir->keystr->nkeys;
-
-    for (tk = adir->keystr->key, i = 0; i < maxa; i++, tk++) {
-       if (tk->kvno == avno) {
-           memcpy(akey, tk->key, 8);
-           UNLOCK_GLOBAL_MUTEX;
-           return 0;
-       }
-    }
-
-    UNLOCK_GLOBAL_MUTEX;
-    return AFSCONF_NOTFOUND;
-}
-
-/* save the key structure in the appropriate file */
-static int
-SaveKeys(struct afsconf_dir *adir)
-{
-    struct afsconf_keys tkeys;
-    register int fd;
-    register afs_int32 i;
-    char tbuffer[256];
-
-    memcpy(&tkeys, adir->keystr, sizeof(struct afsconf_keys));
-
-    /* convert it to net byte order */
-    for (i = 0; i < tkeys.nkeys; i++)
-       tkeys.key[i].kvno = htonl(tkeys.key[i].kvno);
-    tkeys.nkeys = htonl(tkeys.nkeys);
-
-    /* rewrite keys file */
-    strcompose(tbuffer, 256, adir->name, "/", AFSDIR_KEY_FILE, NULL);
-    fd = open(tbuffer, O_RDWR | O_CREAT | O_TRUNC, 0600);
-    if (fd < 0)
-       return AFSCONF_FAILURE;
-    i = write(fd, &tkeys, sizeof(tkeys));
-    if (i != sizeof(tkeys)) {
-       close(fd);
-       return AFSCONF_FAILURE;
-    }
-    if (close(fd) < 0)
-       return AFSCONF_FAILURE;
-    return 0;
-}
-
-int
-afsconf_AddKey(struct afsconf_dir *adir, afs_int32 akvno, char akey[8],
-              afs_int32 overwrite)
-{
-    register struct afsconf_keys *tk;
-    register struct afsconf_key *tkey;
-    register afs_int32 i;
-    int foundSlot;
-
-    LOCK_GLOBAL_MUTEX;
-    tk = adir->keystr;
-
-    if (akvno != 999) {
-       if (akvno < 0 || akvno > 255) {
-           UNLOCK_GLOBAL_MUTEX;
-           return ERANGE;
-       }
-    }
-    foundSlot = 0;
-    for (i = 0, tkey = tk->key; i < tk->nkeys; i++, tkey++) {
-       if (tkey->kvno == akvno) {
-           if (!overwrite) {
-               UNLOCK_GLOBAL_MUTEX;
-               return AFSCONF_KEYINUSE;
-           }
-           foundSlot = 1;
-           break;
-       }
-    }
-    if (!foundSlot) {
-       if (tk->nkeys >= AFSCONF_MAXKEYS) {
-           UNLOCK_GLOBAL_MUTEX;
-           return AFSCONF_FULL;
-       }
-       tkey = &tk->key[tk->nkeys++];
-    }
-    tkey->kvno = akvno;
-    memcpy(tkey->key, akey, 8);
-    i = SaveKeys(adir);
-    afsconf_Touch(adir);
-    UNLOCK_GLOBAL_MUTEX;
-    return i;
-}
-
-/* this proc works by sliding the other guys down, rather than using a funny
-    kvno value, so that callers can count on getting a good key in key[0].
-*/
-int
-afsconf_DeleteKey(struct afsconf_dir *adir, afs_int32 akvno)
-{
-    register struct afsconf_keys *tk;
-    register struct afsconf_key *tkey;
-    register int i;
-    int foundFlag = 0;
-
-    LOCK_GLOBAL_MUTEX;
-    tk = adir->keystr;
-
-    for (i = 0, tkey = tk->key; i < tk->nkeys; i++, tkey++) {
-       if (tkey->kvno == akvno) {
-           foundFlag = 1;
-           break;
-       }
-    }
-    if (!foundFlag) {
-       UNLOCK_GLOBAL_MUTEX;
-       return AFSCONF_NOTFOUND;
-    }
-
-    /* otherwise slide the others down.  i and tkey point at the guy to delete */
-    for (; i < tk->nkeys - 1; i++, tkey++) {
-       tkey->kvno = (tkey + 1)->kvno;
-       memcpy(tkey->key, (tkey + 1)->key, 8);
-    }
-    tk->nkeys--;
-    i = SaveKeys(adir);
-    afsconf_Touch(adir);
-    UNLOCK_GLOBAL_MUTEX;
-    return i;
-}