summaryrefslogtreecommitdiffstats
path: root/src/responder/kcm/kcmsrv_ccache.h
blob: 1061ee2a669a6328ef6db75a37c0f1aa988010f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/*
   SSSD

   KCM Server - the KCM ccache operations

   Copyright (C) Red Hat, 2016

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _KCMSRV_CCACHE_H_
#define _KCMSRV_CCACHE_H_

#include "config.h"

#include <krb5/krb5.h>
#include <uuid/uuid.h>

#include "util/util.h"
#include "util/sss_iobuf.h"
#include "util/util_creds.h"
#include "providers/krb5/krb5_common.h"
#include "responder/kcm/kcmsrv_pvt.h"

#define UUID_BYTES    16
#define UUID_STR_SIZE 37

/* Just to keep the name of the ccache readable */
#define MAX_CC_NUM          99999

/*
 * Credentials are opaque to the KCM server
 *
 * Each ccache has a unique UUID.
 */
struct kcm_cred;

/*
 * An opaque ccache type and its operations
 *
 * Contains zero or some KCM credentials. One credential in the cache
 * is marked as the default one. The client can set and get the default
 * cache (e.g. with kswitch) but one cache is always the default -- we
 * fall back to the one created first.
 *
 * Each cache has a name and a UUID. Heimdal allows the name to be changed,
 * we don't (yet, because the MIT client doesn't allow that either)
 *
 * Each ccache also stores a client principal.
 */
struct kcm_ccache;

/*
 * Create a new KCM ccache owned by mem_ctx on the
 * memory level.
 *
 * When created, the ccache contains no credentials
 */
errno_t kcm_cc_new(TALLOC_CTX *mem_ctx,
                   krb5_context k5c,
                   struct cli_creds *owner,
                   const char *name,
                   krb5_principal princ,
                   struct kcm_ccache **_cc);

/*
 * Duplicate the ccache. Only ccache and credentials are duplicated,
 * but their data are a shallow copy.
 */
struct kcm_ccache *kcm_cc_dup(TALLOC_CTX *mem_ctx,
                              const struct kcm_ccache *cc);

/*
 * Returns true if a client can access a ccache.
 *
 * Note that root can access any ccache */
bool kcm_cc_access(struct kcm_ccache *cc,
                   struct cli_creds *client);

/*
 * Since the kcm_ccache structure is opaque, the kcmsrv_ccache
 * layer contains a number of getsetters to read and write
 * properties of the kcm_ccache structure
 */
const char *kcm_cc_get_name(struct kcm_ccache *cc);
errno_t kcm_cc_get_uuid(struct kcm_ccache *cc, uuid_t _uuid);
krb5_principal kcm_cc_get_client_principal(struct kcm_ccache *cc);
int32_t kcm_cc_get_offset(struct kcm_ccache *cc);

/* Mainly useful for creating a cred structure from a persistent
 * storage
 */
struct kcm_cred *kcm_cred_new(TALLOC_CTX *mem_ctx,
                              uuid_t uuid,
                              struct sss_iobuf *cred_blob);

/* Add a cred to ccache */
errno_t kcm_cc_store_creds(struct kcm_ccache *cc,
                           struct kcm_cred *crd);

/* Set cc header information from sec key and client */
errno_t kcm_cc_set_header(struct kcm_ccache *cc,
                          const char *sec_key,
                          struct cli_creds *client);

krb5_creds **kcm_cc_unmarshal(TALLOC_CTX *mem_ctx,
                              krb5_context krb_context,
                              struct kcm_ccache *cc);

errno_t kcm_cred_get_uuid(struct kcm_cred *crd, uuid_t uuid);

/*
 * At the moment, the credentials are stored without unmarshalling
 * them, just as the clients sends the credentials.
 */
struct sss_iobuf *kcm_cred_get_creds(struct kcm_cred *crd);
errno_t kcm_cc_store_cred_blob(struct kcm_ccache *cc,
                               struct sss_iobuf *cred_blob);
 /*
 * The KCM server can call kcm_cred_get_creds to fetch the first
 * credential, then iterate over the credentials with
 * kcm_cc_next_cred until it returns NULL
 */
struct kcm_cred *kcm_cc_get_cred(struct kcm_ccache *cc);
struct kcm_cred *kcm_cc_next_cred(struct kcm_cred *crd);

/* An opaque database that contains all the ccaches */
struct kcm_ccdb;

/*
 * Initialize a ccache database of type cc_be
 */
