]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
sshkey: Add support for parsing keys from files
authorTobias Brunner <tobias@strongswan.org>
Mon, 19 Aug 2013 11:15:28 +0000 (13:15 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 13 Sep 2013 13:23:49 +0000 (15:23 +0200)
src/libstrongswan/plugins/sshkey/sshkey_builder.c

index d6a7c645aa6fad2231886d5fd3cd8a9c44efe14d..61e829fdff8abbc5adddf95701f9394370bd0aca 100644 (file)
  * for more details.
  */
 
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
 #include "sshkey_builder.h"
 
 #include <asn1/oid.h>
@@ -124,12 +128,85 @@ static sshkey_public_key_t *parse_public_key(chunk_t blob)
        return NULL;
 }
 
+/**
+ * Load SSH key from a FILE stream, closes the stream
+ */
+static sshkey_public_key_t *load_from_stream(FILE *file)
+{
+       sshkey_public_key_t *public = NULL;
+       chunk_t blob = chunk_empty;
+       enumerator_t *enumerator;
+       char line[1024], *token;
+
+       while (!public && fgets(line, sizeof(line), file))
+       {       /* the format is: ssh-[rsa|ecdsa-...] <key(base64)> <identifier> */
+               if (!strpfx(line, "ssh-"))
+               {
+                       continue;
+               }
+               enumerator = enumerator_create_token(line, " ", " ");
+               if (enumerator->enumerate(enumerator, &token) &&
+                       enumerator->enumerate(enumerator, &token))
+               {
+                       blob = chunk_from_base64(chunk_from_str(token), NULL);
+               }
+               enumerator->destroy(enumerator);
+               if (blob.ptr)
+               {
+                       public = parse_public_key(blob);
+                       chunk_free(&blob);
+               }
+       }
+       fclose(file);
+       return public;
+}
+
+/**
+ * Load SSH key from FD
+ */
+static sshkey_public_key_t *load_from_fd(int fd)
+{
+       FILE *stream;
+
+       /* dup the FD as it gets closed in fclose() */
+       fd = dup(fd);
+       if (fd == -1)
+       {
+               return NULL;
+       }
+       stream = fdopen(fd, "r");
+       if (!stream)
+       {
+               close(fd);
+               return NULL;
+       }
+       return load_from_stream(stream);
+}
+
+/**
+ * Load SSH key from file
+ */
+static sshkey_public_key_t *load_from_file(char *file)
+{
+       FILE *stream;
+
+       stream = fopen(file, "r");
+       if (!stream)
+       {
+               DBG1(DBG_LIB, "  opening '%s' failed: %s", file, strerror(errno));
+               return NULL;
+       }
+       return load_from_stream(stream);
+}
+
 /**
  * See header.
  */
 sshkey_public_key_t *sshkey_public_key_load(key_type_t type, va_list args)
 {
        chunk_t blob = chunk_empty;
+       char *file = NULL;
+       int fd = -1;
 
        while (TRUE)
        {
@@ -138,6 +215,12 @@ sshkey_public_key_t *sshkey_public_key_load(key_type_t type, va_list args)
                        case BUILD_BLOB_SSHKEY:
                                blob = va_arg(args, chunk_t);
                                continue;
+                       case BUILD_FROM_FILE:
+                               file = va_arg(args, char*);
+                               continue;
+                       case BUILD_FROM_FD:
+                               fd = va_arg(args, int);
+                               continue;
                        case BUILD_END:
                                break;
                        default:
@@ -145,9 +228,17 @@ sshkey_public_key_t *sshkey_public_key_load(key_type_t type, va_list args)
                }
                break;
        }
-       if (blob.ptr && type == KEY_ANY)
+       if (blob.ptr)
        {
                return parse_public_key(blob);
        }
+       if (file)
+       {
+               return load_from_file(file);
+       }
+       if (fd != -1)
+       {
+               return load_from_fd(fd);
+       }
        return NULL;
 }