bf7bd7
import sssd-2.4.0-3.el8
@@ -0,0 +1,64 @@
|
|
1
|
+
From ff24d1538af88f83d0a3cc2817952cf70e7ca580 Mon Sep 17 00:00:00 2001
|
2
|
+
From: Alexey Tikhonov <atikhono@redhat.com>
|
3
|
+
Date: Sun, 22 Nov 2020 17:44:07 +0100
|
4
|
+
Subject: [PATCH] SYSDB: merge_res_sysdb_attrs() fixed to avoid NULL ptr in
|
5
|
+
msgs[]
|
6
|
+
MIME-Version: 1.0
|
7
|
+
Content-Type: text/plain; charset=UTF-8
|
8
|
+
Content-Transfer-Encoding: 8bit
|
9
|
+
|
10
|
+
This helps to avoid sssd_be segfaults at be_refresh_get_values_ex() due to NULL
|
11
|
+
ptrs in results of sysdb_search_with_ts_attr()
|
12
|
+
|
13
|
+
Resolves: https://github.com/SSSD/sssd/issues/5412
|
14
|
+
|
15
|
+
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
|
16
|
+
---
|
17
|
+
src/db/sysdb_search.c | 11 +++++++----
|
18
|
+
1 file changed, 7 insertions(+), 4 deletions(-)
|
19
|
+
|
20
|
+
diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c
|
21
|
+
index e616fd5bc..4ff65c1ae 100644
|
22
|
+
--- a/src/db/sysdb_search.c
|
23
|
+
+++ b/src/db/sysdb_search.c
|
24
|
+
@@ -221,6 +221,7 @@ static errno_t merge_res_sysdb_attrs(TALLOC_CTX *mem_ctx,
|
25
|
+
const char *attrs[])
|
26
|
+
{
|
27
|
+
errno_t ret;
|
28
|
+
+ size_t ts_cache_res_count = 0;
|
29
|
+
struct ldb_result *ts_cache_res = NULL;
|
30
|
+
|
31
|
+
if (ts_res == NULL || ctx->ldb_ts == NULL) {
|
32
|
+
@@ -231,7 +232,6 @@ static errno_t merge_res_sysdb_attrs(TALLOC_CTX *mem_ctx,
|
33
|
+
if (ts_cache_res == NULL) {
|
34
|
+
return ENOMEM;
|
35
|
+
}
|
36
|
+
- ts_cache_res->count = ts_res->count;
|
37
|
+
ts_cache_res->msgs = talloc_zero_array(ts_cache_res,
|
38
|
+
struct ldb_message *,
|
39
|
+
ts_res->count);
|
40
|
+
@@ -244,15 +244,18 @@ static errno_t merge_res_sysdb_attrs(TALLOC_CTX *mem_ctx,
|
41
|
+
ret = merge_msg_sysdb_attrs(ts_cache_res->msgs,
|
42
|
+
ctx,
|
43
|
+
ts_res->msgs[c],
|
44
|
+
- &ts_cache_res->msgs[c], attrs);
|
45
|
+
- if (ret != EOK) {
|
46
|
+
+ &ts_cache_res->msgs[ts_cache_res_count],
|
47
|
+
+ attrs);
|
48
|
+
+ if ((ret != EOK) || (ts_cache_res->msgs[ts_cache_res_count] == NULL)) {
|
49
|
+
DEBUG(SSSDBG_MINOR_FAILURE,
|
50
|
+
"Cannot merge sysdb cache values for %s\n",
|
51
|
+
ldb_dn_get_linearized(ts_res->msgs[c]->dn));
|
52
|
+
- /* non-fatal, we just get only the non-timestamp attrs */
|
53
|
+
+ /* non-fatal, just skip */
|
54
|
+
continue;
|
55
|
+
}
|
56
|
+
+ ts_cache_res_count += 1;
|
57
|
+
}
|
58
|
+
+ ts_cache_res->count = ts_cache_res_count;
|
59
|
+
|
60
|
+
*_ts_cache_res = ts_cache_res;
|
61
|
+
return EOK;
|
62
|
+
--
|
63
|
+
2.21.3
|
64
|
+
|
@@ -0,0 +1,3226 @@
|
|
1
|
+
From 19c0cfe38670cc56219f0d9acdc2b3363e92616c Mon Sep 17 00:00:00 2001
|
2
|
+
From: Alexey Tikhonov <atikhono@redhat.com>
|
3
|
+
Date: Fri, 4 Dec 2020 12:09:57 +0100
|
4
|
+
Subject: [PATCH] Squashed commit of the following:
|
5
|
+
MIME-Version: 1.0
|
6
|
+
Content-Type: text/plain; charset=UTF-8
|
7
|
+
Content-Transfer-Encoding: 8bit
|
8
|
+
|
9
|
+
commit 325de5a5bb97ba026be6d22492bea8ab2605f1b5
|
10
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
11
|
+
Date: Thu Nov 26 12:07:06 2020 +0100
|
12
|
+
|
13
|
+
secrets: remove base64 enctype
|
14
|
+
|
15
|
+
This was added as part of KCM performance improvements but never used.
|
16
|
+
Ldb is fully capable of holding binary data without the need for base64
|
17
|
+
encoding so this is not needed.
|
18
|
+
|
19
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
20
|
+
|
21
|
+
commit 39277cdadd317b0ab86cdd37de0616bc3eecbe6a
|
22
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
23
|
+
Date: Thu Nov 26 11:55:39 2020 +0100
|
24
|
+
|
25
|
+
secrets: move attrs names to macros
|
26
|
+
|
27
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
28
|
+
|
29
|
+
commit 9c1b51d057390fb5b26151f814a480911cda4cc9
|
30
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
31
|
+
Date: Thu Nov 26 11:47:24 2020 +0100
|
32
|
+
|
33
|
+
secrets: default to "plaintext" if "enctype" attr is missing
|
34
|
+
|
35
|
+
This is a sane fallback behavior, however it should not happen since
|
36
|
+
the attribute should be always present.
|
37
|
+
|
38
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
39
|
+
|
40
|
+
commit bf127d4f3f42e5b2afe25e512211439bc12a9904
|
41
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
42
|
+
Date: Tue Nov 3 13:35:33 2020 +0100
|
43
|
+
|
44
|
+
secrets: fix may_payload_size exceeded debug message
|
45
|
+
|
46
|
+
The unit is bytes (B) not bits (b) and the conversion of the input
|
47
|
+
payload size to KiB was wrong (multiplying bytes * 1024).
|
48
|
+
|
49
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
50
|
+
|
51
|
+
commit c3b314db57c34f64aaca7d74e76a9a955288bb51
|
52
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
53
|
+
Date: Mon Oct 19 12:40:07 2020 +0200
|
54
|
+
|
55
|
+
kcm: store credentials list in hash table to avoid cache lookups
|
56
|
+
|
57
|
+
Iteration over ccache requires CRED_UUID_LIST and then calling
|
58
|
+
CRED_BY_UUID for each uuid in the obtained list. Each CRED_BY_UUID
|
59
|
+
operation invoked ldb_search and decryption. This was a substantional
|
60
|
+
bottle neck.
|
61
|
+
|
62
|
+
Resolves: https://github.com/SSSD/sssd/issues/5349
|
63
|
+
|
64
|
+
:fixes: KCM performance has improved dramatically for cases where
|
65
|
+
large amount of credentials are stored in the ccache.
|
66
|
+
|
67
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
68
|
+
|
69
|
+
commit a370553c90c2ed6df3b94c169c4960a6f978031f
|
70
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
71
|
+
Date: Thu Oct 29 14:57:53 2020 +0100
|
72
|
+
|
73
|
+
sss_ptr_hash: fix double free for circular dependencies
|
74
|
+
|
75
|
+
If the hash table delete callback deletes the stored item,
|
76
|
+
we can end up in double free in case when we try to override
|
77
|
+
an existing item (hash_enter(key) where key already exists).
|
78
|
+
|
79
|
+
```c
|
80
|
+
static void delete_cb(hash_entry_t *item,
|
81
|
+
hash_destroy_enum deltype,
|
82
|
+
void *pvt)
|
83
|
+
{
|
84
|
+
talloc_free(item->value.ptr);
|
85
|
+
}
|
86
|
+
|
87
|
+
hash_enter(key);
|
88
|
+
hash_enter(key);
|
89
|
+
```
|
90
|
+
|
91
|
+
The doble free it self is fine, since it is done via talloc destructor
|
92
|
+
and talloc can cope with that. However, the hash table fails to store
|
93
|
+
the new entry because hash_delete is called twice.
|
94
|
+
|
95
|
+
```
|
96
|
+
_sss_ptr_hash_add -> hash_enter -> hash_delete(old) -> delete_cb -> sss_ptr_hash_value_destructor -> hash_delete
|
97
|
+
```
|
98
|
+
|
99
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
100
|
+
|
101
|
+
commit 241ee30da12f564803793ee2b14c1522aabd9235
|
102
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
103
|
+
Date: Fri Oct 16 15:36:51 2020 +0200
|
104
|
+
|
105
|
+
kcm: add per-connection data to be shared between requests
|
106
|
+
|
107
|
+
Resolves: https://github.com/SSSD/sssd/issues/5349
|
108
|
+
|
109
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
110
|
+
|
111
|
+
commit 194447d35c11eb914f54719491dc5cfaab01b9a1
|
112
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
113
|
+
Date: Tue Oct 27 16:21:31 2020 +0100
|
114
|
+
|
115
|
+
kcm: use binary format to store ccache instead of json
|
116
|
+
|
117
|
+
JSON is computationally complex and the parser is a bottleneck which
|
118
|
+
consumes about 10% of time. It also create the ccache unnecessary
|
119
|
+
large because it requires lots of unneded character and base64
|
120
|
+
encoding.
|
121
|
+
|
122
|
+
Binary format is fast, simple and small.
|
123
|
+
|
124
|
+
This is backwards compatible and there is no need to destroy existing
|
125
|
+
ccache. It will be stored in binary format at first write to the cache.
|
126
|
+
|
127
|
+
Resolves: https://github.com/SSSD/sssd/issues/5349
|
128
|
+
|
129
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
130
|
+
|
131
|
+
commit f17740d831e16449495fff4ec57cc4800aaac83d
|
132
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
133
|
+
Date: Tue Oct 27 17:09:43 2020 +0100
|
134
|
+
|
135
|
+
kcm: add spaces around operators in kcmsrv_ccache_key.c
|
136
|
+
|
137
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
138
|
+
|
139
|
+
commit 15069a647ed6c7f1ead42baa1d421d953c9bc557
|
140
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
141
|
+
Date: Tue Oct 27 16:37:05 2020 +0100
|
142
|
+
|
143
|
+
kcm: avoid suppression of cppcheck warning
|
144
|
+
|
145
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
146
|
+
|
147
|
+
commit e63a15038ac9c186626e4fdf681a6492031d1e40
|
148
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
149
|
+
Date: Tue Oct 27 16:18:11 2020 +0100
|
150
|
+
|
151
|
+
kcm: move sec key parser to separate file so it can be shared
|
152
|
+
|
153
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
154
|
+
|
155
|
+
commit 9b1631defdcaa3ea7e87889eb136e7fa935ab4ce
|
156
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
157
|
+
Date: Thu Oct 22 13:34:52 2020 +0200
|
158
|
+
|
159
|
+
kcm: add json suffix to existing searialization functions
|
160
|
+
|
161
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
162
|
+
|
163
|
+
commit b6cc661b9f4162e590137430e945aa321fc13121
|
164
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
165
|
+
Date: Fri Oct 23 13:10:13 2020 +0200
|
166
|
+
|
167
|
+
iobuf: add more iobuf functions
|
168
|
+
|
169
|
+
These will be used in later patches.
|
170
|
+
|
171
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
172
|
+
|
173
|
+
commit ed08ba0023e63024bf1c52ae3f6596b9d804d0a5
|
174
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
175
|
+
Date: Thu Oct 22 12:18:38 2020 +0200
|
176
|
+
|
177
|
+
secrets: accept binary data instead of string
|
178
|
+
|
179
|
+
Currently, both KCM and secrets responders store JSON formatted string
|
180
|
+
in the secrets database. One of the next commits makes KCM to store
|
181
|
+
binary format instead of JSON string to improve performance. We need
|
182
|
+
to be able to distinguish the formats to keep KCM update compatible
|
183
|
+
with existing ccache and also to keep secrets responder working.
|
184
|
+
|
185
|
+
Secrets responder test had to be ammended to fit into a new maximum
|
186
|
+
payload which is now reduced by one byte for the secrets responder
|
187
|
+
to hold the ending zero of a secret string.
|
188
|
+
|
189
|
+
This is a corner case in a long deprecated responder that is not even
|
190
|
+
built by default and has no known consumers so it is fine to fast fix
|
191
|
+
the test.
|
192
|
+
|
193
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
194
|
+
|
195
|
+
commit 908c15af9a9f8f0556a588e368e4a0b2e24ace1b
|
196
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
197
|
+
Date: Thu Oct 22 11:18:12 2020 +0200
|
198
|
+
|
199
|
+
secrets: allow to specify secret's data format
|
200
|
+
|
201
|
+
Currently, both KCM and secrets responders store JSON formatted string
|
202
|
+
in the secrets database. One of the next commits makes KCM to store
|
203
|
+
binary format instead of JSON string to improve performance. We need
|
204
|
+
to be able to distinguish the formats to keep KCM update compatible
|
205
|
+
with existing ccache and also to keep secrets responder working.
|
206
|
+
|
207
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
208
|
+
|
209
|
+
commit 74fdaa64b27e88a6e0f153f8cb59989c572d4294
|
210
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
211
|
+
Date: Tue Oct 27 16:45:22 2020 +0100
|
212
|
+
|
213
|
+
kcm: avoid multiple debug messages if sss_sec_put fails
|
214
|
+
|
215
|
+
sec_put() already logs a message if the underlaying function fails
|
216
|
+
so this debug message is really unnecessary.
|
217
|
+
|
218
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
219
|
+
|
220
|
+
commit b8f28d9aa9d862cf504691c9c3f92941a63fb0a4
|
221
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
222
|
+
Date: Mon Oct 19 12:59:48 2020 +0200
|
223
|
+
|
224
|
+
kcm: disable encryption
|
225
|
+
|
226
|
+
Encryption was a huge bottleneck for the secdb backend. This is
|
227
|
+
backwards compatible and there is no need to destroy existing
|
228
|
+
ccache. It will be stored unencrypted at first write to the cache.
|
229
|
+
|
230
|
+
Note that the encryption did not provide any security as the cache
|
231
|
+
is accessible only by root and the master key is stored together
|
232
|
+
with the cache. So once someone gains access to the file it can
|
233
|
+
be easily decrypted. Additionaly, there was also no encryption at
|
234
|
+
the memory level.
|
235
|
+
|
236
|
+
Resolves: https://github.com/SSSD/sssd/issues/5349
|
237
|
+
|
238
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
239
|
+
|
240
|
+
commit 8edcea8c377e85d037e83065c1904fa4b92c4a39
|
241
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
242
|
+
Date: Fri Oct 16 15:33:42 2020 +0200
|
243
|
+
|
244
|
+
kcm: avoid name confusion in GET_CRED_UUID_LIST handlers
|
245
|
+
|
246
|
+
The function name did not follow best practices and it got easily confused
|
247
|
+
with `kcm_op_get_cred_by_uuid_getbyname_done`.
|
248
|
+
|
249
|
+
```
|
250
|
+
kcm_op_get_cred_uuid_getbyname_done
|
251
|
+
kcm_op_get_cred_by_uuid_getbyname_done
|
252
|
+
```
|
253
|
+
|
254
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
255
|
+
|
256
|
+
commit 47a316c850107f12d406f27abb216e26383dfab7
|
257
|
+
Author: Pavel Březina <pbrezina@redhat.com>
|
258
|
+
Date: Mon Sep 14 12:44:57 2020 +0200
|
259
|
+
|
260
|
+
kcm: fix typos in debug messages
|
261
|
+
|
262
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
263
|
+
---
|
264
|
+
Makefile.am | 14 +-
|
265
|
+
src/responder/kcm/kcmsrv_ccache.c | 66 ++++
|
266
|
+
src/responder/kcm/kcmsrv_ccache.h | 47 ++-
|
267
|
+
src/responder/kcm/kcmsrv_ccache_binary.c | 308 ++++++++++++++++++
|
268
|
+
src/responder/kcm/kcmsrv_ccache_json.c | 149 +--------
|
269
|
+
src/responder/kcm/kcmsrv_ccache_key.c | 144 ++++++++
|
270
|
+
src/responder/kcm/kcmsrv_ccache_mem.c | 30 +-
|
271
|
+
src/responder/kcm/kcmsrv_ccache_secdb.c | 128 +++-----
|
272
|
+
src/responder/kcm/kcmsrv_ccache_secrets.c | 9 +-
|
273
|
+
src/responder/kcm/kcmsrv_cmd.c | 23 +-
|
274
|
+
src/responder/kcm/kcmsrv_ops.c | 252 ++++++++++----
|
275
|
+
src/responder/kcm/kcmsrv_ops.h | 8 +
|
276
|
+
src/responder/secrets/local.c | 5 +-
|
277
|
+
src/shared/safealign.h | 4 +
|
278
|
+
...n_marshalling.c => test_kcm_marshalling.c} | 147 +++++++--
|
279
|
+
src/tests/cmocka/test_sss_ptr_hash.c | 39 +++
|
280
|
+
src/tests/cmocka/test_utils.c | 3 +
|
281
|
+
src/tests/cmocka/test_utils.h | 1 +
|
282
|
+
src/tests/intg/test_secrets.py | 3 +-
|
283
|
+
src/tests/multihost/basic/test_kcm.py | 12 +-
|
284
|
+
src/util/secrets/sec_pvt.h | 2 +-
|
285
|
+
src/util/secrets/secrets.c | 290 ++++++++++++-----
|
286
|
+
src/util/secrets/secrets.h | 20 +-
|
287
|
+
src/util/sss_iobuf.c | 141 ++++++++
|
288
|
+
src/util/sss_iobuf.h | 46 +++
|
289
|
+
src/util/sss_ptr_hash.c | 20 ++
|
290
|
+
26 files changed, 1457 insertions(+), 454 deletions(-)
|
291
|
+
create mode 100644 src/responder/kcm/kcmsrv_ccache_binary.c
|
292
|
+
create mode 100644 src/responder/kcm/kcmsrv_ccache_key.c
|
293
|
+
rename src/tests/cmocka/{test_kcm_json_marshalling.c => test_kcm_marshalling.c} (71%)
|
294
|
+
|
295
|
+
diff --git a/Makefile.am b/Makefile.am
|
296
|
+
index 97aa1ec66..430b4e842 100644
|
297
|
+
--- a/Makefile.am
|
298
|
+
+++ b/Makefile.am
|
299
|
+
@@ -311,7 +311,7 @@ endif # HAVE_INOTIFY
|
300
|
+
|
301
|
+
if BUILD_KCM
|
302
|
+
non_interactive_cmocka_based_tests += \
|
303
|
+
- test_kcm_json \
|
304
|
+
+ test_kcm_marshalling \
|
305
|
+
test_kcm_queue \
|
306
|
+
$(NULL)
|
307
|
+
endif # BUILD_KCM
|
308
|
+
@@ -1817,8 +1817,10 @@ sssd_kcm_SOURCES = \
|
309
|
+
src/responder/kcm/kcm.c \
|
310
|
+
src/responder/kcm/kcmsrv_cmd.c \
|
311
|
+
src/responder/kcm/kcmsrv_ccache.c \
|
312
|
+
+ src/responder/kcm/kcmsrv_ccache_binary.c \
|
313
|
+
src/responder/kcm/kcmsrv_ccache_mem.c \
|
314
|
+
src/responder/kcm/kcmsrv_ccache_json.c \
|
315
|
+
+ src/responder/kcm/kcmsrv_ccache_key.c \
|
316
|
+
src/responder/kcm/kcmsrv_ccache_secdb.c \
|
317
|
+
src/responder/kcm/kcmsrv_ops.c \
|
318
|
+
src/responder/kcm/kcmsrv_op_queue.c \
|
319
|
+
@@ -3927,18 +3929,20 @@ test_sssd_krb5_locator_plugin_LDADD = \
|
320
|
+
$(NULL)
|
321
|
+
|
322
|
+
if BUILD_KCM
|
323
|
+
-test_kcm_json_SOURCES = \
|
324
|
+
- src/tests/cmocka/test_kcm_json_marshalling.c \
|
325
|
+
+test_kcm_marshalling_SOURCES = \
|
326
|
+
+ src/tests/cmocka/test_kcm_marshalling.c \
|
327
|
+
+ src/responder/kcm/kcmsrv_ccache_binary.c \
|
328
|
+
src/responder/kcm/kcmsrv_ccache_json.c \
|
329
|
+
+ src/responder/kcm/kcmsrv_ccache_key.c \
|
330
|
+
src/responder/kcm/kcmsrv_ccache.c \
|
331
|
+
src/util/sss_krb5.c \
|
332
|
+
src/util/sss_iobuf.c \
|
333
|
+
$(NULL)
|
334
|
+
-test_kcm_json_CFLAGS = \
|
335
|
+
+test_kcm_marshalling_CFLAGS = \
|
336
|
+
$(AM_CFLAGS) \
|
337
|
+
$(UUID_CFLAGS) \
|
338
|
+
$(NULL)
|
339
|
+
-test_kcm_json_LDADD = \
|
340
|
+
+test_kcm_marshalling_LDADD = \
|
341
|
+
$(JANSSON_LIBS) \
|
342
|
+
$(UUID_LIBS) \
|
343
|
+
$(KRB5_LIBS) \
|
344
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache.c b/src/responder/kcm/kcmsrv_ccache.c
|
345
|
+
index 66e2752ba..60eacd451 100644
|
346
|
+
--- a/src/responder/kcm/kcmsrv_ccache.c
|
347
|
+
+++ b/src/responder/kcm/kcmsrv_ccache.c
|
348
|
+
|
349
|
+
#include "responder/kcm/kcmsrv_ccache_pvt.h"
|
350
|
+
#include "responder/kcm/kcmsrv_ccache_be.h"
|
351
|
+
|
352
|
+
+static struct kcm_cred *kcm_cred_dup(TALLOC_CTX *mem_ctx,
|
353
|
+
+ struct kcm_cred *crd);
|
354
|
+
+
|
355
|
+
static int kcm_cc_destructor(struct kcm_ccache *cc)
|
356
|
+
{
|
357
|
+
if (cc == NULL) {
|
358
|
+
@@ -94,6 +97,33 @@ done:
|
359
|
+
return ret;
|
360
|
+
}
|
361
|
+
|
362
|
+
+struct kcm_ccache *kcm_cc_dup(TALLOC_CTX *mem_ctx,
|
363
|
+
+ const struct kcm_ccache *cc)
|
364
|
+
+{
|
365
|
+
+ struct kcm_ccache *dup;
|
366
|
+
+ struct kcm_cred *crd_dup;
|
367
|
+
+ struct kcm_cred *crd;
|
368
|
+
+
|
369
|
+
+ dup = talloc_zero(mem_ctx, struct kcm_ccache);
|
370
|
+
+ if (dup == NULL) {
|
371
|
+
+ return NULL;
|
372
|
+
+ }
|
373
|
+
+ memcpy(dup, cc, sizeof(struct kcm_ccache));
|
374
|
+
+
|
375
|
+
+ dup->creds = NULL;
|
376
|
+
+ DLIST_FOR_EACH(crd, cc->creds) {
|
377
|
+
+ crd_dup = kcm_cred_dup(dup, crd);
|
378
|
+
+ if (crd_dup == NULL) {
|
379
|
+
+ talloc_free(dup);
|
380
|
+
+ return NULL;
|
381
|
+
+ }
|
382
|
+
+
|
383
|
+
+ DLIST_ADD(dup->creds, crd_dup);
|
384
|
+
+ }
|
385
|
+
+
|
386
|
+
+ return dup;
|
387
|
+
+}
|
388
|
+
+
|
389
|
+
const char *kcm_cc_get_name(struct kcm_ccache *cc)
|
390
|
+
{
|
391
|
+
return cc ? cc->name : NULL;
|
392
|
+
@@ -204,6 +234,22 @@ struct kcm_cred *kcm_cred_new(TALLOC_CTX *mem_ctx,
|
393
|
+
return kcreds;
|
394
|
+
}
|
395
|
+
|
396
|
+
+static struct kcm_cred *kcm_cred_dup(TALLOC_CTX *mem_ctx,
|
397
|
+
+ struct kcm_cred *crd)
|
398
|
+
+{
|
399
|
+
+ struct kcm_cred *dup;
|
400
|
+
+
|
401
|
+
+ dup = talloc_zero(mem_ctx, struct kcm_cred);
|
402
|
+
+ if (dup == NULL) {
|
403
|
+
+ return NULL;
|
404
|
+
+ }
|
405
|
+
+
|
406
|
+
+ uuid_copy(dup->uuid, crd->uuid);
|
407
|
+
+ dup->cred_blob = crd->cred_blob;
|
408
|
+
+
|
409
|
+
+ return dup;
|
410
|
+
+}
|
411
|
+
+
|
412
|
+
/* Add a cred to ccache */
|
413
|
+
errno_t kcm_cc_store_creds(struct kcm_ccache *cc,
|
414
|
+
struct kcm_cred *crd)
|
415
|
+
@@ -213,6 +259,26 @@ errno_t kcm_cc_store_creds(struct kcm_ccache *cc,
|
416
|
+
return EOK;
|
417
|
+
}
|
418
|
+
|
419
|
+
+errno_t kcm_cc_set_header(struct kcm_ccache *cc,
|
420
|
+
+ const char *sec_key,
|
421
|
+
+ struct cli_creds *client)
|
422
|
+
+{
|
423
|
+
+ errno_t ret;
|
424
|
+
+
|
425
|
+
+ ret = sec_key_parse(cc, sec_key, &cc->name, cc->uuid);
|
426
|
+
+ if (ret != EOK) {
|
427
|
+
+ return ret;
|
428
|
+
+ }
|
429
|
+
+
|
430
|
+
+ /* We rely on sssd-secrets only searching the user's subtree so we
|
431
|
+
+ * set the ownership to the client
|
432
|
+
+ */
|
433
|
+
+ cc->owner.uid = cli_creds_get_uid(client);
|
434
|
+
+ cc->owner.gid = cli_creds_get_gid(client);
|
435
|
+
+
|
436
|
+
+ return EOK;
|
437
|
+
+}
|
438
|
+
+
|
439
|
+
errno_t kcm_cred_get_uuid(struct kcm_cred *crd, uuid_t _uuid)
|
440
|
+
{
|
441
|
+
if (crd == NULL) {
|
442
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache.h b/src/responder/kcm/kcmsrv_ccache.h
|
443
|
+
index d629923fa..77cf8f61d 100644
|
444
|
+
--- a/src/responder/kcm/kcmsrv_ccache.h
|
445
|
+
+++ b/src/responder/kcm/kcmsrv_ccache.h
|
446
|
+
@@ -72,6 +72,13 @@ errno_t kcm_cc_new(TALLOC_CTX *mem_ctx,
|
447
|
+
krb5_principal princ,
|
448
|
+
struct kcm_ccache **_cc);
|
449
|
+
|
450
|
+
+/*
|
451
|
+
+ * Duplicate the ccache. Only ccache and credentials are duplicated,
|
452
|
+
+ * but their data are a shallow copy.
|
453
|
+
+ */
|
454
|
+
+struct kcm_ccache *kcm_cc_dup(TALLOC_CTX *mem_ctx,
|
455
|
+
+ const struct kcm_ccache *cc);
|
456
|
+
+
|
457
|
+
/*
|
458
|
+
* Returns true if a client can access a ccache.
|
459
|
+
*
|
460
|
+
@@ -100,6 +107,11 @@ struct kcm_cred *kcm_cred_new(TALLOC_CTX *mem_ctx,
|
461
|
+
errno_t kcm_cc_store_creds(struct kcm_ccache *cc,
|
462
|
+
struct kcm_cred *crd);
|
463
|
+
|
464
|
+
+/* Set cc header information from sec key and client */
|
465
|
+
+errno_t kcm_cc_set_header(struct kcm_ccache *cc,
|
466
|
+
+ const char *sec_key,
|
467
|
+
+ struct cli_creds *client);
|
468
|
+
+
|
469
|
+
errno_t kcm_cred_get_uuid(struct kcm_cred *crd, uuid_t uuid);
|
470
|
+
|
471
|
+
/*
|
472
|
+
@@ -320,6 +332,11 @@ bool sec_key_match_name(const char *sec_key,
|
473
|
+
bool sec_key_match_uuid(const char *sec_key,
|
474
|
+
uuid_t uuid);
|
475
|
+
|
476
|
+
+errno_t sec_key_parse(TALLOC_CTX *mem_ctx,
|
477
|
+
+ const char *sec_key,
|
478
|
+
+ const char **_name,
|
479
|
+
+ uuid_t uuid);
|
480
|
+
+
|
481
|
+
const char *sec_key_get_name(const char *sec_key);
|
482
|
+
|
483
|
+
errno_t sec_key_get_uuid(const char *sec_key,
|
484
|
+
@@ -333,16 +350,30 @@ const char *sec_key_create(TALLOC_CTX *mem_ctx,
|
485
|
+
* sec_key is a concatenation of the ccache's UUID and name
|
486
|
+
* sec_value is the JSON dump of the ccache contents
|
487
|
+
*/
|
488
|
+
-errno_t sec_kv_to_ccache(TALLOC_CTX *mem_ctx,
|
489
|
+
- const char *sec_key,
|
490
|
+
- const char *sec_value,
|
491
|
+
- struct cli_creds *client,
|
492
|
+
- struct kcm_ccache **_cc);
|
493
|
+
+errno_t sec_kv_to_ccache_json(TALLOC_CTX *mem_ctx,
|
494
|
+
+ const char *sec_key,
|
495
|
+
+ const char *sec_value,
|
496
|
+
+ struct cli_creds *client,
|
497
|
+
+ struct kcm_ccache **_cc);
|
498
|
+
|
499
|
+
/* Convert a kcm_ccache to a key-value pair to be stored in secrets */
|
500
|
+
-errno_t kcm_ccache_to_sec_input(TALLOC_CTX *mem_ctx,
|
501
|
+
- struct kcm_ccache *cc,
|
502
|
+
+errno_t kcm_ccache_to_sec_input_json(TALLOC_CTX *mem_ctx,
|
503
|
+
+ struct kcm_ccache *cc,
|
504
|
+
+ struct sss_iobuf **_payload);
|
505
|
+
+
|
506
|
+
+/*
|
507
|
+
+ * sec_key is a concatenation of the ccache's UUID and name
|
508
|
+
+ * sec_value is the binary representation of ccache.
|
509
|
+
+ */
|
510
|
+
+errno_t sec_kv_to_ccache_binary(TALLOC_CTX *mem_ctx,
|
511
|
+
+ const char *sec_key,
|
512
|
+
+ struct sss_iobuf *sec_value,
|
513
|
+
struct cli_creds *client,
|
514
|
+
- struct sss_iobuf **_payload);
|
515
|
+
+ struct kcm_ccache **_cc);
|
516
|
+
+
|
517
|
+
+/* Convert a kcm_ccache to its binary representation. */
|
518
|
+
+errno_t kcm_ccache_to_sec_input_binary(TALLOC_CTX *mem_ctx,
|
519
|
+
+ struct kcm_ccache *cc,
|
520
|
+
+ struct sss_iobuf **_payload);
|
521
|
+
|
522
|
+
#endif /* _KCMSRV_CCACHE_H_ */
|
523
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache_binary.c b/src/responder/kcm/kcmsrv_ccache_binary.c
|
524
|
+
new file mode 100644
|
525
|
+
index 000000000..7bfdbf13b
|
526
|
+
--- /dev/null
|
527
|
+
+++ b/src/responder/kcm/kcmsrv_ccache_binary.c
|
528
|
+
|
529
|
+
+/*
|
530
|
+
+ Authors:
|
531
|
+
+ Pavel Březina <pbrezina@redhat.com>
|
532
|
+
+
|
533
|
+
+ Copyright (C) 2020 Red Hat
|
534
|
+
+
|
535
|
+
+ This program is free software; you can redistribute it and/or modify
|
536
|
+
+ it under the terms of the GNU General Public License as published by
|
537
|
+
+ the Free Software Foundation; either version 3 of the License, or
|
538
|
+
+ (at your option) any later version.
|
539
|
+
+
|
540
|
+
+ This program is distributed in the hope that it will be useful,
|
541
|
+
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
542
|
+
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
543
|
+
+ GNU General Public License for more details.
|
544
|
+
+
|
545
|
+
+ You should have received a copy of the GNU General Public License
|
546
|
+
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
547
|
+
+*/
|
548
|
+
+
|
549
|
+
+#include "config.h"
|
550
|
+
+
|
551
|
+
+#include <stdio.h>
|
552
|
+
+#include <talloc.h>
|
553
|
+
+
|
554
|
+
+#include "util/util.h"
|
555
|
+
+#include "util/util_creds.h"
|
556
|
+
+#include "util/crypto/sss_crypto.h"
|
557
|
+
+#include "responder/kcm/kcmsrv_ccache_pvt.h"
|
558
|
+
+
|
559
|
+
+static errno_t krb_data_to_bin(krb5_data *data, struct sss_iobuf *buf)
|
560
|
+
+{
|
561
|
+
+ return sss_iobuf_write_varlen(buf, (uint8_t *)data->data, data->length);
|
562
|
+
+}
|
563
|
+
+
|
564
|
+
+static errno_t princ_to_bin(krb5_principal princ, struct sss_iobuf *buf)
|
565
|
+
+{
|
566
|
+
+ errno_t ret;
|
567
|
+
+
|
568
|
+
+ if (princ == NULL) {
|
569
|
+
+ return sss_iobuf_write_uint8(buf, 0);
|
570
|
+
+ }
|
571
|
+
+
|
572
|
+
+ /* Mark that principal is not empty. */
|
573
|
+
+ ret = sss_iobuf_write_uint8(buf, 1);
|
574
|
+
+ if (ret != EOK) {
|
575
|
+
+ return ret;
|
576
|
+
+ }
|
577
|
+
+
|
578
|
+
+ ret = krb_data_to_bin(&princ->realm, buf);
|
579
|
+
+ if (ret != EOK) {
|
580
|
+
+ return ret;
|
581
|
+
+ }
|
582
|
+
+
|
583
|
+
+ ret = sss_iobuf_write_int32(buf, princ->type);
|
584
|
+
+ if (ret != EOK) {
|
585
|
+
+ return ret;
|
586
|
+
+ }
|
587
|
+
+
|
588
|
+
+ ret = sss_iobuf_write_int32(buf, princ->length);
|
589
|
+
+ if (ret != EOK) {
|
590
|
+
+ return ret;
|
591
|
+
+ }
|
592
|
+
+
|
593
|
+
+ for (krb5_int32 i = 0; i < princ->length; i++) {
|
594
|
+
+ ret = krb_data_to_bin(&princ->data[i], buf);
|
595
|
+
+ if (ret != EOK) {
|
596
|
+
+ return ret;
|
597
|
+
+ }
|
598
|
+
+ }
|
599
|
+
+
|
600
|
+
+ return EOK;
|
601
|
+
+}
|
602
|
+
+
|
603
|
+
+static errno_t creds_to_bin(struct kcm_cred *creds, struct sss_iobuf *buf)
|
604
|
+
+{
|
605
|
+
+ struct kcm_cred *crd;
|
606
|
+
+ uint32_t count = 0;
|
607
|
+
+ errno_t ret;
|
608
|
+
+
|
609
|
+
+ DLIST_FOR_EACH(crd, creds) {
|
610
|
+
+ count++;
|
611
|
+
+ }
|
612
|
+
+
|
613
|
+
+ ret = sss_iobuf_write_uint32(buf, count);
|
614
|
+
+ if (ret != EOK) {
|
615
|
+
+ return ret;
|
616
|
+
+ }
|
617
|
+
+
|
618
|
+
+ DLIST_FOR_EACH(crd, creds) {
|
619
|
+
+ ret = sss_iobuf_write_len(buf, (uint8_t *)crd->uuid, sizeof(uuid_t));
|
620
|
+
+ if (ret != EOK) {
|
621
|
+
+ return ret;
|
622
|
+
+ }
|
623
|
+
+
|
624
|
+
+ ret = sss_iobuf_write_iobuf(buf, crd->cred_blob);
|
625
|
+
+ if (ret != EOK) {
|
626
|
+
+ return ret;
|
627
|
+
+ }
|
628
|
+
+ }
|
629
|
+
+
|
630
|
+
+ return EOK;
|
631
|
+
+}
|
632
|
+
+
|
633
|
+
+errno_t kcm_ccache_to_sec_input_binary(TALLOC_CTX *mem_ctx,
|
634
|
+
+ struct kcm_ccache *cc,
|
635
|
+
+ struct sss_iobuf **_payload)
|
636
|
+
+{
|
637
|
+
+ struct sss_iobuf *buf;
|
638
|
+
+ errno_t ret;
|
639
|
+
+
|
640
|
+
+ buf = sss_iobuf_init_empty(mem_ctx, sizeof(krb5_principal_data), 0);
|
641
|
+
+ if (buf == NULL) {
|
642
|
+
+ return ENOMEM;
|
643
|
+
+ }
|
644
|
+
+
|
645
|
+
+ ret = sss_iobuf_write_int32(buf, cc->kdc_offset);
|
646
|
+
+ if (ret != EOK) {
|
647
|
+
+ goto done;
|
648
|
+
+ }
|
649
|
+
+
|
650
|
+
+ ret = princ_to_bin(cc->client, buf);
|
651
|
+
+ if (ret != EOK) {
|
652
|
+
+ goto done;
|
653
|
+
+ }
|
654
|
+
+
|
655
|
+
+ ret = creds_to_bin(cc->creds, buf);
|
656
|
+
+ if (ret != EOK) {
|
657
|
+
+ goto done;
|
658
|
+
+ }
|
659
|
+
+
|
660
|
+
+ *_payload = buf;
|
661
|
+
+
|
662
|
+
+ ret = EOK;
|
663
|
+
+
|
664
|
+
+done:
|
665
|
+
+ if (ret != EOK) {
|
666
|
+
+ talloc_free(buf);
|
667
|
+
+ }
|
668
|
+
+
|
669
|
+
+ return ret;
|
670
|
+
+}
|
671
|
+
+
|
672
|
+
+static errno_t bin_to_krb_data(TALLOC_CTX *mem_ctx,
|
673
|
+
+ struct sss_iobuf *buf,
|
674
|
+
+ krb5_data *out)
|
675
|
+
+{
|
676
|
+
+ uint8_t *data;
|
677
|
+
+ size_t len;
|
678
|
+
+ errno_t ret;
|
679
|
+
+
|
680
|
+
+ ret = sss_iobuf_read_varlen(mem_ctx, buf, &data, &len);
|
681
|
+
+ if (ret != EOK) {
|
682
|
+
+ return ret;
|
683
|
+
+ }
|
684
|
+
+
|
685
|
+
+ out->magic = 0;
|
686
|
+
+ out->data = (char*)data;
|
687
|
+
+ out->length = len;
|
688
|
+
+
|
689
|
+
+ return EOK;
|
690
|
+
+}
|
691
|
+
+
|
692
|
+
+static errno_t bin_to_princ(TALLOC_CTX *mem_ctx,
|
693
|
+
+ struct sss_iobuf *buf,
|
694
|
+
+ krb5_principal *_princ)
|
695
|
+
+{
|
696
|
+
+ krb5_principal princ;
|
697
|
+
+ uint8_t non_empty;
|
698
|
+
+ krb5_int32 i;
|
699
|
+
+ errno_t ret;
|
700
|
+
+
|
701
|
+
+ ret = sss_iobuf_read_uint8(buf, &non_empty);
|
702
|
+
+ if (ret != EOK) {
|
703
|
+
+ return ret;
|
704
|
+
+ }
|
705
|
+
+
|
706
|
+
+ if (non_empty == 0) {
|
707
|
+
+ *_princ = NULL;
|
708
|
+
+ return EOK;
|
709
|
+
+ }
|
710
|
+
+
|
711
|
+
+ princ = talloc_zero(mem_ctx, struct krb5_principal_data);
|
712
|
+
+ if (princ == NULL) {
|
713
|
+
+ return ENOMEM;
|
714
|
+
+ }
|
715
|
+
+ princ->magic = KV5M_PRINCIPAL;
|
716
|
+
+
|
717
|
+
+ ret = bin_to_krb_data(princ, buf, &princ->realm);
|
718
|
+
+ if (ret != EOK) {
|
719
|
+
+ return ret;
|
720
|
+
+ }
|
721
|
+
+
|
722
|
+
+ ret = sss_iobuf_read_int32(buf, &princ->type);
|
723
|
+
+ if (ret != EOK) {
|
724
|
+
+ return ret;
|
725
|
+
+ }
|
726
|
+
+
|
727
|
+
+ ret = sss_iobuf_read_int32(buf, &princ->length);
|
728
|
+
+ if (ret != EOK) {
|
729
|
+
+ return ret;
|
730
|
+
+ }
|
731
|
+
+
|
732
|
+
+ princ->data = talloc_zero_array(princ, krb5_data, princ->length);
|
733
|
+
+ if (princ->length > 0 && princ->data == NULL) {
|
734
|
+
+ return ENOMEM;
|
735
|
+
+ }
|
736
|
+
+
|
737
|
+
+ for (i = 0; i < princ->length; i++) {
|
738
|
+
+ ret = bin_to_krb_data(princ, buf, &princ->data[i]);
|
739
|
+
+ if (ret != EOK) {
|
740
|
+
+ return ret;
|
741
|
+
+ }
|
742
|
+
+ }
|
743
|
+
+
|
744
|
+
+ *_princ = princ;
|
745
|
+
+
|
746
|
+
+ return EOK;
|
747
|
+
+}
|
748
|
+
+
|
749
|
+
+static errno_t bin_to_creds(TALLOC_CTX *mem_ctx,
|
750
|
+
+ struct sss_iobuf *buf,
|
751
|
+
+ struct kcm_cred **_creds)
|
752
|
+
+{
|
753
|
+
+ struct kcm_cred *creds = NULL;
|
754
|
+
+ struct kcm_cred *crd;
|
755
|
+
+ struct sss_iobuf *cred_blob;
|
756
|
+
+ uint32_t count;
|
757
|
+
+ uuid_t uuid;
|
758
|
+
+ errno_t ret;
|
759
|
+
+
|
760
|
+
+ ret = sss_iobuf_read_uint32(buf, &count);
|
761
|
+
+ if (ret != EOK) {
|
762
|
+
+ return ret;
|
763
|
+
+ }
|
764
|
+
+
|
765
|
+
+ for (uint32_t i = 0; i < count; i++) {
|
766
|
+
+ ret = sss_iobuf_read_len(buf, sizeof(uuid_t), (uint8_t*)uuid);
|
767
|
+
+ if (ret != EOK) {
|
768
|
+
+ return ret;
|
769
|
+
+ }
|
770
|
+
+
|
771
|
+
+ ret = sss_iobuf_read_iobuf(NULL, buf, &cred_blob);
|
772
|
+
+ if (ret != EOK) {
|
773
|
+
+ return ret;
|
774
|
+
+ }
|
775
|
+
+
|
776
|
+
+ crd = kcm_cred_new(mem_ctx, uuid, cred_blob);
|
777
|
+
+ if (crd == NULL) {
|
778
|
+
+ talloc_free(cred_blob);
|
779
|
+
+ return ENOMEM;
|
780
|
+
+ }
|
781
|
+
+
|
782
|
+
+ DLIST_ADD(creds, crd);
|
783
|
+
+ }
|
784
|
+
+
|
785
|
+
+ *_creds = creds;
|
786
|
+
+
|
787
|
+
+ return EOK;
|
788
|
+
+}
|
789
|
+
+
|
790
|
+
+errno_t sec_kv_to_ccache_binary(TALLOC_CTX *mem_ctx,
|
791
|
+
+ const char *sec_key,
|
792
|
+
+ struct sss_iobuf *sec_value,
|
793
|
+
+ struct cli_creds *client,
|
794
|
+
+ struct kcm_ccache **_cc)
|
795
|
+
+{
|
796
|
+
+ struct kcm_ccache *cc;
|
797
|
+
+ errno_t ret;
|
798
|
+
+
|
799
|
+
+ cc = talloc_zero(mem_ctx, struct kcm_ccache);
|
800
|
+
+ if (cc == NULL) {
|
801
|
+
+ return ENOMEM;
|
802
|
+
+ }
|
803
|
+
+
|
804
|
+
+ ret = kcm_cc_set_header(cc, sec_key, client);
|
805
|
+
+ if (ret != EOK) {
|
806
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot store ccache header [%d]: %s\n",
|
807
|
+
+ ret, sss_strerror(ret));
|
808
|
+
+ goto done;
|
809
|
+
+ }
|
810
|
+
+
|
811
|
+
+ ret = sss_iobuf_read_int32(sec_value, &cc->kdc_offset);
|
812
|
+
+ if (ret != EOK) {
|
813
|
+
+ goto done;
|
814
|
+
+ }
|
815
|
+
+
|
816
|
+
+ ret = bin_to_princ(cc, sec_value, &cc->client);
|
817
|
+
+ if (ret != EOK) {
|
818
|
+
+ goto done;
|
819
|
+
+ }
|
820
|
+
+
|
821
|
+
+ ret = bin_to_creds(cc, sec_value, &cc->creds);
|
822
|
+
+ if (ret != EOK) {
|
823
|
+
+ goto done;
|
824
|
+
+ }
|
825
|
+
+
|
826
|
+
+ *_cc = cc;
|
827
|
+
+
|
828
|
+
+ ret = EOK;
|
829
|
+
+
|
830
|
+
+done:
|
831
|
+
+ if (ret != EOK) {
|
832
|
+
+ talloc_free(cc);
|
833
|
+
+ }
|
834
|
+
+
|
835
|
+
+ return ret;
|
836
|
+
+}
|
837
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache_json.c b/src/responder/kcm/kcmsrv_ccache_json.c
|
838
|
+
index f78e9f58c..e790cbea3 100644
|
839
|
+
--- a/src/responder/kcm/kcmsrv_ccache_json.c
|
840
|
+
+++ b/src/responder/kcm/kcmsrv_ccache_json.c
|
841
|
+
|
842
|
+
*/
|
843
|
+
#define KS_JSON_VERSION 1
|
844
|
+
|
845
|
+
-/*
|
846
|
+
- * The secrets store is a key-value store at heart. We store the UUID
|
847
|
+
- * and the name in the key to allow easy lookups be either key
|
848
|
+
- */
|
849
|
+
-#define SEC_KEY_SEPARATOR '-'
|
850
|
+
-
|
851
|
+
/* Compat definition of json_array_foreach for older systems */
|
852
|
+
#ifndef json_array_foreach
|
853
|
+
#define json_array_foreach(array, idx, value) \
|
854
|
+
|
855
|
+
idx++)
|
856
|
+
#endif
|
857
|
+
|
858
|
+
-const char *sec_key_create(TALLOC_CTX *mem_ctx,
|
859
|
+
- const char *name,
|
860
|
+
- uuid_t uuid)
|
861
|
+
-{
|
862
|
+
- char uuid_str[UUID_STR_SIZE];
|
863
|
+
-
|
864
|
+
- uuid_unparse(uuid, uuid_str);
|
865
|
+
- return talloc_asprintf(mem_ctx,
|
866
|
+
- "%s%c%s", uuid_str, SEC_KEY_SEPARATOR, name);
|
867
|
+
-}
|
868
|
+
-
|
869
|
+
-static bool sec_key_valid(const char *sec_key)
|
870
|
+
-{
|
871
|
+
- if (sec_key == NULL) {
|
872
|
+
- return false;
|
873
|
+
- }
|
874
|
+
-
|
875
|
+
- if (strlen(sec_key) < UUID_STR_SIZE + 1) {
|
876
|
+
- /* One char for separator (at UUID_STR_SIZE, because strlen doesn't
|
877
|
+
- * include the '\0', but UUID_STR_SIZE does) and at least one for
|
878
|
+
- * the name */
|
879
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key);
|
880
|
+
- return false;
|
881
|
+
- }
|
882
|
+
-
|
883
|
+
- if (sec_key[UUID_STR_SIZE - 1] != SEC_KEY_SEPARATOR) {
|
884
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n");
|
885
|
+
- return false;
|
886
|
+
- }
|
887
|
+
-
|
888
|
+
- return true;
|
889
|
+
-}
|
890
|
+
-
|
891
|
+
-static errno_t sec_key_parse(TALLOC_CTX *mem_ctx,
|
892
|
+
- const char *sec_key,
|
893
|
+
- const char **_name,
|
894
|
+
- uuid_t uuid)
|
895
|
+
-{
|
896
|
+
- char uuid_str[UUID_STR_SIZE];
|
897
|
+
-
|
898
|
+
- if (!sec_key_valid(sec_key)) {
|
899
|
+
- return EINVAL;
|
900
|
+
- }
|
901
|
+
-
|
902
|
+
- strncpy(uuid_str, sec_key, sizeof(uuid_str)-1);
|
903
|
+
- if (sec_key[UUID_STR_SIZE - 1] != SEC_KEY_SEPARATOR) {
|
904
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n");
|
905
|
+
- return EINVAL;
|
906
|
+
- }
|
907
|
+
- uuid_str[UUID_STR_SIZE-1] = '\0';
|
908
|
+
-
|
909
|
+
- *_name = talloc_strdup(mem_ctx, sec_key + UUID_STR_SIZE);
|
910
|
+
- if (*_name == NULL) {
|
911
|
+
- return ENOMEM;
|
912
|
+
- }
|
913
|
+
- uuid_parse(uuid_str, uuid);
|
914
|
+
-
|
915
|
+
- return EOK;
|
916
|
+
-}
|
917
|
+
-
|
918
|
+
-errno_t sec_key_get_uuid(const char *sec_key,
|
919
|
+
- uuid_t uuid)
|
920
|
+
-{
|
921
|
+
- char uuid_str[UUID_STR_SIZE];
|
922
|
+
-
|
923
|
+
- if (!sec_key_valid(sec_key)) {
|
924
|
+
- return EINVAL;
|
925
|
+
- }
|
926
|
+
-
|
927
|
+
- strncpy(uuid_str, sec_key, UUID_STR_SIZE-1);
|
928
|
+
- uuid_str[UUID_STR_SIZE-1] = '\0';
|
929
|
+
- uuid_parse(uuid_str, uuid);
|
930
|
+
- return EOK;
|
931
|
+
-}
|
932
|
+
-
|
933
|
+
-const char *sec_key_get_name(const char *sec_key)
|
934
|
+
-{
|
935
|
+
- if (!sec_key_valid(sec_key)) {
|
936
|
+
- return NULL;
|
937
|
+
- }
|
938
|
+
-
|
939
|
+
- return sec_key + UUID_STR_SIZE;
|
940
|
+
-}
|
941
|
+
-
|
942
|
+
-bool sec_key_match_name(const char *sec_key,
|
943
|
+
- const char *name)
|
944
|
+
-{
|
945
|
+
- if (!sec_key_valid(sec_key) || name == NULL) {
|
946
|
+
- return false;
|
947
|
+
- }
|
948
|
+
-
|
949
|
+
- return strcmp(sec_key + UUID_STR_SIZE, name) == 0;
|
950
|
+
-}
|
951
|
+
-
|
952
|
+
-bool sec_key_match_uuid(const char *sec_key,
|
953
|
+
- uuid_t uuid)
|
954
|
+
-{
|
955
|
+
- errno_t ret;
|
956
|
+
- uuid_t key_uuid;
|
957
|
+
-
|
958
|
+
- /* `key_uuid` is output arg and isn't read in sec_key_get_uuid() but
|
959
|
+
- * since libuuid is opaque for cppcheck it generates false positive here
|
960
|
+
- */
|
961
|
+
- /* cppcheck-suppress uninitvar */
|
962
|
+
- ret = sec_key_get_uuid(sec_key, key_uuid);
|
963
|
+
- if (ret != EOK) {
|
964
|
+
- DEBUG(SSSDBG_MINOR_FAILURE, "Cannot convert key to UUID\n");
|
965
|
+
- return false;
|
966
|
+
- }
|
967
|
+
-
|
968
|
+
- return uuid_compare(key_uuid, uuid) == 0;
|
969
|
+
-}
|
970
|
+
-
|
971
|
+
/*
|
972
|
+
* Creates an array of principal elements that will be used later
|
973
|
+
* in the form of:
|
974
|
+
@@ -460,10 +341,9 @@ static errno_t ccache_to_sec_val(TALLOC_CTX *mem_ctx,
|
975
|
+
return EOK;
|
976
|
+
}
|
977
|
+
|
978
|
+
-errno_t kcm_ccache_to_sec_input(TALLOC_CTX *mem_ctx,
|
979
|
+
- struct kcm_ccache *cc,
|
980
|
+
- struct cli_creds *client,
|
981
|
+
- struct sss_iobuf **_payload)
|
982
|
+
+errno_t kcm_ccache_to_sec_input_json(TALLOC_CTX *mem_ctx,
|
983
|
+
+ struct kcm_ccache *cc,
|
984
|
+
+ struct sss_iobuf **_payload)
|
985
|
+
{
|
986
|
+
errno_t ret;
|
987
|
+
const char *value;
|
988
|
+
@@ -897,11 +777,11 @@ static errno_t sec_json_value_to_ccache(struct kcm_ccache *cc,
|
989
|
+
* sec_key is a concatenation of the ccache's UUID and name
|
990
|
+
* sec_value is the JSON dump of the ccache contents
|
991
|
+
*/
|
992
|
+
-errno_t sec_kv_to_ccache(TALLOC_CTX *mem_ctx,
|
993
|
+
- const char *sec_key,
|
994
|
+
- const char *sec_value,
|
995
|
+
- struct cli_creds *client,
|
996
|
+
- struct kcm_ccache **_cc)
|
997
|
+
+errno_t sec_kv_to_ccache_json(TALLOC_CTX *mem_ctx,
|
998
|
+
+ const char *sec_key,
|
999
|
+
+ const char *sec_value,
|
1000
|
+
+ struct cli_creds *client,
|
1001
|
+
+ struct kcm_ccache **_cc)
|
1002
|
+
{
|
1003
|
+
errno_t ret;
|
1004
|
+
json_t *root = NULL;
|
1005
|
+
@@ -911,7 +791,7 @@ errno_t sec_kv_to_ccache(TALLOC_CTX *mem_ctx,
|
1006
|
+
ret = sec_value_to_json(sec_value, &root);
|
1007
|
+
if (ret != EOK) {
|
1008
|
+
DEBUG(SSSDBG_CRIT_FAILURE,
|
1009
|
+
- "Cannot store secret to JSN [%d]: %s\n",
|
1010
|
+
+ "Cannot store secret to JSON [%d]: %s\n",
|
1011
|
+
ret, sss_strerror(ret));
|
1012
|
+
goto done;
|
1013
|
+
}
|
1014
|
+
@@ -928,16 +808,9 @@ errno_t sec_kv_to_ccache(TALLOC_CTX *mem_ctx,
|
1015
|
+
goto done;
|
1016
|
+
}
|
1017
|
+
|
1018
|
+
- /* We rely on sssd-secrets only searching the user's subtree so we
|
1019
|
+
- * set the ownership to the client
|
1020
|
+
- */
|
1021
|
+
- cc->owner.uid = cli_creds_get_uid(client);
|
1022
|
+
- cc->owner.gid = cli_creds_get_gid(client);
|
1023
|
+
-
|
1024
|
+
- ret = sec_key_parse(cc, sec_key, &cc->name, cc->uuid);
|
1025
|
+
+ ret = kcm_cc_set_header(cc, sec_key, client);
|
1026
|
+
if (ret != EOK) {
|
1027
|
+
- DEBUG(SSSDBG_CRIT_FAILURE,
|
1028
|
+
- "Cannt parse secret key [%d]: %s\n",
|
1029
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot store ccache header [%d]: %s\n",
|
1030
|
+
ret, sss_strerror(ret));
|
1031
|
+
goto done;
|
1032
|
+
}
|
1033
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache_key.c b/src/responder/kcm/kcmsrv_ccache_key.c
|
1034
|
+
new file mode 100644
|
1035
|
+
index 000000000..59d60453c
|
1036
|
+
--- /dev/null
|
1037
|
+
+++ b/src/responder/kcm/kcmsrv_ccache_key.c
|
1038
|
+
|
1039
|
+
+/*
|
1040
|
+
+ SSSD
|
1041
|
+
+
|
1042
|
+
+ Copyright (C) Red Hat, 2020
|
1043
|
+
+
|
1044
|
+
+ This program is free software; you can redistribute it and/or modify
|
1045
|
+
+ it under the terms of the GNU General Public License as published by
|
1046
|
+
+ the Free Software Foundation; either version 3 of the License, or
|
1047
|
+
+ (at your option) any later version.
|
1048
|
+
+
|
1049
|
+
+ This program is distributed in the hope that it will be useful,
|
1050
|
+
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
1051
|
+
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
1052
|
+
+ GNU General Public License for more details.
|
1053
|
+
+
|
1054
|
+
+ You should have received a copy of the GNU General Public License
|
1055
|
+
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
1056
|
+
+*/
|
1057
|
+
+
|
1058
|
+
+#include "config.h"
|
1059
|
+
+
|
1060
|
+
+#include <stdio.h>
|
1061
|
+
+#include <talloc.h>
|
1062
|
+
+
|
1063
|
+
+#include "util/util.h"
|
1064
|
+
+#include "responder/kcm/kcmsrv_ccache_pvt.h"
|
1065
|
+
+
|
1066
|
+
+/*
|
1067
|
+
+ * The secrets store is a key-value store at heart. We store the UUID
|
1068
|
+
+ * and the name in the key to allow easy lookups by either part.
|
1069
|
+
+ */
|
1070
|
+
+#define SEC_KEY_SEPARATOR '-'
|
1071
|
+
+
|
1072
|
+
+const char *sec_key_create(TALLOC_CTX *mem_ctx,
|
1073
|
+
+ const char *name,
|
1074
|
+
+ uuid_t uuid)
|
1075
|
+
+{
|
1076
|
+
+ char uuid_str[UUID_STR_SIZE];
|
1077
|
+
+
|
1078
|
+
+ uuid_unparse(uuid, uuid_str);
|
1079
|
+
+ return talloc_asprintf(mem_ctx,
|
1080
|
+
+ "%s%c%s", uuid_str, SEC_KEY_SEPARATOR, name);
|
1081
|
+
+}
|
1082
|
+
+
|
1083
|
+
+static bool sec_key_valid(const char *sec_key)
|
1084
|
+
+{
|
1085
|
+
+ if (sec_key == NULL) {
|
1086
|
+
+ return false;
|
1087
|
+
+ }
|
1088
|
+
+
|
1089
|
+
+ if (strlen(sec_key) < UUID_STR_SIZE + 1) {
|
1090
|
+
+ /* One char for separator (at UUID_STR_SIZE, because strlen doesn't
|
1091
|
+
+ * include the '\0', but UUID_STR_SIZE does) and at least one for
|
1092
|
+
+ * the name */
|
1093
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Key %s is too short\n", sec_key);
|
1094
|
+
+ return false;
|
1095
|
+
+ }
|
1096
|
+
+
|
1097
|
+
+ if (sec_key[UUID_STR_SIZE - 1] != SEC_KEY_SEPARATOR) {
|
1098
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n");
|
1099
|
+
+ return false;
|
1100
|
+
+ }
|
1101
|
+
+
|
1102
|
+
+ return true;
|
1103
|
+
+}
|
1104
|
+
+
|
1105
|
+
+errno_t sec_key_parse(TALLOC_CTX *mem_ctx,
|
1106
|
+
+ const char *sec_key,
|
1107
|
+
+ const char **_name,
|
1108
|
+
+ uuid_t uuid)
|
1109
|
+
+{
|
1110
|
+
+ char uuid_str[UUID_STR_SIZE];
|
1111
|
+
+
|
1112
|
+
+ if (!sec_key_valid(sec_key)) {
|
1113
|
+
+ return EINVAL;
|
1114
|
+
+ }
|
1115
|
+
+
|
1116
|
+
+ strncpy(uuid_str, sec_key, sizeof(uuid_str) - 1);
|
1117
|
+
+ if (sec_key[UUID_STR_SIZE - 1] != SEC_KEY_SEPARATOR) {
|
1118
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Key doesn't contain the separator\n");
|
1119
|
+
+ return EINVAL;
|
1120
|
+
+ }
|
1121
|
+
+ uuid_str[UUID_STR_SIZE - 1] = '\0';
|
1122
|
+
+
|
1123
|
+
+ *_name = talloc_strdup(mem_ctx, sec_key + UUID_STR_SIZE);
|
1124
|
+
+ if (*_name == NULL) {
|
1125
|
+
+ return ENOMEM;
|
1126
|
+
+ }
|
1127
|
+
+ uuid_parse(uuid_str, uuid);
|
1128
|
+
+
|
1129
|
+
+ return EOK;
|
1130
|
+
+}
|
1131
|
+
+
|
1132
|
+
+errno_t sec_key_get_uuid(const char *sec_key,
|
1133
|
+
+ uuid_t uuid)
|
1134
|
+
+{
|
1135
|
+
+ char uuid_str[UUID_STR_SIZE];
|
1136
|
+
+
|
1137
|
+
+ if (!sec_key_valid(sec_key)) {
|
1138
|
+
+ return EINVAL;
|
1139
|
+
+ }
|
1140
|
+
+
|
1141
|
+
+ strncpy(uuid_str, sec_key, UUID_STR_SIZE - 1);
|
1142
|
+
+ uuid_str[UUID_STR_SIZE - 1] = '\0';
|
1143
|
+
+ uuid_parse(uuid_str, uuid);
|
1144
|
+
+ return EOK;
|
1145
|
+
+}
|
1146
|
+
+
|
1147
|
+
+const char *sec_key_get_name(const char *sec_key)
|
1148
|
+
+{
|
1149
|
+
+ if (!sec_key_valid(sec_key)) {
|
1150
|
+
+ return NULL;
|
1151
|
+
+ }
|
1152
|
+
+
|
1153
|
+
+ return sec_key + UUID_STR_SIZE;
|
1154
|
+
+}
|
1155
|
+
+
|
1156
|
+
+bool sec_key_match_name(const char *sec_key,
|
1157
|
+
+ const char *name)
|
1158
|
+
+{
|
1159
|
+
+ if (!sec_key_valid(sec_key) || name == NULL) {
|
1160
|
+
+ return false;
|
1161
|
+
+ }
|
1162
|
+
+
|
1163
|
+
+ return strcmp(sec_key + UUID_STR_SIZE, name) == 0;
|
1164
|
+
+}
|
1165
|
+
+
|
1166
|
+
+bool sec_key_match_uuid(const char *sec_key,
|
1167
|
+
+ uuid_t uuid)
|
1168
|
+
+{
|
1169
|
+
+ errno_t ret;
|
1170
|
+
+ uuid_t key_uuid;
|
1171
|
+
+
|
1172
|
+
+ /* Clear uuid value to avoid cppcheck warning. */
|
1173
|
+
+ uuid_clear(key_uuid);
|
1174
|
+
+
|
1175
|
+
+ ret = sec_key_get_uuid(sec_key, key_uuid);
|
1176
|
+
+ if (ret != EOK) {
|
1177
|
+
+ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot convert key to UUID\n");
|
1178
|
+
+ return false;
|
1179
|
+
+ }
|
1180
|
+
+
|
1181
|
+
+ return uuid_compare(key_uuid, uuid) == 0;
|
1182
|
+
+}
|
1183
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache_mem.c b/src/responder/kcm/kcmsrv_ccache_mem.c
|
1184
|
+
index baa698054..0e3a7b239 100644
|
1185
|
+
--- a/src/responder/kcm/kcmsrv_ccache_mem.c
|
1186
|
+
+++ b/src/responder/kcm/kcmsrv_ccache_mem.c
|
1187
|
+
@@ -49,24 +49,6 @@ struct ccdb_mem {
|
1188
|
+
unsigned int nextid;
|
1189
|
+
};
|
1190
|
+
|
1191
|
+
-/* In order to provide a consistent interface, we need to let the caller
|
1192
|
+
- * of getbyXXX own the ccache, therefore the memory back end returns a shallow
|
1193
|
+
- * copy of the ccache
|
1194
|
+
- */
|
1195
|
+
-static struct kcm_ccache *kcm_ccache_dup(TALLOC_CTX *mem_ctx,
|
1196
|
+
- struct kcm_ccache *in)
|
1197
|
+
-{
|
1198
|
+
- struct kcm_ccache *out;
|
1199
|
+
-
|
1200
|
+
- out = talloc_zero(mem_ctx, struct kcm_ccache);
|
1201
|
+
- if (out == NULL) {
|
1202
|
+
- return NULL;
|
1203
|
+
- }
|
1204
|
+
- memcpy(out, in, sizeof(struct kcm_ccache));
|
1205
|
+
-
|
1206
|
+
- return out;
|
1207
|
+
-}
|
1208
|
+
-
|
1209
|
+
static struct ccache_mem_wrap *memdb_get_by_uuid(struct ccdb_mem *memdb,
|
1210
|
+
struct cli_creds *client,
|
1211
|
+
uuid_t uuid)
|
1212
|
+
@@ -417,7 +399,11 @@ static struct tevent_req *ccdb_mem_getbyuuid_send(TALLOC_CTX *mem_ctx,
|
1213
|
+
|
1214
|
+
ccwrap = memdb_get_by_uuid(memdb, client, uuid);
|
1215
|
+
if (ccwrap != NULL) {
|
1216
|
+
- state->cc = kcm_ccache_dup(state, ccwrap->cc);
|
1217
|
+
+ /* In order to provide a consistent interface, we need to let the caller
|
1218
|
+
+ * of getbyXXX own the ccache, therefore the memory back end returns a shallow
|
1219
|
+
+ * copy of the ccache
|
1220
|
+
+ */
|
1221
|
+
+ state->cc = kcm_cc_dup(state, ccwrap->cc);
|
1222
|
+
if (state->cc == NULL) {
|
1223
|
+
ret = ENOMEM;
|
1224
|
+
goto immediate;
|
1225
|
+
@@ -470,7 +456,11 @@ static struct tevent_req *ccdb_mem_getbyname_send(TALLOC_CTX *mem_ctx,
|
1226
|
+
|
1227
|
+
ccwrap = memdb_get_by_name(memdb, client, name);
|
1228
|
+
if (ccwrap != NULL) {
|
1229
|
+
- state->cc = kcm_ccache_dup(state, ccwrap->cc);
|
1230
|
+
+ /* In order to provide a consistent interface, we need to let the caller
|
1231
|
+
+ * of getbyXXX own the ccache, therefore the memory back end returns a shallow
|
1232
|
+
+ * copy of the ccache
|
1233
|
+
+ */
|
1234
|
+
+ state->cc = kcm_cc_dup(state, ccwrap->cc);
|
1235
|
+
if (state->cc == NULL) {
|
1236
|
+
ret = ENOMEM;
|
1237
|
+
goto immediate;
|
1238
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache_secdb.c b/src/responder/kcm/kcmsrv_ccache_secdb.c
|
1239
|
+
index ed1c8247f..726711ac4 100644
|
1240
|
+
--- a/src/responder/kcm/kcmsrv_ccache_secdb.c
|
1241
|
+
+++ b/src/responder/kcm/kcmsrv_ccache_secdb.c
|
1242
|
+
|
1243
|
+
#define KCM_SECDB_CCACHE_FMT KCM_SECDB_BASE_FMT"ccache/"
|
1244
|
+
#define KCM_SECDB_DFL_FMT KCM_SECDB_BASE_FMT"default"
|
1245
|
+
|
1246
|
+
-static errno_t sec_get_b64(TALLOC_CTX *mem_ctx,
|
1247
|
+
- struct sss_sec_req *req,
|
1248
|
+
- struct sss_iobuf **_buf)
|
1249
|
+
+static errno_t sec_get(TALLOC_CTX *mem_ctx,
|
1250
|
+
+ struct sss_sec_req *req,
|
1251
|
+
+ struct sss_iobuf **_buf,
|
1252
|
+
+ char **_datatype)
|
1253
|
+
{
|
1254
|
+
errno_t ret;
|
1255
|
+
TALLOC_CTX *tmp_ctx;
|
1256
|
+
- char *b64_sec;
|
1257
|
+
+ char *datatype;
|
1258
|
+
uint8_t *data;
|
1259
|
+
- size_t data_size;
|
1260
|
+
+ size_t len;
|
1261
|
+
struct sss_iobuf *buf;
|
1262
|
+
|
1263
|
+
tmp_ctx = talloc_new(mem_ctx);
|
1264
|
+
@@ -51,101 +52,61 @@ static errno_t sec_get_b64(TALLOC_CTX *mem_ctx,
|
1265
|
+
return ENOMEM;
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
- ret = sss_sec_get(tmp_ctx, req, &b64_sec);
|
1269
|
+
+ ret = sss_sec_get(tmp_ctx, req, &data, &len, &datatype);
|
1270
|
+
if (ret != EOK) {
|
1271
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
1272
|
+
"Cannot retrieve the secret [%d]: %s\n", ret, sss_strerror(ret));
|
1273
|
+
goto done;
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
- data = sss_base64_decode(tmp_ctx, b64_sec, &data_size);
|
1277
|
+
- if (data == NULL) {
|
1278
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot decode secret from base64\n");
|
1279
|
+
- ret = EIO;
|
1280
|
+
- goto done;
|
1281
|
+
- }
|
1282
|
+
-
|
1283
|
+
- buf = sss_iobuf_init_readonly(tmp_ctx, data, data_size);
|
1284
|
+
+ buf = sss_iobuf_init_steal(tmp_ctx, data, len);
|
1285
|
+
if (buf == NULL) {
|
1286
|
+
DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init the iobuf\n");
|
1287
|
+
ret = EIO;
|
1288
|
+
goto done;
|
1289
|
+
}
|
1290
|
+
|
1291
|
+
- ret = EOK;
|
1292
|
+
*_buf = talloc_steal(mem_ctx, buf);
|
1293
|
+
+ if (_datatype != NULL) {
|
1294
|
+
+ *_datatype = talloc_steal(mem_ctx, datatype);
|
1295
|
+
+ }
|
1296
|
+
+
|
1297
|
+
+ ret = EOK;
|
1298
|
+
+
|
1299
|
+
done:
|
1300
|
+
talloc_free(tmp_ctx);
|
1301
|
+
return ret;
|
1302
|
+
}
|
1303
|
+
|
1304
|
+
-static errno_t sec_put_b64(TALLOC_CTX *mem_ctx,
|
1305
|
+
- struct sss_sec_req *req,
|
1306
|
+
- struct sss_iobuf *buf)
|
1307
|
+
+static errno_t sec_put(TALLOC_CTX *mem_ctx,
|
1308
|
+
+ struct sss_sec_req *req,
|
1309
|
+
+ struct sss_iobuf *buf)
|
1310
|
+
{
|
1311
|
+
errno_t ret;
|
1312
|
+
- TALLOC_CTX *tmp_ctx;
|
1313
|
+
- char *secret;
|
1314
|
+
|
1315
|
+
- tmp_ctx = talloc_new(mem_ctx);
|
1316
|
+
- if (tmp_ctx == NULL) {
|
1317
|
+
- return ENOMEM;
|
1318
|
+
- }
|
1319
|
+
-
|
1320
|
+
- secret = sss_base64_encode(tmp_ctx,
|
1321
|
+
- sss_iobuf_get_data(buf),
|
1322
|
+
- sss_iobuf_get_size(buf));
|
1323
|
+
- if (secret == NULL) {
|
1324
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot encode secret to base64\n");
|
1325
|
+
- ret = EIO;
|
1326
|
+
- goto done;
|
1327
|
+
- }
|
1328
|
+
-
|
1329
|
+
- ret = sss_sec_put(req, secret);
|
1330
|
+
+ ret = sss_sec_put(req, sss_iobuf_get_data(buf), sss_iobuf_get_size(buf),
|
1331
|
+
+ SSS_SEC_PLAINTEXT, "binary");
|
1332
|
+
if (ret != EOK) {
|
1333
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
1334
|
+
"Cannot write the secret [%d]: %s\n", ret, sss_strerror(ret));
|
1335
|
+
- goto done;
|
1336
|
+
}
|
1337
|
+
|
1338
|
+
- ret = EOK;
|
1339
|
+
-done:
|
1340
|
+
- talloc_free(tmp_ctx);
|
1341
|
+
return ret;
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
-static errno_t sec_update_b64(TALLOC_CTX *mem_ctx,
|
1345
|
+
- struct sss_sec_req *req,
|
1346
|
+
- struct sss_iobuf *buf)
|
1347
|
+
+static errno_t sec_update(TALLOC_CTX *mem_ctx,
|
1348
|
+
+ struct sss_sec_req *req,
|
1349
|
+
+ struct sss_iobuf *buf)
|
1350
|
+
{
|
1351
|
+
errno_t ret;
|
1352
|
+
- TALLOC_CTX *tmp_ctx;
|
1353
|
+
- char *secret;
|
1354
|
+
-
|
1355
|
+
- tmp_ctx = talloc_new(mem_ctx);
|
1356
|
+
- if (tmp_ctx == NULL) {
|
1357
|
+
- return ENOMEM;
|
1358
|
+
- }
|
1359
|
+
-
|
1360
|
+
- secret = sss_base64_encode(tmp_ctx,
|
1361
|
+
- sss_iobuf_get_data(buf),
|
1362
|
+
- sss_iobuf_get_size(buf));
|
1363
|
+
- if (secret == NULL) {
|
1364
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot encode secret to base64\n");
|
1365
|
+
- ret = EIO;
|
1366
|
+
- goto done;
|
1367
|
+
- }
|
1368
|
+
|
1369
|
+
- ret = sss_sec_update(req, secret);
|
1370
|
+
+ ret = sss_sec_update(req, sss_iobuf_get_data(buf), sss_iobuf_get_size(buf),
|
1371
|
+
+ SSS_SEC_PLAINTEXT, "binary");
|
1372
|
+
if (ret != EOK) {
|
1373
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
1374
|
+
"Cannot write the secret [%d]: %s\n", ret, sss_strerror(ret));
|
1375
|
+
- goto done;
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
- ret = EOK;
|
1379
|
+
-done:
|
1380
|
+
- talloc_free(tmp_ctx);
|
1381
|
+
return ret;
|
1382
|
+
}
|
1383
|
+
|
1384
|
+
@@ -206,7 +167,7 @@ static errno_t kcm_ccache_to_secdb_kv(TALLOC_CTX *mem_ctx,
|
1385
|
+
goto done;
|
1386
|
+
}
|
1387
|
+
|
1388
|
+
- ret = kcm_ccache_to_sec_input(mem_ctx, cc, client, &payload);
|
1389
|
+
+ ret = kcm_ccache_to_sec_input_binary(mem_ctx, cc, &payload);
|
1390
|
+
if (ret != EOK) {
|
1391
|
+
DEBUG(SSSDBG_CRIT_FAILURE,
|
1392
|
+
"Cannot convert ccache to a secret [%d][%s]\n", ret, sss_strerror(ret));
|
1393
|
+
@@ -480,6 +441,7 @@ static errno_t secdb_get_cc(TALLOC_CTX *mem_ctx,
|
1394
|
+
struct kcm_ccache *cc = NULL;
|
1395
|
+
struct sss_sec_req *sreq = NULL;
|
1396
|
+
struct sss_iobuf *ccbuf;
|
1397
|
+
+ char *datatype;
|
1398
|
+
|
1399
|
+
tmp_ctx = talloc_new(mem_ctx);
|
1400
|
+
if (tmp_ctx == NULL) {
|
1401
|
+
@@ -493,22 +455,23 @@ static errno_t secdb_get_cc(TALLOC_CTX *mem_ctx,
|
1402
|
+
goto done;
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
- ret = sec_get_b64(tmp_ctx, sreq, &ccbuf);
|
1406
|
+
+ ret = sec_get(tmp_ctx, sreq, &ccbuf, &datatype);
|
1407
|
+
if (ret != EOK) {
|
1408
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
1409
|
+
"Cannot get the secret [%d][%s]\n", ret, sss_strerror(ret));
|
1410
|
+
goto done;
|
1411
|
+
}
|
1412
|
+
|
1413
|
+
- ret = sec_kv_to_ccache(tmp_ctx,
|
1414
|
+
- secdb_key,
|
1415
|
+
- (const char *) sss_iobuf_get_data(ccbuf),
|
1416
|
+
- client,
|
1417
|
+
- &cc);
|
1418
|
+
+ if (strcmp(datatype, "binary") == 0) {
|
1419
|
+
+ ret = sec_kv_to_ccache_binary(tmp_ctx, secdb_key, ccbuf, client, &cc);
|
1420
|
+
+ } else {
|
1421
|
+
+ ret = sec_kv_to_ccache_json(tmp_ctx, secdb_key,
|
1422
|
+
+ (const char *)sss_iobuf_get_data(ccbuf),
|
1423
|
+
+ client, &cc);
|
1424
|
+
+ }
|
1425
|
+
if (ret != EOK) {
|
1426
|
+
- DEBUG(SSSDBG_OP_FAILURE,
|
1427
|
+
- "Cannot convert JSON keyval to ccache blob [%d]: %s\n",
|
1428
|
+
- ret, sss_strerror(ret));
|
1429
|
+
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot convert %s data to ccache "
|
1430
|
+
+ "[%d]: %s\n", datatype, ret, sss_strerror(ret));
|
1431
|
+
goto done;
|
1432
|
+
}
|
1433
|
+
|
1434
|
+
@@ -746,11 +709,11 @@ static struct tevent_req *ccdb_secdb_set_default_send(TALLOC_CTX *mem_ctx,
|
1435
|
+
goto immediate;
|
1436
|
+
}
|
1437
|
+
|
1438
|
+
- ret = sss_sec_get(state, sreq, &cur_default);
|
1439
|
+
+ ret = sss_sec_get(state, sreq, (uint8_t**)&cur_default, NULL, NULL);
|
1440
|
+
if (ret == ENOENT) {
|
1441
|
+
- ret = sec_put_b64(state, sreq, iobuf);
|
1442
|
+
+ ret = sec_put(state, sreq, iobuf);
|
1443
|
+
} else if (ret == EOK) {
|
1444
|
+
- ret = sec_update_b64(state, sreq, iobuf);
|
1445
|
+
+ ret = sec_update(state, sreq, iobuf);
|
1446
|
+
}
|
1447
|
+
|
1448
|
+
if (ret != EOK) {
|
1449
|
+
@@ -804,7 +767,7 @@ static struct tevent_req *ccdb_secdb_get_default_send(TALLOC_CTX *mem_ctx,
|
1450
|
+
goto immediate;
|
1451
|
+
}
|
1452
|
+
|
1453
|
+
- ret = sec_get_b64(state, sreq, &dfl_iobuf);
|
1454
|
+
+ ret = sec_get(state, sreq, &dfl_iobuf, NULL);
|
1455
|
+
if (ret == ENOENT) {
|
1456
|
+
uuid_clear(state->uuid);
|
1457
|
+
ret = EOK;
|
1458
|
+
@@ -1230,9 +1193,8 @@ static struct tevent_req *ccdb_secdb_create_send(TALLOC_CTX *mem_ctx,
|
1459
|
+
goto immediate;
|
1460
|
+
}
|
1461
|
+
|
1462
|
+
- ret = sec_put_b64(state, ccache_req, ccache_payload);
|
1463
|
+
+ ret = sec_put(state, ccache_req, ccache_payload);
|
1464
|
+
if (ret != EOK) {
|
1465
|
+
- DEBUG(SSSDBG_OP_FAILURE, "Failed to add the payload\n");
|
1466
|
+
goto immediate;
|
1467
|
+
}
|
1468
|
+
|
1469
|
+
@@ -1298,7 +1260,7 @@ static struct tevent_req *ccdb_secdb_mod_send(TALLOC_CTX *mem_ctx,
|
1470
|
+
goto immediate;
|
1471
|
+
}
|
1472
|
+
|
1473
|
+
- ret = kcm_ccache_to_sec_input(state, cc, client, &payload);
|
1474
|
+
+ ret = kcm_ccache_to_sec_input_binary(state, cc, &payload);
|
1475
|
+
if (ret != EOK) {
|
1476
|
+
goto immediate;
|
1477
|
+
}
|
1478
|
+
@@ -1308,7 +1270,7 @@ static struct tevent_req *ccdb_secdb_mod_send(TALLOC_CTX *mem_ctx,
|
1479
|
+
goto immediate;
|
1480
|
+
}
|
1481
|
+
|
1482
|
+
- ret = sec_update_b64(state, sreq, payload);
|
1483
|
+
+ ret = sec_update(state, sreq, payload);
|
1484
|
+
if (ret != EOK) {
|
1485
|
+
goto immediate;
|
1486
|
+
}
|
1487
|
+
@@ -1374,7 +1336,7 @@ static struct tevent_req *ccdb_secdb_store_cred_send(TALLOC_CTX *mem_ctx,
|
1488
|
+
goto immediate;
|
1489
|
+
}
|
1490
|
+
|
1491
|
+
- ret = kcm_ccache_to_sec_input(state, cc, client, &payload);
|
1492
|
+
+ ret = kcm_ccache_to_sec_input_binary(state, cc, &payload);
|
1493
|
+
if (ret != EOK) {
|
1494
|
+
goto immediate;
|
1495
|
+
}
|
1496
|
+
@@ -1384,7 +1346,7 @@ static struct tevent_req *ccdb_secdb_store_cred_send(TALLOC_CTX *mem_ctx,
|
1497
|
+
goto immediate;
|
1498
|
+
}
|
1499
|
+
|
1500
|
+
- ret = sec_update_b64(state, sreq, payload);
|
1501
|
+
+ ret = sec_update(state, sreq, payload);
|
1502
|
+
if (ret != EOK) {
|
1503
|
+
goto immediate;
|
1504
|
+
}
|
1505
|
+
diff --git a/src/responder/kcm/kcmsrv_ccache_secrets.c b/src/responder/kcm/kcmsrv_ccache_secrets.c
|
1506
|
+
index 440ab3bb9..f3d69842c 100644
|
1507
|
+
--- a/src/responder/kcm/kcmsrv_ccache_secrets.c
|
1508
|
+
+++ b/src/responder/kcm/kcmsrv_ccache_secrets.c
|
1509
|
+
@@ -195,7 +195,7 @@ static errno_t kcm_ccache_to_sec_kv(TALLOC_CTX *mem_ctx,
|
1510
|
+
goto done;
|
1511
|
+
}
|
1512
|
+
|
1513
|
+
- ret = kcm_ccache_to_sec_input(mem_ctx, cc, client, &payload);
|
1514
|
+
+ ret = kcm_ccache_to_sec_input_json(mem_ctx, cc, &payload);
|
1515
|
+
if (ret != EOK) {
|
1516
|
+
goto done;
|
1517
|
+
}
|
1518
|
+
@@ -489,11 +489,8 @@ static void sec_get_done(struct tevent_req *subreq)
|
1519
|
+
return;
|
1520
|
+
}
|
1521
|
+
|
1522
|
+
- ret = sec_kv_to_ccache(state,
|
1523
|
+
- state->sec_key,
|
1524
|
+
- sec_value,
|
1525
|
+
- state->client,
|
1526
|
+
- &state->cc);
|
1527
|
+
+ ret = sec_kv_to_ccache_json(state, state->sec_key, sec_value, state->client,
|
1528
|
+
+ &state->cc);
|
1529
|
+
if (ret != EOK) {
|
1530
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
1531
|
+
"Cannot convert JSON keyval to ccache blob [%d]: %s\n",
|
1532
|
+
diff --git a/src/responder/kcm/kcmsrv_cmd.c b/src/responder/kcm/kcmsrv_cmd.c
|
1533
|
+
index 421bf4bc5..a1aa9aa20 100644
|
1534
|
+
--- a/src/responder/kcm/kcmsrv_cmd.c
|
1535
|
+
+++ b/src/responder/kcm/kcmsrv_cmd.c
|
1536
|
+
@@ -314,7 +314,7 @@ static void kcm_reply_error(struct cli_ctx *cctx,
|
1537
|
+
krb5_error_code kerr;
|
1538
|
+
|
1539
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
1540
|
+
- "KCM operation returs failure [%d]: %s\n",
|
1541
|
+
+ "KCM operation returns failure [%d]: %s\n",
|
1542
|
+
retcode, sss_strerror(retcode));
|
1543
|
+
kerr = sss2krb5_error(retcode);
|
1544
|
+
|
1545
|
+
@@ -373,13 +373,16 @@ static errno_t kcm_cmd_dispatch(struct kcm_ctx *kctx,
|
1546
|
+
{
|
1547
|
+
struct tevent_req *req;
|
1548
|
+
struct cli_ctx *cctx;
|
1549
|
+
+ struct kcm_conn_data *conn_data;
|
1550
|
+
|
1551
|
+
cctx = req_ctx->cctx;
|
1552
|
+
+ conn_data = talloc_get_type(cctx->state_ctx, struct kcm_conn_data);
|
1553
|
+
|
1554
|
+
req = kcm_cmd_send(req_ctx,
|
1555
|
+
cctx->ev,
|
1556
|
+
kctx->qctx,
|
1557
|
+
req_ctx->kctx->kcm_data,
|
1558
|
+
+ conn_data,
|
1559
|
+
req_ctx->cctx->creds,
|
1560
|
+
&req_ctx->op_io.request,
|
1561
|
+
req_ctx->op_io.op);
|
1562
|
+
@@ -492,7 +495,7 @@ static void kcm_recv(struct cli_ctx *cctx)
|
1563
|
+
int ret;
|
1564
|
+
|
1565
|
+
kctx = talloc_get_type(cctx->rctx->pvt_ctx, struct kcm_ctx);
|
1566
|
+
- req = talloc_get_type(cctx->state_ctx, struct kcm_req_ctx);
|
1567
|
+
+ req = talloc_get_type(cctx->protocol_ctx, struct kcm_req_ctx);
|
1568
|
+
if (req == NULL) {
|
1569
|
+
/* A new request comes in, setup data structures. */
|
1570
|
+
req = kcm_new_req(cctx, kctx);
|
1571
|
+
@@ -503,7 +506,17 @@ static void kcm_recv(struct cli_ctx *cctx)
|
1572
|
+
return;
|
1573
|
+
}
|
1574
|
+
|
1575
|
+
- cctx->state_ctx = req;
|
1576
|
+
+ cctx->protocol_ctx = req;
|
1577
|
+
+ }
|
1578
|
+
+
|
1579
|
+
+ /* Shared data between requests that originates in the same connection. */
|
1580
|
+
+ if (cctx->state_ctx == NULL) {
|
1581
|
+
+ cctx->state_ctx = talloc_zero(cctx, struct kcm_conn_data);
|
1582
|
+
+ if (cctx->state_ctx == NULL) {
|
1583
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up client state\n");
|
1584
|
+
+ talloc_free(cctx);
|
1585
|
+
+ return;
|
1586
|
+
+ }
|
1587
|
+
}
|
1588
|
+
|
1589
|
+
ret = kcm_recv_data(req, cctx->cfd, &req->reqbuf);
|
1590
|
+
@@ -558,7 +571,7 @@ static int kcm_send_data(struct cli_ctx *cctx)
|
1591
|
+
struct kcm_req_ctx *req;
|
1592
|
+
errno_t ret;
|
1593
|
+
|
1594
|
+
- req = talloc_get_type(cctx->state_ctx, struct kcm_req_ctx);
|
1595
|
+
+ req = talloc_get_type(cctx->protocol_ctx, struct kcm_req_ctx);
|
1596
|
+
|
1597
|
+
ret = kcm_write_iovec(cctx->cfd, &req->repbuf.v_len);
|
1598
|
+
if (ret != EOK) {
|
1599
|
+
@@ -604,7 +617,7 @@ static void kcm_send(struct cli_ctx *cctx)
|
1600
|
+
DEBUG(SSSDBG_TRACE_INTERNAL, "All data sent!\n");
|
1601
|
+
TEVENT_FD_NOT_WRITEABLE(cctx->cfde);
|
1602
|
+
TEVENT_FD_READABLE(cctx->cfde);
|
1603
|
+
- talloc_zfree(cctx->state_ctx);
|
1604
|
+
+ talloc_zfree(cctx->protocol_ctx);
|
1605
|
+
return;
|
1606
|
+
}
|
1607
|
+
|
1608
|
+
diff --git a/src/responder/kcm/kcmsrv_ops.c b/src/responder/kcm/kcmsrv_ops.c
|
1609
|
+
index 6ac66c150..f458c724b 100644
|
1610
|
+
--- a/src/responder/kcm/kcmsrv_ops.c
|
1611
|
+
+++ b/src/responder/kcm/kcmsrv_ops.c
|
1612
|
+
|
1613
|
+
#include "config.h"
|
1614
|
+
|
1615
|
+
#include <krb5/krb5.h>
|
1616
|
+
+#include <dhash.h>
|
1617
|
+
|
1618
|
+
#include "util/sss_iobuf.h"
|
1619
|
+
#include "util/sss_krb5.h"
|
1620
|
+
+#include "util/sss_ptr_hash.h"
|
1621
|
+
#include "util/util_creds.h"
|
1622
|
+
#include "responder/kcm/kcm.h"
|
1623
|
+
#include "responder/kcm/kcmsrv_pvt.h"
|
1624
|
+
|
1625
|
+
|
1626
|
+
struct kcm_op_ctx {
|
1627
|
+
struct kcm_resp_ctx *kcm_data;
|
1628
|
+
+ struct kcm_conn_data *conn_data;
|
1629
|
+
struct cli_creds *client;
|
1630
|
+
|
1631
|
+
struct sss_iobuf *input;
|
1632
|
+
@@ -86,6 +89,7 @@ struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx,
|
1633
|
+
struct tevent_context *ev,
|
1634
|
+
struct kcm_ops_queue_ctx *qctx,
|
1635
|
+
struct kcm_resp_ctx *kcm_data,
|
1636
|
+
+ struct kcm_conn_data *conn_data,
|
1637
|
+
struct cli_creds *client,
|
1638
|
+
struct kcm_data *input,
|
1639
|
+
struct kcm_op *op)
|
1640
|
+
@@ -135,6 +139,7 @@ struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx,
|
1641
|
+
}
|
1642
|
+
|
1643
|
+
state->op_ctx->kcm_data = kcm_data;
|
1644
|
+
+ state->op_ctx->conn_data = conn_data;
|
1645
|
+
state->op_ctx->client = client;
|
1646
|
+
|
1647
|
+
state->op_ctx->input = sss_iobuf_init_readonly(state->op_ctx,
|
1648
|
+
@@ -1071,8 +1076,75 @@ static void kcm_op_get_principal_getbyname_done(struct tevent_req *subreq)
|
1649
|
+
tevent_req_done(req);
|
1650
|
+
}
|
1651
|
+
|
1652
|
+
+static void
|
1653
|
+
+kcm_creds_table_delete_cb(hash_entry_t *item,
|
1654
|
+
+ hash_destroy_enum deltype,
|
1655
|
+
+ void *pvt)
|
1656
|
+
+{
|
1657
|
+
+ /* Delete the old credential if it is being overwritten. */
|
1658
|
+
+ talloc_free(item->value.ptr);
|
1659
|
+
+}
|
1660
|
+
+
|
1661
|
+
+/* Store credentials in a hash table.
|
1662
|
+
+ *
|
1663
|
+
+ * If the table already exist we add the new credentials to the table and
|
1664
|
+
+ * overwrite the ones that already exist. This allows us to correctly serve
|
1665
|
+
+ * also parallel GET_CRED_UUID_LIST requests from the same connection since
|
1666
|
+
+ * it will have its own uuid list and cursor on the client side and we make
|
1667
|
+
+ * all uuid (old, updated and newly added) available.
|
1668
|
+
+ */
|
1669
|
+
+static errno_t
|
1670
|
+
+kcm_creds_to_table(TALLOC_CTX *mem_ctx,
|
1671
|
+
+ struct kcm_cred *creds,
|
1672
|
+
+ hash_table_t **_table)
|
1673
|
+
+{
|
1674
|
+
+ char str[UUID_STR_SIZE];
|
1675
|
+
+ uuid_t uuid;
|
1676
|
+
+ errno_t ret;
|
1677
|
+
+
|
1678
|
+
+ if (*_table == NULL) {
|
1679
|
+
+ *_table = sss_ptr_hash_create(mem_ctx, kcm_creds_table_delete_cb, NULL);
|
1680
|
+
+ if (*_table == NULL) {
|
1681
|
+
+ return ENOMEM;
|
1682
|
+
+ }
|
1683
|
+
+ }
|
1684
|
+
+
|
1685
|
+
+ for (struct kcm_cred *crd = creds;
|
1686
|
+
+ crd != NULL;
|
1687
|
+
+ crd = kcm_cc_next_cred(crd)) {
|
1688
|
+
+ ret = kcm_cred_get_uuid(crd, uuid);
|
1689
|
+
+ if (ret != EOK) {
|
1690
|
+
+ DEBUG(SSSDBG_MINOR_FAILURE, "Credential has no UUID, skipping\n");
|
1691
|
+
+ continue;
|
1692
|
+
+ }
|
1693
|
+
+ uuid_unparse(uuid, str);
|
1694
|
+
+
|
1695
|
+
+ ret = sss_ptr_hash_add_or_override(*_table, str, crd, struct kcm_cred);
|
1696
|
+
+ if (ret != EOK) {
|
1697
|
+
+ return ret;
|
1698
|
+
+ }
|
1699
|
+
+
|
1700
|
+
+ talloc_steal(*_table, crd);
|
1701
|
+
+ }
|
1702
|
+
+
|
1703
|
+
+ return EOK;
|
1704
|
+
+}
|
1705
|
+
+
|
1706
|
+
+static struct kcm_cred *
|
1707
|
+
+kcm_creds_lookup(hash_table_t *table, uuid_t uuid)
|
1708
|
+
+{
|
1709
|
+
+ char str[UUID_STR_SIZE];
|
1710
|
+
+
|
1711
|
+
+ if (uuid == NULL) {
|
1712
|
+
+ return NULL;
|
1713
|
+
+ }
|
1714
|
+
+
|
1715
|
+
+ uuid_unparse(uuid, str);
|
1716
|
+
+ return sss_ptr_hash_lookup(table, str, struct kcm_cred);
|
1717
|
+
+}
|
1718
|
+
+
|
1719
|
+
/* (name) -> (uuid, ...) */
|
1720
|
+
-static void kcm_op_get_cred_uuid_getbyname_done(struct tevent_req *subreq);
|
1721
|
+
+static void kcm_op_get_cred_uuid_list_getbyname_done(struct tevent_req *subreq);
|
1722
|
+
|
1723
|
+
static struct tevent_req *
|
1724
|
+
kcm_op_get_cred_uuid_list_send(TALLOC_CTX *mem_ctx,
|
1725
|
+
@@ -1106,7 +1178,7 @@ kcm_op_get_cred_uuid_list_send(TALLOC_CTX *mem_ctx,
|
1726
|
+
ret = ENOMEM;
|
1727
|
+
goto immediate;
|
1728
|
+
}
|
1729
|
+
- tevent_req_set_callback(subreq, kcm_op_get_cred_uuid_getbyname_done, req);
|
1730
|
+
+ tevent_req_set_callback(subreq, kcm_op_get_cred_uuid_list_getbyname_done, req);
|
1731
|
+
return req;
|
1732
|
+
|
1733
|
+
immediate:
|
1734
|
+
@@ -1115,17 +1187,20 @@ immediate:
|
1735
|
+
return req;
|
1736
|
+
}
|
1737
|
+
|
1738
|
+
-static void kcm_op_get_cred_uuid_getbyname_done(struct tevent_req *subreq)
|
1739
|
+
+static void kcm_op_get_cred_uuid_list_getbyname_done(struct tevent_req *subreq)
|
1740
|
+
{
|
1741
|
+
errno_t ret;
|
1742
|
+
struct kcm_ccache *cc;
|
1743
|
+
struct kcm_cred *crd;
|
1744
|
+
+ struct kcm_conn_data *conn_data;
|
1745
|
+
uuid_t uuid;
|
1746
|
+
struct tevent_req *req = tevent_req_callback_data(subreq,
|
1747
|
+
struct tevent_req);
|
1748
|
+
struct kcm_op_common_state *state = tevent_req_data(req,
|
1749
|
+
struct kcm_op_common_state);
|
1750
|
+
|
1751
|
+
+ conn_data = state->op_ctx->conn_data;
|
1752
|
+
+
|
1753
|
+
ret = kcm_ccdb_getbyname_recv(subreq, state, &cc);
|
1754
|
+
talloc_zfree(subreq);
|
1755
|
+
if (ret != EOK) {
|
1756
|
+
@@ -1137,12 +1212,20 @@ static void kcm_op_get_cred_uuid_getbyname_done(struct tevent_req *subreq)
|
1757
|
+
}
|
1758
|
+
|
1759
|
+
if (cc == NULL) {
|
1760
|
+
- DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that UUID\n");
|
1761
|
+
+ DEBUG(SSSDBG_MINOR_FAILURE, "No ccache by that name\n");
|
1762
|
+
state->op_ret = ERR_NO_CREDS;
|
1763
|
+
tevent_req_done(req);
|
1764
|
+
return;
|
1765
|
+
}
|
1766
|
+
|
1767
|
+
+ ret = kcm_creds_to_table(conn_data, kcm_cc_get_cred(cc), &conn_data->creds);
|
1768
|
+
+ if (ret != EOK) {
|
1769
|
+
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to build credentials hash table "
|
1770
|
+
+ "[%d]: %s\n", ret, sss_strerror(ret));
|
1771
|
+
+ tevent_req_error(req, ret);
|
1772
|
+
+ return;
|
1773
|
+
+ }
|
1774
|
+
+
|
1775
|
+
for (crd = kcm_cc_get_cred(cc);
|
1776
|
+
crd != NULL;
|
1777
|
+
crd = kcm_cc_next_cred(crd)) {
|
1778
|
+
@@ -1169,6 +1252,34 @@ static void kcm_op_get_cred_uuid_getbyname_done(struct tevent_req *subreq)
|
1779
|
+
tevent_req_done(req);
|
1780
|
+
}
|
1781
|
+
|
1782
|
+
+static errno_t
|
1783
|
+
+kcm_op_get_cred_by_uuid_reply(struct kcm_cred *crd,
|
1784
|
+
+ struct sss_iobuf *reply)
|
1785
|
+
+{
|
1786
|
+
+ struct sss_iobuf *cred_blob;
|
1787
|
+
+ errno_t ret;
|
1788
|
+
+
|
1789
|
+
+ cred_blob = kcm_cred_get_creds(crd);
|
1790
|
+
+ if (cred_blob == NULL) {
|
1791
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Credentials lack the creds blob\n");
|
1792
|
+
+ return ERR_NO_CREDS;
|
1793
|
+
+ }
|
1794
|
+
+
|
1795
|
+
+ ret = sss_iobuf_write_len(reply, sss_iobuf_get_data(cred_blob),
|
1796
|
+
+ sss_iobuf_get_size(cred_blob));
|
1797
|
+
+ if (ret != EOK) {
|
1798
|
+
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot write ccache blob [%d]: %s\n",
|
1799
|
+
+ ret, sss_strerror(ret));
|
1800
|
+
+ }
|
1801
|
+
+
|
1802
|
+
+ return ret;
|
1803
|
+
+}
|
1804
|
+
+
|
1805
|
+
+struct kcm_op_get_cred_by_uuid_state {
|
1806
|
+
+ struct kcm_op_common_state common;
|
1807
|
+
+ uuid_t uuid;
|
1808
|
+
+};
|
1809
|
+
+
|
1810
|
+
/* (name, uuid) -> (cred) */
|
1811
|
+
static void kcm_op_get_cred_by_uuid_getbyname_done(struct tevent_req *subreq);
|
1812
|
+
|
1813
|
+
@@ -1179,20 +1290,51 @@ kcm_op_get_cred_by_uuid_send(TALLOC_CTX *mem_ctx,
|
1814
|
+
{
|
1815
|
+
struct tevent_req *req = NULL;
|
1816
|
+
struct tevent_req *subreq = NULL;
|
1817
|
+
- struct kcm_op_common_state *state = NULL;
|
1818
|
+
+ struct kcm_op_get_cred_by_uuid_state *state;
|
1819
|
+
+ struct kcm_cred *crd;
|
1820
|
+
errno_t ret;
|
1821
|
+
const char *name;
|
1822
|
+
|
1823
|
+
- req = tevent_req_create(mem_ctx, &state, struct kcm_op_common_state);
|
1824
|
+
+ req = tevent_req_create(mem_ctx, &state,
|
1825
|
+
+ struct kcm_op_get_cred_by_uuid_state);
|
1826
|
+
if (req == NULL) {
|
1827
|
+
return NULL;
|
1828
|
+
}
|
1829
|
+
- state->op_ctx = op_ctx;
|
1830
|
+
+ state->common.op_ctx = op_ctx;
|
1831
|
+
|
1832
|
+
ret = sss_iobuf_read_stringz(op_ctx->input, &name);
|
1833
|
+
if (ret != EOK) {
|
1834
|
+
goto immediate;
|
1835
|
+
}
|
1836
|
+
+
|
1837
|
+
+ ret = sss_iobuf_read_len(state->common.op_ctx->input, UUID_BYTES,
|
1838
|
+
+ state->uuid);
|
1839
|
+
+ if (ret != EOK) {
|
1840
|
+
+ DEBUG(SSSDBG_OP_FAILURE, "Cannot read input UUID [%d]: %s\n",
|
1841
|
+
+ ret, sss_strerror(ret));
|
1842
|
+
+ goto immediate;
|
1843
|
+
+ }
|
1844
|
+
+
|
1845
|
+
+ if (op_ctx->conn_data->creds != NULL) {
|
1846
|
+
+ crd = kcm_creds_lookup(op_ctx->conn_data->creds, state->uuid);
|
1847
|
+
+ if (crd == NULL) {
|
1848
|
+
+ /* This should not happen, it can only happen if wrong UUID was
|
1849
|
+
+ * requested which suggests bug in the caller application. */
|
1850
|
+
+ DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that UUID\n");
|
1851
|
+
+ kcm_debug_uuid(state->uuid);
|
1852
|
+
+ state->common.op_ret = ERR_KCM_CC_END;
|
1853
|
+
+ ret = EOK;
|
1854
|
+
+ goto immediate;
|
1855
|
+
+ } else {
|
1856
|
+
+ ret = kcm_op_get_cred_by_uuid_reply(crd, op_ctx->reply);
|
1857
|
+
+ if (ret == ERR_NO_CREDS) {
|
1858
|
+
+ state->common.op_ret = ret;
|
1859
|
+
+ ret = EOK;
|
1860
|
+
+ }
|
1861
|
+
+ goto immediate;
|
1862
|
+
+ }
|
1863
|
+
+ }
|
1864
|
+
+
|
1865
|
+
DEBUG(SSSDBG_TRACE_LIBS, "Returning creds by UUID for %s\n", name);
|
1866
|
+
|
1867
|
+
subreq = kcm_ccdb_getbyname_send(state, ev,
|
1868
|
+
@@ -1207,7 +1349,11 @@ kcm_op_get_cred_by_uuid_send(TALLOC_CTX *mem_ctx,
|
1869
|
+
return req;
|
1870
|
+
|
1871
|
+
immediate:
|
1872
|
+
- tevent_req_error(req, ret);
|
1873
|
+
+ if (ret == EOK) {
|
1874
|
+
+ tevent_req_done(req);
|
1875
|
+
+ } else {
|
1876
|
+
+ tevent_req_error(req, ret);
|
1877
|
+
+ }
|
1878
|
+
tevent_req_post(req, ev);
|
1879
|
+
return req;
|
1880
|
+
}
|
1881
|
+
@@ -1216,14 +1362,14 @@ static void kcm_op_get_cred_by_uuid_getbyname_done(struct tevent_req *subreq)
|
1882
|
+
{
|
1883
|
+
struct tevent_req *req = tevent_req_callback_data(subreq,
|
1884
|
+
struct tevent_req);
|
1885
|
+
- struct kcm_op_common_state *state = tevent_req_data(req,
|
1886
|
+
- struct kcm_op_common_state);
|
1887
|
+
+ struct kcm_op_get_cred_by_uuid_state *state = tevent_req_data(req,
|
1888
|
+
+ struct kcm_op_get_cred_by_uuid_state);
|
1889
|
+
errno_t ret;
|
1890
|
+
struct kcm_ccache *cc;
|
1891
|
+
struct kcm_cred *crd;
|
1892
|
+
- uuid_t uuid_in;
|
1893
|
+
- uuid_t uuid;
|
1894
|
+
- struct sss_iobuf *cred_blob;
|
1895
|
+
+ struct kcm_conn_data *conn_data;
|
1896
|
+
+
|
1897
|
+
+ conn_data = state->common.op_ctx->conn_data;
|
1898
|
+
|
1899
|
+
ret = kcm_ccdb_getbyname_recv(subreq, state, &cc);
|
1900
|
+
talloc_zfree(subreq);
|
1901
|
+
@@ -1235,67 +1381,43 @@ static void kcm_op_get_cred_by_uuid_getbyname_done(struct tevent_req *subreq)
|
1902
|
+
return;
|
1903
|
+
}
|
1904
|
+
|
1905
|
+
- if (cc == NULL) {
|
1906
|
+
- DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that name\n");
|
1907
|
+
- state->op_ret = ERR_NO_MATCHING_CREDS;
|
1908
|
+
- tevent_req_done(req);
|
1909
|
+
- return;
|
1910
|
+
- }
|
1911
|
+
-
|
1912
|
+
- ret = sss_iobuf_read_len(state->op_ctx->input,
|
1913
|
+
- UUID_BYTES, uuid_in);
|
1914
|
+
+ ret = kcm_creds_to_table(conn_data, kcm_cc_get_cred(cc), &conn_data->creds);
|
1915
|
+
if (ret != EOK) {
|
1916
|
+
- DEBUG(SSSDBG_OP_FAILURE,
|
1917
|
+
- "Cannot read input UUID [%d]: %s\n",
|
1918
|
+
- ret, sss_strerror(ret));
|
1919
|
+
+ DEBUG(SSSDBG_OP_FAILURE, "Unable to build credentials hash table "
|
1920
|
+
+ "[%d]: %s\n", ret, sss_strerror(ret));
|
1921
|
+
tevent_req_error(req, ret);
|
1922
|
+
return;
|
1923
|
+
}
|
1924
|
+
|
1925
|
+
- for (crd = kcm_cc_get_cred(cc);
|
1926
|
+
- crd != NULL;
|
1927
|
+
- crd = kcm_cc_next_cred(crd)) {
|
1928
|
+
- ret = kcm_cred_get_uuid(crd, uuid);
|
1929
|
+
- if (ret != EOK) {
|
1930
|
+
- DEBUG(SSSDBG_MINOR_FAILURE,
|
1931
|
+
- "Cannot get UUID from creds, skipping\n");
|
1932
|
+
- continue;
|
1933
|
+
+ if (conn_data->creds != NULL) {
|
1934
|
+
+ crd = kcm_creds_lookup(conn_data->creds, state->uuid);
|
1935
|
+
+ if (crd == NULL) {
|
1936
|
+
+ DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that UUID\n");
|
1937
|
+
+ kcm_debug_uuid(state->uuid);
|
1938
|
+
+ state->common.op_ret = ERR_KCM_CC_END;
|
1939
|
+
+ } else {
|
1940
|
+
+ ret = kcm_op_get_cred_by_uuid_reply(crd, state->common.op_ctx->reply);
|
1941
|
+
+ if (ret != EOK && ret != ERR_NO_CREDS) {
|
1942
|
+
+ tevent_req_error(req, ret);
|
1943
|
+
+ return;
|
1944
|
+
+ }
|
1945
|
+
+ state->common.op_ret = ret;
|
1946
|
+
}
|
1947
|
+
-
|
1948
|
+
- if (uuid_compare(uuid, uuid_in) == 0) {
|
1949
|
+
- break;
|
1950
|
+
- }
|
1951
|
+
- kcm_debug_uuid(uuid);
|
1952
|
+
}
|
1953
|
+
|
1954
|
+
- if (crd == NULL) {
|
1955
|
+
- state->op_ret = ERR_KCM_CC_END;
|
1956
|
+
- DEBUG(SSSDBG_MINOR_FAILURE, "No credentials by that UUID\n");
|
1957
|
+
- tevent_req_done(req);
|
1958
|
+
- return;
|
1959
|
+
- }
|
1960
|
+
+ tevent_req_done(req);
|
1961
|
+
+}
|
1962
|
+
|
1963
|
+
- cred_blob = kcm_cred_get_creds(crd);
|
1964
|
+
- if (cred_blob == NULL) {
|
1965
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Credentials lack the creds blob\n");
|
1966
|
+
- state->op_ret = ERR_NO_CREDS;
|
1967
|
+
- tevent_req_done(req);
|
1968
|
+
- return;
|
1969
|
+
- }
|
1970
|
+
+static errno_t kcm_op_get_cred_by_uuid_recv(struct tevent_req *req,
|
1971
|
+
+ uint32_t *_op_ret)
|
1972
|
+
+{
|
1973
|
+
+ struct kcm_op_get_cred_by_uuid_state *state;
|
1974
|
+
|
1975
|
+
- ret = sss_iobuf_write_len(state->op_ctx->reply,
|
1976
|
+
- sss_iobuf_get_data(cred_blob),
|
1977
|
+
- sss_iobuf_get_size(cred_blob));
|
1978
|
+
- if (ret != EOK) {
|
1979
|
+
- DEBUG(SSSDBG_OP_FAILURE,
|
1980
|
+
- "Cannot write ccache blob [%d]: %s\n",
|
1981
|
+
- ret, sss_strerror(ret));
|
1982
|
+
- tevent_req_error(req, ret);
|
1983
|
+
- return;
|
1984
|
+
- }
|
1985
|
+
+ state = tevent_req_data(req, struct kcm_op_get_cred_by_uuid_state);
|
1986
|
+
|
1987
|
+
- state->op_ret = EOK;
|
1988
|
+
- tevent_req_done(req);
|
1989
|
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
|
1990
|
+
+ *_op_ret = state->common.op_ret;
|
1991
|
+
+ return EOK;
|
1992
|
+
}
|
1993
|
+
|
1994
|
+
/* (name, flags, credtag) -> () */
|
1995
|
+
@@ -1468,7 +1590,7 @@ static void kcm_op_get_cache_by_uuid_done(struct tevent_req *subreq)
|
1996
|
+
talloc_zfree(subreq);
|
1997
|
+
if (ret != EOK) {
|
1998
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
1999
|
+
- "Cannot get ccahe by UUID [%d]: %s\n",
|
2000
|
+
+ "Cannot get ccache by UUID [%d]: %s\n",
|
2001
|
+
ret, sss_strerror(ret));
|
2002
|
+
tevent_req_error(req, ret);
|
2003
|
+
return;
|
2004
|
+
@@ -2153,7 +2275,7 @@ static struct kcm_op kcm_optable[] = {
|
2005
|
+
{ "RETRIEVE", NULL, NULL },
|
2006
|
+
{ "GET_PRINCIPAL", kcm_op_get_principal_send, NULL },
|
2007
|
+
{ "GET_CRED_UUID_LIST", kcm_op_get_cred_uuid_list_send, NULL },
|
2008
|
+
- { "GET_CRED_BY_UUID", kcm_op_get_cred_by_uuid_send, NULL },
|
2009
|
+
+ { "GET_CRED_BY_UUID", kcm_op_get_cred_by_uuid_send, kcm_op_get_cred_by_uuid_recv },
|
2010
|
+
{ "REMOVE_CRED", kcm_op_remove_cred_send, NULL },
|
2011
|
+
{ "SET_FLAGS", NULL, NULL },
|
2012
|
+
{ "CHOWN", NULL, NULL },
|
2013
|
+
diff --git a/src/responder/kcm/kcmsrv_ops.h b/src/responder/kcm/kcmsrv_ops.h
|
2014
|
+
index 67d9f8602..ab6c13791 100644
|
2015
|
+
--- a/src/responder/kcm/kcmsrv_ops.h
|
2016
|
+
+++ b/src/responder/kcm/kcmsrv_ops.h
|
2017
|
+
|
2018
|
+
|
2019
|
+
#include "config.h"
|
2020
|
+
|
2021
|
+
+#include <dhash.h>
|
2022
|
+
#include <sys/types.h>
|
2023
|
+
#include "util/sss_iobuf.h"
|
2024
|
+
#include "responder/kcm/kcmsrv_pvt.h"
|
2025
|
+
@@ -32,10 +33,17 @@ struct kcm_op;
|
2026
|
+
struct kcm_op *kcm_get_opt(uint16_t opcode);
|
2027
|
+
const char *kcm_opt_name(struct kcm_op *op);
|
2028
|
+
|
2029
|
+
+struct kcm_conn_data {
|
2030
|
+
+ /* Credentials obtained by GET_CRED_UUID_LIST. We use to improve performance
|
2031
|
+
+ * by avoiding ccache lookups in GET_CRED_BY_UUID. */
|
2032
|
+
+ hash_table_t *creds;
|
2033
|
+
+};
|
2034
|
+
+
|
2035
|
+
struct tevent_req *kcm_cmd_send(TALLOC_CTX *mem_ctx,
|
2036
|
+
struct tevent_context *ev,
|
2037
|
+
struct kcm_ops_queue_ctx *qctx,
|
2038
|
+
struct kcm_resp_ctx *kcm_data,
|
2039
|
+
+ struct kcm_conn_data *conn_data,
|
2040
|
+
struct cli_creds *client,
|
2041
|
+
struct kcm_data *input,
|
2042
|
+
struct kcm_op *op);
|
2043
|
+
diff --git a/src/responder/secrets/local.c b/src/responder/secrets/local.c
|
2044
|
+
index eb37c08b7..252ef3a1d 100644
|
2045
|
+
--- a/src/responder/secrets/local.c
|
2046
|
+
+++ b/src/responder/secrets/local.c
|
2047
|
+
@@ -134,7 +134,7 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
|
2048
|
+
break;
|
2049
|
+
}
|
2050
|
+
|
2051
|
+
- ret = sss_sec_get(state, ssec_req, &secret);
|
2052
|
+
+ ret = sss_sec_get(state, ssec_req, (uint8_t**)&secret, NULL, NULL);
|
2053
|
+
if (ret) goto done;
|
2054
|
+
|
2055
|
+
if (body_is_json) {
|
2056
|
+
@@ -168,7 +168,8 @@ static struct tevent_req *local_secret_req(TALLOC_CTX *mem_ctx,
|
2057
|
+
}
|
2058
|
+
if (ret) goto done;
|
2059
|
+
|
2060
|
+
- ret = sss_sec_put(ssec_req, secret);
|
2061
|
+
+ ret = sss_sec_put(ssec_req, (uint8_t *)secret, strlen(secret) + 1,
|
2062
|
+
+ SSS_SEC_MASTERKEY, "simple");
|
2063
|
+
if (ret) goto done;
|
2064
|
+
break;
|
2065
|
+
|
2066
|
+
diff --git a/src/shared/safealign.h b/src/shared/safealign.h
|
2067
|
+
index b00c37f5b..35909faa2 100644
|
2068
|
+
--- a/src/shared/safealign.h
|
2069
|
+
+++ b/src/shared/safealign.h
|
2070
|
+
@@ -97,6 +97,10 @@ safealign_memcpy(void *dest, const void *src, size_t n, size_t *counter)
|
2071
|
+
#define SAFEALIGN_SETMEM_UINT16(dest, value, pctr) \
|
2072
|
+
SAFEALIGN_SETMEM_VALUE(dest, value, uint16_t, pctr)
|
2073
|
+
|
2074
|
+
+/* SAFEALIGN_SETMEM_UINT8(void *dest, uint8_t value, size_t *pctr) */
|
2075
|
+
+#define SAFEALIGN_SETMEM_UINT8(dest, value, pctr) \
|
2076
|
+
+ SAFEALIGN_SETMEM_VALUE(dest, value, uint8_t, pctr)
|
2077
|
+
+
|
2078
|
+
/* These macros are the same as their equivalents without _CHECK suffix,
|
2079
|
+
* but additionally make the caller return EINVAL immediately if *pctr
|
2080
|
+
* would exceed len. */
|
2081
|
+
diff --git a/src/tests/cmocka/test_kcm_json_marshalling.c b/src/tests/cmocka/test_kcm_marshalling.c
|
2082
|
+
similarity index 71%
|
2083
|
+
rename from src/tests/cmocka/test_kcm_json_marshalling.c
|
2084
|
+
rename to src/tests/cmocka/test_kcm_marshalling.c
|
2085
|
+
index 48ee92bd6..cebebac80 100644
|
2086
|
+
--- a/src/tests/cmocka/test_kcm_json_marshalling.c
|
2087
|
+
+++ b/src/tests/cmocka/test_kcm_marshalling.c
|
2088
|
+
@@ -154,7 +154,7 @@ static void assert_cc_equal(struct kcm_ccache *cc1,
|
2089
|
+
assert_cc_offset_equal(cc1, cc2);
|
2090
|
+
}
|
2091
|
+
|
2092
|
+
-static void test_kcm_ccache_marshall_unmarshall(void **state)
|
2093
|
+
+static void test_kcm_ccache_marshall_unmarshall_json(void **state)
|
2094
|
+
{
|
2095
|
+
struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state,
|
2096
|
+
struct kcm_marshalling_test_ctx);
|
2097
|
+
@@ -182,10 +182,7 @@ static void test_kcm_ccache_marshall_unmarshall(void **state)
|
2098
|
+
&cc);
|
2099
|
+
assert_int_equal(ret, EOK);
|
2100
|
+
|
2101
|
+
- ret = kcm_ccache_to_sec_input(test_ctx,
|
2102
|
+
- cc,
|
2103
|
+
- &owner,
|
2104
|
+
- &payload);
|
2105
|
+
+ ret = kcm_ccache_to_sec_input_json(test_ctx, cc, &payload);
|
2106
|
+
assert_int_equal(ret, EOK);
|
2107
|
+
|
2108
|
+
data = sss_iobuf_get_data(payload);
|
2109
|
+
@@ -196,25 +193,19 @@ static void test_kcm_ccache_marshall_unmarshall(void **state)
|
2110
|
+
key = sec_key_create(test_ctx, name, uuid);
|
2111
|
+
assert_non_null(key);
|
2112
|
+
|
2113
|
+
- ret = sec_kv_to_ccache(test_ctx,
|
2114
|
+
- key,
|
2115
|
+
- (const char *) data,
|
2116
|
+
- &owner,
|
2117
|
+
- &cc2);
|
2118
|
+
+ ret = sec_kv_to_ccache_json(test_ctx, key, (const char *)data, &owner,
|
2119
|
+
+ &cc2);
|
2120
|
+
assert_int_equal(ret, EOK);
|
2121
|
+
|
2122
|
+
assert_cc_equal(cc, cc2);
|
2123
|
+
|
2124
|
+
/* This key is exactly one byte shorter than it should be */
|
2125
|
+
- ret = sec_kv_to_ccache(test_ctx,
|
2126
|
+
- TEST_UUID_STR"-",
|
2127
|
+
- (const char *) data,
|
2128
|
+
- &owner,
|
2129
|
+
- &cc2);
|
2130
|
+
+ ret = sec_kv_to_ccache_json(test_ctx, TEST_UUID_STR "-", (const char *)data,
|
2131
|
+
+ &owner, &cc2);
|
2132
|
+
assert_int_equal(ret, EINVAL);
|
2133
|
+
}
|
2134
|
+
|
2135
|
+
-static void test_kcm_ccache_no_princ(void **state)
|
2136
|
+
+static void test_kcm_ccache_no_princ_json(void **state)
|
2137
|
+
{
|
2138
|
+
struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state,
|
2139
|
+
struct kcm_marshalling_test_ctx);
|
2140
|
+
@@ -246,10 +237,7 @@ static void test_kcm_ccache_no_princ(void **state)
|
2141
|
+
princ = kcm_cc_get_client_principal(cc);
|
2142
|
+
assert_null(princ);
|
2143
|
+
|
2144
|
+
- ret = kcm_ccache_to_sec_input(test_ctx,
|
2145
|
+
- cc,
|
2146
|
+
- &owner,
|
2147
|
+
- &payload);
|
2148
|
+
+ ret = kcm_ccache_to_sec_input_json(test_ctx, cc, &payload);
|
2149
|
+
assert_int_equal(ret, EOK);
|
2150
|
+
|
2151
|
+
data = sss_iobuf_get_data(payload);
|
2152
|
+
@@ -260,11 +248,110 @@ static void test_kcm_ccache_no_princ(void **state)
|
2153
|
+
key = sec_key_create(test_ctx, name, uuid);
|
2154
|
+
assert_non_null(key);
|
2155
|
+
|
2156
|
+
- ret = sec_kv_to_ccache(test_ctx,
|
2157
|
+
- key,
|
2158
|
+
- (const char *) data,
|
2159
|
+
- &owner,
|
2160
|
+
- &cc2);
|
2161
|
+
+ ret = sec_kv_to_ccache_json(test_ctx, key, (const char *)data, &owner,
|
2162
|
+
+ &cc2);
|
2163
|
+
+ assert_int_equal(ret, EOK);
|
2164
|
+
+
|
2165
|
+
+ assert_cc_equal(cc, cc2);
|
2166
|
+
+}
|
2167
|
+
+
|
2168
|
+
+static void test_kcm_ccache_marshall_unmarshall_binary(void **state)
|
2169
|
+
+{
|
2170
|
+
+ struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state,
|
2171
|
+
+ struct kcm_marshalling_test_ctx);
|
2172
|
+
+ errno_t ret;
|
2173
|
+
+ struct cli_creds owner;
|
2174
|
+
+ struct kcm_ccache *cc;
|
2175
|
+
+ struct kcm_ccache *cc2;
|
2176
|
+
+ struct sss_iobuf *payload;
|
2177
|
+
+ const char *name;
|
2178
|
+
+ const char *key;
|
2179
|
+
+ uint8_t *data;
|
2180
|
+
+ uuid_t uuid;
|
2181
|
+
+
|
2182
|
+
+ owner.ucred.uid = getuid();
|
2183
|
+
+ owner.ucred.gid = getuid();
|
2184
|
+
+
|
2185
|
+
+ name = talloc_asprintf(test_ctx, "%"SPRIuid, getuid());
|
2186
|
+
+ assert_non_null(name);
|
2187
|
+
+
|
2188
|
+
+ ret = kcm_cc_new(test_ctx,
|
2189
|
+
+ test_ctx->kctx,
|
2190
|
+
+ &owner,
|
2191
|
+
+ name,
|
2192
|
+
+ test_ctx->princ,
|
2193
|
+
+ &cc);
|
2194
|
+
+ assert_int_equal(ret, EOK);
|
2195
|
+
+
|
2196
|
+
+ ret = kcm_ccache_to_sec_input_binary(test_ctx, cc, &payload);
|
2197
|
+
+ assert_int_equal(ret, EOK);
|
2198
|
+
+
|
2199
|
+
+ data = sss_iobuf_get_data(payload);
|
2200
|
+
+ assert_non_null(data);
|
2201
|
+
+
|
2202
|
+
+ ret = kcm_cc_get_uuid(cc, uuid);
|
2203
|
+
+ assert_int_equal(ret, EOK);
|
2204
|
+
+ key = sec_key_create(test_ctx, name, uuid);
|
2205
|
+
+ assert_non_null(key);
|
2206
|
+
+
|
2207
|
+
+ sss_iobuf_cursor_reset(payload);
|
2208
|
+
+ ret = sec_kv_to_ccache_binary(test_ctx, key, payload, &owner, &cc2);
|
2209
|
+
+ assert_int_equal(ret, EOK);
|
2210
|
+
+
|
2211
|
+
+ assert_cc_equal(cc, cc2);
|
2212
|
+
+
|
2213
|
+
+ /* This key is exactly one byte shorter than it should be */
|
2214
|
+
+ sss_iobuf_cursor_reset(payload);
|
2215
|
+
+ ret = sec_kv_to_ccache_binary(test_ctx, TEST_UUID_STR "-", payload, &owner,
|
2216
|
+
+ &cc2);
|
2217
|
+
+ assert_int_equal(ret, EINVAL);
|
2218
|
+
+}
|
2219
|
+
+
|
2220
|
+
+static void test_kcm_ccache_no_princ_binary(void **state)
|
2221
|
+
+{
|
2222
|
+
+ struct kcm_marshalling_test_ctx *test_ctx = talloc_get_type(*state,
|
2223
|
+
+ struct kcm_marshalling_test_ctx);
|
2224
|
+
+ errno_t ret;
|
2225
|
+
+ struct cli_creds owner;
|
2226
|
+
+ const char *name;
|
2227
|
+
+ struct kcm_ccache *cc;
|
2228
|
+
+ krb5_principal princ;
|
2229
|
+
+ struct kcm_ccache *cc2;
|
2230
|
+
+ struct sss_iobuf *payload;
|
2231
|
+
+ const char *key;
|
2232
|
+
+ uint8_t *data;
|
2233
|
+
+ uuid_t uuid;
|
2234
|
+
+
|
2235
|
+
+ owner.ucred.uid = getuid();
|
2236
|
+
+ owner.ucred.gid = getuid();
|
2237
|
+
+
|
2238
|
+
+ name = talloc_asprintf(test_ctx, "%"SPRIuid, getuid());
|
2239
|
+
+ assert_non_null(name);
|
2240
|
+
+
|
2241
|
+
+ ret = kcm_cc_new(test_ctx,
|
2242
|
+
+ test_ctx->kctx,
|
2243
|
+
+ &owner,
|
2244
|
+
+ name,
|
2245
|
+
+ NULL,
|
2246
|
+
+ &cc);
|
2247
|
+
+ assert_int_equal(ret, EOK);
|
2248
|
+
+
|
2249
|
+
+ princ = kcm_cc_get_client_principal(cc);
|
2250
|
+
+ assert_null(princ);
|
2251
|
+
+
|
2252
|
+
+ ret = kcm_ccache_to_sec_input_binary(test_ctx, cc, &payload);
|
2253
|
+
+ assert_int_equal(ret, EOK);
|
2254
|
+
+
|
2255
|
+
+ data = sss_iobuf_get_data(payload);
|
2256
|
+
+ assert_non_null(data);
|
2257
|
+
+
|
2258
|
+
+ ret = kcm_cc_get_uuid(cc, uuid);
|
2259
|
+
+ assert_int_equal(ret, EOK);
|
2260
|
+
+ key = sec_key_create(test_ctx, name, uuid);
|
2261
|
+
+ assert_non_null(key);
|
2262
|
+
+
|
2263
|
+
+ sss_iobuf_cursor_reset(payload);
|
2264
|
+
+ ret = sec_kv_to_ccache_binary(test_ctx, key, payload, &owner, &cc2);
|
2265
|
+
assert_int_equal(ret, EOK);
|
2266
|
+
|
2267
|
+
assert_cc_equal(cc, cc2);
|
2268
|
+
@@ -340,10 +427,16 @@ int main(int argc, const char *argv[])
|
2269
|
+
};
|
2270
|
+
|
2271
|
+
const struct CMUnitTest tests[] = {
|
2272
|
+
- cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall,
|
2273
|
+
+ cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall_binary,
|
2274
|
+
+ setup_kcm_marshalling,
|
2275
|
+
+ teardown_kcm_marshalling),
|
2276
|
+
+ cmocka_unit_test_setup_teardown(test_kcm_ccache_no_princ_binary,
|
2277
|
+
+ setup_kcm_marshalling,
|
2278
|
+
+ teardown_kcm_marshalling),
|
2279
|
+
+ cmocka_unit_test_setup_teardown(test_kcm_ccache_marshall_unmarshall_json,
|
2280
|
+
setup_kcm_marshalling,
|
2281
|
+
teardown_kcm_marshalling),
|
2282
|
+
- cmocka_unit_test_setup_teardown(test_kcm_ccache_no_princ,
|
2283
|
+
+ cmocka_unit_test_setup_teardown(test_kcm_ccache_no_princ_json,
|
2284
|
+
setup_kcm_marshalling,
|
2285
|
+
teardown_kcm_marshalling),
|
2286
|
+
cmocka_unit_test(test_sec_key_get_uuid),
|
2287
|
+
diff --git a/src/tests/cmocka/test_sss_ptr_hash.c b/src/tests/cmocka/test_sss_ptr_hash.c
|
2288
|
+
index 1458238f5..31cf8b705 100644
|
2289
|
+
--- a/src/tests/cmocka/test_sss_ptr_hash.c
|
2290
|
+
+++ b/src/tests/cmocka/test_sss_ptr_hash.c
|
2291
|
+
@@ -91,6 +91,45 @@ void test_sss_ptr_hash_with_free_cb(void **state)
|
2292
|
+
assert_int_equal(free_counter, MAX_ENTRIES_AMOUNT*2);
|
2293
|
+
}
|
2294
|
+
|
2295
|
+
+void test_sss_ptr_hash_overwrite_with_free_cb(void **state)
|
2296
|
+
+{
|
2297
|
+
+ hash_table_t *table;
|
2298
|
+
+ int free_counter = 0;
|
2299
|
+
+ unsigned long count;
|
2300
|
+
+ char *payload;
|
2301
|
+
+ char *value;
|
2302
|
+
+ errno_t ret;
|
2303
|
+
+
|
2304
|
+
+ table = sss_ptr_hash_create(global_talloc_context,
|
2305
|
+
+ free_payload_cb,
|
2306
|
+
+ &free_counter);
|
2307
|
+
+ assert_non_null(table);
|
2308
|
+
+
|
2309
|
+
+ payload = talloc_strdup(table, "test_value1");
|
2310
|
+
+ assert_non_null(payload);
|
2311
|
+
+ talloc_set_name_const(payload, "char");
|
2312
|
+
+ ret = sss_ptr_hash_add_or_override(table, "test", payload, char);
|
2313
|
+
+ assert_int_equal(ret, 0);
|
2314
|
+
+ count = hash_count(table);
|
2315
|
+
+ assert_int_equal(count, 1);
|
2316
|
+
+ value = sss_ptr_hash_lookup(table, "test", char);
|
2317
|
+
+ assert_ptr_equal(value, payload);
|
2318
|
+
+
|
2319
|
+
+
|
2320
|
+
+ payload = talloc_strdup(table, "test_value2");
|
2321
|
+
+ assert_non_null(payload);
|
2322
|
+
+ talloc_set_name_const(payload, "char");
|
2323
|
+
+ ret = sss_ptr_hash_add_or_override(table, "test", payload, char);
|
2324
|
+
+ assert_int_equal(ret, 0);
|
2325
|
+
+ count = hash_count(table);
|
2326
|
+
+ assert_int_equal(count, 1);
|
2327
|
+
+ value = sss_ptr_hash_lookup(table, "test", char);
|
2328
|
+
+ assert_ptr_equal(value, payload);
|
2329
|
+
+
|
2330
|
+
+ talloc_free(table);
|
2331
|
+
+ assert_int_equal(free_counter, 2);
|
2332
|
+
+}
|
2333
|
+
+
|
2334
|
+
struct table_wrapper
|
2335
|
+
{
|
2336
|
+
hash_table_t **table;
|
2337
|
+
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
|
2338
|
+
index d77a972c1..d258622fb 100644
|
2339
|
+
--- a/src/tests/cmocka/test_utils.c
|
2340
|
+
+++ b/src/tests/cmocka/test_utils.c
|
2341
|
+
@@ -2144,6 +2144,9 @@ int main(int argc, const char *argv[])
|
2342
|
+
cmocka_unit_test_setup_teardown(test_sss_ptr_hash_with_free_cb,
|
2343
|
+
setup_leak_tests,
|
2344
|
+
teardown_leak_tests),
|
2345
|
+
+ cmocka_unit_test_setup_teardown(test_sss_ptr_hash_overwrite_with_free_cb,
|
2346
|
+
+ setup_leak_tests,
|
2347
|
+
+ teardown_leak_tests),
|
2348
|
+
cmocka_unit_test_setup_teardown(test_sss_ptr_hash_with_lookup_cb,
|
2349
|
+
setup_leak_tests,
|
2350
|
+
teardown_leak_tests),
|
2351
|
+
diff --git a/src/tests/cmocka/test_utils.h b/src/tests/cmocka/test_utils.h
|
2352
|
+
index 44b9479f9..458bcb750 100644
|
2353
|
+
--- a/src/tests/cmocka/test_utils.h
|
2354
|
+
+++ b/src/tests/cmocka/test_utils.h
|
2355
|
+
@@ -35,6 +35,7 @@ void test_concatenate_string_array(void **state);
|
2356
|
+
|
2357
|
+
/* from src/tests/cmocka/test_sss_ptr_hash.c */
|
2358
|
+
void test_sss_ptr_hash_with_free_cb(void **state);
|
2359
|
+
+void test_sss_ptr_hash_overwrite_with_free_cb(void **state);
|
2360
|
+
void test_sss_ptr_hash_with_lookup_cb(void **state);
|
2361
|
+
void test_sss_ptr_hash_without_cb(void **state);
|
2362
|
+
|
2363
|
+
diff --git a/src/tests/intg/test_secrets.py b/src/tests/intg/test_secrets.py
|
2364
|
+
index 00933fb34..18d722c13 100644
|
2365
|
+
--- a/src/tests/intg/test_secrets.py
|
2366
|
+
+++ b/src/tests/intg/test_secrets.py
|
2367
|
+
@@ -438,7 +438,8 @@ def run_quota_test(cli, max_secrets, max_payload_size):
|
2368
|
+
KILOBYTE = 1024
|
2369
|
+
kb_payload_size = max_payload_size * KILOBYTE
|
2370
|
+
|
2371
|
+
- sec_value = "x" * kb_payload_size
|
2372
|
+
+ # Adjust payload size to hold terminal zero byte.
|
2373
|
+
+ sec_value = "x" * (kb_payload_size - 1)
|
2374
|
+
|
2375
|
+
cli.set_secret("foo", sec_value)
|
2376
|
+
|
2377
|
+
diff --git a/src/tests/multihost/basic/test_kcm.py b/src/tests/multihost/basic/test_kcm.py
|
2378
|
+
index e5d315827..6f65431f8 100644
|
2379
|
+
--- a/src/tests/multihost/basic/test_kcm.py
|
2380
|
+
+++ b/src/tests/multihost/basic/test_kcm.py
|
2381
|
+
@@ -310,6 +310,12 @@ class TestSanityKCM(object):
|
2382
|
+
set_param(multihost, 'kcm', 'max_ccache_size', '1')
|
2383
|
+
self._restart_kcm(multihost)
|
2384
|
+
|
2385
|
+
- with pytest.raises(paramiko.ssh_exception.AuthenticationException):
|
2386
|
+
- ssh_foo3 = SSHClient(multihost.master[0].sys_hostname,
|
2387
|
+
- username='foo3', password='Secret123')
|
2388
|
+
+ # We use kinit to exceed the maximum ccache size as it creates payload
|
2389
|
+
+ # of 1280 bytes by acquiring tgt and also some control credentials.
|
2390
|
+
+ # SSH authentication is not sufficient as it stores only tgt.
|
2391
|
+
+ ssh_foo3 = SSHClient(multihost.master[0].sys_hostname,
|
2392
|
+
+ username='foo3', password='Secret123')
|
2393
|
+
+ (_, _, exit_status) = ssh_foo3.execute_cmd(
|
2394
|
+
+ 'kinit foo3@EXAMPLE.TEST', 'Secret123'
|
2395
|
+
+ )
|
2396
|
+
+ assert exit_status != 0
|
2397
|
+
diff --git a/src/util/secrets/sec_pvt.h b/src/util/secrets/sec_pvt.h
|
2398
|
+
index 92e2b8b25..0e77a660e 100644
|
2399
|
+
--- a/src/util/secrets/sec_pvt.h
|
2400
|
+
+++ b/src/util/secrets/sec_pvt.h
|
2401
|
+
|
2402
|
+
#define SSS_SEC_KCM_BASEPATH "/kcm/"
|
2403
|
+
|
2404
|
+
struct sss_sec_data {
|
2405
|
+
- char *data;
|
2406
|
+
+ uint8_t *data;
|
2407
|
+
size_t length;
|
2408
|
+
};
|
2409
|
+
|
2410
|
+
diff --git a/src/util/secrets/secrets.c b/src/util/secrets/secrets.c
|
2411
|
+
index d701face0..c6310b585 100644
|
2412
|
+
--- a/src/util/secrets/secrets.c
|
2413
|
+
+++ b/src/util/secrets/secrets.c
|
2414
|
+
|
2415
|
+
#define SECRETS_BASEDN "cn=secrets"
|
2416
|
+
#define KCM_BASEDN "cn=kcm"
|
2417
|
+
|
2418
|
+
-#define LOCAL_SIMPLE_FILTER "(type=simple)"
|
2419
|
+
+#define LOCAL_SIMPLE_FILTER "(|(type=simple)(type=binary))"
|
2420
|
+
#define LOCAL_CONTAINER_FILTER "(type=container)"
|
2421
|
+
|
2422
|
+
+#define SEC_ATTR_SECRET "secret"
|
2423
|
+
+#define SEC_ATTR_ENCTYPE "enctype"
|
2424
|
+
+#define SEC_ATTR_TYPE "type"
|
2425
|
+
+#define SEC_ATTR_CTIME "creationTime"
|
2426
|
+
+
|
2427
|
+
typedef int (*url_mapper_fn)(TALLOC_CTX *mem_ctx,
|
2428
|
+
const char *url,
|
2429
|
+
uid_t client,
|
2430
|
+
@@ -63,90 +68,136 @@ static struct sss_sec_quota default_kcm_quota = {
|
2431
|
+
.containers_nest_level = DEFAULT_SEC_CONTAINERS_NEST_LEVEL,
|
2432
|
+
};
|
2433
|
+
|
2434
|
+
-static int local_decrypt(struct sss_sec_ctx *sctx, TALLOC_CTX *mem_ctx,
|
2435
|
+
- const char *secret, const char *enctype,
|
2436
|
+
- char **plain_secret)
|
2437
|
+
+static const char *sss_sec_enctype_to_str(enum sss_sec_enctype enctype)
|
2438
|
+
{
|
2439
|
+
- char *output;
|
2440
|
+
+ switch (enctype) {
|
2441
|
+
+ case SSS_SEC_PLAINTEXT:
|
2442
|
+
+ return "plaintext";
|
2443
|
+
+ case SSS_SEC_MASTERKEY:
|
2444
|
+
+ return "masterkey";
|
2445
|
+
+ default:
|
2446
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: unknown encryption type %d\n",
|
2447
|
+
+ enctype);
|
2448
|
+
+ return "unknown";
|
2449
|
+
+ }
|
2450
|
+
+}
|
2451
|
+
|
2452
|
+
- if (enctype && strcmp(enctype, "masterkey") == 0) {
|
2453
|
+
- DEBUG(SSSDBG_TRACE_INTERNAL, "Decrypting with masterkey\n");
|
2454
|
+
+static enum sss_sec_enctype sss_sec_str_to_enctype(const char *str)
|
2455
|
+
+{
|
2456
|
+
+ if (strcmp("plaintext", str) == 0) {
|
2457
|
+
+ return SSS_SEC_PLAINTEXT;
|
2458
|
+
+ }
|
2459
|
+
|
2460
|
+
- struct sss_sec_data _secret;
|
2461
|
+
- size_t outlen;
|
2462
|
+
- int ret;
|
2463
|
+
+ if (strcmp("masterkey", str) == 0) {
|
2464
|
+
+ return SSS_SEC_MASTERKEY;
|
2465
|
+
+ }
|
2466
|
+
+
|
2467
|
+
+ return SSS_SEC_ENCTYPE_SENTINEL;
|
2468
|
+
+}
|
2469
|
+
|
2470
|
+
- _secret.data = (char *)sss_base64_decode(mem_ctx, secret,
|
2471
|
+
- &_secret.length);
|
2472
|
+
+static int local_decrypt(struct sss_sec_ctx *sctx,
|
2473
|
+
+ TALLOC_CTX *mem_ctx,
|
2474
|
+
+ uint8_t *secret,
|
2475
|
+
+ size_t secret_len,
|
2476
|
+
+ enum sss_sec_enctype enctype,
|
2477
|
+
+ uint8_t **_output,
|
2478
|
+
+ size_t *_output_len)
|
2479
|
+
+{
|
2480
|
+
+ struct sss_sec_data _secret;
|
2481
|
+
+ uint8_t *output;
|
2482
|
+
+ size_t output_len;
|
2483
|
+
+ int ret;
|
2484
|
+
+
|
2485
|
+
+ switch (enctype) {
|
2486
|
+
+ case SSS_SEC_PLAINTEXT:
|
2487
|
+
+ output = talloc_memdup(mem_ctx, secret, secret_len);
|
2488
|
+
+ output_len = secret_len;
|
2489
|
+
+ break;
|
2490
|
+
+ case SSS_SEC_MASTERKEY:
|
2491
|
+
+ _secret.data = (uint8_t *)sss_base64_decode(mem_ctx,
|
2492
|
+
+ (const char *)secret,
|
2493
|
+
+ &_secret.length);
|
2494
|
+
if (!_secret.data) {
|
2495
|
+
DEBUG(SSSDBG_OP_FAILURE, "sss_base64_decode failed\n");
|
2496
|
+
return EINVAL;
|
2497
|
+
}
|
2498
|
+
|
2499
|
+
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Decrypting with masterkey\n");
|
2500
|
+
ret = sss_decrypt(mem_ctx, AES256CBC_HMAC_SHA256,
|
2501
|
+
- (uint8_t *)sctx->master_key.data,
|
2502
|
+
+ sctx->master_key.data,
|
2503
|
+
sctx->master_key.length,
|
2504
|
+
- (uint8_t *)_secret.data, _secret.length,
|
2505
|
+
- (uint8_t **)&output, &outlen);
|
2506
|
+
+ _secret.data, _secret.length,
|
2507
|
+
+ &output, &output_len);
|
2508
|
+
talloc_free(_secret.data);
|
2509
|
+
if (ret) {
|
2510
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2511
|
+
"sss_decrypt failed [%d]: %s\n", ret, sss_strerror(ret));
|
2512
|
+
return ret;
|
2513
|
+
}
|
2514
|
+
+ break;
|
2515
|
+
+ default:
|
2516
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unknown encryption type '%d'\n", enctype);
|
2517
|
+
+ return EINVAL;
|
2518
|
+
+ }
|
2519
|
+
|
2520
|
+
- if (((strnlen(output, outlen) + 1) != outlen) ||
|
2521
|
+
- output[outlen - 1] != '\0') {
|
2522
|
+
- DEBUG(SSSDBG_CRIT_FAILURE,
|
2523
|
+
- "Output length mismatch or output not NULL-terminated\n");
|
2524
|
+
- talloc_free(output);
|
2525
|
+
- return EIO;
|
2526
|
+
- }
|
2527
|
+
- } else {
|
2528
|
+
- DEBUG(SSSDBG_TRACE_INTERNAL, "Unexpected enctype (not 'masterkey')\n");
|
2529
|
+
- output = talloc_strdup(mem_ctx, secret);
|
2530
|
+
- if (!output) return ENOMEM;
|
2531
|
+
+ if (output == NULL) {
|
2532
|
+
+ return ENOMEM;
|
2533
|
+
}
|
2534
|
+
|
2535
|
+
- *plain_secret = output;
|
2536
|
+
+ *_output = output;
|
2537
|
+
+ *_output_len = output_len;
|
2538
|
+
+
|
2539
|
+
return EOK;
|
2540
|
+
}
|
2541
|
+
|
2542
|
+
-static int local_encrypt(struct sss_sec_ctx *sec_ctx, TALLOC_CTX *mem_ctx,
|
2543
|
+
- const char *secret, const char *enctype,
|
2544
|
+
- char **ciphertext)
|
2545
|
+
+static int local_encrypt(struct sss_sec_ctx *sec_ctx,
|
2546
|
+
+ TALLOC_CTX *mem_ctx,
|
2547
|
+
+ uint8_t *secret,
|
2548
|
+
+ size_t secret_len,
|
2549
|
+
+ enum sss_sec_enctype enctype,
|
2550
|
+
+ uint8_t **_output,
|
2551
|
+
+ size_t *_output_len)
|
2552
|
+
{
|
2553
|
+
struct sss_sec_data _secret;
|
2554
|
+
- char *output;
|
2555
|
+
+ uint8_t *output;
|
2556
|
+
+ size_t output_len;
|
2557
|
+
+ char *b64;
|
2558
|
+
int ret;
|
2559
|
+
|
2560
|
+
- if (enctype == NULL) {
|
2561
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "No encryption type\n");
|
2562
|
+
- return EINVAL;
|
2563
|
+
- }
|
2564
|
+
+ switch (enctype) {
|
2565
|
+
+ case SSS_SEC_PLAINTEXT:
|
2566
|
+
+ output = talloc_memdup(mem_ctx, secret, secret_len);
|
2567
|
+
+ output_len = secret_len;
|
2568
|
+
+ break;
|
2569
|
+
+ case SSS_SEC_MASTERKEY:
|
2570
|
+
+ ret = sss_encrypt(mem_ctx, AES256CBC_HMAC_SHA256,
|
2571
|
+
+ sec_ctx->master_key.data,
|
2572
|
+
+ sec_ctx->master_key.length,
|
2573
|
+
+ secret, secret_len,
|
2574
|
+
+ &_secret.data, &_secret.length);
|
2575
|
+
+ if (ret) {
|
2576
|
+
+ DEBUG(SSSDBG_OP_FAILURE,
|
2577
|
+
+ "sss_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
|
2578
|
+
+ return ret;
|
2579
|
+
+ }
|
2580
|
+
|
2581
|
+
- if (strcmp(enctype, "masterkey") != 0) {
|
2582
|
+
- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown encryption type '%s'\n", enctype);
|
2583
|
+
+ b64 = sss_base64_encode(mem_ctx, _secret.data, _secret.length);
|
2584
|
+
+ output = (uint8_t*)b64;
|
2585
|
+
+ output_len = strlen(b64) + 1;
|
2586
|
+
+ talloc_free(_secret.data);
|
2587
|
+
+ break;
|
2588
|
+
+ default:
|
2589
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unknown encryption type '%d'\n", enctype);
|
2590
|
+
return EINVAL;
|
2591
|
+
}
|
2592
|
+
|
2593
|
+
- ret = sss_encrypt(mem_ctx, AES256CBC_HMAC_SHA256,
|
2594
|
+
- (uint8_t *)sec_ctx->master_key.data,
|
2595
|
+
- sec_ctx->master_key.length,
|
2596
|
+
- (const uint8_t *)secret, strlen(secret) + 1,
|
2597
|
+
- (uint8_t **)&_secret.data, &_secret.length);
|
2598
|
+
- if (ret) {
|
2599
|
+
- DEBUG(SSSDBG_OP_FAILURE,
|
2600
|
+
- "sss_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
|
2601
|
+
- return ret;
|
2602
|
+
+ if (output == NULL) {
|
2603
|
+
+ return ENOMEM;
|
2604
|
+
}
|
2605
|
+
|
2606
|
+
- output = sss_base64_encode(mem_ctx,
|
2607
|
+
- (uint8_t *)_secret.data, _secret.length);
|
2608
|
+
- talloc_free(_secret.data);
|
2609
|
+
- if (!output) return ENOMEM;
|
2610
|
+
+ *_output = output;
|
2611
|
+
+ *_output_len = output_len;
|
2612
|
+
|
2613
|
+
- *ciphertext = output;
|
2614
|
+
return EOK;
|
2615
|
+
}
|
2616
|
+
|
2617
|
+
@@ -338,14 +389,14 @@ static int local_check_max_payload_size(struct sss_sec_req *req,
|
2618
|
+
return EOK;
|
2619
|
+
}
|
2620
|
+
|
2621
|
+
- max_payload_size = req->quota->max_payload_size * 1024; /* kb */
|
2622
|
+
+ max_payload_size = req->quota->max_payload_size * 1024; /* KiB */
|
2623
|
+
if (payload_size > max_payload_size) {
|
2624
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2625
|
+
- "Secrets' payload size [%d kb (%d)] exceeds the maximum allowed "
|
2626
|
+
- "payload size [%d kb (%d)]\n",
|
2627
|
+
- payload_size * 1024, /* kb */
|
2628
|
+
+ "Secrets' payload size [%d KiB (%d B)] exceeds the maximum "
|
2629
|
+
+ "allowed payload size [%d KiB (%d B)]\n",
|
2630
|
+
+ payload_size / 1024, /* KiB */
|
2631
|
+
payload_size,
|
2632
|
+
- req->quota->max_payload_size, /* kb */
|
2633
|
+
+ req->quota->max_payload_size, /* KiB */
|
2634
|
+
max_payload_size);
|
2635
|
+
|
2636
|
+
return ERR_SEC_PAYLOAD_SIZE_IS_TOO_LARGE;
|
2637
|
+
@@ -404,7 +455,7 @@ static int local_db_create(struct sss_sec_req *req)
|
2638
|
+
ret = local_db_check_containers_nest_level(req, msg->dn);
|
2639
|
+
if (ret != EOK) goto done;
|
2640
|
+
|
2641
|
+
- ret = ldb_msg_add_string(msg, "type", "container");
|
2642
|
+
+ ret = ldb_msg_add_string(msg, SEC_ATTR_TYPE, "container");
|
2643
|
+
if (ret != EOK) {
|
2644
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2645
|
+
"ldb_msg_add_string failed adding type:container [%d]: %s\n",
|
2646
|
+
@@ -412,7 +463,7 @@ static int local_db_create(struct sss_sec_req *req)
|
2647
|
+
goto done;
|
2648
|
+
}
|
2649
|
+
|
2650
|
+
- ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
|
2651
|
+
+ ret = ldb_msg_add_fmt(msg, SEC_ATTR_CTIME, "%lu", time(NULL));
|
2652
|
+
if (ret != EOK) {
|
2653
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2654
|
+
"ldb_msg_add_string failed adding creationTime [%d]: %s\n",
|
2655
|
+
@@ -892,7 +943,7 @@ errno_t sss_sec_list(TALLOC_CTX *mem_ctx,
|
2656
|
+
size_t *_num_keys)
|
2657
|
+
{
|
2658
|
+
TALLOC_CTX *tmp_ctx;
|
2659
|
+
- static const char *attrs[] = { "secret", NULL };
|
2660
|
+
+ static const char *attrs[] = { SEC_ATTR_SECRET, NULL };
|
2661
|
+
struct ldb_result *res;
|
2662
|
+
char **keys;
|
2663
|
+
int ret;
|
2664
|
+
@@ -951,13 +1002,21 @@ done:
|
2665
|
+
|
2666
|
+
errno_t sss_sec_get(TALLOC_CTX *mem_ctx,
|
2667
|
+
struct sss_sec_req *req,
|
2668
|
+
- char **_secret)
|
2669
|
+
+ uint8_t **_secret,
|
2670
|
+
+ size_t *_secret_len,
|
2671
|
+
+ char **_datatype)
|
2672
|
+
{
|
2673
|
+
TALLOC_CTX *tmp_ctx;
|
2674
|
+
- static const char *attrs[] = { "secret", "enctype", NULL };
|
2675
|
+
+ static const char *attrs[] = { SEC_ATTR_SECRET, SEC_ATTR_ENCTYPE,
|
2676
|
+
+ SEC_ATTR_TYPE, NULL };
|
2677
|
+
struct ldb_result *res;
|
2678
|
+
- const char *attr_secret;
|
2679
|
+
+ const struct ldb_val *attr_secret;
|
2680
|
+
const char *attr_enctype;
|
2681
|
+
+ const char *attr_datatype;
|
2682
|
+
+ enum sss_sec_enctype enctype;
|
2683
|
+
+ char *datatype;
|
2684
|
+
+ uint8_t *secret;
|
2685
|
+
+ size_t secret_len;
|
2686
|
+
int ret;
|
2687
|
+
|
2688
|
+
if (req == NULL || _secret == NULL) {
|
2689
|
+
@@ -996,21 +1055,38 @@ errno_t sss_sec_get(TALLOC_CTX *mem_ctx,
|
2690
|
+
goto done;
|
2691
|
+
}
|
2692
|
+
|
2693
|
+
- attr_secret = ldb_msg_find_attr_as_string(res->msgs[0], "secret", NULL);
|
2694
|
+
+ attr_secret = ldb_msg_find_ldb_val(res->msgs[0], SEC_ATTR_SECRET);
|
2695
|
+
if (!attr_secret) {
|
2696
|
+
DEBUG(SSSDBG_CRIT_FAILURE, "The 'secret' attribute is missing\n");
|
2697
|
+
ret = ENOENT;
|
2698
|
+
goto done;
|
2699
|
+
}
|
2700
|
+
|
2701
|
+
- attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], "enctype", NULL);
|
2702
|
+
+ attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], SEC_ATTR_ENCTYPE,
|
2703
|
+
+ "plaintext");
|
2704
|
+
+ enctype = sss_sec_str_to_enctype(attr_enctype);
|
2705
|
+
+ ret = local_decrypt(req->sctx, tmp_ctx, attr_secret->data,
|
2706
|
+
+ attr_secret->length, enctype, &secret, &secret_len);
|
2707
|
+
+ if (ret) goto done;
|
2708
|
+
|
2709
|
+
- if (attr_enctype) {
|
2710
|
+
- ret = local_decrypt(req->sctx, mem_ctx, attr_secret, attr_enctype, _secret);
|
2711
|
+
- if (ret) goto done;
|
2712
|
+
- } else {
|
2713
|
+
- *_secret = talloc_strdup(mem_ctx, attr_secret);
|
2714
|
+
+ if (_datatype != NULL) {
|
2715
|
+
+ attr_datatype = ldb_msg_find_attr_as_string(res->msgs[0], SEC_ATTR_TYPE,
|
2716
|
+
+ "simple");
|
2717
|
+
+ datatype = talloc_strdup(tmp_ctx, attr_datatype);
|
2718
|
+
+ if (datatype == NULL) {
|
2719
|
+
+ ret = ENOMEM;
|
2720
|
+
+ goto done;
|
2721
|
+
+ }
|
2722
|
+
+
|
2723
|
+
+ *_datatype = talloc_steal(mem_ctx, datatype);
|
2724
|
+
}
|
2725
|
+
+
|
2726
|
+
+ *_secret = talloc_steal(mem_ctx, secret);
|
2727
|
+
+
|
2728
|
+
+ if (_secret_len) {
|
2729
|
+
+ *_secret_len = secret_len;
|
2730
|
+
+ }
|
2731
|
+
+
|
2732
|
+
ret = EOK;
|
2733
|
+
|
2734
|
+
done:
|
2735
|
+
@@ -1019,11 +1095,13 @@ done:
|
2736
|
+
}
|
2737
|
+
|
2738
|
+
errno_t sss_sec_put(struct sss_sec_req *req,
|
2739
|
+
- const char *secret)
|
2740
|
+
+ uint8_t *secret,
|
2741
|
+
+ size_t secret_len,
|
2742
|
+
+ enum sss_sec_enctype enctype,
|
2743
|
+
+ const char *datatype)
|
2744
|
+
{
|
2745
|
+
struct ldb_message *msg;
|
2746
|
+
- const char *enctype = "masterkey";
|
2747
|
+
- char *enc_secret;
|
2748
|
+
+ struct ldb_val enc_secret;
|
2749
|
+
int ret;
|
2750
|
+
|
2751
|
+
if (req == NULL || secret == NULL) {
|
2752
|
+
@@ -1064,7 +1142,7 @@ errno_t sss_sec_put(struct sss_sec_req *req,
|
2753
|
+
goto done;
|
2754
|
+
}
|
2755
|
+
|
2756
|
+
- ret = local_check_max_payload_size(req, strlen(secret));
|
2757
|
+
+ ret = local_check_max_payload_size(req, secret_len);
|
2758
|
+
if (ret != EOK) {
|
2759
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2760
|
+
"local_check_max_payload_size failed [%d]: %s\n",
|
2761
|
+
@@ -1072,22 +1150,24 @@ errno_t sss_sec_put(struct sss_sec_req *req,
|
2762
|
+
goto done;
|
2763
|
+
}
|
2764
|
+
|
2765
|
+
- ret = local_encrypt(req->sctx, msg, secret, enctype, &enc_secret);
|
2766
|
+
+ ret = local_encrypt(req->sctx, msg, secret, secret_len, enctype,
|
2767
|
+
+ &enc_secret.data, &enc_secret.length);
|
2768
|
+
if (ret != EOK) {
|
2769
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2770
|
+
"local_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
|
2771
|
+
goto done;
|
2772
|
+
}
|
2773
|
+
|
2774
|
+
- ret = ldb_msg_add_string(msg, "type", "simple");
|
2775
|
+
+ ret = ldb_msg_add_string(msg, SEC_ATTR_TYPE, datatype);
|
2776
|
+
if (ret != EOK) {
|
2777
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2778
|
+
- "ldb_msg_add_string failed adding type:simple [%d]: %s\n",
|
2779
|
+
- ret, sss_strerror(ret));
|
2780
|
+
+ "ldb_msg_add_string failed adding type:%s [%d]: %s\n",
|
2781
|
+
+ datatype, ret, sss_strerror(ret));
|
2782
|
+
goto done;
|
2783
|
+
}
|
2784
|
+
|
2785
|
+
- ret = ldb_msg_add_string(msg, "enctype", enctype);
|
2786
|
+
+ ret = ldb_msg_add_string(msg, SEC_ATTR_ENCTYPE,
|
2787
|
+
+ sss_sec_enctype_to_str(enctype));
|
2788
|
+
if (ret != EOK) {
|
2789
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2790
|
+
"ldb_msg_add_string failed adding enctype [%d]: %s\n",
|
2791
|
+
@@ -1095,7 +1175,7 @@ errno_t sss_sec_put(struct sss_sec_req *req,
|
2792
|
+
goto done;
|
2793
|
+
}
|
2794
|
+
|
2795
|
+
- ret = ldb_msg_add_string(msg, "secret", enc_secret);
|
2796
|
+
+ ret = ldb_msg_add_value(msg, SEC_ATTR_SECRET, &enc_secret, NULL);
|
2797
|
+
if (ret != EOK) {
|
2798
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2799
|
+
"ldb_msg_add_string failed adding secret [%d]: %s\n",
|
2800
|
+
@@ -1103,7 +1183,7 @@ errno_t sss_sec_put(struct sss_sec_req *req,
|
2801
|
+
goto done;
|
2802
|
+
}
|
2803
|
+
|
2804
|
+
- ret = ldb_msg_add_fmt(msg, "creationTime", "%lu", time(NULL));
|
2805
|
+
+ ret = ldb_msg_add_fmt(msg, SEC_ATTR_CTIME, "%lu", time(NULL));
|
2806
|
+
if (ret != EOK) {
|
2807
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2808
|
+
"ldb_msg_add_string failed adding creationTime [%d]: %s\n",
|
2809
|
+
@@ -1132,11 +1212,13 @@ done:
|
2810
|
+
}
|
2811
|
+
|
2812
|
+
errno_t sss_sec_update(struct sss_sec_req *req,
|
2813
|
+
- const char *secret)
|
2814
|
+
+ uint8_t *secret,
|
2815
|
+
+ size_t secret_len,
|
2816
|
+
+ enum sss_sec_enctype enctype,
|
2817
|
+
+ const char *datatype)
|
2818
|
+
{
|
2819
|
+
struct ldb_message *msg;
|
2820
|
+
- const char *enctype = "masterkey";
|
2821
|
+
- char *enc_secret;
|
2822
|
+
+ struct ldb_val enc_secret;
|
2823
|
+
int ret;
|
2824
|
+
|
2825
|
+
if (req == NULL || secret == NULL) {
|
2826
|
+
@@ -1177,7 +1259,7 @@ errno_t sss_sec_update(struct sss_sec_req *req,
|
2827
|
+
goto done;
|
2828
|
+
}
|
2829
|
+
|
2830
|
+
- ret = local_check_max_payload_size(req, strlen(secret));
|
2831
|
+
+ ret = local_check_max_payload_size(req, secret_len);
|
2832
|
+
if (ret != EOK) {
|
2833
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2834
|
+
"local_check_max_payload_size failed [%d]: %s\n",
|
2835
|
+
@@ -1185,15 +1267,49 @@ errno_t sss_sec_update(struct sss_sec_req *req,
|
2836
|
+
goto done;
|
2837
|
+
}
|
2838
|
+
|
2839
|
+
- ret = local_encrypt(req->sctx, msg, secret, enctype, &enc_secret);
|
2840
|
+
+ ret = local_encrypt(req->sctx, msg, secret, secret_len, enctype,
|
2841
|
+
+ &enc_secret.data, &enc_secret.length);
|
2842
|
+
if (ret != EOK) {
|
2843
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
2844
|
+
"local_encrypt failed [%d]: %s\n", ret, sss_strerror(ret));
|
2845
|
+
goto done;
|
2846
|
+
}
|
2847
|
+
|
2848
|
+
+ ret = ldb_msg_add_empty(msg, SEC_ATTR_ENCTYPE, LDB_FLAG_MOD_REPLACE, NULL);
|
2849
|
+
+ if (ret != LDB_SUCCESS) {
|
2850
|
+
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
2851
|
+
+ "ldb_msg_add_empty failed: [%s]\n", ldb_strerror(ret));
|
2852
|
+
+ ret = EIO;
|
2853
|
+
+ goto done;
|
2854
|
+
+ }
|
2855
|
+
+
|
2856
|
+
+ ret = ldb_msg_add_string(msg, SEC_ATTR_ENCTYPE,
|
2857
|
+
+ sss_sec_enctype_to_str(enctype));
|
2858
|
+
+ if (ret != EOK) {
|
2859
|
+
+ DEBUG(SSSDBG_OP_FAILURE,
|
2860
|
+
+ "ldb_msg_add_string failed adding enctype [%d]: %s\n",
|
2861
|
+
+ ret, sss_strerror(ret));
|
2862
|
+
+ goto done;
|
2863
|
+
+ }
|
2864
|
+
+
|
2865
|
+
+ ret = ldb_msg_add_empty(msg, SEC_ATTR_TYPE, LDB_FLAG_MOD_REPLACE, NULL);
|
2866
|
+
+ if (ret != LDB_SUCCESS) {
|
2867
|
+
+ DEBUG(SSSDBG_MINOR_FAILURE,
|
2868
|
+
+ "ldb_msg_add_empty failed: [%s]\n", ldb_strerror(ret));
|
2869
|
+
+ ret = EIO;
|
2870
|
+
+ goto done;
|
2871
|
+
+ }
|
2872
|
+
+
|
2873
|
+
+ ret = ldb_msg_add_string(msg, SEC_ATTR_TYPE, datatype);
|
2874
|
+
+ if (ret != EOK) {
|
2875
|
+
+ DEBUG(SSSDBG_OP_FAILURE,
|
2876
|
+
+ "ldb_msg_add_string failed adding type:%s [%d]: %s\n",
|
2877
|
+
+ datatype, ret, sss_strerror(ret));
|
2878
|
+
+ goto done;
|
2879
|
+
+ }
|
2880
|
+
+
|
2881
|
+
/* FIXME - should we have a lastUpdate timestamp? */
|
2882
|
+
- ret = ldb_msg_add_empty(msg, "secret", LDB_FLAG_MOD_REPLACE, NULL);
|
2883
|
+
+ ret = ldb_msg_add_empty(msg, SEC_ATTR_SECRET, LDB_FLAG_MOD_REPLACE, NULL);
|
2884
|
+
if (ret != LDB_SUCCESS) {
|
2885
|
+
DEBUG(SSSDBG_MINOR_FAILURE,
|
2886
|
+
"ldb_msg_add_empty failed: [%s]\n", ldb_strerror(ret));
|
2887
|
+
@@ -1201,7 +1317,7 @@ errno_t sss_sec_update(struct sss_sec_req *req,
|
2888
|
+
goto done;
|
2889
|
+
}
|
2890
|
+
|
2891
|
+
- ret = ldb_msg_add_string(msg, "secret", enc_secret);
|
2892
|
+
+ ret = ldb_msg_add_value(msg, SEC_ATTR_SECRET, &enc_secret, NULL);
|
2893
|
+
if (ret != LDB_SUCCESS) {
|
2894
|
+
DEBUG(SSSDBG_MINOR_FAILURE,
|
2895
|
+
"ldb_msg_add_string failed: [%s]\n", ldb_strerror(ret));
|
2896
|
+
diff --git a/src/util/secrets/secrets.h b/src/util/secrets/secrets.h
|
2897
|
+
index 9cf397516..f79bfaa4b 100644
|
2898
|
+
--- a/src/util/secrets/secrets.h
|
2899
|
+
+++ b/src/util/secrets/secrets.h
|
2900
|
+
|
2901
|
+
#define DEFAULT_SEC_KCM_MAX_UID_SECRETS 64
|
2902
|
+
#define DEFAULT_SEC_KCM_MAX_PAYLOAD_SIZE 65536
|
2903
|
+
|
2904
|
+
+enum sss_sec_enctype {
|
2905
|
+
+ SSS_SEC_PLAINTEXT,
|
2906
|
+
+ SSS_SEC_MASTERKEY,
|
2907
|
+
+ SSS_SEC_ENCTYPE_SENTINEL
|
2908
|
+
+};
|
2909
|
+
+
|
2910
|
+
struct sss_sec_ctx;
|
2911
|
+
|
2912
|
+
struct sss_sec_req;
|
2913
|
+
@@ -88,13 +94,21 @@ errno_t sss_sec_list(TALLOC_CTX *mem_ctx,
|
2914
|
+
|
2915
|
+
errno_t sss_sec_get(TALLOC_CTX *mem_ctx,
|
2916
|
+
struct sss_sec_req *req,
|
2917
|
+
- char **_secret);
|
2918
|
+
+ uint8_t **_secret,
|
2919
|
+
+ size_t *_secret_len,
|
2920
|
+
+ char **_datatype);
|
2921
|
+
|
2922
|
+
errno_t sss_sec_put(struct sss_sec_req *req,
|
2923
|
+
- const char *secret);
|
2924
|
+
+ uint8_t *secret,
|
2925
|
+
+ size_t secret_len,
|
2926
|
+
+ enum sss_sec_enctype enctype,
|
2927
|
+
+ const char *datatype);
|
2928
|
+
|
2929
|
+
errno_t sss_sec_update(struct sss_sec_req *req,
|
2930
|
+
- const char *secret);
|
2931
|
+
+ uint8_t *secret,
|
2932
|
+
+ size_t secret_len,
|
2933
|
+
+ enum sss_sec_enctype enctype,
|
2934
|
+
+ const char *datatype);
|
2935
|
+
|
2936
|
+
errno_t sss_sec_create_container(struct sss_sec_req *req);
|
2937
|
+
|
2938
|
+
diff --git a/src/util/sss_iobuf.c b/src/util/sss_iobuf.c
|
2939
|
+
index 518713e4c..3056a7b0d 100644
|
2940
|
+
--- a/src/util/sss_iobuf.c
|
2941
|
+
+++ b/src/util/sss_iobuf.c
|
2942
|
+
@@ -66,6 +66,30 @@ struct sss_iobuf *sss_iobuf_init_readonly(TALLOC_CTX *mem_ctx,
|
2943
|
+
return iobuf;
|
2944
|
+
}
|
2945
|
+
|
2946
|
+
+struct sss_iobuf *sss_iobuf_init_steal(TALLOC_CTX *mem_ctx,
|
2947
|
+
+ uint8_t *data,
|
2948
|
+
+ size_t size)
|
2949
|
+
+{
|
2950
|
+
+ struct sss_iobuf *iobuf;
|
2951
|
+
+
|
2952
|
+
+ iobuf = talloc_zero(mem_ctx, struct sss_iobuf);
|
2953
|
+
+ if (iobuf == NULL) {
|
2954
|
+
+ return NULL;
|
2955
|
+
+ }
|
2956
|
+
+
|
2957
|
+
+ iobuf->data = talloc_steal(iobuf, data);
|
2958
|
+
+ iobuf->size = size;
|
2959
|
+
+ iobuf->capacity = size;
|
2960
|
+
+ iobuf->dp = 0;
|
2961
|
+
+
|
2962
|
+
+ return iobuf;
|
2963
|
+
+}
|
2964
|
+
+
|
2965
|
+
+void sss_iobuf_cursor_reset(struct sss_iobuf *iobuf)
|
2966
|
+
+{
|
2967
|
+
+ iobuf->dp = 0;
|
2968
|
+
+}
|
2969
|
+
+
|
2970
|
+
size_t sss_iobuf_get_len(struct sss_iobuf *iobuf)
|
2971
|
+
{
|
2972
|
+
if (iobuf == NULL) {
|
2973
|
+
@@ -223,6 +247,109 @@ errno_t sss_iobuf_write_len(struct sss_iobuf *iobuf,
|
2974
|
+
return EOK;
|
2975
|
+
}
|
2976
|
+
|
2977
|
+
+errno_t sss_iobuf_read_varlen(TALLOC_CTX *mem_ctx,
|
2978
|
+
+ struct sss_iobuf *iobuf,
|
2979
|
+
+ uint8_t **_out,
|
2980
|
+
+ size_t *_len)
|
2981
|
+
+{
|
2982
|
+
+ uint8_t *out;
|
2983
|
+
+ uint32_t len;
|
2984
|
+
+ size_t slen;
|
2985
|
+
+ errno_t ret;
|
2986
|
+
+
|
2987
|
+
+ if (iobuf == NULL || _out == NULL || _len == NULL) {
|
2988
|
+
+ return EINVAL;
|
2989
|
+
+ }
|
2990
|
+
+
|
2991
|
+
+ ret = sss_iobuf_read_uint32(iobuf, &len);
|
2992
|
+
+ if (ret != EOK) {
|
2993
|
+
+ return ret;
|
2994
|
+
+ }
|
2995
|
+
+
|
2996
|
+
+ if (len == 0) {
|
2997
|
+
+ *_out = NULL;
|
2998
|
+
+ *_len = 0;
|
2999
|
+
+ return EOK;
|
3000
|
+
+ }
|
3001
|
+
+
|
3002
|
+
+ out = talloc_array(mem_ctx, uint8_t, len);
|
3003
|
+
+ if (out == NULL) {
|
3004
|
+
+ return ENOMEM;
|
3005
|
+
+ }
|
3006
|
+
+
|
3007
|
+
+ slen = len;
|
3008
|
+
+ ret = sss_iobuf_read_len(iobuf, slen, out);
|
3009
|
+
+ if (ret != EOK) {
|
3010
|
+
+ talloc_free(out);
|
3011
|
+
+ return ret;
|
3012
|
+
+ }
|
3013
|
+
+
|
3014
|
+
+ *_out = out;
|
3015
|
+
+ *_len = slen;
|
3016
|
+
+
|
3017
|
+
+ return EOK;
|
3018
|
+
+}
|
3019
|
+
+
|
3020
|
+
+errno_t sss_iobuf_write_varlen(struct sss_iobuf *iobuf,
|
3021
|
+
+ uint8_t *data,
|
3022
|
+
+ size_t len)
|
3023
|
+
+{
|
3024
|
+
+ errno_t ret;
|
3025
|
+
+
|
3026
|
+
+ if (iobuf == NULL || (data == NULL && len != 0)) {
|
3027
|
+
+ return EINVAL;
|
3028
|
+
+ }
|
3029
|
+
+
|
3030
|
+
+ ret = sss_iobuf_write_uint32(iobuf, len);
|
3031
|
+
+ if (ret != EOK) {
|
3032
|
+
+ return ret;
|
3033
|
+
+ }
|
3034
|
+
+
|
3035
|
+
+ if (len == 0) {
|
3036
|
+
+ return EOK;
|
3037
|
+
+ }
|
3038
|
+
+
|
3039
|
+
+ return sss_iobuf_write_len(iobuf, data, len);
|
3040
|
+
+}
|
3041
|
+
+
|
3042
|
+
+errno_t sss_iobuf_read_iobuf(TALLOC_CTX *mem_ctx,
|
3043
|
+
+ struct sss_iobuf *iobuf,
|
3044
|
+
+ struct sss_iobuf **_out)
|
3045
|
+
+{
|
3046
|
+
+ struct sss_iobuf *out;
|
3047
|
+
+ uint8_t *data;
|
3048
|
+
+ size_t len;
|
3049
|
+
+ errno_t ret;
|
3050
|
+
+
|
3051
|
+
+ ret = sss_iobuf_read_varlen(NULL, iobuf, &data, &len);
|
3052
|
+
+ if (ret != EOK) {
|
3053
|
+
+ return ret;
|
3054
|
+
+ }
|
3055
|
+
+
|
3056
|
+
+ out = sss_iobuf_init_steal(mem_ctx, data, len);
|
3057
|
+
+ if (out == NULL) {
|
3058
|
+
+ return ENOMEM;
|
3059
|
+
+ }
|
3060
|
+
+
|
3061
|
+
+ *_out = out;
|
3062
|
+
+
|
3063
|
+
+ return EOK;
|
3064
|
+
+}
|
3065
|
+
+
|
3066
|
+
+errno_t sss_iobuf_write_iobuf(struct sss_iobuf *iobuf,
|
3067
|
+
+ struct sss_iobuf *data)
|
3068
|
+
+{
|
3069
|
+
+ return sss_iobuf_write_varlen(iobuf, data->data, data->size);
|
3070
|
+
+}
|
3071
|
+
+
|
3072
|
+
+errno_t sss_iobuf_read_uint8(struct sss_iobuf *iobuf,
|
3073
|
+
+ uint8_t *_val)
|
3074
|
+
+{
|
3075
|
+
+ SAFEALIGN_COPY_UINT8_CHECK(_val, iobuf_ptr(iobuf),
|
3076
|
+
+ iobuf->capacity, &iobuf->dp);
|
3077
|
+
+ return EOK;
|
3078
|
+
+}
|
3079
|
+
+
|
3080
|
+
errno_t sss_iobuf_read_uint32(struct sss_iobuf *iobuf,
|
3081
|
+
uint32_t *_val)
|
3082
|
+
{
|
3083
|
+
@@ -239,6 +366,20 @@ errno_t sss_iobuf_read_int32(struct sss_iobuf *iobuf,
|
3084
|
+
return EOK;
|
3085
|
+
}
|
3086
|
+
|
3087
|
+
+errno_t sss_iobuf_write_uint8(struct sss_iobuf *iobuf,
|
3088
|
+
+ uint8_t val)
|
3089
|
+
+{
|
3090
|
+
+ errno_t ret;
|
3091
|
+
+
|
3092
|
+
+ ret = ensure_bytes(iobuf, sizeof(uint8_t));
|
3093
|
+
+ if (ret != EOK) {
|
3094
|
+
+ return ret;
|
3095
|
+
+ }
|
3096
|
+
+
|
3097
|
+
+ SAFEALIGN_SETMEM_UINT8(iobuf_ptr(iobuf), val, &iobuf->dp);
|
3098
|
+
+ return EOK;
|
3099
|
+
+}
|
3100
|
+
+
|
3101
|
+
errno_t sss_iobuf_write_uint32(struct sss_iobuf *iobuf,
|
3102
|
+
uint32_t val)
|
3103
|
+
{
|
3104
|
+
diff --git a/src/util/sss_iobuf.h b/src/util/sss_iobuf.h
|
3105
|
+
index cc3dfd1e9..159fbc0b9 100644
|
3106
|
+
--- a/src/util/sss_iobuf.h
|
3107
|
+
+++ b/src/util/sss_iobuf.h
|
3108
|
+
@@ -50,6 +50,29 @@ struct sss_iobuf *sss_iobuf_init_readonly(TALLOC_CTX *mem_ctx,
|
3109
|
+
const uint8_t *data,
|
3110
|
+
size_t size);
|
3111
|
+
|
3112
|
+
+/*
|
3113
|
+
+ * @brief Allocate an IO buffer with a fixed size, stealing input data.
|
3114
|
+
+ *
|
3115
|
+
+ * This function is useful for parsing an input buffer from an existing
|
3116
|
+
+ * buffer pointed to by data.
|
3117
|
+
+ *
|
3118
|
+
+ * The iobuf assumes ownership of the data buffer.
|
3119
|
+
+ *
|
3120
|
+
+ * @param[in] mem_ctx The talloc context that owns the iobuf
|
3121
|
+
+ * @param[in] data The data to initialize the IO buffer with.
|
3122
|
+
+ * @param[in] size The size of the data buffer
|
3123
|
+
+ *
|
3124
|
+
+ * @return The newly created buffer on success or NULL on an error.
|
3125
|
+
+ */
|
3126
|
+
+struct sss_iobuf *sss_iobuf_init_steal(TALLOC_CTX *mem_ctx,
|
3127
|
+
+ uint8_t *data,
|
3128
|
+
+ size_t size);
|
3129
|
+
+
|
3130
|
+
+/*
|
3131
|
+
+ * @brief Reset internal cursor of the IO buffer (seek to the start)
|
3132
|
+
+ */
|
3133
|
+
+void sss_iobuf_cursor_reset(struct sss_iobuf *iobuf);
|
3134
|
+
+
|
3135
|
+
/*
|
3136
|
+
* @brief Returns the number of bytes currently stored in the iobuf
|
3137
|
+
*
|
3138
|
+
@@ -131,6 +154,28 @@ errno_t sss_iobuf_write_len(struct sss_iobuf *iobuf,
|
3139
|
+
uint8_t *buf,
|
3140
|
+
size_t len);
|
3141
|
+
|
3142
|
+
+errno_t sss_iobuf_read_varlen(TALLOC_CTX *mem_ctx,
|
3143
|
+
+ struct sss_iobuf *iobuf,
|
3144
|
+
+ uint8_t **_out,
|
3145
|
+
+ size_t *_len);
|
3146
|
+
+
|
3147
|
+
+errno_t sss_iobuf_write_varlen(struct sss_iobuf *iobuf,
|
3148
|
+
+ uint8_t *data,
|
3149
|
+
+ size_t len);
|
3150
|
+
+
|
3151
|
+
+errno_t sss_iobuf_read_iobuf(TALLOC_CTX *mem_ctx,
|
3152
|
+
+ struct sss_iobuf *iobuf,
|
3153
|
+
+ struct sss_iobuf **_out);
|
3154
|
+
+
|
3155
|
+
+errno_t sss_iobuf_write_iobuf(struct sss_iobuf *iobuf,
|
3156
|
+
+ struct sss_iobuf *data);
|
3157
|
+
+
|
3158
|
+
+errno_t sss_iobuf_read_uint8(struct sss_iobuf *iobuf,
|
3159
|
+
+ uint8_t *_val);
|
3160
|
+
+
|
3161
|
+
+errno_t sss_iobuf_write_uint8(struct sss_iobuf *iobuf,
|
3162
|
+
+ uint8_t val);
|
3163
|
+
+
|
3164
|
+
errno_t sss_iobuf_read_uint32(struct sss_iobuf *iobuf,
|
3165
|
+
uint32_t *_val);
|
3166
|
+
|
3167
|
+
@@ -148,4 +193,5 @@ errno_t sss_iobuf_read_stringz(struct sss_iobuf *iobuf,
|
3168
|
+
|
3169
|
+
errno_t sss_iobuf_write_stringz(struct sss_iobuf *iobuf,
|
3170
|
+
const char *str);
|
3171
|
+
+
|
3172
|
+
#endif /* __SSS_IOBUF_H_ */
|
3173
|
+
diff --git a/src/util/sss_ptr_hash.c b/src/util/sss_ptr_hash.c
|
3174
|
+
index 6409236c7..e3805dac4 100644
|
3175
|
+
--- a/src/util/sss_ptr_hash.c
|
3176
|
+
+++ b/src/util/sss_ptr_hash.c
|
3177
|
+
@@ -54,6 +54,7 @@ struct sss_ptr_hash_value {
|
3178
|
+
hash_table_t *table;
|
3179
|
+
const char *key;
|
3180
|
+
void *payload;
|
3181
|
+
+ bool delete_in_progress;
|
3182
|
+
};
|
3183
|
+
|
3184
|
+
static int
|
3185
|
+
@@ -61,12 +62,22 @@ sss_ptr_hash_value_destructor(struct sss_ptr_hash_value *value)
|
3186
|
+
{
|
3187
|
+
hash_key_t table_key;
|
3188
|
+
|
3189
|
+
+ /* Do not call hash_delete() if we got here from hash delete callback when
|
3190
|
+
+ * the callback calls talloc_free(payload) which frees the value. This
|
3191
|
+
+ * should not happen since talloc will avoid circular free but let's be
|
3192
|
+
+ * over protective here. */
|
3193
|
+
+ if (value->delete_in_progress) {
|
3194
|
+
+ return 0;
|
3195
|
+
+ }
|
3196
|
+
+
|
3197
|
+
+ value->delete_in_progress = true;
|
3198
|
+
if (value->table && value->key) {
|
3199
|
+
table_key.type = HASH_KEY_STRING;
|
3200
|
+
table_key.str = discard_const_p(char, value->key);
|
3201
|
+
if (hash_delete(value->table, &table_key) != HASH_SUCCESS) {
|
3202
|
+
DEBUG(SSSDBG_CRIT_FAILURE,
|
3203
|
+
"failed to delete entry with key '%s'\n", value->key);
|
3204
|
+
+ value->delete_in_progress = false;
|
3205
|
+
}
|
3206
|
+
}
|
3207
|
+
|
3208
|
+
@@ -127,6 +138,15 @@ sss_ptr_hash_delete_cb(hash_entry_t *item,
|
3209
|
+
callback_entry.key = item->key;
|
3210
|
+
callback_entry.value.type = HASH_VALUE_PTR;
|
3211
|
+
callback_entry.value.ptr = value->payload;
|
3212
|
+
+
|
3213
|
+
+ /* Delete the value in case this callback has been called directly
|
3214
|
+
+ * from dhash (overwriting existing entry) instead of hash_delete()
|
3215
|
+
+ * in value's destructor. */
|
3216
|
+
+ if (!value->delete_in_progress) {
|
3217
|
+
+ talloc_set_destructor(value, NULL);
|
3218
|
+
+ talloc_free(value);
|
3219
|
+
+ }
|
3220
|
+
+
|
3221
|
+
/* Even if execution is already in the context of
|
3222
|
+
* talloc_free(payload) -> talloc_free(value) -> ...
|
3223
|
+
* there still might be legitimate reasons to execute callback.
|
3224
|
+
--
|
3225
|
+
2.21.3
|
3226
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
From 833034f5332d2492d413a9c97fded1480b58bf14 Mon Sep 17 00:00:00 2001
|
2
|
+
From: Alexey Tikhonov <atikhono@redhat.com>
|
3
|
+
Date: Wed, 21 Oct 2020 18:47:32 +0200
|
4
|
+
Subject: [PATCH 3/4] DEBUG: journal_send() was made static
|
5
|
+
MIME-Version: 1.0
|
6
|
+
Content-Type: text/plain; charset=UTF-8
|
7
|
+
Content-Transfer-Encoding: 8bit
|
8
|
+
|
9
|
+
Reviewed-by: Tomáš Halman <thalman@redhat.com>
|
10
|
+
---
|
11
|
+
src/util/debug.c | 2 +-
|
12
|
+
1 file changed, 1 insertion(+), 1 deletion(-)
|
13
|
+
|
14
|
+
diff --git a/src/util/debug.c b/src/util/debug.c
|
15
|
+
index 1d5f75e4d..c162987b9 100644
|
16
|
+
--- a/src/util/debug.c
|
17
|
+
+++ b/src/util/debug.c
|
18
|
+
@@ -201,7 +201,7 @@ static void debug_printf(const char *format, ...)
|
19
|
+
}
|
20
|
+
|
21
|
+
#ifdef WITH_JOURNALD
|
22
|
+
-errno_t journal_send(const char *file,
|
23
|
+
+static errno_t journal_send(const char *file,
|
24
|
+
long line,
|
25
|
+
const char *function,
|
26
|
+
int level,
|
27
|
+
--
|
28
|
+
2.21.3
|
29
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
From 18233532b72e62452eac6886652fa633ba055d8c Mon Sep 17 00:00:00 2001
|
2
|
+
From: Alexey Tikhonov <atikhono@redhat.com>
|
3
|
+
Date: Wed, 21 Oct 2020 19:20:03 +0200
|
4
|
+
Subject: [PATCH 4/4] DEBUG: fixes program identifier as seen in syslog
|
5
|
+
MIME-Version: 1.0
|
6
|
+
Content-Type: text/plain; charset=UTF-8
|
7
|
+
Content-Transfer-Encoding: 8bit
|
8
|
+
|
9
|
+
Commit 225fe9950f2807d5fb226f6b3be1ff4cefd731f0 changed `debug_prg_name`
|
10
|
+
to accomodate needs of own SSSD logs, but this affected journal/syslog
|
11
|
+
as well.
|
12
|
+
|
13
|
+
This patch amends situation:
|
14
|
+
- journal messages gets "umbrella" identifier "sssd[]"
|
15
|
+
- syslog uses default which is program name
|
16
|
+
|
17
|
+
Resolves: https://github.com/SSSD/sssd/issues/5384
|
18
|
+
|
19
|
+
Reviewed-by: Tomáš Halman <thalman@redhat.com>
|
20
|
+
---
|
21
|
+
src/util/debug.c | 2 +-
|
22
|
+
src/util/sss_log.c | 12 +++---------
|
23
|
+
2 files changed, 4 insertions(+), 10 deletions(-)
|
24
|
+
|
25
|
+
diff --git a/src/util/debug.c b/src/util/debug.c
|
26
|
+
index c162987b9..f05b26500 100644
|
27
|
+
--- a/src/util/debug.c
|
28
|
+
+++ b/src/util/debug.c
|
29
|
+
@@ -250,7 +250,7 @@ static errno_t journal_send(const char *file,
|
30
|
+
"MESSAGE=%s", message,
|
31
|
+
"PRIORITY=%i", LOG_DEBUG,
|
32
|
+
"SSSD_DOMAIN=%s", domain,
|
33
|
+
- "SSSD_PRG_NAME=%s", debug_prg_name,
|
34
|
+
+ "SSSD_PRG_NAME=sssd[%s]", debug_prg_name,
|
35
|
+
"SSSD_DEBUG_LEVEL=%x", level,
|
36
|
+
NULL);
|
37
|
+
ret = -res;
|
38
|
+
diff --git a/src/util/sss_log.c b/src/util/sss_log.c
|
39
|
+
index 48e73dbea..c6b7435c6 100644
|
40
|
+
--- a/src/util/sss_log.c
|
41
|
+
+++ b/src/util/sss_log.c
|
42
|
+
@@ -107,7 +107,7 @@ static void sss_log_internal(int priority, int facility, const char *format,
|
43
|
+
"SSSD_DOMAIN=%s", domain,
|
44
|
+
"PRIORITY=%i", syslog_priority,
|
45
|
+
"SYSLOG_FACILITY=%i", LOG_FAC(facility),
|
46
|
+
- "SYSLOG_IDENTIFIER=%s", debug_prg_name,
|
47
|
+
+ "SYSLOG_IDENTIFIER=sssd[%s]", debug_prg_name,
|
48
|
+
NULL);
|
49
|
+
|
50
|
+
free(message);
|
51
|
+
@@ -118,15 +118,9 @@ static void sss_log_internal(int priority, int facility, const char *format,
|
52
|
+
static void sss_log_internal(int priority, int facility, const char *format,
|
53
|
+
va_list ap)
|
54
|
+
{
|
55
|
+
- int syslog_priority;
|
56
|
+
-
|
57
|
+
- syslog_priority = sss_to_syslog(priority);
|
58
|
+
-
|
59
|
+
- openlog(debug_prg_name, 0, facility);
|
60
|
+
-
|
61
|
+
- vsyslog(syslog_priority, format, ap);
|
62
|
+
+ int syslog_priority = sss_to_syslog(priority);
|
63
|
+
|
64
|
+
- closelog();
|
65
|
+
+ vsyslog(facility|syslog_priority, format, ap);
|
66
|
+
}
|
67
|
+
|
68
|
+
#endif /* WITH_JOURNALD */
|
69
|
+
--
|
70
|
+
2.21.3
|
71
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
From 0e1bcf77bd73baa0fea64830eb1f4f65a63c7afe Mon Sep 17 00:00:00 2001
|
2
|
+
From: Sumit Bose <sbose@redhat.com>
|
3
|
+
Date: Thu, 8 Oct 2020 12:18:41 +0200
|
4
|
+
Subject: [PATCH 5/8] negcache: make sure domain config does not leak into
|
5
|
+
global
|
6
|
+
|
7
|
+
Resolves: https://github.com/SSSD/sssd/issues/5238
|
8
|
+
|
9
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
10
|
+
---
|
11
|
+
src/responder/common/negcache.c | 2 ++
|
12
|
+
1 file changed, 2 insertions(+)
|
13
|
+
|
14
|
+
diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
|
15
|
+
index ce1c0ab8c..139218420 100644
|
16
|
+
--- a/src/responder/common/negcache.c
|
17
|
+
+++ b/src/responder/common/negcache.c
|
18
|
+
@@ -1050,6 +1050,7 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
+ talloc_zfree(filter_list);
|
23
|
+
/* Populate non domain-specific negative cache user entries */
|
24
|
+
ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
|
25
|
+
CONFDB_NSS_FILTER_USERS, &filter_list);
|
26
|
+
@@ -1185,6 +1186,7 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
+ talloc_zfree(filter_list);
|
31
|
+
/* Populate non domain-specific negative cache group entries */
|
32
|
+
ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
|
33
|
+
CONFDB_NSS_FILTER_GROUPS, &filter_list);
|
34
|
+
--
|
35
|
+
2.21.3
|
36
|
+
|
@@ -0,0 +1,106 @@
|
|
1
|
+
From 385af99ff4d5a75d0c1edc9ad830da3eb7478295 Mon Sep 17 00:00:00 2001
|
2
|
+
From: Sumit Bose <sbose@redhat.com>
|
3
|
+
Date: Thu, 8 Oct 2020 17:57:29 +0200
|
4
|
+
Subject: [PATCH 6/8] utils: add SSS_GND_SUBDOMAINS flag for get_next_domain()
|
5
|
+
|
6
|
+
To allow to only iterate over a singel domain an its sub-domains a new
|
7
|
+
flag is added to get_next_domain().
|
8
|
+
|
9
|
+
Resolves: https://github.com/SSSD/sssd/issues/5238
|
10
|
+
|
11
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
12
|
+
---
|
13
|
+
src/tests/cmocka/test_utils.c | 31 +++++++++++++++++++++++++++++++
|
14
|
+
src/util/domain_info_utils.c | 10 +++++++---
|
15
|
+
src/util/util.h | 4 ++++
|
16
|
+
3 files changed, 42 insertions(+), 3 deletions(-)
|
17
|
+
|
18
|
+
diff --git a/src/tests/cmocka/test_utils.c b/src/tests/cmocka/test_utils.c
|
19
|
+
index 945f5cb44..d77a972c1 100644
|
20
|
+
--- a/src/tests/cmocka/test_utils.c
|
21
|
+
+++ b/src/tests/cmocka/test_utils.c
|
22
|
+
@@ -877,6 +877,37 @@ static void test_get_next_domain_flags(void **state)
|
23
|
+
|
24
|
+
dom = get_next_domain(dom, gnd_flags);
|
25
|
+
assert_null(dom);
|
26
|
+
+
|
27
|
+
+ /* Descend only to subdomains */
|
28
|
+
+ gnd_flags = SSS_GND_SUBDOMAINS | SSS_GND_INCLUDE_DISABLED;
|
29
|
+
+
|
30
|
+
+ dom = get_next_domain(test_ctx->dom_list, gnd_flags);
|
31
|
+
+ assert_non_null(dom);
|
32
|
+
+ assert_string_equal(dom->name, "sub1a");
|
33
|
+
+
|
34
|
+
+ dom = get_next_domain(dom, gnd_flags);
|
35
|
+
+ assert_null(dom);
|
36
|
+
+
|
37
|
+
+ dom = find_domain_by_name_ex(test_ctx->dom_list, "dom2", true,
|
38
|
+
+ SSS_GND_ALL_DOMAINS);
|
39
|
+
+ assert_non_null(dom);
|
40
|
+
+ assert_string_equal(dom->name, "dom2");
|
41
|
+
+
|
42
|
+
+ dom = get_next_domain(dom, gnd_flags);
|
43
|
+
+ assert_non_null(dom);
|
44
|
+
+ assert_string_equal(dom->name, "sub2a");
|
45
|
+
+
|
46
|
+
+ dom = get_next_domain(dom, gnd_flags);
|
47
|
+
+ assert_non_null(dom);
|
48
|
+
+ assert_string_equal(dom->name, "sub2b");
|
49
|
+
+
|
50
|
+
+ dom = get_next_domain(dom, gnd_flags);
|
51
|
+
+ assert_null(dom);
|
52
|
+
+
|
53
|
+
+ /* Expect NULL if the domain has no sub-domains */
|
54
|
+
+ test_ctx->dom_list->subdomains = NULL;
|
55
|
+
+ dom = get_next_domain(test_ctx->dom_list, gnd_flags);
|
56
|
+
+ assert_null(dom);
|
57
|
+
}
|
58
|
+
|
59
|
+
struct name_init_test_ctx {
|
60
|
+
diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c
|
61
|
+
index aa3582f03..4d4726daa 100644
|
62
|
+
--- a/src/util/domain_info_utils.c
|
63
|
+
+++ b/src/util/domain_info_utils.c
|
64
|
+
@@ -39,16 +39,20 @@ struct sss_domain_info *get_next_domain(struct sss_domain_info *domain,
|
65
|
+
uint32_t gnd_flags)
|
66
|
+
{
|
67
|
+
struct sss_domain_info *dom;
|
68
|
+
- bool descend = gnd_flags & SSS_GND_DESCEND;
|
69
|
+
+ bool descend = gnd_flags & (SSS_GND_DESCEND | SSS_GND_SUBDOMAINS);
|
70
|
+
bool include_disabled = gnd_flags & SSS_GND_INCLUDE_DISABLED;
|
71
|
+
+ bool only_subdomains = gnd_flags & SSS_GND_SUBDOMAINS;
|
72
|
+
|
73
|
+
dom = domain;
|
74
|
+
while (dom) {
|
75
|
+
if (descend && dom->subdomains) {
|
76
|
+
dom = dom->subdomains;
|
77
|
+
- } else if (dom->next) {
|
78
|
+
+ } else if (dom->next && only_subdomains && IS_SUBDOMAIN(dom)) {
|
79
|
+
dom = dom->next;
|
80
|
+
- } else if (descend && IS_SUBDOMAIN(dom) && dom->parent->next) {
|
81
|
+
+ } else if (dom->next && !only_subdomains) {
|
82
|
+
+ dom = dom->next;
|
83
|
+
+ } else if (descend && !only_subdomains && IS_SUBDOMAIN(dom)
|
84
|
+
+ && dom->parent->next) {
|
85
|
+
dom = dom->parent->next;
|
86
|
+
} else {
|
87
|
+
dom = NULL;
|
88
|
+
diff --git a/src/util/util.h b/src/util/util.h
|
89
|
+
index fbcac5cd0..581c0edfb 100644
|
90
|
+
--- a/src/util/util.h
|
91
|
+
+++ b/src/util/util.h
|
92
|
+
@@ -565,7 +565,11 @@ struct sss_domain_info *get_domains_head(struct sss_domain_info *domain);
|
93
|
+
|
94
|
+
#define SSS_GND_DESCEND 0x01
|
95
|
+
#define SSS_GND_INCLUDE_DISABLED 0x02
|
96
|
+
+/* Descend to sub-domains of current domain but do not go to next parent */
|
97
|
+
+#define SSS_GND_SUBDOMAINS 0x04
|
98
|
+
#define SSS_GND_ALL_DOMAINS (SSS_GND_DESCEND | SSS_GND_INCLUDE_DISABLED)
|
99
|
+
+#define SSS_GND_ALL_SUBDOMAINS (SSS_GND_SUBDOMAINS | SSS_GND_INCLUDE_DISABLED)
|
100
|
+
+
|
101
|
+
struct sss_domain_info *get_next_domain(struct sss_domain_info *domain,
|
102
|
+
uint32_t gnd_flags);
|
103
|
+
struct sss_domain_info *find_domain_by_name(struct sss_domain_info *domain,
|
104
|
+
--
|
105
|
+
2.21.3
|
106
|
+
|
@@ -0,0 +1,443 @@
|
|
1
|
+
From 0dc81a52e2836010974e9f71b1f3e47c20fd498d Mon Sep 17 00:00:00 2001
|
2
|
+
From: Sumit Bose <sbose@redhat.com>
|
3
|
+
Date: Fri, 9 Oct 2020 11:56:21 +0200
|
4
|
+
Subject: [PATCH 7/8] negcache: make sure short names are added to sub-domains
|
5
|
+
|
6
|
+
If short names are used with filter_users or filter_groups in a
|
7
|
+
[domain/...] section they should be added to the sub-domains of this
|
8
|
+
domain as well.
|
9
|
+
|
10
|
+
Resolves: https://github.com/SSSD/sssd/issues/5238
|
11
|
+
|
12
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
13
|
+
---
|
14
|
+
src/responder/common/negcache.c | 105 +++++++------
|
15
|
+
src/tests/cmocka/test_negcache.c | 254 +++++++++++++++++++++++++++++++
|
16
|
+
2 files changed, 312 insertions(+), 47 deletions(-)
|
17
|
+
|
18
|
+
diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
|
19
|
+
index 139218420..9ee39ce3e 100644
|
20
|
+
--- a/src/responder/common/negcache.c
|
21
|
+
+++ b/src/responder/common/negcache.c
|
22
|
+
@@ -971,6 +971,7 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
23
|
+
char *name = NULL;
|
24
|
+
struct sss_domain_info *dom = NULL;
|
25
|
+
struct sss_domain_info *domain_list = rctx->domains;
|
26
|
+
+ struct sss_domain_info *ddom;
|
27
|
+
char *domainname = NULL;
|
28
|
+
char *conf_path = NULL;
|
29
|
+
TALLOC_CTX *tmpctx = talloc_new(NULL);
|
30
|
+
@@ -1013,39 +1014,44 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
31
|
+
continue;
|
32
|
+
}
|
33
|
+
|
34
|
+
- if (domainname && strcmp(domainname, dom->name)) {
|
35
|
+
- DEBUG(SSSDBG_TRACE_FUNC,
|
36
|
+
- "Mismatch between domain name (%s) and name "
|
37
|
+
- "set in FQN (%s), assuming %s is UPN\n",
|
38
|
+
- dom->name, domainname, filter_list[i]);
|
39
|
+
- ret = sss_ncache_set_upn(ncache, true, dom, filter_list[i]);
|
40
|
+
+ /* Check domain and its sub-domains */
|
41
|
+
+ for (ddom = dom; ddom != NULL;
|
42
|
+
+ ddom = get_next_domain(ddom, SSS_GND_ALL_SUBDOMAINS)) {
|
43
|
+
+
|
44
|
+
+ if (domainname && strcmp(domainname, ddom->name)) {
|
45
|
+
+ DEBUG(SSSDBG_TRACE_FUNC,
|
46
|
+
+ "Mismatch between domain name (%s) and name "
|
47
|
+
+ "set in FQN (%s), assuming %s is UPN\n",
|
48
|
+
+ ddom->name, domainname, filter_list[i]);
|
49
|
+
+ ret = sss_ncache_set_upn(ncache, true, ddom, filter_list[i]);
|
50
|
+
+ if (ret != EOK) {
|
51
|
+
+ DEBUG(SSSDBG_OP_FAILURE,
|
52
|
+
+ "sss_ncache_set_upn failed (%d [%s]), ignored\n",
|
53
|
+
+ ret, sss_strerror(ret));
|
54
|
+
+ }
|
55
|
+
+ continue;
|
56
|
+
+ }
|
57
|
+
+
|
58
|
+
+ fqname = sss_create_internal_fqname(tmpctx, name, ddom->name);
|
59
|
+
+ if (fqname == NULL) {
|
60
|
+
+ continue;
|
61
|
+
+ }
|
62
|
+
+
|
63
|
+
+ ret = sss_ncache_set_upn(ncache, true, ddom, fqname);
|
64
|
+
if (ret != EOK) {
|
65
|
+
DEBUG(SSSDBG_OP_FAILURE,
|
66
|
+
"sss_ncache_set_upn failed (%d [%s]), ignored\n",
|
67
|
+
ret, sss_strerror(ret));
|
68
|
+
}
|
69
|
+
- continue;
|
70
|
+
- }
|
71
|
+
-
|
72
|
+
- fqname = sss_create_internal_fqname(tmpctx, name, dom->name);
|
73
|
+
- if (fqname == NULL) {
|
74
|
+
- continue;
|
75
|
+
- }
|
76
|
+
-
|
77
|
+
- ret = sss_ncache_set_upn(ncache, true, dom, fqname);
|
78
|
+
- if (ret != EOK) {
|
79
|
+
- DEBUG(SSSDBG_OP_FAILURE,
|
80
|
+
- "sss_ncache_set_upn failed (%d [%s]), ignored\n",
|
81
|
+
- ret, sss_strerror(ret));
|
82
|
+
- }
|
83
|
+
- ret = sss_ncache_set_user(ncache, true, dom, fqname);
|
84
|
+
- talloc_zfree(fqname);
|
85
|
+
- if (ret != EOK) {
|
86
|
+
- DEBUG(SSSDBG_CRIT_FAILURE,
|
87
|
+
- "Failed to store permanent user filter for [%s]"
|
88
|
+
- " (%d [%s])\n", filter_list[i],
|
89
|
+
- ret, sss_strerror(ret));
|
90
|
+
- continue;
|
91
|
+
+ ret = sss_ncache_set_user(ncache, true, ddom, fqname);
|
92
|
+
+ talloc_zfree(fqname);
|
93
|
+
+ if (ret != EOK) {
|
94
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
95
|
+
+ "Failed to store permanent user filter for [%s]"
|
96
|
+
+ " (%d [%s])\n", filter_list[i],
|
97
|
+
+ ret, sss_strerror(ret));
|
98
|
+
+ continue;
|
99
|
+
+ }
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
@@ -1161,27 +1167,32 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
104
|
+
continue;
|
105
|
+
}
|
106
|
+
|
107
|
+
- if (domainname && strcmp(domainname, dom->name)) {
|
108
|
+
- DEBUG(SSSDBG_CRIT_FAILURE,
|
109
|
+
- "Mismatch between domain name (%s) and name "
|
110
|
+
- "set in FQN (%s), skipping group %s\n",
|
111
|
+
- dom->name, domainname, name);
|
112
|
+
- continue;
|
113
|
+
- }
|
114
|
+
+ /* Check domain and its sub-domains */
|
115
|
+
+ for (ddom = dom;
|
116
|
+
+ ddom != NULL && (ddom == dom || ddom->parent != NULL);
|
117
|
+
+ ddom = get_next_domain(ddom, SSS_GND_ALL_DOMAINS)) {
|
118
|
+
+ if (domainname && strcmp(domainname, ddom->name)) {
|
119
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
120
|
+
+ "Mismatch between domain name (%s) and name "
|
121
|
+
+ "set in FQN (%s), skipping group %s\n",
|
122
|
+
+ ddom->name, domainname, name);
|
123
|
+
+ continue;
|
124
|
+
+ }
|
125
|
+
|
126
|
+
- fqname = sss_create_internal_fqname(tmpctx, name, dom->name);
|
127
|
+
- if (fqname == NULL) {
|
128
|
+
- continue;
|
129
|
+
- }
|
130
|
+
+ fqname = sss_create_internal_fqname(tmpctx, name, ddom->name);
|
131
|
+
+ if (fqname == NULL) {
|
132
|
+
+ continue;
|
133
|
+
+ }
|
134
|
+
|
135
|
+
- ret = sss_ncache_set_group(ncache, true, dom, fqname);
|
136
|
+
- talloc_zfree(fqname);
|
137
|
+
- if (ret != EOK) {
|
138
|
+
- DEBUG(SSSDBG_CRIT_FAILURE,
|
139
|
+
- "Failed to store permanent group filter for [%s]"
|
140
|
+
- " (%d [%s])\n", filter_list[i],
|
141
|
+
- ret, strerror(ret));
|
142
|
+
- continue;
|
143
|
+
+ ret = sss_ncache_set_group(ncache, true, ddom, fqname);
|
144
|
+
+ talloc_zfree(fqname);
|
145
|
+
+ if (ret != EOK) {
|
146
|
+
+ DEBUG(SSSDBG_CRIT_FAILURE,
|
147
|
+
+ "Failed to store permanent group filter for [%s]"
|
148
|
+
+ " (%d [%s])\n", filter_list[i],
|
149
|
+
+ ret, strerror(ret));
|
150
|
+
+ continue;
|
151
|
+
+ }
|
152
|
+
}
|
153
|
+
}
|
154
|
+
}
|
155
|
+
diff --git a/src/tests/cmocka/test_negcache.c b/src/tests/cmocka/test_negcache.c
|
156
|
+
index b3a379227..fb306b110 100644
|
157
|
+
--- a/src/tests/cmocka/test_negcache.c
|
158
|
+
+++ b/src/tests/cmocka/test_negcache.c
|
159
|
+
@@ -119,6 +119,8 @@ static int setup(void **state)
|
160
|
+
int ret;
|
161
|
+
struct test_state *ts;
|
162
|
+
|
163
|
+
+ test_dom_suite_setup(TESTS_PATH);
|
164
|
+
+
|
165
|
+
ts = talloc(NULL, struct test_state);
|
166
|
+
assert_non_null(ts);
|
167
|
+
|
168
|
+
@@ -133,6 +135,7 @@ static int setup(void **state)
|
169
|
+
static int teardown(void **state)
|
170
|
+
{
|
171
|
+
struct test_state *ts = talloc_get_type_abort(*state, struct test_state);
|
172
|
+
+ test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME);
|
173
|
+
talloc_free(ts);
|
174
|
+
return 0;
|
175
|
+
}
|
176
|
+
@@ -921,6 +924,255 @@ static void test_sss_ncache_reset_prepopulate(void **state)
|
177
|
+
assert_int_equal(ret, EEXIST);
|
178
|
+
}
|
179
|
+
|
180
|
+
+/* The main purpose of test_sss_ncache_short_name_in_domain is to test that
|
181
|
+
+ * short names in the filter_users or filter_groups options in a [domain/...]
|
182
|
+
+ * section are properly added to the related sub-domains as well (if there are
|
183
|
+
+ * any) and not added to domains from other [domain/...] sections. For
|
184
|
+
+ * completeness entries with fully-qualified names of the parent and the
|
185
|
+
+ * sub-domain and the generic UPN are added as well.
|
186
|
+
+ *
|
187
|
+
+ * The result should of course be independent of the present domains. To
|
188
|
+
+ * verify this the domains are added one after the other and the negative
|
189
|
+
+ * cache is repopulated each time.
|
190
|
+
+ *
|
191
|
+
+ * With the given domains, users and group we have to following expectations:
|
192
|
+
+ * - the short name entry will be added to the domain and all sub-domains as
|
193
|
+
+ * name and as upn by expanding it to a fully-qualified name with the
|
194
|
+
+ * domain name or sub-domain name respectively
|
195
|
+
+ * - the fully-qualified name from the parent domain is added as name and upn
|
196
|
+
+ * to the parent domain and as upn to all sub-domains
|
197
|
+
+ * - the fully-qualified name from the sub-domain is added as name to the
|
198
|
+
+ * sub-domain and as upn to the parent and all sub-domains
|
199
|
+
+ * - the generic upn is nowhere added as name and as upn to the parent and all
|
200
|
+
+ * sub-domains
|
201
|
+
+ * - none of the names is added to a different parent domain
|
202
|
+
+ *
|
203
|
+
+ * The following table should illustrated the expectations:
|
204
|
+
+ *
|
205
|
+
+ * user (name):
|
206
|
+
+ * | shortuser | parentu@TEST_DOM_NAME | subdomu@subTEST_DOM_NAME | upn@upn.dom
|
207
|
+
+ *-----------------+-----------+-----------------------+--------------------------+------------
|
208
|
+
+ * TEST_DOM_NAME | PRESENT | PRESENT | MISSING | MISSING
|
209
|
+
+ * subTEST_DOM_NAME| PRESENT | MISSING | PRESENT | MISSING
|
210
|
+
+ * TEST_DOM_NAME2 | MISSING | MISSING | MISSING | MISSING
|
211
|
+
+ *
|
212
|
+
+ * user (upn):
|
213
|
+
+ * | shortuser | parentu@TEST_DOM_NAME | subdomu@subTEST_DOM_NAME | upn@upn.dom
|
214
|
+
+ *-----------------+-----------+-----------------------+--------------------------+------------
|
215
|
+
+ * TEST_DOM_NAME | PRESENT | PRESENT | PRESENT | PRESENT
|
216
|
+
+ * subTEST_DOM_NAME| PRESENT | PRESENT | PRESENT | PRESENT
|
217
|
+
+ * TEST_DOM_NAME2 | MISSING | MISSING | MISSING | MISSING
|
218
|
+
+ *
|
219
|
+
+ *
|
220
|
+
+ *
|
221
|
+
+ * groups:
|
222
|
+
+ * | shortgroup | parentg@TEST_DOM_NAME | subdomg@subTEST_DOM_NAME
|
223
|
+
+ *-----------------+------------+-----------------------+-------------------------
|
224
|
+
+ * TEST_DOM_NAME | PRESENT | PRESENT | MISSING
|
225
|
+
+ * subTEST_DOM_NAME| PRESENT | MISSING | PRESENT
|
226
|
+
+ * TEST_DOM_NAME2 | MISSING | MISSING | MISSING
|
227
|
+
+ *
|
228
|
+
+ *
|
229
|
+
+ * The following expect_*() implement checks for the expextations:
|
230
|
+
+ */
|
231
|
+
+
|
232
|
+
+static void expect_in_parent(struct sss_nc_ctx *ncache,
|
233
|
+
+ struct sss_domain_info *dom)
|
234
|
+
+{
|
235
|
+
+ int ret;
|
236
|
+
+
|
237
|
+
+ ret = check_user_in_ncache(ncache, dom, "shortuser");
|
238
|
+
+ assert_int_equal(ret, EEXIST);
|
239
|
+
+ ret = sss_ncache_check_upn(ncache, dom, "shortuser@"TEST_DOM_NAME);
|
240
|
+
+ assert_int_equal(ret, EEXIST);
|
241
|
+
+
|
242
|
+
+ ret = check_user_in_ncache(ncache, dom, "parentu");
|
243
|
+
+ assert_int_equal(ret, EEXIST);
|
244
|
+
+ ret = sss_ncache_check_upn(ncache, dom, "parentu@"TEST_DOM_NAME);
|
245
|
+
+ assert_int_equal(ret, EEXIST);
|
246
|
+
+
|
247
|
+
+ ret = check_user_in_ncache(ncache, dom, "subdomu");
|
248
|
+
+ assert_int_equal(ret, ENOENT);
|
249
|
+
+ ret = sss_ncache_check_upn(ncache, dom, "subdomu@sub"TEST_DOM_NAME);
|
250
|
+
+ assert_int_equal(ret, EEXIST);
|
251
|
+
+
|
252
|
+
+ ret = check_user_in_ncache(ncache, dom, "upn");
|
253
|
+
+ assert_int_equal(ret, ENOENT);
|
254
|
+
+ ret = sss_ncache_check_upn(ncache, dom, "upn@upn.dom");
|
255
|
+
+ assert_int_equal(ret, EEXIST);
|
256
|
+
+
|
257
|
+
+ ret = check_group_in_ncache(ncache, dom, "shortgroup");
|
258
|
+
+ assert_int_equal(ret, EEXIST);
|
259
|
+
+
|
260
|
+
+ ret = check_group_in_ncache(ncache, dom, "parentg");
|
261
|
+
+ assert_int_equal(ret, EEXIST);
|
262
|
+
+
|
263
|
+
+ ret = check_group_in_ncache(ncache, dom, "subdomg");
|
264
|
+
+ assert_int_equal(ret, ENOENT);
|
265
|
+
+}
|
266
|
+
+
|
267
|
+
+static void expect_in_subdomain(struct sss_nc_ctx *ncache,
|
268
|
+
+ struct sss_domain_info *sub_dom)
|
269
|
+
+{
|
270
|
+
+ int ret;
|
271
|
+
+
|
272
|
+
+ ret = check_user_in_ncache(ncache, sub_dom, "shortuser");
|
273
|
+
+ assert_int_equal(ret, EEXIST);
|
274
|
+
+ ret = sss_ncache_check_upn(ncache, sub_dom, "shortuser@sub"TEST_DOM_NAME);
|
275
|
+
+ assert_int_equal(ret, EEXIST);
|
276
|
+
+
|
277
|
+
+ ret = check_user_in_ncache(ncache, sub_dom, "subdomu");
|
278
|
+
+ assert_int_equal(ret, EEXIST);
|
279
|
+
+ ret = sss_ncache_check_upn(ncache, sub_dom, "subdomu@sub"TEST_DOM_NAME);
|
280
|
+
+ assert_int_equal(ret, EEXIST);
|
281
|
+
+
|
282
|
+
+ ret = check_user_in_ncache(ncache, sub_dom, "upn");
|
283
|
+
+ assert_int_equal(ret, ENOENT);
|
284
|
+
+ ret = sss_ncache_check_upn(ncache, sub_dom, "upn@upn.dom");
|
285
|
+
+ assert_int_equal(ret, EEXIST);
|
286
|
+
+
|
287
|
+
+ ret = check_user_in_ncache(ncache, sub_dom, "parentu");
|
288
|
+
+ assert_int_equal(ret, ENOENT);
|
289
|
+
+ ret = sss_ncache_check_upn(ncache, sub_dom, "parentu@"TEST_DOM_NAME);
|
290
|
+
+ assert_int_equal(ret, EEXIST);
|
291
|
+
+
|
292
|
+
+
|
293
|
+
+ ret = check_group_in_ncache(ncache, sub_dom, "shortgroup");
|
294
|
+
+ assert_int_equal(ret, EEXIST);
|
295
|
+
+
|
296
|
+
+ ret = check_group_in_ncache(ncache, sub_dom, "parentg");
|
297
|
+
+ assert_int_equal(ret, ENOENT);
|
298
|
+
+
|
299
|
+
+ ret = check_group_in_ncache(ncache, sub_dom, "subdomg");
|
300
|
+
+ assert_int_equal(ret, EEXIST);
|
301
|
+
+}
|
302
|
+
+static void expect_no_entries_in_dom(struct sss_nc_ctx *ncache,
|
303
|
+
+ struct sss_domain_info *dom2)
|
304
|
+
+{
|
305
|
+
+ int ret;
|
306
|
+
+
|
307
|
+
+ ret = check_user_in_ncache(ncache, dom2, "shortuser");
|
308
|
+
+ assert_int_equal(ret, ENOENT);
|
309
|
+
+ ret = sss_ncache_check_upn(ncache, dom2, "shortuser"TEST_DOM_NAME);
|
310
|
+
+ assert_int_equal(ret, ENOENT);
|
311
|
+
+
|
312
|
+
+ ret = check_user_in_ncache(ncache, dom2, "parentu");
|
313
|
+
+ assert_int_equal(ret, ENOENT);
|
314
|
+
+ ret = sss_ncache_check_upn(ncache, dom2, "parentu@"TEST_DOM_NAME);
|
315
|
+
+ assert_int_equal(ret, ENOENT);
|
316
|
+
+
|
317
|
+
+ ret = check_user_in_ncache(ncache, dom2, "subdomu");
|
318
|
+
+ assert_int_equal(ret, ENOENT);
|
319
|
+
+ ret = sss_ncache_check_upn(ncache, dom2, "subdomu@sub"TEST_DOM_NAME);
|
320
|
+
+ assert_int_equal(ret, ENOENT);
|
321
|
+
+
|
322
|
+
+ ret = check_user_in_ncache(ncache, dom2, "upn");
|
323
|
+
+ assert_int_equal(ret, ENOENT);
|
324
|
+
+ ret = sss_ncache_check_upn(ncache, dom2, "upn@upn.dom");
|
325
|
+
+ assert_int_equal(ret, ENOENT);
|
326
|
+
+
|
327
|
+
+ ret = check_group_in_ncache(ncache, dom2, "shortgroup");
|
328
|
+
+ assert_int_equal(ret, ENOENT);
|
329
|
+
+
|
330
|
+
+ ret = check_group_in_ncache(ncache, dom2, "parentg");
|
331
|
+
+ assert_int_equal(ret, ENOENT);
|
332
|
+
+
|
333
|
+
+ ret = check_group_in_ncache(ncache, dom2, "subdomg");
|
334
|
+
+ assert_int_equal(ret, ENOENT);
|
335
|
+
+}
|
336
|
+
+
|
337
|
+
+static void test_sss_ncache_short_name_in_domain(void **state)
|
338
|
+
+{
|
339
|
+
+ int ret;
|
340
|
+
+ struct test_state *ts;
|
341
|
+
+ struct tevent_context *ev;
|
342
|
+
+ struct sss_nc_ctx *ncache;
|
343
|
+
+ struct sss_test_ctx *tc;
|
344
|
+
+ struct sss_domain_info *dom;
|
345
|
+
+ struct sss_domain_info *dom2;
|
346
|
+
+ struct sss_domain_info *sub_dom;
|
347
|
+
+
|
348
|
+
+ struct sss_test_conf_param params[] = {
|
349
|
+
+ { "filter_users", "shortuser, parentu@"TEST_DOM_NAME", "
|
350
|
+
+ "subdomu@sub"TEST_DOM_NAME", upn@upn.dom" },
|
351
|
+
+ { "filter_groups", "shortgroup, parentg@"TEST_DOM_NAME", "
|
352
|
+
+ "subdomg@sub"TEST_DOM_NAME },
|
353
|
+
+ { NULL, NULL },
|
354
|
+
+ };
|
355
|
+
+
|
356
|
+
+ const char *nss_filter_users[] = { params[0].value, NULL};
|
357
|
+
+ const char *nss_filter_groups[] = { params[1].value, NULL};
|
358
|
+
+
|
359
|
+
+ ts = talloc_get_type_abort(*state, struct test_state);
|
360
|
+
+
|
361
|
+
+ ev = tevent_context_init(ts);
|
362
|
+
+ assert_non_null(ev);
|
363
|
+
+
|
364
|
+
+ dom = talloc_zero(ts, struct sss_domain_info);
|
365
|
+
+ assert_non_null(dom);
|
366
|
+
+ dom->name = discard_const_p(char, TEST_DOM_NAME);
|
367
|
+
+ sss_domain_set_state(dom, DOM_ACTIVE);
|
368
|
+
+
|
369
|
+
+ ts->nctx = mock_nctx(ts);
|
370
|
+
+ assert_non_null(ts->nctx);
|
371
|
+
+
|
372
|
+
+ tc = create_dom_test_ctx(ts, TESTS_PATH, TEST_CONF_DB,
|
373
|
+
+ TEST_DOM_NAME, TEST_ID_PROVIDER, params);
|
374
|
+
+ assert_non_null(tc);
|
375
|
+
+
|
376
|
+
+ ret = confdb_add_param(tc->confdb, true, "config/domain/"TEST_DOM_NAME,
|
377
|
+
+ "filter_users", nss_filter_users);
|
378
|
+
+ assert_int_equal(ret, EOK);
|
379
|
+
+
|
380
|
+
+ ret = confdb_add_param(tc->confdb, true, "config/domain"TEST_DOM_NAME,
|
381
|
+
+ "filter_groups", nss_filter_groups);
|
382
|
+
+ assert_int_equal(ret, EOK);
|
383
|
+
+
|
384
|
+
+ ncache = ts->ctx;
|
385
|
+
+ ts->rctx = mock_rctx(ts, ev, dom, ts->nctx);
|
386
|
+
+ assert_non_null(ts->rctx);
|
387
|
+
+ ts->rctx->cdb = tc->confdb;
|
388
|
+
+
|
389
|
+
+ ret = sss_names_init(ts, tc->confdb, TEST_DOM_NAME, &dom->names);
|
390
|
+
+ assert_int_equal(ret, EOK);
|
391
|
+
+
|
392
|
+
+ ret = sss_ncache_reset_repopulate_permanent(ts->rctx, ncache);
|
393
|
+
+ assert_int_equal(ret, EOK);
|
394
|
+
+
|
395
|
+
+ /* Add another domain */
|
396
|
+
+ dom2 = talloc_zero(ts, struct sss_domain_info);
|
397
|
+
+ assert_non_null(dom2);
|
398
|
+
+ dom2->name = discard_const_p(char, TEST_DOM_NAME"2");
|
399
|
+
+ sss_domain_set_state(dom2, DOM_ACTIVE);
|
400
|
+
+ dom->next = dom2;
|
401
|
+
+ dom2->names = dom->names;
|
402
|
+
+
|
403
|
+
+ expect_in_parent(ncache, dom);
|
404
|
+
+ expect_no_entries_in_dom(ncache, dom2);
|
405
|
+
+
|
406
|
+
+ ret = sss_ncache_reset_repopulate_permanent(ts->rctx, ncache);
|
407
|
+
+ assert_int_equal(ret, EOK);
|
408
|
+
+
|
409
|
+
+ expect_in_parent(ncache, dom);
|
410
|
+
+ expect_no_entries_in_dom(ncache, dom2);
|
411
|
+
+
|
412
|
+
+ /* Add a sub domain */
|
413
|
+
+ sub_dom = talloc_zero(ts, struct sss_domain_info);
|
414
|
+
+ assert_non_null(sub_dom);
|
415
|
+
+ sub_dom->name = discard_const_p(char, "sub"TEST_DOM_NAME);
|
416
|
+
+ sss_domain_set_state(sub_dom, DOM_ACTIVE);
|
417
|
+
+ sub_dom->parent = dom;
|
418
|
+
+ dom->subdomains = sub_dom;
|
419
|
+
+ sub_dom->names = dom->names;
|
420
|
+
+
|
421
|
+
+ ret = sss_ncache_reset_repopulate_permanent(ts->rctx, ncache);
|
422
|
+
+ assert_int_equal(ret, EOK);
|
423
|
+
+
|
424
|
+
+ expect_in_parent(ncache, dom);
|
425
|
+
+ expect_in_subdomain(ncache, sub_dom);
|
426
|
+
+ expect_no_entries_in_dom(ncache, dom2);
|
427
|
+
+}
|
428
|
+
+
|
429
|
+
static void test_sss_ncache_reset(void **state)
|
430
|
+
{
|
431
|
+
errno_t ret;
|
432
|
+
@@ -1083,6 +1335,8 @@ int main(void)
|
433
|
+
setup, teardown),
|
434
|
+
cmocka_unit_test_setup_teardown(test_sss_ncache_reset_prepopulate,
|
435
|
+
setup, teardown),
|
436
|
+
+ cmocka_unit_test_setup_teardown(test_sss_ncache_short_name_in_domain,
|
437
|
+
+ setup, teardown),
|
438
|
+
cmocka_unit_test_setup_teardown(test_sss_ncache_reset,
|
439
|
+
setup, teardown),
|
440
|
+
cmocka_unit_test_setup_teardown(test_sss_ncache_locate_uid_gid,
|
441
|
+
--
|
442
|
+
2.21.3
|
443
|
+
|
@@ -0,0 +1,154 @@
|
|
1
|
+
From fa4b46e7de7297da3c0e37913eab8cba7f103629 Mon Sep 17 00:00:00 2001
|
2
|
+
From: Sumit Bose <sbose@redhat.com>
|
3
|
+
Date: Fri, 9 Oct 2020 15:26:39 +0200
|
4
|
+
Subject: [PATCH 8/8] negcache: do not use default_domain_suffix
|
5
|
+
|
6
|
+
When splitting the names from the filter_users and filter_groups options
|
7
|
+
do not use the default_domain_suffix because it will hide that the
|
8
|
+
original name is a short name and should be added everywhere.
|
9
|
+
|
10
|
+
Additionally this patch fixes a typo where sss_parse_name() was used
|
11
|
+
instead of sss_parse_name_for_domains().
|
12
|
+
|
13
|
+
Resolves: https://github.com/SSSD/sssd/issues/5238
|
14
|
+
|
15
|
+
Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
|
16
|
+
---
|
17
|
+
src/responder/common/negcache.c | 29 +++++++++++++++--------------
|
18
|
+
src/tests/cmocka/test_negcache.c | 22 ++++++++++++++++++++--
|
19
|
+
2 files changed, 35 insertions(+), 16 deletions(-)
|
20
|
+
|
21
|
+
diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c
|
22
|
+
index 9ee39ce3e..59e8ad7e7 100644
|
23
|
+
--- a/src/responder/common/negcache.c
|
24
|
+
+++ b/src/responder/common/negcache.c
|
25
|
+
@@ -1000,13 +1000,13 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
26
|
+
|
27
|
+
for (i = 0; (filter_list && filter_list[i]); i++) {
|
28
|
+
ret = sss_parse_name_for_domains(tmpctx, domain_list,
|
29
|
+
- rctx->default_domain,
|
30
|
+
+ NULL,
|
31
|
+
filter_list[i],
|
32
|
+
&domainname, &name);
|
33
|
+
if (ret == EAGAIN) {
|
34
|
+
DEBUG(SSSDBG_MINOR_FAILURE,
|
35
|
+
- "cannot add [%s] to negcache because the required or "
|
36
|
+
- "default domain are not known yet\n", filter_list[i]);
|
37
|
+
+ "Can add [%s] only as UPN to negcache because the "
|
38
|
+
+ "required domain is not known yet\n", filter_list[i]);
|
39
|
+
} else if (ret != EOK) {
|
40
|
+
DEBUG(SSSDBG_CRIT_FAILURE,
|
41
|
+
"Invalid name in filterUsers list: [%s] (%d)\n",
|
42
|
+
@@ -1066,12 +1066,12 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
43
|
+
|
44
|
+
for (i = 0; (filter_list && filter_list[i]); i++) {
|
45
|
+
ret = sss_parse_name_for_domains(tmpctx, domain_list,
|
46
|
+
- rctx->default_domain, filter_list[i],
|
47
|
+
+ NULL, filter_list[i],
|
48
|
+
&domainname, &name);
|
49
|
+
if (ret == EAGAIN) {
|
50
|
+
DEBUG(SSSDBG_MINOR_FAILURE,
|
51
|
+
- "Cannot add [%s] to negcache because the required or "
|
52
|
+
- "default domain are not known yet\n", filter_list[i]);
|
53
|
+
+ "Can add [%s] only as UPN to negcache because the "
|
54
|
+
+ "required domain is not known yet\n", filter_list[i]);
|
55
|
+
} else if (ret != EOK) {
|
56
|
+
DEBUG(SSSDBG_CRIT_FAILURE,
|
57
|
+
"Invalid name in filterUsers list: [%s] (%d)\n",
|
58
|
+
@@ -1158,9 +1158,12 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
59
|
+
if (ret != EOK) goto done;
|
60
|
+
|
61
|
+
for (i = 0; (filter_list && filter_list[i]); i++) {
|
62
|
+
- ret = sss_parse_name(tmpctx, dom->names, filter_list[i],
|
63
|
+
- &domainname, &name);
|
64
|
+
+ ret = sss_parse_name_for_domains(tmpctx, domain_list,
|
65
|
+
+ NULL, filter_list[i],
|
66
|
+
+ &domainname, &name);
|
67
|
+
if (ret != EOK) {
|
68
|
+
+ /* Groups do not have UPNs, so domain names, if present,
|
69
|
+
+ * must be known */
|
70
|
+
DEBUG(SSSDBG_CRIT_FAILURE,
|
71
|
+
"Invalid name in filterGroups list: [%s] (%d)\n",
|
72
|
+
filter_list[i], ret);
|
73
|
+
@@ -1207,13 +1210,11 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
|
74
|
+
|
75
|
+
for (i = 0; (filter_list && filter_list[i]); i++) {
|
76
|
+
ret = sss_parse_name_for_domains(tmpctx, domain_list,
|
77
|
+
- rctx->default_domain, filter_list[i],
|
78
|
+
+ NULL, filter_list[i],
|
79
|
+
&domainname, &name);
|
80
|
+
- if (ret == EAGAIN) {
|
81
|
+
- DEBUG(SSSDBG_MINOR_FAILURE,
|
82
|
+
- "Cannot add [%s] to negcache because the required or "
|
83
|
+
- "default domain are not known yet\n", filter_list[i]);
|
84
|
+
- } else if (ret != EOK) {
|
85
|
+
+ if (ret != EOK) {
|
86
|
+
+ /* Groups do not have UPNs, so domain names, if present,
|
87
|
+
+ * must be known */
|
88
|
+
DEBUG(SSSDBG_CRIT_FAILURE,
|
89
|
+
"Invalid name in filterGroups list: [%s] (%d)\n",
|
90
|
+
filter_list[i], ret);
|
91
|
+
diff --git a/src/tests/cmocka/test_negcache.c b/src/tests/cmocka/test_negcache.c
|
92
|
+
index fb306b110..30218d52a 100644
|
93
|
+
--- a/src/tests/cmocka/test_negcache.c
|
94
|
+
+++ b/src/tests/cmocka/test_negcache.c
|
95
|
+
@@ -933,7 +933,9 @@ static void test_sss_ncache_reset_prepopulate(void **state)
|
96
|
+
*
|
97
|
+
* The result should of course be independent of the present domains. To
|
98
|
+
* verify this the domains are added one after the other and the negative
|
99
|
+
- * cache is repopulated each time.
|
100
|
+
+ * cache is repopulated each time. The result should be also independent of
|
101
|
+
+ * the setting of default_domain_suffix option which is tested by
|
102
|
+
+ * test_sss_ncache_short_name_in_domain_with_prefix.
|
103
|
+
*
|
104
|
+
* With the given domains, users and group we have to following expectations:
|
105
|
+
* - the short name entry will be added to the domain and all sub-domains as
|
106
|
+
@@ -1081,7 +1083,8 @@ static void expect_no_entries_in_dom(struct sss_nc_ctx *ncache,
|
107
|
+
assert_int_equal(ret, ENOENT);
|
108
|
+
}
|
109
|
+
|
110
|
+
-static void test_sss_ncache_short_name_in_domain(void **state)
|
111
|
+
+static void run_sss_ncache_short_name_in_domain(void **state,
|
112
|
+
+ bool use_default_domain_prefix)
|
113
|
+
{
|
114
|
+
int ret;
|
115
|
+
struct test_state *ts;
|
116
|
+
@@ -1131,6 +1134,9 @@ static void test_sss_ncache_short_name_in_domain(void **state)
|
117
|
+
ncache = ts->ctx;
|
118
|
+
ts->rctx = mock_rctx(ts, ev, dom, ts->nctx);
|
119
|
+
assert_non_null(ts->rctx);
|
120
|
+
+ if (use_default_domain_prefix) {
|
121
|
+
+ ts->rctx->default_domain = discard_const(TEST_DOM_NAME);
|
122
|
+
+ }
|
123
|
+
ts->rctx->cdb = tc->confdb;
|
124
|
+
|
125
|
+
ret = sss_names_init(ts, tc->confdb, TEST_DOM_NAME, &dom->names);
|
126
|
+
@@ -1173,6 +1179,16 @@ static void test_sss_ncache_short_name_in_domain(void **state)
|
127
|
+
expect_no_entries_in_dom(ncache, dom2);
|
128
|
+
}
|
129
|
+
|
130
|
+
+static void test_sss_ncache_short_name_in_domain(void **state)
|
131
|
+
+{
|
132
|
+
+ run_sss_ncache_short_name_in_domain(state, false);
|
133
|
+
+}
|
134
|
+
+
|
135
|
+
+static void test_sss_ncache_short_name_in_domain_with_prefix(void **state)
|
136
|
+
+{
|
137
|
+
+ run_sss_ncache_short_name_in_domain(state, true);
|
138
|
+
+}
|
139
|
+
+
|
140
|
+
static void test_sss_ncache_reset(void **state)
|
141
|
+
{
|
142
|
+
errno_t ret;
|
143
|
+
@@ -1337,6 +1353,8 @@ int main(void)
|
144
|
+
setup, teardown),
|
145
|
+
cmocka_unit_test_setup_teardown(test_sss_ncache_short_name_in_domain,
|
146
|
+
setup, teardown),
|
147
|
+
+ cmocka_unit_test_setup_teardown(test_sss_ncache_short_name_in_domain_with_prefix,
|
148
|
+
+ setup, teardown),
|
149
|
+
cmocka_unit_test_setup_teardown(test_sss_ncache_reset,
|
150
|
+
setup, teardown),
|
151
|
+
cmocka_unit_test_setup_teardown(test_sss_ncache_locate_uid_gid,
|
152
|
+
--
|
153
|
+
2.21.3
|
154
|
+
|
@@ -26,7 +26,7 @@
|
|
26
26
|
|
27
27
|
Name: sssd
|
28
28
|
Version: 2.4.0
|
29
|
-
Release:
|
29
|
+
Release: 3%{?dist}
|
30
30
|
Group: Applications/System
|
31
31
|
Summary: System Security Services Daemon
|
32
32
|
License: GPLv3+
|
@@ -34,6 +34,14 @@ URL: https://pagure.io/SSSD/sssd/
|
|
34
34
|
Source0: https://releases.pagure.org/SSSD/sssd/%{name}-%{version}.tar.gz
|
35
35
|
|
36
36
|
### Patches ###
|
37
|
+
Patch0001: 0001-SYSDB-merge_res_sysdb_attrs-fixed-to-avoid-NULL-ptr-.patch
|
38
|
+
Patch0002: 0002-KCM-perf-improvements.patch
|
39
|
+
Patch0003: 0003-DEBUG-journal_send-was-made-static.patch
|
40
|
+
Patch0004: 0004-DEBUG-fixes-program-identifier-as-seen-in-syslog.patch
|
41
|
+
Patch0005: 0005-negcache-make-sure-domain-config-does-not-leak-into-.patch
|
42
|
+
Patch0006: 0006-utils-add-SSS_GND_SUBDOMAINS-flag-for-get_next_domai.patch
|
43
|
+
Patch0007: 0007-negcache-make-sure-short-names-are-added-to-sub-doma.patch
|
44
|
+
Patch0008: 0008-negcache-do-not-use-default_domain_suffix.patch
|
37
45
|
|
38
46
|
### Downstream Patches ###
|
39
47
|
|
@@ -1207,6 +1215,12 @@ fi
|
|
1207
1215
|
%{_libdir}/%{name}/modules/libwbclient.so
|
1208
1216
|
|
1209
1217
|
%changelog
|
1218
|
+
* Mon Dec 07 2020 Alexey Tikhonov <atikhono@redhat.com> - 2.4.0-3
|
1219
|
+
- Resolves: rhbz#1900733 - sssd_be segfaults at be_refresh_get_values_ex() due to NULL ptrs in results of sysdb_search_with_ts_attr()
|
1220
|
+
- Resolves: rhbz#1876514 - High CPU utilization by the sssd_kcm process
|
1221
|
+
- Resolves: rhbz#1894540 - sssd component logging is now too generic in syslog/journal
|
1222
|
+
- Resolves: rhbz#1828483 - filtered ID is appearing due to strange negative cache behavior
|
1223
|
+
|
1210
1224
|
* Thu Nov 12 2020 Alexey Tikhonov <atikhono@redhat.com> - 2.4.0-2
|
1211
1225
|
- This is to bump version to allow rebuild against rebased libldb.
|
1212
1226
|
|