blob: b228e86d7c6186979968e8c894d930be219c9a99 [file] [log] [blame]
Darin Petkov083047b2011-06-23 20:42:48 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "shill/key_file_store.h"
6
7#include <base/file_util.h>
8#include <base/logging.h>
9
10using std::set;
11using std::string;
Darin Petkovb2841fd2011-06-30 12:54:12 -070012using std::vector;
Darin Petkov083047b2011-06-23 20:42:48 -070013
14namespace shill {
15
Darin Petkov86964e02011-06-29 13:49:28 -070016KeyFileStore::KeyFileStore(GLib *glib)
17 : glib_(glib),
18 crypto_(glib),
19 key_file_(NULL) {}
Darin Petkov083047b2011-06-23 20:42:48 -070020
21KeyFileStore::~KeyFileStore() {
22 ReleaseKeyFile();
23}
24
25void KeyFileStore::ReleaseKeyFile() {
26 if (key_file_) {
27 glib_->KeyFileFree(key_file_);
28 key_file_ = NULL;
29 }
30}
31
32bool KeyFileStore::Open() {
33 CHECK(!path_.empty());
34 CHECK(!key_file_);
Darin Petkov86964e02011-06-29 13:49:28 -070035 crypto_.Init();
Darin Petkov083047b2011-06-23 20:42:48 -070036 key_file_ = glib_->KeyFileNew();
37 int64 file_size = 0;
38 if (!file_util::GetFileSize(path_, &file_size) || file_size == 0) {
39 LOG(INFO) << "Creating a new key file at " << path_.value();
40 return true;
41 }
42 GError *error = NULL;
43 if (glib_->KeyFileLoadFromFile(
44 key_file_,
45 path_.value().c_str(),
46 static_cast<GKeyFileFlags>(G_KEY_FILE_KEEP_COMMENTS |
47 G_KEY_FILE_KEEP_TRANSLATIONS),
48 &error)) {
49 return true;
50 }
51 LOG(ERROR) << "Failed to load key file from " << path_.value() << ": "
52 << glib_->ConvertErrorToMessage(error);
53 ReleaseKeyFile();
54 return false;
55}
56
57bool KeyFileStore::Close() {
58 CHECK(key_file_);
59 GError *error = NULL;
60 gsize length = 0;
61 gchar *data = glib_->KeyFileToData(key_file_, &length, &error);
62 ReleaseKeyFile();
63
64 bool success = true;
65 if (path_.empty()) {
66 LOG(ERROR) << "Empty key file path.";
67 success = false;
68 }
69 if (success && (!data || error)) {
70 LOG(ERROR) << "Failed to convert key file to string: "
71 << glib_->ConvertErrorToMessage(error);
72 success = false;
73 }
mukesh agrawalf60e4062011-05-27 13:13:41 -070074 if (success) {
75 int written = file_util::WriteFile(path_, data, length);
76 if (written < 0 ||
77 static_cast<unsigned int>(written) != length) {
78 LOG(ERROR) << "Failed to store key file: " << path_.value();
79 success = false;
80 }
Darin Petkov083047b2011-06-23 20:42:48 -070081 }
82 glib_->Free(data);
83 return success;
84}
85
86set<string> KeyFileStore::GetGroups() {
87 CHECK(key_file_);
88 gsize length = 0;
89 gchar **groups = g_key_file_get_groups(key_file_, &length);
90 if (!groups) {
91 LOG(ERROR) << "Unable to obtain groups.";
92 return set<string>();
93 }
94 set<string> group_set(groups, groups + length);
95 glib_->Strfreev(groups);
96 return group_set;
97}
98
99bool KeyFileStore::ContainsGroup(const string &group) {
100 CHECK(key_file_);
101 return glib_->KeyFileHasGroup(key_file_, group.c_str());
102}
103
104bool KeyFileStore::DeleteKey(const string &group, const string &key) {
105 CHECK(key_file_);
106 GError *error = NULL;
107 glib_->KeyFileRemoveKey(key_file_, group.c_str(), key.c_str(), &error);
108 if (error) {
109 LOG(ERROR) << "Failed to delete (" << group << ":" << key << "): "
110 << glib_->ConvertErrorToMessage(error);
111 return false;
112 }
113 return true;
114}
115
116bool KeyFileStore::DeleteGroup(const string &group) {
117 CHECK(key_file_);
118 GError *error = NULL;
119 glib_->KeyFileRemoveGroup(key_file_, group.c_str(), &error);
120 if (error) {
Darin Petkov86964e02011-06-29 13:49:28 -0700121 LOG(ERROR) << "Failed to delete group " << group << ": "
Darin Petkov083047b2011-06-23 20:42:48 -0700122 << glib_->ConvertErrorToMessage(error);
123 return false;
124 }
125 return true;
126}
127
128bool KeyFileStore::GetString(const string &group,
129 const string &key,
130 string *value) {
131 CHECK(key_file_);
132 GError *error = NULL;
133 gchar *data =
134 glib_->KeyFileGetString(key_file_, group.c_str(), key.c_str(), &error);
135 if (!data) {
136 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
137 << glib_->ConvertErrorToMessage(error);
138 return false;
139 }
140 if (value) {
141 *value = data;
142 }
143 glib_->Free(data);
144 return true;
145}
146
147bool KeyFileStore::SetString(const string &group,
148 const string &key,
149 const string &value) {
150 CHECK(key_file_);
151 glib_->KeyFileSetString(key_file_, group.c_str(), key.c_str(), value.c_str());
152 return true;
153}
154
155bool KeyFileStore::GetBool(const string &group,
156 const string &key,
157 bool *value) {
158 CHECK(key_file_);
159 GError *error = NULL;
160 gboolean data =
161 glib_->KeyFileGetBoolean(key_file_, group.c_str(), key.c_str(), &error);
162 if (error) {
163 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
164 << glib_->ConvertErrorToMessage(error);
165 return false;
166 }
167 if (value) {
168 *value = data;
169 }
170 return true;
171}
172
173bool KeyFileStore::SetBool(const string &group, const string &key, bool value) {
174 CHECK(key_file_);
175 glib_->KeyFileSetBoolean(key_file_,
176 group.c_str(),
177 key.c_str(),
178 value ? TRUE : FALSE);
179 return true;
180}
181
182bool KeyFileStore::GetInt(const string &group, const string &key, int *value) {
183 CHECK(key_file_);
184 GError *error = NULL;
185 gint data =
186 glib_->KeyFileGetInteger(key_file_, group.c_str(), key.c_str(), &error);
187 if (error) {
188 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
189 << glib_->ConvertErrorToMessage(error);
190 return false;
191 }
192 if (value) {
193 *value = data;
194 }
195 return true;
196}
197
198bool KeyFileStore::SetInt(const string &group, const string &key, int value) {
199 CHECK(key_file_);
200 glib_->KeyFileSetInteger(key_file_, group.c_str(), key.c_str(), value);
201 return true;
202}
203
Darin Petkovb2841fd2011-06-30 12:54:12 -0700204bool KeyFileStore::GetStringList(const string &group,
205 const string &key,
206 vector<string> *value) {
207 CHECK(key_file_);
208 gsize length = 0;
209 GError *error = NULL;
210 gchar **data = glib_->KeyFileGetStringList(key_file_,
211 group.c_str(),
212 key.c_str(),
213 &length,
214 &error);
215 if (!data) {
216 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
217 << glib_->ConvertErrorToMessage(error);
218 return false;
219 }
220 if (value) {
221 value->assign(data, data + length);
222 }
223 glib_->Strfreev(data);
224 return true;
225}
226
227bool KeyFileStore::SetStringList(const string &group,
228 const string &key,
229 const vector<string> &value) {
230 CHECK(key_file_);
231 vector<const char *> list;
232 for (vector<string>::const_iterator it = value.begin();
233 it != value.end(); ++it) {
234 list.push_back(it->c_str());
235 }
236 glib_->KeyFileSetStringList(key_file_,
237 group.c_str(),
238 key.c_str(),
239 list.data(),
240 list.size());
241 return true;
242}
243
Darin Petkov86964e02011-06-29 13:49:28 -0700244bool KeyFileStore::GetCryptedString(const string &group,
245 const string &key,
246 string *value) {
247 if (!GetString(group, key, value)) {
248 return false;
249 }
250 if (value) {
251 *value = crypto_.Decrypt(*value);
252 }
253 return true;
254}
255
256bool KeyFileStore::SetCryptedString(const string &group,
257 const string &key,
258 const string &value) {
259 return SetString(group, key, crypto_.Encrypt(value));
260}
261
Darin Petkov083047b2011-06-23 20:42:48 -0700262} // namespace shill