]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
keyring: can parse plain text keyring files
authorYehuda Sadeh <yehuda@hq.newdream.net>
Mon, 10 Jan 2011 23:50:26 +0000 (15:50 -0800)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Mon, 10 Jan 2011 23:51:31 +0000 (15:51 -0800)
src/auth/KeyRing.cc
src/auth/KeyRing.h

index b4c48b069a2091dbae7ae13234e5ede5c11628eb..1bc54eb0ed1255f857205ffc1182250ecd0f4df4 100644 (file)
@@ -30,14 +30,195 @@ using namespace std;
 
 KeyRing g_keyring;
 
+int KeyRing::parse_name(char *line, EntityName& name)
+{
+  string s(line);
+  if (!name.from_str(s))
+    return -EINVAL;
+
+  return 0;
+}
+
+int KeyRing::parse_caps(char *line, map<string, bufferlist>& caps)
+{
+  char *name;
+
+  if (*line != '[')
+    return -EINVAL;
+
+  line++;
+
+  while (*line && isspace(*line))
+    line++;
+  name = line;
+
+  while (*line && !isspace(*line) && (*line != ']'))
+    line++;
+
+  if (isspace(*line)) {
+    *line = '\0';
+    line++;
+    while (isspace(*line))
+      line++;
+  }
+
+  if (*line != ']')
+    return -EINVAL;
+  *line = '\0';
+
+  string n(name);
+
+  line++;
+  while (isspace(*line))
+    line++;
+
+  string val(line);
+  bufferlist bl;
+  ::encode(val, bl);
+  caps[name] = bl;
+  return 0;
+}
+
+int KeyRing::parse_modifier(char *line, EntityName& name, map<string, bufferlist>& caps)
+{
+  char *type = strsep(&line, ":");
+  if (!line)
+    return -EINVAL;
+
+  while (*line && isspace(*line))
+    line++;
+
+  if (strcmp(type, "key") == 0) {
+    CryptoKey key;
+    string l(line);
+    try {
+      key.decode_base64(l);
+    } catch (const buffer::error& err) {
+      return -EINVAL;
+    }
+    set_key(name, key);
+  } else if (strcmp(type, "caps") == 0) {
+    int ret = parse_caps(line, caps);
+    if (ret < 0)
+      return ret;
+    set_caps(name, caps);
+  } else if (strcmp(type, "auid") == 0) {
+    uint64_t auid = strtoull(line, NULL, 0);
+    set_uid(name, auid);
+  } else
+    return -EINVAL;
+
+  return 0;
+}
+
+
+void KeyRing::decode_plaintext(bufferlist::iterator& bl)
+{
+  int ret = -EINVAL;
+
+  bufferlist::iterator iter = bl;
+
+  // find out the size of the buffer
+  char c;
+  int len = 0;
+  try {
+    do {
+      ::decode(c, iter);
+      len++;
+    } while (c);
+  } catch (buffer::error& err) {
+  }
+
+  char *orig_src = new char[len + 1];
+  orig_src[len] = '\0';
+  iter = bl;
+  int i;
+  for (i = 0; i < len; i++) {
+    ::decode(c, iter);
+    orig_src[i] = c;
+  }
+
+  char *src = orig_src;
+
+  char *line;
+  int line_count;
+
+  EntityName name;
+  bool has_name = false;
+  map<string, bufferlist> caps;
+
+  for (line_count = 1; src; line_count++) {
+    line = strsep(&src, "\n\r");
+
+    int alpha_index = 0;
+    bool had_alpha = 0;
+
+    for (i = 0; line[i]; i++) {
+      switch (line[i]) {
+      case '#':
+        if (had_alpha)
+          goto parse_err;
+        continue;
+      case ' ':
+      case '\t':
+        continue;
+      case '.': // this is a name
+        ret = parse_name(line + alpha_index, name);
+        if (ret < 0)
+          goto parse_err;
+        has_name = true;
+        caps.clear();
+        break;
+      case ':': // this is a modifier
+        if (!has_name)
+          goto parse_err;
+        ret = parse_modifier(line + alpha_index, name, caps);
+        if (ret < 0)
+          goto parse_err;
+        break;
+      default:
+        if (!had_alpha)
+          alpha_index = i;
+        had_alpha = 1;
+        break;
+      }
+    }
+  }
+
+  if (!has_name)
+    goto parse_err;
+
+  delete[] orig_src;
+
+  return;
+
+parse_err:
+  derr << "parse error at line " << line_count << ":" << dendl;
+  derr << line << dendl;
+  delete[] orig_src;
+  throw buffer::error();
+}
+
+void KeyRing::decode(bufferlist::iterator& bl) {
+  __u8 struct_v;
+  bufferlist::iterator start_pos = bl;
+  try {
+    ::decode(struct_v, bl);
+    ::decode(keys, bl);
+  } catch (buffer::error& err) {
+    keys.clear();
+    decode_plaintext(start_pos);
+  }
+}
+
 int KeyRing::load(const char *filename)
 {
   if (!filename)
     return -EINVAL;
 
   bufferlist bl;
-  int ret = bl.read_file(filename);
-  if (ret) {
+  int ret = bl.read_file(filename, true);
+  if (ret < 0) {
     derr << "error reading file: " << filename << dendl;
     return ret;
   }
@@ -46,9 +227,8 @@ int KeyRing::load(const char *filename)
     bufferlist::iterator iter = bl.begin();
     decode(iter);
   }
-  catch (const buffer::error &err) {
+  catch (const buffer::errorerr) {
     derr << "error parsing file " << filename << dendl;
-    return -EIO;
   }
 
   dout(2) << "KeyRing::load: loaded key file " << filename << dendl;
index 80231e2af0dc5e9d1bce969f5db1e426fedcc379..e5e767e3a0a2307499aa906acad34f3ae220c147 100644 (file)
 class KeyRing {
   map<EntityName, EntityAuth> keys;
 
+  int parse_name(char *line, EntityName& name);
+  int parse_caps(char *line, map<string, bufferlist>& caps);
+  int parse_modifier(char *line, EntityName& name, map<string, bufferlist>& caps);
+  void decode_plaintext(bufferlist::iterator& bl);
 public:
   map<EntityName, EntityAuth>& get_keys() { return keys; }  // yuck
 
@@ -58,6 +62,9 @@ public:
   void set_uid(EntityName& ename, uint64_t auid) {
     keys[ename].auid = auid;
   }
+  void set_key(EntityName& ename, CryptoKey& key) {
+    keys[ename].key = key;
+  }
   void import(KeyRing& other);
 
   // encoders
@@ -66,11 +73,7 @@ public:
     ::encode(struct_v, bl);
     ::encode(keys, bl);
   }
-  void decode(bufferlist::iterator& bl) {
-    __u8 struct_v;
-    ::decode(struct_v, bl);
-    ::decode(keys, bl);
-  }
+  void decode(bufferlist::iterator& bl);
 };
 WRITE_CLASS_ENCODER(KeyRing)