auth: Don't leak key on file parse error
[openafs.git] / src / auth / keys.c
index aa265f1..ba6843d 100644 (file)
@@ -81,15 +81,20 @@ listToArray(struct kvnoList *kvnoEntry, struct afsconf_typedKeyList **keys)
     /* Allocate space for the keys we've got stored */
     retval = malloc(sizeof(struct afsconf_typedKeyList));
     retval->nkeys = opr_queue_Count(&kvnoEntry->subTypeList);
-    retval->keys  = calloc(retval->nkeys, sizeof(struct afsconf_typedKey *));
 
-    i = 0;
-    for(opr_queue_Scan(&kvnoEntry->subTypeList, cursor)) {
-       struct subTypeList *entry;
+    if (retval->nkeys > 0) {
+        retval->keys  = calloc(retval->nkeys, sizeof(struct afsconf_typedKey *));
 
-       entry = opr_queue_Entry(cursor, struct subTypeList, link);
-       retval->keys[i] = afsconf_typedKey_get(entry->key);
-       i++;
+       i = 0;
+        for(opr_queue_Scan(&kvnoEntry->subTypeList, cursor)) {
+           struct subTypeList *entry;
+
+           entry = opr_queue_Entry(cursor, struct subTypeList, link);
+           retval->keys[i] = afsconf_typedKey_get(entry->key);
+           i++;
+        }
+    } else {
+       retval->keys = NULL;
     }
 
     *keys = retval;
@@ -415,14 +420,17 @@ _writeOriginalKeyFile(struct afsconf_dir *dir, char *fileName)
        return AFSCONF_FAILURE;
 
     typeEntry = findByType(dir, afsconf_rxkad);
-    if (typeEntry == NULL)
-       goto out;
-
-    nkeys = opr_queue_Count(&typeEntry->kvnoList);
+    if (typeEntry)
+       nkeys = opr_queue_Count(&typeEntry->kvnoList);
+    else
+       nkeys = 0;
 
     if (writeWord(fd, nkeys))
        goto fail;
 
+    if (typeEntry == NULL)
+       goto out;
+
     for (opr_queue_Scan(&typeEntry->kvnoList, cursor)) {
        struct kvnoList *kvnoEntry;
         struct subTypeList *subEntry;
@@ -450,7 +458,7 @@ _parseExtendedKeyFile(struct afsconf_dir *dir, char *fileName)
 {
     int fd, i, code;
     afs_int32 nkeys;
-    struct afsconf_typedKey *key;
+    struct afsconf_typedKey *key = NULL;
 
     fd = open(fileName, O_RDONLY);
     if (fd < 0)
@@ -522,6 +530,9 @@ _parseExtendedKeyFile(struct afsconf_dir *dir, char *fileName)
     return 0;
 
 fail:
+    if (key)
+       afsconf_typedKey_put(&key);
+
     close(fd);
     return EIO;
 }
@@ -811,6 +822,73 @@ out:
 }
 
 int
+afsconf_GetAllKeys(struct afsconf_dir *dir, struct afsconf_typedKeyList **keys)
+{
+    int code;
+    struct afsconf_typedKeyList *retval;
+    struct opr_queue *typeCursor;
+    struct keyTypeList *typeEntry;
+    struct opr_queue *kvnoCursor;
+    struct kvnoList *kvnoEntry;
+    struct opr_queue *subCursor;
+    struct subTypeList *subEntry;
+    int count;
+
+    LOCK_GLOBAL_MUTEX;
+
+    code = _afsconf_Check(dir);
+    if (code)
+       goto out;
+
+    count = 0;
+    /* First, work out how many keys we have in total */
+    for (opr_queue_Scan(&dir->keyList, typeCursor)) {
+       typeEntry = opr_queue_Entry(typeCursor, struct keyTypeList, link);
+       for (opr_queue_Scan(&typeEntry->kvnoList, kvnoCursor)) {
+           kvnoEntry = opr_queue_Entry(kvnoCursor, struct kvnoList, link);
+           for (opr_queue_Scan(&kvnoEntry->subTypeList, subCursor)) {
+               subEntry = opr_queue_Entry(subCursor, struct subTypeList, link);
+               count++;
+           }
+       }
+    }
+
+    /* Allocate space for all of these */
+    retval = malloc(sizeof(struct afsconf_typedKeyList));
+    retval->nkeys = count;
+
+    if (count > 0) {
+       retval->keys = calloc(retval->nkeys,
+                             sizeof(struct afsconf_typedKey *));
+
+       /* Populate the key list */
+        count = 0;
+       for (opr_queue_Scan(&dir->keyList, typeCursor)) {
+           typeEntry = opr_queue_Entry(typeCursor,
+                                       struct keyTypeList, link);
+           for (opr_queue_Scan(&typeEntry->kvnoList, kvnoCursor)) {
+               kvnoEntry = opr_queue_Entry(kvnoCursor,
+                                           struct kvnoList, link);
+               for (opr_queue_Scan(&kvnoEntry->subTypeList, subCursor)) {
+                   subEntry = opr_queue_Entry(subCursor,
+                                              struct subTypeList, link);
+                   retval->keys[count] = afsconf_typedKey_get(subEntry->key);
+                   count++;
+               }
+           }
+       }
+    } else {
+       retval->keys = NULL;
+    }
+
+    *keys = retval;
+
+out:
+    UNLOCK_GLOBAL_MUTEX;
+    return code;
+}
+
+int
 afsconf_GetKeyByTypes(struct afsconf_dir *dir, afsconf_keyType type,
                      int kvno, int subType, struct afsconf_typedKey **key)
 {
@@ -932,7 +1010,10 @@ afsconf_PutTypedKeyList(struct afsconf_typedKeyList **keys)
 
      for (i=0;i<(*keys)->nkeys;i++)
        afsconf_typedKey_put(&((*keys)->keys[i]));
-     free((*keys)->keys);
+
+     if ((*keys)->keys != NULL)
+       free((*keys)->keys);
+
      free(*keys);
      *keys = NULL;
 }