Line data Source code
1 : /*
2 : SSSD
3 :
4 : Configuration Database
5 :
6 : Copyright (C) Stephen Gallagher <sgallagh@redhat.com> 2009
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : #include "config.h"
23 : #include <sys/stat.h>
24 : #include "util/util.h"
25 : #include "db/sysdb.h"
26 : #include "confdb.h"
27 : #include "confdb_private.h"
28 : #include "confdb_setup.h"
29 : #include "util/sss_ini.h"
30 :
31 :
32 0 : int confdb_test(struct confdb_ctx *cdb)
33 : {
34 : char **values;
35 : int ret;
36 :
37 0 : ret = confdb_get_param(cdb, cdb,
38 : "config",
39 : "version",
40 : &values);
41 0 : if (ret != EOK) {
42 0 : return ret;
43 : }
44 :
45 0 : if (values[0] == NULL) {
46 : /* empty database, will need to init */
47 0 : talloc_free(values);
48 0 : return ENOENT;
49 : }
50 :
51 0 : if (values[1] != NULL) {
52 : /* more than 1 value ?? */
53 0 : talloc_free(values);
54 0 : return EIO;
55 : }
56 :
57 0 : if (strcmp(values[0], CONFDB_VERSION) != 0) {
58 : /* Existing version does not match executable version */
59 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Upgrading confdb version from %s to %s\n",
60 : values[0], CONFDB_VERSION);
61 :
62 : /* This is recoverable, since we purge the confdb file
63 : * when we re-initialize it.
64 : */
65 0 : talloc_free(values);
66 0 : return ENOENT;
67 : }
68 :
69 0 : talloc_free(values);
70 0 : return EOK;
71 : }
72 :
73 0 : static int confdb_purge(struct confdb_ctx *cdb)
74 : {
75 : int ret, i;
76 : TALLOC_CTX *tmp_ctx;
77 : struct ldb_result *res;
78 : struct ldb_dn *dn;
79 0 : const char *attrs[] = { "dn", NULL };
80 :
81 0 : tmp_ctx = talloc_new(NULL);
82 :
83 0 : dn = ldb_dn_new(tmp_ctx, cdb->ldb, "cn=config");
84 :
85 : /* Get the list of all DNs */
86 0 : ret = ldb_search(cdb->ldb, tmp_ctx, &res, dn,
87 : LDB_SCOPE_SUBTREE, attrs, NULL);
88 0 : if (ret != LDB_SUCCESS) {
89 0 : ret = sysdb_error_to_errno(ret);
90 0 : goto done;
91 : }
92 :
93 0 : for(i=0; i<res->count; i++) {
94 : /* Delete this DN */
95 0 : ret = ldb_delete(cdb->ldb, res->msgs[i]->dn);
96 0 : if (ret != LDB_SUCCESS) {
97 0 : ret = sysdb_error_to_errno(ret);
98 0 : goto done;
99 : }
100 : }
101 :
102 : done:
103 0 : talloc_free(tmp_ctx);
104 0 : return ret;
105 : }
106 :
107 0 : int confdb_create_base(struct confdb_ctx *cdb)
108 : {
109 : int ret;
110 : struct ldb_ldif *ldif;
111 :
112 0 : const char *base_ldif = CONFDB_BASE_LDIF;
113 :
114 0 : while ((ldif = ldb_ldif_read_string(cdb->ldb, &base_ldif))) {
115 0 : ret = ldb_add(cdb->ldb, ldif->msg);
116 0 : if (ret != LDB_SUCCESS) {
117 0 : DEBUG(SSSDBG_FATAL_FAILURE,
118 : "Failed to initialize DB (%d,[%s]), aborting!\n",
119 : ret, ldb_errstring(cdb->ldb));
120 0 : return EIO;
121 : }
122 0 : ldb_ldif_read_free(cdb->ldb, ldif);
123 : }
124 :
125 0 : return EOK;
126 : }
127 :
128 0 : int confdb_init_db(const char *config_file, struct confdb_ctx *cdb)
129 : {
130 : TALLOC_CTX *tmp_ctx;
131 : int ret;
132 0 : int sret = EOK;
133 : int version;
134 : char timestr[21];
135 : char *lasttimestr;
136 0 : bool in_transaction = false;
137 : const char *config_ldif;
138 0 : const char *vals[2] = { timestr, NULL };
139 : struct ldb_ldif *ldif;
140 : struct sss_ini_initdata *init_data;
141 :
142 :
143 0 : tmp_ctx = talloc_new(cdb);
144 0 : if (tmp_ctx == NULL) {
145 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n");
146 0 : return ENOMEM;
147 : }
148 :
149 0 : init_data = sss_ini_initdata_init(tmp_ctx);
150 0 : if (!init_data) {
151 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory.\n");
152 0 : ret = ENOMEM;
153 0 : goto done;
154 : }
155 :
156 : /* Open config file */
157 0 : ret = sss_ini_config_file_open(init_data, config_file);
158 0 : if (ret != EOK) {
159 0 : DEBUG(SSSDBG_TRACE_FUNC,
160 : "sss_ini_config_file_open failed: %s [%d]\n", strerror(ret),
161 : ret);
162 0 : if (ret == ENOENT) {
163 : /* sss specific error denoting missing configuration file */
164 0 : ret = ERR_MISSING_CONF;
165 : }
166 0 : goto done;
167 : }
168 :
169 0 : ret = sss_ini_config_access_check(init_data);
170 0 : if (ret != EOK) {
171 0 : DEBUG(SSSDBG_CRIT_FAILURE,
172 : "Permission check on config file failed.\n");
173 0 : ret = EPERM;
174 0 : goto done;
175 : }
176 :
177 : /* Determine if the conf file has changed since we last updated
178 : * the confdb
179 : */
180 0 : ret = sss_ini_get_stat(init_data);
181 0 : if (ret != EOK) {
182 0 : DEBUG(SSSDBG_FATAL_FAILURE,
183 : "Status check on config file failed.\n");
184 0 : ret = errno;
185 0 : goto done;
186 : }
187 :
188 0 : errno = 0;
189 :
190 0 : ret = sss_ini_get_mtime(init_data, sizeof(timestr), timestr);
191 0 : if (ret <= 0 || ret >= sizeof(timestr)) {
192 0 : DEBUG(SSSDBG_FATAL_FAILURE,
193 : "Failed to convert time_t to string ??\n");
194 0 : ret = errno ? errno : EFAULT;
195 : }
196 0 : ret = confdb_get_string(cdb, tmp_ctx, "config", "lastUpdate",
197 : NULL, &lasttimestr);
198 0 : if (ret == EOK) {
199 :
200 : /* check if we lastUpdate and last file modification change differ*/
201 0 : if ((lasttimestr != NULL) && (strcmp(lasttimestr, timestr) == 0)) {
202 : /* not changed, get out, nothing more to do */
203 0 : ret = EOK;
204 0 : goto done;
205 : }
206 : } else {
207 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to get lastUpdate attribute.\n");
208 0 : goto done;
209 : }
210 :
211 0 : ret = sss_ini_get_config(init_data, config_file);
212 0 : if (ret != EOK) {
213 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Failed to load configuration\n");
214 0 : goto done;
215 : }
216 :
217 : /* Make sure that the config file version matches the confdb version */
218 0 : ret = sss_ini_get_cfgobj(init_data, "sssd", "config_file_version");
219 0 : if (ret != EOK) {
220 0 : DEBUG(SSSDBG_FATAL_FAILURE,
221 : "Internal error determining config_file_version\n");
222 0 : goto done;
223 : }
224 :
225 0 : ret = sss_ini_check_config_obj(init_data);
226 0 : if (ret != EOK) {
227 : /* No known version. Use default. */
228 0 : DEBUG(SSSDBG_CONF_SETTINGS,
229 : "Value of config_file_version option not found. "
230 : "Assumed to be version %d.\n", CONFDB_DEFAULT_CFG_FILE_VER);
231 : } else {
232 0 : version = sss_ini_get_int_config_value(init_data,
233 : CONFDB_DEFAULT_CFG_FILE_VER,
234 : -1, &ret);
235 0 : if (ret != EOK) {
236 0 : DEBUG(SSSDBG_FATAL_FAILURE,
237 : "Config file version could not be determined\n");
238 0 : goto done;
239 0 : } else if (version < CONFDB_VERSION_INT) {
240 0 : DEBUG(SSSDBG_FATAL_FAILURE,
241 : "Config file is an old version. "
242 : "Please run configuration upgrade script.\n");
243 0 : ret = EINVAL;
244 0 : goto done;
245 0 : } else if (version > CONFDB_VERSION_INT) {
246 0 : DEBUG(SSSDBG_FATAL_FAILURE,
247 : "Config file version is newer than confdb\n");
248 0 : ret = EINVAL;
249 0 : goto done;
250 : }
251 : }
252 :
253 : /* Set up a transaction to replace the configuration */
254 0 : ret = ldb_transaction_start(cdb->ldb);
255 0 : if (ret != LDB_SUCCESS) {
256 0 : DEBUG(SSSDBG_FATAL_FAILURE,
257 : "Failed to start a transaction for "
258 : "updating the configuration\n");
259 0 : ret = sysdb_error_to_errno(ret);
260 0 : goto done;
261 : }
262 0 : in_transaction = true;
263 :
264 : /* Purge existing database */
265 0 : ret = confdb_purge(cdb);
266 0 : if (ret != EOK) {
267 0 : DEBUG(SSSDBG_FATAL_FAILURE,
268 : "Could not purge existing configuration\n");
269 0 : goto done;
270 : }
271 :
272 0 : ret = sss_confdb_create_ldif(tmp_ctx, init_data, &config_ldif);
273 0 : if (ret != EOK) {
274 0 : DEBUG(SSSDBG_FATAL_FAILURE, "Could not create LDIF for confdb\n");
275 0 : goto done;
276 : }
277 :
278 0 : DEBUG(SSSDBG_TRACE_LIBS, "LDIF file to import: \n%s\n", config_ldif);
279 :
280 0 : while ((ldif = ldb_ldif_read_string(cdb->ldb, &config_ldif))) {
281 0 : ret = ldb_add(cdb->ldb, ldif->msg);
282 0 : if (ret != LDB_SUCCESS) {
283 0 : DEBUG(SSSDBG_FATAL_FAILURE,
284 : "Failed to initialize DB (%d,[%s]), aborting!\n",
285 : ret, ldb_errstring(cdb->ldb));
286 0 : ret = EIO;
287 0 : goto done;
288 : }
289 0 : ldb_ldif_read_free(cdb->ldb, ldif);
290 : }
291 :
292 : /* now store the lastUpdate time so that we do not re-init if nothing
293 : * changed on restart */
294 :
295 0 : ret = confdb_add_param(cdb, true, "config", "lastUpdate", vals);
296 0 : if (ret != EOK) {
297 0 : DEBUG(SSSDBG_FATAL_FAILURE,
298 : "Failed to set last update time on db!\n");
299 0 : goto done;
300 : }
301 :
302 0 : ret = ldb_transaction_commit(cdb->ldb);
303 0 : if (ret != EOK) {
304 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
305 0 : goto done;
306 : }
307 0 : in_transaction = false;
308 :
309 0 : ret = EOK;
310 :
311 : done:
312 0 : if (in_transaction) {
313 0 : sret = ldb_transaction_cancel(cdb->ldb);
314 0 : if (sret != EOK) {
315 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n");
316 : }
317 : }
318 :
319 0 : sss_ini_config_destroy(init_data);
320 0 : sss_ini_close_file(init_data);
321 :
322 0 : talloc_zfree(tmp_ctx);
323 0 : return ret;
324 : }
|