]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mount.ceph: Use kernel key management API when possible.
authorTommi Virtanen <tommi.virtanen@dreamhost.com>
Tue, 29 Mar 2011 18:39:26 +0000 (11:39 -0700)
committerTommi Virtanen <tommi.virtanen@dreamhost.com>
Tue, 29 Mar 2011 19:55:17 +0000 (12:55 -0700)
Backwards compatible with older kenrnels, for now.

Fixes: #852
Signed-off-by: Tommi Virtanen <tommi.virtanen@dreamhost.com>
configure.ac
src/Makefile.am
src/mount/mount.ceph.c

index 177f95946bf3bf21e78249ae63ad3ebf3c0c4db5..d3218eb0163b72aed21eaafe65c6a6c93012cc17 100644 (file)
@@ -36,6 +36,7 @@ AC_PROG_LIBTOOL
 # Checks for libraries.
 AC_CHECK_LIB([m], [pow], [true], AC_MSG_FAILURE([libm not found]))
 AC_CHECK_LIB([pthread], [pthread_create], [true], AC_MSG_FAILURE([libpthread not found]))
+AC_CHECK_LIB([keyutils], [add_key], [true], AC_MSG_FAILURE([libkeyutils not found]))
 
 # Find some crypto library for us to use, while letting user to decide which one to use.
 AC_ARG_WITH([cryptopp],
index 73e4e3320818e86f29ae8120e1b6c63846889d72..734043586ce54528eaf503ec66884a54996f2962 100644 (file)
@@ -96,7 +96,8 @@ osdmaptool_SOURCES = osdmaptool.cc
 osdmaptool_LDADD = libcrush.a libcommon.a -lpthread -lm $(CRYPTO_LIBS) $(EXTRALIBS)
 bin_PROGRAMS += monmaptool crushtool osdmaptool
 
-mount_ceph_SOURCES = mount/mount.ceph.c
+mount_ceph_SOURCES = mount/mount.ceph.c common/armor.c
+mount_ceph_LDFLAGS = -lkeyutils
 sbin_PROGRAMS += mount.ceph
 
 # user tools
index 5ec62a2693ef7359984516e1cc081542aecaf119..ee479294ff9fa58550114f2b8f4e027a7d371b82 100755 (executable)
@@ -4,6 +4,9 @@
 #include <netdb.h>
 #include <errno.h>
 #include <sys/mount.h>
+#include <keyutils.h>
+
+#include "common/armor.h"
 
 #ifndef MS_RELATIME
 # define MS_RELATIME (1<<21)
@@ -14,6 +17,9 @@
 int verboseflag = 0;
 static const char * const EMPTY_STRING = "";
 
+/* TODO duplicates logic from kernel */
+#define CEPH_AUTH_NAME_DEFAULT "guest"
+
 #include "mtab.c"
 
 static void block_signals (int how)
@@ -182,6 +188,8 @@ static char *parse_options(const char *data, int *filesys_flags)
        int pos = 0;
        char *newdata = 0;
        char secret[1000];
+       char *saw_name = NULL;
+       char *saw_secret = NULL;
 
        if(verboseflag)
                printf("parsing options: %s\n", data);
@@ -273,12 +281,39 @@ static char *parse_options(const char *data, int *filesys_flags)
 
                        if (verboseflag)
                                printf("read secret of len %d from %s\n", len, fn);
-                       data = "secret";
-                       value = secret;
-                       skip = 0;
+
+                       /* see comment for "secret" */
+                       saw_secret = secret;
+                       skip = 1;
                } else if (strncmp(data, "secret", 6) == 0) {
-                       skip = 0;
+                       if (!value || !*value) {
+                               printf("mount option secret requires a value.\n");
+                               return NULL;
+                       }
+
+                       /* secret is only added to kernel options as
+                          backwards compatilbity, if add_key doesn't
+                          recognize our keytype; hence, it is skipped
+                          here and appended to options on add_key
+                          failure */
+                       strncpy(secret, value, sizeof(secret));
+                       saw_secret = secret;
+                       skip = 1;
                } else if (strncmp(data, "name", 4) == 0) {
+                       if (!value || !*value) {
+                               printf("mount option name requires a value.\n");
+                               return NULL;
+                       }
+
+                       /* take a copy of the name, to be used for
+                          naming the keys that we add to kernel;
+                          ignore memleak as mount.ceph is
+                          short-lived */
+                       saw_name = strdup(value);
+                       if (!saw_name) {
+                               printf("out of memory.\n");
+                               return NULL;
+                       }
                        skip = 0;
                } else {
                        skip = 0;
@@ -307,6 +342,50 @@ static char *parse_options(const char *data, int *filesys_flags)
                data = next_keyword;
        } while (data);
 
+       if (saw_secret) {
+               /* try to submit key to kernel via the keys api */
+               key_serial_t serial;
+               int ret;
+               int secret_len = strlen(saw_secret);
+               char payload[((secret_len * 3) / 4) + 4];
+               char *name = NULL;
+               int name_len = 0;
+               int name_pos = 0;
+
+               ret = ceph_unarmor(payload, payload+sizeof(payload), saw_secret, saw_secret+secret_len);
+               if (ret < 0) {
+                       printf("secret is not valid base64: %s.\n", strerror(-ret));
+                       return NULL;
+               }
+
+               name_pos = safe_cat(&name, &name_len, name_pos, "client.");
+               if (!saw_name) {
+                       name_pos = safe_cat(&name, &name_len, name_pos, CEPH_AUTH_NAME_DEFAULT);
+               } else {
+                       name_pos = safe_cat(&name, &name_len, name_pos, saw_name);
+               }
+               serial = add_key("ceph", name, payload, sizeof(payload), KEY_SPEC_USER_KEYRING);
+               if (serial < 0) {
+                       if (errno == ENODEV) {
+                               /* running against older kernel; fall back to secret= in options */
+                               if (pos)
+                                       pos = safe_cat(&out, &out_len, pos, ",");
+                               pos = safe_cat(&out, &out_len, pos, "secret=");
+                               pos = safe_cat(&out, &out_len, pos, saw_secret);
+                       } else {
+                               perror("adding ceph secret key to kernel failed");
+                       }
+               } else {
+                       if (verboseflag)
+                               printf("added key %s with serial %d\n", name, serial);
+                       /* add key= option to identify key to use */
+                       if (pos)
+                               pos = safe_cat(&out, &out_len, pos, ",");
+                       pos = safe_cat(&out, &out_len, pos, "key=");
+                       pos = safe_cat(&out, &out_len, pos, name);
+               }
+       }
+
        if (!out)
                return strdup(EMPTY_STRING);
        return out;