Branch data Line data Source code
1 : : /*
2 : : Authors:
3 : : Jan Cholasta <jcholast@redhat.com>
4 : :
5 : : Copyright (C) 2012 Red Hat
6 : :
7 : : This program is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3 of the License, or
10 : : (at your option) any later version.
11 : :
12 : : This program is distributed in the hope that it will be useful,
13 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : GNU General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : : */
20 : :
21 : : #include <talloc.h>
22 : :
23 : : #include "db/sysdb_ssh.h"
24 : : #include "db/sysdb_private.h"
25 : :
26 : : static errno_t
27 : 2 : sysdb_update_ssh_host(struct sysdb_ctx *sysdb,
28 : : const char *name,
29 : : struct sysdb_attrs *attrs)
30 : : {
31 : : errno_t ret;
32 : :
33 : 2 : ret = sysdb_store_custom(sysdb, name, SSH_HOSTS_SUBDIR, attrs);
34 [ - + ]: 2 : if (ret != EOK) {
35 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
36 : : ("Error storing host %s [%d]: %s\n", name, ret, strerror(ret)));
37 : 2 : return ret;
38 : : }
39 : :
40 : : return EOK;
41 : : }
42 : :
43 : : errno_t
44 : 2 : sysdb_store_ssh_host(struct sysdb_ctx *sysdb,
45 : : const char *name,
46 : : const char *alias,
47 : : time_t now,
48 : : struct sysdb_attrs *attrs)
49 : : {
50 : : TALLOC_CTX *tmp_ctx;
51 : : errno_t ret, sret;
52 : 2 : bool in_transaction = false;
53 : 2 : const char *search_attrs[] = { SYSDB_NAME_ALIAS, NULL };
54 : : bool new_alias;
55 : 2 : struct ldb_message *host = NULL;
56 : : struct ldb_message_element *el;
57 : : unsigned int i;
58 : :
59 [ + - ][ + - ]: 2 : DEBUG(SSSDBG_TRACE_FUNC, ("Storing host %s\n", name));
[ - + ][ # # ]
[ # # ]
60 : :
61 : 2 : tmp_ctx = talloc_new(NULL);
62 [ + - ]: 2 : if (!tmp_ctx) {
63 : : return ENOMEM;
64 : : }
65 : :
66 : 2 : ret = sysdb_transaction_start(sysdb);
67 [ - + ]: 2 : if (ret != EOK) {
68 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
[ # # ][ # # ]
[ # # ]
69 : : goto done;
70 : : }
71 : :
72 : 2 : in_transaction = true;
73 : :
74 : 2 : ret = sysdb_get_ssh_host(tmp_ctx, sysdb, name, search_attrs, &host);
75 [ + - ]: 2 : if (ret != EOK && ret != ENOENT) {
76 : : goto done;
77 : : }
78 : :
79 : 2 : ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, SYSDB_SSH_HOST_OC);
80 [ - + ]: 2 : if (ret != EOK) {
81 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
82 : : ("Could not set object class [%d]: %s\n", ret, strerror(ret)));
83 : : goto done;
84 : : }
85 : :
86 : 2 : ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name);
87 [ - + ]: 2 : if (ret != EOK) {
88 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
89 : : ("Could not set name attribute [%d]: %s\n", ret, strerror(ret)));
90 : : goto done;
91 : : }
92 : :
93 [ - + ]: 2 : if (alias) {
94 : 0 : new_alias = true;
95 : :
96 : : /* copy aliases from the existing entry */
97 [ # # ]: 0 : if (host) {
98 : 0 : el = ldb_msg_find_element(host, SYSDB_NAME_ALIAS);
99 : :
100 [ # # ]: 0 : if (el) {
101 [ # # ]: 0 : for (i = 0; i < el->num_values; i++) {
102 [ # # ]: 0 : if (strcmp((char *)el->values[i].data, alias) == 0) {
103 : 0 : new_alias = false;
104 : : }
105 : :
106 : 0 : ret = sysdb_attrs_add_val(attrs,
107 : : SYSDB_NAME_ALIAS, &el->values[i]);
108 [ # # ]: 0 : if (ret != EOK) {
109 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
110 : : ("Could not add name alias %s [%d]: %s\n",
111 : : el->values[i].data, ret, strerror(ret)));
112 : : goto done;
113 : : }
114 : : }
115 : : }
116 : : }
117 : :
118 : : /* add alias only if it is not already present */
119 [ # # ]: 0 : if (new_alias) {
120 : 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, alias);
121 [ # # ]: 0 : if (ret != EOK) {
122 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
123 : : ("Could not add name alias %s [%d]: %s\n",
124 : : alias, ret, strerror(ret)));
125 : : goto done;
126 : : }
127 : : }
128 : : }
129 : :
130 : : /* make sure sshPublicKey is present when modifying an existing host */
131 [ - + ]: 2 : if (host) {
132 : 0 : ret = sysdb_attrs_get_el(attrs, SYSDB_SSH_PUBKEY, &el);
133 [ # # ]: 0 : if (ret != EOK) {
134 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
135 : : ("Could not get sysdb sshPublicKey [%d]: %s\n",
136 : : ret, strerror(ret)));
137 : : goto done;
138 : : }
139 : : }
140 : :
141 : 2 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
142 [ - + ]: 2 : if (ret != EOK) {
143 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
144 : : ("Could not set sysdb lastUpdate [%d]: %s\n",
145 : : ret, strerror(ret)));
146 : : goto done;
147 : : }
148 : :
149 : 2 : ret = sysdb_update_ssh_host(sysdb, name, attrs);
150 [ + - ]: 2 : if (ret != EOK) {
151 : : goto done;
152 : : }
153 : :
154 : 2 : ret = sysdb_transaction_commit(sysdb);
155 [ - + ]: 2 : if (ret != EOK) {
156 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
[ # # ][ # # ]
[ # # ]
157 : : goto done;
158 : : }
159 : :
160 : : in_transaction = false;
161 : :
162 : : ret = EOK;
163 : :
164 : : done:
165 [ - + ]: 2 : if (in_transaction) {
166 : 0 : sret = sysdb_transaction_cancel(sysdb);
167 [ # # ]: 0 : if (sret != EOK) {
168 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
[ # # ][ # # ]
[ # # ]
169 : : }
170 : : }
171 : :
172 : 2 : talloc_free(tmp_ctx);
173 : :
174 : : return ret;
175 : : }
176 : :
177 : : errno_t
178 : 0 : sysdb_update_ssh_known_host_expire(struct sysdb_ctx *sysdb,
179 : : const char *name,
180 : : time_t now,
181 : : int known_hosts_timeout)
182 : : {
183 : : TALLOC_CTX *tmp_ctx;
184 : : errno_t ret;
185 : : struct sysdb_attrs *attrs;
186 : :
187 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC,
[ # # ][ # # ]
[ # # ]
188 : : ("Updating known_hosts expire time of host %s\n", name));
189 : :
190 : 0 : tmp_ctx = talloc_new(NULL);
191 [ # # ]: 0 : if (!tmp_ctx) {
192 : : return ENOMEM;
193 : : }
194 : :
195 : 0 : attrs = sysdb_new_attrs(tmp_ctx);
196 [ # # ]: 0 : if (!attrs) {
197 : : ret = ENOMEM;
198 : : goto done;
199 : : }
200 : :
201 : 0 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_SSH_KNOWN_HOSTS_EXPIRE,
202 : : now + known_hosts_timeout);
203 [ # # ]: 0 : if (ret != EOK) {
204 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE,
[ # # ][ # # ]
[ # # ]
205 : : ("Could not set known_hosts expire time [%d]: %s\n",
206 : : ret, strerror(ret)));
207 : : goto done;
208 : : }
209 : :
210 : 0 : ret = sysdb_update_ssh_host(sysdb, name, attrs);
211 [ # # ]: 0 : if (ret != EOK) {
212 : : goto done;
213 : : }
214 : :
215 : 0 : ret = EOK;
216 : :
217 : : done:
218 : 0 : talloc_free(tmp_ctx);
219 : :
220 : 0 : return ret;
221 : : }
222 : :
223 : : errno_t
224 : 2 : sysdb_delete_ssh_host(struct sysdb_ctx *sysdb,
225 : : const char *name)
226 : : {
227 [ + - ][ + - ]: 2 : DEBUG(SSSDBG_TRACE_FUNC, ("Deleting host %s\n", name));
[ - + ][ # # ]
[ # # ]
228 : 2 : return sysdb_delete_custom(sysdb, name, SSH_HOSTS_SUBDIR);
229 : : }
230 : :
231 : : static errno_t
232 : 3 : sysdb_search_ssh_hosts(TALLOC_CTX *mem_ctx,
233 : : struct sysdb_ctx *sysdb,
234 : : const char *filter,
235 : : const char **attrs,
236 : : struct ldb_message ***hosts,
237 : : size_t *num_hosts)
238 : : {
239 : : errno_t ret;
240 : : TALLOC_CTX *tmp_ctx;
241 : : struct ldb_message **results;
242 : : size_t num_results;
243 : :
244 : 3 : tmp_ctx = talloc_new(NULL);
245 [ + - ]: 3 : if (!tmp_ctx) {
246 : : return ENOMEM;
247 : : }
248 : :
249 : 3 : ret = sysdb_search_custom(tmp_ctx, sysdb, filter, SSH_HOSTS_SUBDIR, attrs,
250 : : &num_results, &results);
251 [ - + ]: 3 : if (ret != EOK && ret != ENOENT) {
252 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
253 : : ("Error looking up host [%d]: %s\n",
254 : : ret, strerror(ret)));
255 : : goto done;
256 [ + + ]: 3 : } if (ret == ENOENT) {
257 [ + - ][ + - ]: 2 : DEBUG(SSSDBG_TRACE_FUNC, ("No such host\n"));
[ - + ][ # # ]
[ # # ]
258 : 2 : *hosts = NULL;
259 : 2 : *num_hosts = 0;
260 : 2 : goto done;
261 : : }
262 : :
263 : 1 : *hosts = talloc_steal(mem_ctx, results);
264 : 1 : *num_hosts = num_results;
265 : 1 : ret = EOK;
266 : :
267 : : done:
268 : 3 : talloc_free(tmp_ctx);
269 : :
270 : : return ret;
271 : : }
272 : :
273 : : errno_t
274 : 3 : sysdb_get_ssh_host(TALLOC_CTX *mem_ctx,
275 : : struct sysdb_ctx *sysdb,
276 : : const char *name,
277 : : const char **attrs,
278 : : struct ldb_message **host)
279 : : {
280 : : TALLOC_CTX *tmp_ctx;
281 : : errno_t ret;
282 : : const char *filter;
283 : : struct ldb_message **hosts;
284 : : size_t num_hosts;
285 : :
286 : 3 : tmp_ctx = talloc_new(NULL);
287 [ + - ]: 3 : if (!tmp_ctx) {
288 : : return ENOMEM;
289 : : }
290 : :
291 : 3 : filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_NAME, name);
292 [ + - ]: 3 : if (!filter) {
293 : : ret = ENOMEM;
294 : : goto done;
295 : : }
296 : :
297 : 3 : ret = sysdb_search_ssh_hosts(tmp_ctx, sysdb, filter, attrs,
298 : : &hosts, &num_hosts);
299 [ + + ]: 3 : if (ret != EOK) {
300 : : goto done;
301 : : }
302 : :
303 [ - + ]: 1 : if (num_hosts > 1) {
304 : 0 : ret = EINVAL;
305 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE,
[ # # ][ # # ]
[ # # ]
306 : : ("Found more than one host with name %s\n", name));
307 : : goto done;
308 : : }
309 : :
310 : 1 : *host = talloc_steal(mem_ctx, hosts[0]);
311 : 1 : ret = EOK;
312 : :
313 : : done:
314 : 3 : talloc_free(tmp_ctx);
315 : :
316 : : return ret;
317 : : }
318 : :
319 : : errno_t
320 : 0 : sysdb_get_ssh_known_hosts(TALLOC_CTX *mem_ctx,
321 : : struct sysdb_ctx *sysdb,
322 : : time_t now,
323 : : const char **attrs,
324 : : struct ldb_message ***hosts,
325 : : size_t *num_hosts)
326 : : {
327 : : TALLOC_CTX *tmp_ctx;
328 : : errno_t ret;
329 : : const char *filter;
330 : :
331 : 0 : tmp_ctx = talloc_new(NULL);
332 [ # # ]: 0 : if (!tmp_ctx) {
333 : : return ENOMEM;
334 : : }
335 : :
336 : 0 : filter = talloc_asprintf(tmp_ctx, "(%s>=%ld)",
337 : : SYSDB_SSH_KNOWN_HOSTS_EXPIRE, (long)now);
338 [ # # ]: 0 : if (!filter) {
339 : : ret = ENOMEM;
340 : : goto done;
341 : : }
342 : :
343 : 0 : ret = sysdb_search_ssh_hosts(mem_ctx, sysdb, filter, attrs,
344 : : hosts, num_hosts);
345 : :
346 : : done:
347 : 0 : talloc_free(tmp_ctx);
348 : :
349 : 0 : return ret;
350 : : }
|