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;
}
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;
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
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
::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)