Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2011 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.h"
24 : #include "db/sysdb_sudo.h"
25 : #include "providers/ldap/sdap_sudo_cache.h"
26 :
27 : /* ========== Functions specific for the native sudo LDAP schema ========== */
28 0 : static errno_t sdap_sudo_get_usn(TALLOC_CTX *mem_ctx,
29 : struct sysdb_attrs *attrs,
30 : struct sdap_attr_map *map,
31 : const char *name,
32 : char **_usn)
33 : {
34 : const char *usn;
35 : errno_t ret;
36 :
37 0 : if (_usn == NULL) {
38 0 : return EINVAL;
39 : }
40 :
41 0 : ret = sysdb_attrs_get_string(attrs, map[SDAP_AT_SUDO_USN].sys_name, &usn);
42 0 : if (ret != EOK) {
43 0 : DEBUG(SSSDBG_MINOR_FAILURE,
44 : "Failed to retrieve USN value: [%s]\n", strerror(ret));
45 :
46 0 : return ret;
47 : }
48 :
49 0 : *_usn = talloc_strdup(mem_ctx, usn);
50 0 : if (*_usn == NULL) {
51 0 : return ENOMEM;
52 : }
53 :
54 0 : return EOK;
55 : }
56 :
57 : static errno_t
58 0 : sdap_save_native_sudorule(TALLOC_CTX *mem_ctx,
59 : struct sss_domain_info *domain,
60 : struct sdap_attr_map *map,
61 : struct sysdb_attrs *attrs,
62 : int cache_timeout,
63 : time_t now,
64 : char **_usn)
65 : {
66 : errno_t ret;
67 : const char *rule_name;
68 :
69 0 : ret = sysdb_attrs_get_string(attrs, map[SDAP_AT_SUDO_NAME].sys_name,
70 : &rule_name);
71 0 : if (ret == ERANGE) {
72 0 : DEBUG(SSSDBG_OP_FAILURE, "Warning: found rule that contains none "
73 : "or multiple CN values. It will be skipped.\n");
74 0 : return ret;
75 0 : } else if (ret != EOK) {
76 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not get rule name [%d]: %s\n",
77 : ret, strerror(ret));
78 0 : return ret;
79 : }
80 :
81 0 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
82 0 : (cache_timeout ? (now + cache_timeout) : 0));
83 0 : if (ret) {
84 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not set sysdb cache expire [%d]: %s\n",
85 : ret, strerror(ret));
86 0 : return ret;
87 : }
88 :
89 0 : ret = sdap_sudo_get_usn(mem_ctx, attrs, map, rule_name, _usn);
90 0 : if (ret != EOK) {
91 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Could not read USN from %s\n", rule_name);
92 0 : *_usn = NULL;
93 : /* but we will store the rule anyway */
94 : }
95 :
96 0 : ret = sysdb_save_sudorule(domain, rule_name, attrs);
97 0 : if (ret != EOK) {
98 0 : DEBUG(SSSDBG_OP_FAILURE, "Could not save sudorule %s\n", rule_name);
99 0 : return ret;
100 : }
101 :
102 0 : return ret;
103 : }
104 :
105 : errno_t
106 0 : sdap_save_native_sudorule_list(TALLOC_CTX *mem_ctx,
107 : struct sss_domain_info *domain,
108 : struct sdap_attr_map *map,
109 : struct sysdb_attrs **replies,
110 : size_t replies_count,
111 : int cache_timeout,
112 : time_t now,
113 : char **_usn)
114 : {
115 0 : TALLOC_CTX *tmp_ctx = NULL;
116 0 : char *higher_usn = NULL;
117 0 : char *usn_value = NULL;
118 : errno_t ret, tret;
119 0 : bool in_transaction = false;
120 : size_t i;
121 :
122 0 : tmp_ctx = talloc_new(NULL);
123 0 : if (tmp_ctx == NULL) {
124 0 : DEBUG(SSSDBG_FATAL_FAILURE, "talloc_new() failed\n");
125 0 : return ENOMEM;
126 : }
127 :
128 0 : ret = sysdb_transaction_start(domain->sysdb);
129 0 : if (ret != EOK) {
130 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not start transaction\n");
131 0 : goto fail;
132 : }
133 0 : in_transaction = true;
134 :
135 0 : for (i=0; i < replies_count; i++) {
136 0 : usn_value = NULL;
137 0 : ret = sdap_save_native_sudorule(tmp_ctx, domain, map, replies[i],
138 : cache_timeout, now, &usn_value);
139 0 : if (ret != EOK) {
140 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to save sudo rule, "
141 : "will continue with next...\n");
142 0 : continue;
143 : }
144 :
145 : /* find highest usn */
146 0 : if (usn_value) {
147 0 : if (higher_usn) {
148 0 : if ((strlen(usn_value) > strlen(higher_usn)) ||
149 0 : (strcmp(usn_value, higher_usn) > 0)) {
150 0 : talloc_zfree(higher_usn);
151 0 : higher_usn = usn_value;
152 : } else {
153 0 : talloc_zfree(usn_value);
154 : }
155 : } else {
156 0 : higher_usn = usn_value;
157 : }
158 : }
159 : }
160 :
161 0 : ret = sysdb_transaction_commit(domain->sysdb);
162 0 : if (ret != EOK) {
163 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
164 0 : goto fail;
165 : }
166 0 : in_transaction = false;
167 :
168 0 : if (higher_usn != NULL) {
169 0 : *_usn = talloc_steal(mem_ctx, higher_usn);
170 : }
171 :
172 0 : ret = EOK;
173 : fail:
174 0 : if (in_transaction) {
175 0 : tret = sysdb_transaction_cancel(domain->sysdb);
176 0 : if (tret != EOK) {
177 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
178 : }
179 : }
180 :
181 0 : talloc_free(tmp_ctx);
182 :
183 0 : return ret;
184 : }
|