1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
20 #include "auth/KeyRing.h"
21 #include "common/config.h"
22 #include "common/debug.h"
23 #include "common/errno.h"
24 #include "common/Formatter.h"
26 #define dout_subsys ceph_subsys_auth
29 #define dout_prefix *_dout << "auth: "
33 int KeyRing::from_ceph_context(CephContext *cct)
35 const md_config_t *conf = cct->_conf;
38 int ret = ceph_resolve_file_search(conf->keyring, filename);
40 ret = load(cct, filename);
42 lderr(cct) << "failed to load " << filename
43 << ": " << cpp_strerror(ret) << dendl;
45 lderr(cct) << "unable to find a keyring on " << conf->keyring
46 << ": " << cpp_strerror(ret) << dendl;
49 if (!conf->key.empty()) {
52 ea.key.decode_base64(conf->key);
56 catch (buffer::error& e) {
57 lderr(cct) << "failed to decode key '" << conf->key << "'" << dendl;
62 if (!conf->keyfile.empty()) {
65 int r = bl.read_file(conf->keyfile.c_str(), &err);
67 lderr(cct) << err << dendl;
70 string k(bl.c_str(), bl.length());
73 ea.key.decode_base64(k);
76 catch (buffer::error& e) {
77 lderr(cct) << "failed to decode key '" << k << "'" << dendl;
86 KeyRing *KeyRing::create_empty()
91 int KeyRing::set_modifier(const char *type, const char *val, EntityName& name, map<string, bufferlist>& caps)
96 if (strcmp(type, "key") == 0) {
100 key.decode_base64(l);
101 } catch (const buffer::error& err) {
105 } else if (strncmp(type, "caps ", 5) == 0) {
106 const char *caps_entity = type + 5;
112 caps[caps_entity] = bl;
113 set_caps(name, caps);
114 } else if (strcmp(type, "auid") == 0) {
115 uint64_t auid = strtoull(val, NULL, 0);
123 void KeyRing::encode_plaintext(bufferlist& bl)
125 std::ostringstream os;
127 string str = os.str();
131 void KeyRing::encode_formatted(string label, Formatter *f, bufferlist& bl)
133 std::ostringstream(os);
134 f->open_array_section(label.c_str());
135 for (map<EntityName, EntityAuth>::iterator p = keys.begin();
139 f->open_object_section("auth_entities");
140 f->dump_string("entity", p->first.to_str().c_str());
141 std::ostringstream keyss;
142 keyss << p->second.key;
143 f->dump_string("key", keyss.str());
144 if (p->second.auid != CEPH_AUTH_UID_DEFAULT)
145 f->dump_int("auid", p->second.auid);
146 f->open_object_section("caps");
147 for (map<string, bufferlist>::iterator q = p->second.caps.begin();
148 q != p->second.caps.end();
150 bufferlist::iterator dataiter = q->second.begin();
152 ::decode(caps, dataiter);
153 f->dump_string(q->first.c_str(), caps);
155 f->close_section(); /* caps */
156 f->close_section(); /* auth_entities */
158 f->close_section(); /* auth_dump */
162 void KeyRing::decode_plaintext(bufferlist::iterator& bli)
168 std::deque<std::string> parse_errors;
170 if (cf.parse_bufferlist(&bl, &parse_errors, NULL) != 0) {
171 throw buffer::malformed_input("cannot parse buffer");
174 for (ConfFile::const_section_iter_t s = cf.sections_begin();
175 s != cf.sections_end(); ++s) {
176 string name = s->first;
177 if (name == "global")
181 map<string, bufferlist> caps;
182 if (!ename.from_str(name)) {
184 oss << "bad entity name in keyring: " << name;
185 throw buffer::malformed_input(oss.str().c_str());
188 for (ConfSection::const_line_iter_t l = s->second.lines.begin();
189 l != s->second.lines.end(); ++l) {
193 std::replace(k.begin(), k.end(), '_', ' ');
194 ret = set_modifier(k.c_str(), l->val.c_str(), ename, caps);
197 oss << "error setting modifier for [" << name << "] type=" << k
198 << " val=" << l->val;
199 throw buffer::malformed_input(oss.str().c_str());
205 void KeyRing::decode(bufferlist::iterator& bl) {
207 bufferlist::iterator start_pos = bl;
209 ::decode(struct_v, bl);
211 } catch (buffer::error& err) {
213 decode_plaintext(start_pos);
217 int KeyRing::load(CephContext *cct, const std::string &filename)
219 if (filename.empty())
224 int ret = bl.read_file(filename.c_str(), &err);
226 lderr(cct) << "error reading file: " << filename << ": " << err << dendl;
231 bufferlist::iterator iter = bl.begin();
234 catch (const buffer::error& err) {
235 lderr(cct) << "error parsing file " << filename << dendl;
239 ldout(cct, 2) << "KeyRing::load: loaded key file " << filename << dendl;
243 void KeyRing::print(ostream& out)
245 for (map<EntityName, EntityAuth>::iterator p = keys.begin();
248 out << "[" << p->first << "]" << std::endl;
249 out << "\tkey = " << p->second.key << std::endl;
250 if (p->second.auid != CEPH_AUTH_UID_DEFAULT)
251 out << "\tauid = " << p->second.auid << std::endl;
253 for (map<string, bufferlist>::iterator q = p->second.caps.begin();
254 q != p->second.caps.end();
256 bufferlist::iterator dataiter = q->second.begin();
258 ::decode(caps, dataiter);
259 out << "\tcaps " << q->first << " = \"" << caps << '"' << std::endl;
264 void KeyRing::import(CephContext *cct, KeyRing& other)
266 for (map<EntityName, EntityAuth>::iterator p = other.keys.begin();
267 p != other.keys.end();
269 ldout(cct, 10) << " importing " << p->first << dendl;
270 ldout(cct, 30) << " " << p->second << dendl;
271 keys[p->first] = p->second;