struct kcm_ccdb *kcm_ccdb_init(TALLOC_CTX *mem_ctx,
                               struct tevent_context *ev,
                               struct confdb_ctx *cdb,
                               const char *confdb_service_path,
                               enum kcm_ccdb_be cc_be);
/*
 * Prepare KCM ccache list for renewals
 */
errno_t kcm_ccdb_renew_tgts(TALLOC_CTX *mem_ctx,
                            struct krb5_ctx *kctx,
                            struct tevent_context *ev,
                            struct kcm_ccdb *cdb,
                            struct kcm_ccache ***_cc_list);

/*
 * In KCM, each ccache name is usually in the form of "UID:<num>
 *
 * The <num> is generated by the KCM ccache database. Use this function
 * to retrieve the next number
 */
struct tevent_req *kcm_ccdb_nextid_send(TALLOC_CTX *mem_ctx,
                                        struct tevent_context *ev,
                                        struct kcm_ccdb *db,
                                        struct cli_creds *client);
errno_t kcm_ccdb_nextid_recv(struct tevent_req *req,
                             TALLOC_CTX *mem_ctx,
                             char **_nextid);

/*
 * List all ccaches that belong to a given client
 *
 * The cc_list the recv function returns is NULL-terminated.
 *
 * NOTE: Contrary to how Heimdal behaves, root CAN NOT list all ccaches
 * of all users. This is a deliberate decision to treat root as any other
 * user, except it can access a ccache of another user by name, just not
 * list them.
 *
 * If a client has no ccaches, the function returns OK, but an empty list
 * containing just the NULL sentinel.
 */
struct tevent_req *kcm_ccdb_list_send(TALLOC_CTX *mem_ctx,
                                      struct tevent_context *ev,
                                      struct kcm_ccdb *db,
                                      struct cli_creds *client);
errno_t kcm_ccdb_list_recv(struct tevent_req *req,
                           TALLOC_CTX *mem_ctx,
                           uuid_t **_uuid_list);

/*
 * Retrieve a ccache by name.
 *
 * If there is no such ccache, return EOK, but a NULL _cc pointer
 */
struct tevent_req *kcm_ccdb_getbyname_send(TALLOC_CTX *mem_ctx,
                                           struct tevent_context *ev,
                                           struct kcm_ccdb *db,
                                           struct cli_creds *client,
                                           const char *name);
errno_t kcm_ccdb_getbyname_recv(struct tevent_req *req,
                                TALLOC_CTX *mem_ctx,
                                struct kcm_ccache **_cc);

/*
 * Retrieve a ccache by UUID
 *
 * If there is no such ccache, return EOK, but a NULL _cc pointer
 */
struct tevent_req *kcm_ccdb_getbyuuid_send(TALLOC_CTX *mem_ctx,
                                           struct tevent_context *ev,
                                           struct kcm_ccdb *db,
                                           struct cli_creds *client,
                                           uuid_t uuid);
errno_t kcm_ccdb_getbyuuid_recv(struct tevent_req *req,
                                TALLOC_CTX *mem_ctx,
                                struct kcm_ccache **_cc);

/*
 * Retrieve the default ccache. If there is no default cache,
 * return EOK, but a NULL UUID.
 */
struct tevent_req *kcm_ccdb_get_default_send(TALLOC_CTX *mem_ctx,
                                             struct tevent_context *ev,
                                             struct kcm_ccdb *db,
                                             struct cli_creds *client);
errno_t kcm_ccdb_get_default_recv(struct tevent_req *req,
                                  uuid_t *uuid);

/*
 * Translating name to UUID is often considerably faster than doing a full
 * CC retrieval, hence this function and the converse. If the UUID cannot
 * be found in the database, return ERR_KCM_CC_END
 */
struct tevent_req *kcm_ccdb_name_by_uuid_send(TALLOC_CTX *mem_ctx,
                                              struct tevent_context *ev,
                                              struct kcm_ccdb *db,
                                              struct cli_creds *client,
                                              uuid_t uuid);
errno_t kcm_ccdb_name_by_uuid_recv(struct tevent_req *req,
                                   TALLOC_CTX *mem_ctx,
                                   const char **_name);

/*
 * Translating UUID to name is often considerably faster than doing a full
 * CC retrieval, hence this function and the converse. If the UUID cannot
 * be found in the database, return ERR_KCM_CC_END
 */
struct tevent_req *kcm_ccdb_uuid_by_name_send(TALLOC_CTX *mem_ctx,
                                              struct tevent_context *ev,
                                              struct kcm_ccdb *db,
                                              struct cli_creds *client,
                                              const char *name);
errno_t kcm_ccdb_uuid_by_name_recv(struct tevent_req *req,
                                   TALLOC_CTX *mem_ctx,
                                   uuid_t _uuid);

