From e9a70f15029d397ebf0414e5f16fda321af5f55b Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Mon, 10 Jan 2011 15:50:26 -0800 Subject: [PATCH] keyring: can parse plain text keyring files --- src/auth/KeyRing.cc | 188 +++++++++++++++++++++++++++++++++++++++++++- src/auth/KeyRing.h | 13 +-- 2 files changed, 192 insertions(+), 9 deletions(-) diff --git a/src/auth/KeyRing.cc b/src/auth/KeyRing.cc index b4c48b069a209..1bc54eb0ed125 100644 --- a/src/auth/KeyRing.cc +++ b/src/auth/KeyRing.cc @@ -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& 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& 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 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::error& err) { derr << "error parsing file " << filename << dendl; - return -EIO; } dout(2) << "KeyRing::load: loaded key file " << filename << dendl; diff --git a/src/auth/KeyRing.h b/src/auth/KeyRing.h index 80231e2af0dc5..e5e767e3a0a23 100644 --- a/src/auth/KeyRing.h +++ b/src/auth/KeyRing.h @@ -23,6 +23,10 @@ class KeyRing { map keys; + int parse_name(char *line, EntityName& name); + int parse_caps(char *line, map& caps); + int parse_modifier(char *line, EntityName& name, map& caps); + void decode_plaintext(bufferlist::iterator& bl); public: map& 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) -- 2.39.5