From: Tommi Virtanen Date: Tue, 29 Mar 2011 18:39:26 +0000 (-0700) Subject: mount.ceph: Use kernel key management API when possible. X-Git-Tag: v0.27~220 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bee85518e2885cc93fe8ca634292ad4846515456;p=ceph.git mount.ceph: Use kernel key management API when possible. Backwards compatible with older kenrnels, for now. Fixes: #852 Signed-off-by: Tommi Virtanen --- diff --git a/configure.ac b/configure.ac index 177f95946bf3..d3218eb0163b 100644 --- a/configure.ac +++ b/configure.ac @@ -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], diff --git a/src/Makefile.am b/src/Makefile.am index 73e4e3320818..734043586ce5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 diff --git a/src/mount/mount.ceph.c b/src/mount/mount.ceph.c index 5ec62a2693ef..ee479294ff9f 100755 --- a/src/mount/mount.ceph.c +++ b/src/mount/mount.ceph.c @@ -4,6 +4,9 @@ #include #include #include +#include + +#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;