smbd: Ensure we grant owner sid in check_parent_access_fsp()
[samba.git] / source4 / kdc / sdb_to_kdb.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 <kdb.h>
26 #include "sdb.h"
27 #include "sdb_kdb.h"
28 #include "kdc/samba_kdc.h"
29 #include "lib/krb5_wrap/krb5_samba.h"
30
31 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_KERBEROS
33
34 static int SDBFlags_to_kflags(const struct SDBFlags *s,
35                               krb5_flags *k)
36 {
37         *k = 0;
38
39         if (s->initial) {
40                 *k |= KRB5_KDB_DISALLOW_TGT_BASED;
41         }
42         /* The forwardable and proxiable flags are set according to client and
43          * server attributes. */
44         if (!s->forwardable) {
45                 *k |= KRB5_KDB_DISALLOW_FORWARDABLE;
46         }
47         if (!s->proxiable) {
48                 *k |= KRB5_KDB_DISALLOW_PROXIABLE;
49         }
50         if (s->renewable) {
51                 ;
52         }
53         if (s->postdate) {
54                 ;
55         }
56         if (s->server) {
57                 ;
58         }
59         if (s->client) {
60                 ;
61         }
62         if (s->invalid) {
63                 *k |= KRB5_KDB_DISALLOW_ALL_TIX;
64         }
65         if (s->require_preauth) {
66                 *k |= KRB5_KDB_REQUIRES_PRE_AUTH;
67         }
68         if (s->change_pw) {
69                 *k |= KRB5_KDB_PWCHANGE_SERVICE;
70         }
71 #if 0
72         /*
73          * Do not set KRB5_KDB_REQUIRES_HW_AUTH as this would tell the client
74          * to enforce hardware authentication. It prevents the use of files
75          * based public key authentication which we use for testing.
76          */
77         if (s->require_hwauth) {
78                 *k |= KRB5_KDB_REQUIRES_HW_AUTH;
79         }
80 #endif
81         if (s->ok_as_delegate) {
82                 *k |= KRB5_KDB_OK_AS_DELEGATE;
83         }
84         if (s->user_to_user) {
85                 ;
86         }
87         if (s->immutable) {
88                 ;
89         }
90         if (s->trusted_for_delegation) {
91                 *k |= KRB5_KDB_OK_TO_AUTH_AS_DELEGATE;
92         }
93         if (s->allow_kerberos4) {
94                 ;
95         }
96         if (s->allow_digest) {
97                 ;
98         }
99         if (s->no_auth_data_reqd) {
100                 *k |= KRB5_KDB_NO_AUTH_DATA_REQUIRED;
101         }
102
103         return 0;
104 }
105
106 static int sdb_event_to_kmod(krb5_context context,
107                              const struct sdb_event *s,
108                              krb5_db_entry *k)
109 {
110         krb5_error_code ret;
111         krb5_principal principal = NULL;
112
113         if (s->principal != NULL) {
114                 ret = krb5_copy_principal(context,
115                                           s->principal,
116                                           &principal);
117                 if (ret != 0) {
118                         return ret;
119                 }
120         }
121
122         ret = krb5_dbe_update_mod_princ_data(context,
123                                              k, s->time,
124                                              principal);
125
126         krb5_free_principal(context, principal);
127
128         return ret;
129 }
130
131 /* sets up salt on the 2nd array position */
132
133 static int sdb_salt_to_krb5_key_data(const struct sdb_salt *s,
134                                      krb5_key_data *k)
135 {
136         switch (s->type) {
137 #if 0
138         /* for now use the special mechanism where the MIT KDC creates the salt
139          * on its own */
140         case 3: /* FIXME KRB5_PW_SALT */
141                 k->key_data_type[1] = KRB5_KDB_SALTTYPE_NORMAL;
142                 break;
143         /*
144         case hdb_afs3_salt:
145                 k->key_data_type[1] = KRB5_KDB_SALTTYPE_AFS3;
146                 break;
147         */
148 #endif
149         default:
150                 k->key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
151                 break;
152         }
153
154         k->key_data_contents[1] = malloc(s->salt.length);
155         if (k->key_data_contents[1] == NULL) {
156                 return ENOMEM;
157         }
158         memcpy(k->key_data_contents[1],
159                s->salt.data,
160                s->salt.length);
161         k->key_data_length[1] = s->salt.length;
162
163         return 0;
164 }
165
166 static int sdb_key_to_krb5_key_data(const struct sdb_key *s,
167                                     int kvno,
168                                     krb5_key_data *k)
169 {
170         int ret = 0;
171
172         ZERO_STRUCTP(k);
173
174         k->key_data_ver = KRB5_KDB_V1_KEY_DATA_ARRAY;
175         k->key_data_kvno = kvno;
176
177         k->key_data_type[0] = KRB5_KEY_TYPE(&s->key);
178         k->key_data_length[0] = KRB5_KEY_LENGTH(&s->key);
179         k->key_data_contents[0] = malloc(k->key_data_length[0]);
180         if (k->key_data_contents[0] == NULL) {
181                 return ENOMEM;
182         }
183
184         memcpy(k->key_data_contents[0],
185                KRB5_KEY_DATA(&s->key),
186                k->key_data_length[0]);
187
188         if (s->salt != NULL) {
189                 ret = sdb_salt_to_krb5_key_data(s->salt, k);
190                 if (ret) {
191                         memset(k->key_data_contents[0], 0, k->key_data_length[0]);
192                         free(k->key_data_contents[0]);
193                 }
194         }
195
196         return ret;
197 }
198
199 static void free_krb5_db_entry(krb5_context context,
200                                krb5_db_entry *k)
201 {
202         krb5_tl_data *tl_data_next = NULL;
203         krb5_tl_data *tl_data = NULL;
204         int i, j;
205
206         if (k == NULL) {
207                 return;
208         }
209
210         krb5_free_principal(context, k->princ);
211
212         for (tl_data = k->tl_data; tl_data; tl_data = tl_data_next) {
213                 tl_data_next = tl_data->tl_data_next;
214                 if (tl_data->tl_data_contents != NULL) {
215                         free(tl_data->tl_data_contents);
216                 }
217                 free(tl_data);
218         }
219
220         if (k->key_data != NULL) {
221                 for (i = 0; i < k->n_key_data; i++) {
222                         for (j = 0; j < k->key_data[i].key_data_ver; j++) {
223                                 if (k->key_data[i].key_data_length[j] != 0) {
224                                         if (k->key_data[i].key_data_contents[j] != NULL) {
225                                                 BURN_PTR_SIZE(k->key_data[i].key_data_contents[j], k->key_data[i].key_data_length[j]);
226                                                 free(k->key_data[i].key_data_contents[j]);
227                                         }
228                                 }
229                                 k->key_data[i].key_data_contents[j] = NULL;
230                                 k->key_data[i].key_data_length[j] = 0;
231                                 k->key_data[i].key_data_type[j] = 0;
232                         }
233                 }
234                 free(k->key_data);
235         }
236
237         ZERO_STRUCTP(k);
238 }
239
240 int sdb_entry_to_krb5_db_entry(krb5_context context,
241                                const struct sdb_entry *s,
242                                krb5_db_entry *k)
243 {
244         struct samba_kdc_entry *ske = s->skdc_entry;
245         krb5_error_code ret;
246         int i;
247
248         ZERO_STRUCTP(k);
249
250         k->magic = KRB5_KDB_MAGIC_NUMBER;
251         k->len = KRB5_KDB_V1_BASE_LENGTH;
252
253         ret = krb5_copy_principal(context,
254                                   s->principal,
255                                   &k->princ);
256         if (ret) {
257                 free_krb5_db_entry(context, k);
258                 return ret;
259         }
260
261         ret = SDBFlags_to_kflags(&s->flags,
262                                  &k->attributes);
263         if (ret) {
264                 free_krb5_db_entry(context, k);
265                 return ret;
266         }
267
268         if (s->max_life != NULL) {
269                 k->max_life = *s->max_life;
270         }
271         if (s->max_renew != NULL) {
272                 k->max_renewable_life = *s->max_renew;
273         }
274         if (s->valid_end != NULL) {
275                 k->expiration = *s->valid_end;
276         }
277         if (s->pw_end != NULL) {
278                 k->pw_expiration = *s->pw_end;
279         }
280
281         /* last_success */
282         /* last_failed */
283         /* fail_auth_count */
284         /* n_tl_data */
285
286         /*
287          * If we leave early when looking up the realm, we do not have all
288          * information about a principal. We need to construct a db entry
289          * with minimal information, so skip this part.
290          */
291         if (s->created_by.time != 0) {
292                 ret = sdb_event_to_kmod(context,
293                                         s->modified_by ? s->modified_by : &s->created_by,
294                                         k);
295                 if (ret) {
296                         free_krb5_db_entry(context, k);
297                         return ret;
298                 }
299         }
300
301         /* FIXME: TODO HDB Extensions */
302
303         /*
304          * Don't copy keys (allow password auth) if s->flags.require_hwauth is
305          * set which translates to UF_SMARTCARD_REQUIRED.
306          */
307         if (s->keys.len > 0 && s->flags.require_hwauth == 0) {
308                 k->key_data = malloc(s->keys.len * sizeof(krb5_key_data));
309                 if (k->key_data == NULL) {
310                         free_krb5_db_entry(context, k);
311                         return ret;
312                 }
313
314                 for (i=0; i < s->keys.len; i++) {
315                         ret = sdb_key_to_krb5_key_data(&s->keys.val[i],
316                                                        s->kvno,
317                                                        &k->key_data[i]);
318                         if (ret) {
319                                 free_krb5_db_entry(context, k);
320                                 return ret;
321                         }
322
323                         k->n_key_data++;
324                 }
325         }
326
327         k->e_data = (void *)ske;
328         if (ske != NULL) {
329                 ske->kdc_entry = k;
330         }
331         return 0;
332 }