blob: 227a54ced0f55b059ba67fa7845a41ae7c84661e [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() {
Chris Masoneb9c00592011-10-06 13:10:39 -070058 bool success = Flush();
59 ReleaseKeyFile();
60 return success;
61}
62
63bool KeyFileStore::Flush() {
Darin Petkov083047b2011-06-23 20:42:48 -070064 CHECK(key_file_);
65 GError *error = NULL;
66 gsize length = 0;
67 gchar *data = glib_->KeyFileToData(key_file_, &length, &error);
Darin Petkov083047b2011-06-23 20:42:48 -070068
69 bool success = true;
70 if (path_.empty()) {
71 LOG(ERROR) << "Empty key file path.";
72 success = false;
73 }
74 if (success && (!data || error)) {
75 LOG(ERROR) << "Failed to convert key file to string: "
76 << glib_->ConvertErrorToMessage(error);
77 success = false;
78 }
mukesh agrawalf60e4062011-05-27 13:13:41 -070079 if (success) {
80 int written = file_util::WriteFile(path_, data, length);
81 if (written < 0 ||
82 static_cast<unsigned int>(written) != length) {
83 LOG(ERROR) << "Failed to store key file: " << path_.value();
84 success = false;
85 }
Darin Petkov083047b2011-06-23 20:42:48 -070086 }
87 glib_->Free(data);
88 return success;
89}
90
91set<string> KeyFileStore::GetGroups() {
92 CHECK(key_file_);
93 gsize length = 0;
94 gchar **groups = g_key_file_get_groups(key_file_, &length);
95 if (!groups) {
96 LOG(ERROR) << "Unable to obtain groups.";
97 return set<string>();
98 }
99 set<string> group_set(groups, groups + length);
100 glib_->Strfreev(groups);
101 return group_set;
102}
103
104bool KeyFileStore::ContainsGroup(const string &group) {
105 CHECK(key_file_);
106 return glib_->KeyFileHasGroup(key_file_, group.c_str());
107}
108
109bool KeyFileStore::DeleteKey(const string &group, const string &key) {
110 CHECK(key_file_);
111 GError *error = NULL;
112 glib_->KeyFileRemoveKey(key_file_, group.c_str(), key.c_str(), &error);
Chris Masone9d779932011-08-25 16:33:41 -0700113 if (error && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
Darin Petkov083047b2011-06-23 20:42:48 -0700114 LOG(ERROR) << "Failed to delete (" << group << ":" << key << "): "
115 << glib_->ConvertErrorToMessage(error);
116 return false;
117 }
118 return true;
119}
120
121bool KeyFileStore::DeleteGroup(const string &group) {
122 CHECK(key_file_);
123 GError *error = NULL;
124 glib_->KeyFileRemoveGroup(key_file_, group.c_str(), &error);
Chris Masone9d779932011-08-25 16:33:41 -0700125 if (error && error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND) {
Darin Petkov86964e02011-06-29 13:49:28 -0700126 LOG(ERROR) << "Failed to delete group " << group << ": "
Darin Petkov083047b2011-06-23 20:42:48 -0700127 << glib_->ConvertErrorToMessage(error);
128 return false;
129 }
130 return true;
131}
132
133bool KeyFileStore::GetString(const string &group,
134 const string &key,
135 string *value) {
136 CHECK(key_file_);
137 GError *error = NULL;
138 gchar *data =
139 glib_->KeyFileGetString(key_file_, group.c_str(), key.c_str(), &error);
140 if (!data) {
141 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
142 << glib_->ConvertErrorToMessage(error);
143 return false;
144 }
145 if (value) {
146 *value = data;
147 }
148 glib_->Free(data);
149 return true;
150}
151
152bool KeyFileStore::SetString(const string &group,
153 const string &key,
154 const string &value) {
155 CHECK(key_file_);
156 glib_->KeyFileSetString(key_file_, group.c_str(), key.c_str(), value.c_str());
157 return true;
158}
159
160bool KeyFileStore::GetBool(const string &group,
161 const string &key,
162 bool *value) {
163 CHECK(key_file_);
164 GError *error = NULL;
165 gboolean data =
166 glib_->KeyFileGetBoolean(key_file_, group.c_str(), key.c_str(), &error);
167 if (error) {
168 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
169 << glib_->ConvertErrorToMessage(error);
170 return false;
171 }
172 if (value) {
173 *value = data;
174 }
175 return true;
176}
177
178bool KeyFileStore::SetBool(const string &group, const string &key, bool value) {
179 CHECK(key_file_);
180 glib_->KeyFileSetBoolean(key_file_,
181 group.c_str(),
182 key.c_str(),
183 value ? TRUE : FALSE);
184 return true;
185}
186
187bool KeyFileStore::GetInt(const string &group, const string &key, int *value) {
188 CHECK(key_file_);
189 GError *error = NULL;
190 gint data =
191 glib_->KeyFileGetInteger(key_file_, group.c_str(), key.c_str(), &error);
192 if (error) {
193 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
194 << glib_->ConvertErrorToMessage(error);
195 return false;
196 }
197 if (value) {
198 *value = data;
199 }
200 return true;
201}
202
203bool KeyFileStore::SetInt(const string &group, const string &key, int value) {
204 CHECK(key_file_);
205 glib_->KeyFileSetInteger(key_file_, group.c_str(), key.c_str(), value);
206 return true;
207}
208
Darin Petkovb2841fd2011-06-30 12:54:12 -0700209bool KeyFileStore::GetStringList(const string &group,
210 const string &key,
211 vector<string> *value) {
212 CHECK(key_file_);
213 gsize length = 0;
214 GError *error = NULL;
215 gchar **data = glib_->KeyFileGetStringList(key_file_,
216 group.c_str(),
217 key.c_str(),
218 &length,
219 &error);
220 if (!data) {
221 LOG(ERROR) << "Failed to lookup (" << group << ":" << key << "): "
222 << glib_->ConvertErrorToMessage(error);
223 return false;
224 }
225 if (value) {
226 value->assign(data, data + length);
227 }
228 glib_->Strfreev(data);
229 return true;
230}
231
232bool KeyFileStore::SetStringList(const string &group,
233 const string &key,
234 const vector<string> &value) {
235 CHECK(key_file_);
236 vector<const char *> list;
237 for (vector<string>::const_iterator it = value.begin();
238 it != value.end(); ++it) {
239 list.push_back(it->c_str());
240 }
241 glib_->KeyFileSetStringList(key_file_,
242 group.c_str(),
243 key.c_str(),
244 list.data(),
245 list.size());
246 return true;
247}
248
Darin Petkov86964e02011-06-29 13:49:28 -0700249bool KeyFileStore::GetCryptedString(const string &group,
250 const string &key,
251 string *value) {
252 if (!GetString(group, key, value)) {
253 return false;
254 }
255 if (value) {
256 *value = crypto_.Decrypt(*value);
257 }
258 return true;
259}
260
261bool KeyFileStore::SetCryptedString(const string &group,
262 const string &key,
263 const string &value) {
264 return SetString(group, key, crypto_.Encrypt(value));
265}
266
Darin Petkov083047b2011-06-23 20:42:48 -0700267} // namespace shill