s4:kdc: Cache user info and resource groups from PACs
[samba.git] / source4 / kdc / sdb_to_hdb.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Database Glue between Samba and the KDC
5
6    Copyright (C) Guenther Deschner <gd@samba.org> 2014
7    Copyright (C) Andreas Schneider <asn@samba.org> 2014
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include <hdb.h>
26 #include "sdb.h"
27 #include "sdb_hdb.h"
28 #include "lib/krb5_wrap/krb5_samba.h"
29 #include "librpc/gen_ndr/security.h"
30 #include "kdc/samba_kdc.h"
31
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_KERBEROS
34
35 static void sdb_flags_to_hdb_flags(const struct SDBFlags *s,
36                                    HDBFlags *h)
37 {
38         SMB_ASSERT(sizeof(struct SDBFlags) == sizeof(HDBFlags));
39
40         h->initial = s->initial;
41         h->forwardable = s->forwardable;
42         h->proxiable = s->proxiable;
43         h->renewable = s->renewable;
44         h->postdate = s->postdate;
45         h->server = s->server;
46         h->client = s->client;
47         h->invalid = s->invalid;
48         h->require_preauth = s->require_preauth;
49         h->change_pw = s->change_pw;
50         h->require_hwauth = s->require_hwauth;
51         h->ok_as_delegate = s->ok_as_delegate;
52         h->user_to_user = s->user_to_user;
53         h->immutable = s->immutable;
54         h->trusted_for_delegation = s->trusted_for_delegation;
55         h->allow_kerberos4 = s->allow_kerberos4;
56         h->allow_digest = s->allow_digest;
57         h->locked_out = s->locked_out;
58         h->require_pwchange = s->require_pwchange;
59         h->materialize = s->materialize;
60         h->virtual_keys = s->virtual_keys;
61         h->virtual = s->virtual;
62         h->synthetic = s->synthetic;
63         h->no_auth_data_reqd = s->no_auth_data_reqd;
64         h->auth_data_reqd = s->auth_data_reqd;
65         h->_unused25 = s->_unused25;
66         h->_unused26 = s->_unused26;
67         h->_unused27 = s->_unused27;
68         h->_unused28 = s->_unused28;
69         h->_unused29 = s->_unused29;
70         h->force_canonicalize = s->force_canonicalize;
71         h->do_not_store = s->do_not_store;
72 }
73
74 static int sdb_salt_to_Salt(const struct sdb_salt *s, Salt *h)
75 {
76         int ret;
77
78         *h = (struct Salt) {};
79
80         h->type = s->type;
81         ret = smb_krb5_copy_data_contents(&h->salt, s->salt.data, s->salt.length);
82         if (ret != 0) {
83                 free_Salt(h);
84                 return ENOMEM;
85         }
86
87         return 0;
88 }
89
90 static int sdb_key_to_Key(const struct sdb_key *s, Key *h)
91 {
92         int rc;
93
94         *h = (struct Key) {};
95
96         h->key.keytype = s->key.keytype;
97         rc = smb_krb5_copy_data_contents(&h->key.keyvalue,
98                                          s->key.keyvalue.data,
99                                          s->key.keyvalue.length);
100         if (rc != 0) {
101                 goto error_nomem;
102         }
103
104         if (s->salt != NULL) {
105                 h->salt = malloc(sizeof(Salt));
106                 if (h->salt == NULL) {
107                         goto error_nomem;
108                 }
109
110                 rc = sdb_salt_to_Salt(s->salt,
111                                       h->salt);
112                 if (rc != 0) {
113                         goto error_nomem;
114                 }
115         }
116
117         return 0;
118
119 error_nomem:
120         free_Key(h);
121         return ENOMEM;
122 }
123
124 static int sdb_keys_to_Keys(const struct sdb_keys *s, Keys *h)
125 {
126         int ret, i;
127
128         *h = (struct Keys) {};
129
130         if (s->val != NULL) {
131                 h->val = malloc(s->len * sizeof(Key));
132                 if (h->val == NULL) {
133                         return ENOMEM;
134                 }
135                 for (i = 0; i < s->len; i++) {
136                         ret = sdb_key_to_Key(&s->val[i],
137                                              &h->val[i]);
138                         if (ret != 0) {
139                                 free_Keys(h);
140                                 return ENOMEM;
141                         }
142
143                         ++h->len;
144                 }
145         }
146
147         return 0;
148 }
149
150 static int sdb_keys_to_HistKeys(krb5_context context,
151                                 const struct sdb_keys *s,
152                                 krb5_kvno kvno,
153                                 hdb_entry *h)
154 {
155         unsigned int i;
156
157         for (i = 0; i < s->len; i++) {
158                 Key k = { 0, };
159                 int ret;
160
161                 ret = sdb_key_to_Key(&s->val[i], &k);
162                 if (ret != 0) {
163                         return ENOMEM;
164                 }
165                 ret = hdb_add_history_key(context, h, kvno, &k);
166                 free_Key(&k);
167                 if (ret != 0) {
168                         return ENOMEM;
169                 }
170         }
171
172         return 0;
173 }
174
175 static int sdb_event_to_Event(krb5_context context,
176                               const struct sdb_event *s, Event *h)
177 {
178         int ret;
179
180         *h = (struct Event) {};
181
182         if (s->principal != NULL) {
183                 ret = krb5_copy_principal(context,
184                                           s->principal,
185                                           &h->principal);
186                 if (ret != 0) {
187                         free_Event(h);
188                         return ret;
189                 }
190         }
191         h->time = s->time;
192
193         return 0;
194 }
195
196 int sdb_entry_to_hdb_entry(krb5_context context,
197                            const struct sdb_entry *s,
198                            hdb_entry *h)
199 {
200         struct samba_kdc_entry *ske = s->skdc_entry;
201         unsigned int i;
202         int rc;
203
204         *h = (hdb_entry) {};
205
206         if (s->principal != NULL) {
207                 rc = krb5_copy_principal(context,
208                                          s->principal,
209                                          &h->principal);
210                 if (rc != 0) {
211                         return rc;
212                 }
213         }
214
215         h->kvno = s->kvno;
216
217         rc = sdb_keys_to_Keys(&s->keys, &h->keys);
218         if (rc != 0) {
219                 goto error;
220         }
221
222         if (h->kvno > 1) {
223                 rc = sdb_keys_to_HistKeys(context,
224                                           &s->old_keys,
225                                           h->kvno - 1,
226                                           h);
227                 if (rc != 0) {
228                         goto error;
229                 }
230         }
231
232         if (h->kvno > 2) {
233                 rc = sdb_keys_to_HistKeys(context,
234                                           &s->older_keys,
235                                           h->kvno - 2,
236                                           h);
237                 if (rc != 0) {
238                         goto error;
239                 }
240         }
241
242         rc = sdb_event_to_Event(context,
243                                  &s->created_by,
244                                  &h->created_by);
245         if (rc != 0) {
246                 goto error;
247         }
248
249         if (s->modified_by) {
250                 h->modified_by = malloc(sizeof(Event));
251                 if (h->modified_by == NULL) {
252                         rc = ENOMEM;
253                         goto error;
254                 }
255
256                 rc = sdb_event_to_Event(context,
257                                          s->modified_by,
258                                          h->modified_by);
259                 if (rc != 0) {
260                         goto error;
261                 }
262         }
263
264         if (s->valid_start != NULL) {
265                 h->valid_start = malloc(sizeof(KerberosTime));
266                 if (h->valid_start == NULL) {
267                         rc = ENOMEM;
268                         goto error;
269                 }
270                 *h->valid_start = *s->valid_start;
271         }
272
273         if (s->valid_end != NULL) {
274                 h->valid_end = malloc(sizeof(KerberosTime));
275                 if (h->valid_end == NULL) {
276                         rc = ENOMEM;
277                         goto error;
278                 }
279                 *h->valid_end = *s->valid_end;
280         }
281
282         if (s->pw_end != NULL) {
283                 h->pw_end = malloc(sizeof(KerberosTime));
284                 if (h->pw_end == NULL) {
285                         rc = ENOMEM;
286                         goto error;
287                 }
288                 *h->pw_end = *s->pw_end;
289         }
290
291         if (s->max_life != NULL) {
292                 h->max_life = malloc(sizeof(*h->max_life));
293                 if (h->max_life == NULL) {
294                         rc = ENOMEM;
295                         goto error;
296                 }
297                 *h->max_life = *s->max_life;
298         }
299
300         if (s->max_renew != NULL) {
301                 h->max_renew = malloc(sizeof(*h->max_renew));
302                 if (h->max_renew == NULL) {
303                         rc = ENOMEM;
304                         goto error;
305                 }
306                 *h->max_renew = *s->max_renew;
307         }
308
309         sdb_flags_to_hdb_flags(&s->flags, &h->flags);
310
311         if (s->etypes != NULL) {
312                 h->etypes = malloc(sizeof(*h->etypes));
313                 if (h->etypes == NULL) {
314                         rc = ENOMEM;
315                         goto error;
316                 }
317
318                 h->etypes->len = s->etypes->len;
319
320                 h->etypes->val = calloc(h->etypes->len, sizeof(int));
321                 if (h->etypes->val == NULL) {
322                         rc = ENOMEM;
323                         goto error;
324                 }
325
326                 for (i = 0; i < h->etypes->len; i++) {
327                         h->etypes->val[i] = s->etypes->val[i];
328                 }
329         }
330
331         if (s->session_etypes != NULL) {
332                 h->session_etypes = malloc(sizeof(*h->session_etypes));
333                 if (h->session_etypes == NULL) {
334                         rc = ENOMEM;
335                         goto error;
336                 }
337
338                 h->session_etypes->len = s->session_etypes->len;
339
340                 h->session_etypes->val = calloc(h->session_etypes->len, sizeof(*h->session_etypes->val));
341                 if (h->session_etypes->val == NULL) {
342                         rc = ENOMEM;
343                         goto error;
344                 }
345
346                 for (i = 0; i < h->session_etypes->len; ++i) {
347                         h->session_etypes->val[i] = s->session_etypes->val[i];
348                 }
349         }
350
351         h->context = ske;
352         if (ske != NULL) {
353                 ske->kdc_entry = h;
354         }
355         return 0;
356 error:
357         free_hdb_entry(h);
358         return rc;
359 }