bf7bd7 import sssd-2.4.0-3.el8

Authored and Committed by centosrcm 4 years ago
    import sssd-2.4.0-3.el8
    
        
SOURCES/0001-SYSDB-merge_res_sysdb_attrs-fixed-to-avoid-NULL-ptr-.patch ADDED
@@ -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
+
SOURCES/0002-KCM-perf-improvements.patch ADDED
@@ -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
+ @@ -28,6 +28,9 @@
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
+ @@ -0,0 +1,308 @@
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
+ @@ -37,12 +37,6 @@
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
+ @@ -51,119 +45,6 @@
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
+ @@ -0,0 +1,144 @@
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
+ @@ -35,15 +35,16 @@
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
+ @@ -22,9 +22,11 @@
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
+ @@ -38,6 +40,7 @@
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
+ @@ -24,6 +24,7 @@
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
+ @@ -33,7 +33,7 @@
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
+ @@ -36,9 +36,14 @@
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
+ @@ -43,6 +43,12 @@
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
+
SOURCES/0003-DEBUG-journal_send-was-made-static.patch ADDED
@@ -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
+
SOURCES/0004-DEBUG-fixes-program-identifier-as-seen-in-syslog.patch ADDED
@@ -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
+
SOURCES/0005-negcache-make-sure-domain-config-does-not-leak-into-.patch ADDED
@@ -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
+
SOURCES/0006-utils-add-SSS_GND_SUBDOMAINS-flag-for-get_next_domai.patch ADDED
@@ -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
+
SOURCES/0007-negcache-make-sure-short-names-are-added-to-sub-doma.patch ADDED
@@ -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
+
SOURCES/0008-negcache-do-not-use-default_domain_suffix.patch ADDED
@@ -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
+
file modified
+15 -1
SPECS/sssd.spec CHANGED
@@ -26,7 +26,7 @@
26
26
27
27
Name: sssd
28
28
Version: 2.4.0
29
- Release: 2%{?dist}
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