/*
 * Set the default ccache. Passing a NULL UUID is a legal operation
 * that 'unsets' the default ccache.
 */
struct tevent_req *kcm_ccdb_set_default_send(TALLOC_CTX *mem_ctx,
                                             struct tevent_context *ev,
                                             struct kcm_ccdb *db,
                                             struct cli_creds *client,
                                             uuid_t uuid);
errno_t kcm_ccdb_set_default_recv(struct tevent_req *req);

/*
 * Add a ccache to the database.
 */
struct tevent_req *kcm_ccdb_create_cc_send(TALLOC_CTX *mem_ctx,
                                           struct tevent_context *ev,
                                           struct kcm_ccdb *db,
                                           struct cli_creds *client,
                                           struct kcm_ccache *cc);
errno_t kcm_ccdb_create_cc_recv(struct tevent_req *req);

/*
 * Modify cache properties in a db
 */
struct kcm_mod_ctx {
    int32_t kdc_offset;
    krb5_principal client;
    /* More settable properties (like name, when we support renames
     * will be added later
     */
};

struct kcm_mod_ctx *kcm_mod_ctx_new(TALLOC_CTX *mem_ctx);
errno_t kcm_mod_cc(struct kcm_ccache *cc, struct kcm_mod_ctx *mod_ctx);

struct tevent_req *kcm_ccdb_mod_cc_send(TALLOC_CTX *mem_ctx,
                                        struct tevent_context *ev,
                                        struct kcm_ccdb *db,
                                        struct cli_creds *client,
                                        uuid_t uuid,
                                        struct kcm_mod_ctx *mod_cc);
errno_t kcm_ccdb_mod_cc_recv(struct tevent_req *req);

/*
 * Store a credential in a cache
 */
struct tevent_req *kcm_ccdb_store_cred_blob_send(TALLOC_CTX *mem_ctx,
                                                 struct tevent_context *ev,
                                                 struct kcm_ccdb *db,
                                                 struct cli_creds *client,
                                                 uuid_t uuid,
                                                 struct sss_iobuf *cred_blob);
errno_t kcm_ccdb_store_cred_blob_recv(struct tevent_req *req);

/*
 * Delete a ccache from the database
 */
struct tevent_req *kcm_ccdb_delete_cc_send(TALLOC_CTX *mem_ctx,
                                           struct tevent_context *ev,
                                           struct kcm_ccdb *db,
                                           struct cli_creds *client,
                                           uuid_t uuid);
errno_t kcm_ccdb_delete_cc_recv(struct tevent_req *req);

void kcm_debug_uuid(uuid_t uuid);

/*
 * The KCM clients are not allowed (except root) to create ccaches
 * with arbitrary names. Instead, we assert that the ccache name
 * begins with UID where UID is the stringified representation of
 * the client's UID number
 */
errno_t kcm_check_name(const char *name, struct cli_creds *client);

/*
 * ccahe marshalling to and from JSON. This is used when the ccaches
 * are stored in the secrets store
 */

/*
 * The secrets store is a key-value store at heart. We store the UUID
 * and the name in the key to allow easy lookups be either key
 */
bool sec_key_match_name(const char *sec_key,
                        const char *name);

bool sec_key_match_uuid(const char *sec_key,
                        uuid_t uuid);

errno_t sec_key_parse(TALLOC_CTX *mem_ctx,
                      const char *sec_key,
                      const char **_name,
                      uuid_t uuid);

const char *sec_key_get_name(const char *sec_key);

errno_t sec_key_get_uuid(const char *sec_key,
                         uuid_t uuid);

const char *sec_key_create(TALLOC_CTX *mem_ctx,
                           const char *name,
                           uuid_t uuid);

/*
 * sec_key is a concatenation of the ccache's UUID and name
 * sec_value is the binary representation of ccache.
 */
errno_t sec_kv_to_ccache_binary(TALLOC_CTX *mem_ctx,
                                const char *sec_key,
                                struct sss_iobuf *sec_value,
                                struct cli_creds *client,
                                struct kcm_ccache **_cc);

/* Convert a kcm_ccache to its binary representation. */
errno_t kcm_ccache_to_sec_input_binary(TALLOC_CTX *mem_ctx,
                                       struct kcm_ccache *cc,
                                       struct sss_iobuf **_payload);

errno_t bin_to_krb_data(TALLOC_CTX *mem_ctx,
                        struct sss_iobuf *buf,
                        krb5_data *out);
#endif /* _KCMSRV_CCACHE_H_ */