librpc: Do not include the ndr_table for libnet_join.idl and libnetapi.idl in the...
[Samba.git] / source4 / kdc / sdb_to_kdb.c
blob1411b0f5f66b462b0da852643d74df6332a351f1
1 /*
2 Unix SMB/CIFS implementation.
4 Database Glue between Samba and the KDC
6 Copyright (C) Guenther Deschner <gd@samba.org> 2014
7 Copyright (C) Andreas Schneider <asn@samba.org> 2014
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.
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.
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/>.
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"
31 static int SDBFlags_to_kflags(const struct SDBFlags *s,
32 krb5_flags *k)
34 *k = 0;
36 if (s->initial) {
37 *k |= KRB5_KDB_DISALLOW_TGT_BASED;
40 * Do not set any disallow rules for forwardable, proxiable,
41 * renewable, postdate and server.
43 * The KDC will take care setting the flags based on the incoming
44 * ticket.
46 if (s->forwardable) {
49 if (s->proxiable) {
52 if (s->renewable) {
55 if (s->postdate) {
58 if (s->server) {
61 if (s->client) {
64 if (s->invalid) {
65 *k |= KRB5_KDB_DISALLOW_ALL_TIX;
67 if (s->require_preauth) {
68 *k |= KRB5_KDB_REQUIRES_PRE_AUTH;
70 if (s->change_pw) {
71 *k |= KRB5_KDB_PWCHANGE_SERVICE;
73 if (s->require_hwauth) {
74 *k |= KRB5_KDB_REQUIRES_HW_AUTH;
76 if (s->ok_as_delegate) {
77 *k |= KRB5_KDB_OK_AS_DELEGATE;
79 if (s->user_to_user) {
82 if (s->immutable) {
85 if (s->trusted_for_delegation) {
86 *k |= KRB5_KDB_OK_TO_AUTH_AS_DELEGATE;
88 if (s->allow_kerberos4) {
91 if (s->allow_digest) {
95 return 0;
98 static int sdb_event_to_kmod(krb5_context context,
99 const struct sdb_event *s,
100 krb5_db_entry *k)
102 krb5_error_code ret;
103 krb5_principal principal = NULL;
105 if (s->principal != NULL) {
106 ret = krb5_copy_principal(context,
107 s->principal,
108 &principal);
109 if (ret != 0) {
110 return ret;
114 ret = krb5_dbe_update_mod_princ_data(context,
115 k, s->time,
116 principal);
118 krb5_free_principal(context, principal);
120 return ret;
123 /* sets up salt on the 2nd array position */
125 static int sdb_salt_to_krb5_key_data(const struct sdb_salt *s,
126 krb5_key_data *k)
128 switch (s->type) {
129 #if 0
130 /* for now use the special mechanism where the MIT KDC creates the salt
131 * on its own */
132 case 3: /* FIXME KRB5_PW_SALT */
133 k->key_data_type[1] = KRB5_KDB_SALTTYPE_NORMAL;
134 break;
136 case hdb_afs3_salt:
137 k->key_data_type[1] = KRB5_KDB_SALTTYPE_AFS3;
138 break;
140 #endif
141 default:
142 k->key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
143 break;
146 k->key_data_contents[1] = malloc(s->salt.length);
147 if (k->key_data_contents[1] == NULL) {
148 return ENOMEM;
150 memcpy(k->key_data_contents[1],
151 s->salt.data,
152 s->salt.length);
153 k->key_data_length[1] = s->salt.length;
155 return 0;
158 static int sdb_key_to_krb5_key_data(const struct sdb_key *s,
159 int kvno,
160 krb5_key_data *k)
162 int ret = 0;
164 ZERO_STRUCTP(k);
166 k->key_data_ver = KRB5_KDB_V1_KEY_DATA_ARRAY;
167 k->key_data_kvno = kvno;
169 k->key_data_type[0] = KRB5_KEY_TYPE(&s->key);
170 k->key_data_length[0] = KRB5_KEY_LENGTH(&s->key);
171 k->key_data_contents[0] = malloc(k->key_data_length[0]);
172 if (k->key_data_contents[0] == NULL) {
173 return ENOMEM;
176 memcpy(k->key_data_contents[0],
177 KRB5_KEY_DATA(&s->key),
178 k->key_data_length[0]);
180 if (s->salt != NULL) {
181 ret = sdb_salt_to_krb5_key_data(s->salt, k);
182 if (ret) {
183 memset(k->key_data_contents[0], 0, k->key_data_length[0]);
184 free(k->key_data_contents[0]);
188 return ret;
191 static void free_krb5_db_entry(krb5_context context,
192 krb5_db_entry *k)
194 krb5_tl_data *tl_data_next = NULL;
195 krb5_tl_data *tl_data = NULL;
196 int i, j;
198 if (k == NULL) {
199 return;
202 krb5_free_principal(context, k->princ);
204 for (tl_data = k->tl_data; tl_data; tl_data = tl_data_next) {
205 tl_data_next = tl_data->tl_data_next;
206 if (tl_data->tl_data_contents != NULL) {
207 free(tl_data->tl_data_contents);
209 free(tl_data);
212 if (k->key_data != NULL) {
213 for (i = 0; i < k->n_key_data; i++) {
214 for (j = 0; j < k->key_data[i].key_data_ver; j++) {
215 if (k->key_data[i].key_data_length[j] != 0) {
216 if (k->key_data[i].key_data_contents[j] != NULL) {
217 memset(k->key_data[i].key_data_contents[j], 0, k->key_data[i].key_data_length[j]);
218 free(k->key_data[i].key_data_contents[j]);
221 k->key_data[i].key_data_contents[j] = NULL;
222 k->key_data[i].key_data_length[j] = 0;
223 k->key_data[i].key_data_type[j] = 0;
226 free(k->key_data);
229 ZERO_STRUCTP(k);
232 static int sdb_entry_ex_to_krb5_db_entry(krb5_context context,
233 const struct sdb_entry *s,
234 krb5_db_entry *k)
236 krb5_error_code ret;
237 int i;
239 k->magic = KRB5_KDB_MAGIC_NUMBER;
240 k->len = KRB5_KDB_V1_BASE_LENGTH;
242 ret = krb5_copy_principal(context,
243 s->principal,
244 &k->princ);
245 if (ret) {
246 free_krb5_db_entry(context, k);
247 return ret;
250 ret = SDBFlags_to_kflags(&s->flags,
251 &k->attributes);
252 if (ret) {
253 free_krb5_db_entry(context, k);
254 return ret;
257 if (s->max_life != NULL) {
258 k->max_life = *s->max_life;
260 if (s->max_renew != NULL) {
261 k->max_renewable_life = *s->max_renew;
263 if (s->valid_end != NULL) {
264 k->expiration = *s->valid_end;
266 if (s->pw_end != NULL) {
267 k->pw_expiration = *s->pw_end;
270 /* last_success */
271 /* last_failed */
272 /* fail_auth_count */
273 /* n_tl_data */
276 * If we leave early when looking up the realm, we do not have all
277 * information about a principal. We need to construct a db entry
278 * with minimal information, so skip this part.
280 if (s->created_by.time != 0) {
281 ret = sdb_event_to_kmod(context,
282 s->modified_by ? s->modified_by : &s->created_by,
284 if (ret) {
285 free_krb5_db_entry(context, k);
286 return ret;
290 /* FIXME: TODO HDB Extensions */
292 if (s->keys.len > 0) {
293 k->key_data = malloc(s->keys.len * sizeof(krb5_key_data));
294 if (k->key_data == NULL) {
295 free_krb5_db_entry(context, k);
296 return ret;
299 for (i=0; i < s->keys.len; i++) {
300 ret = sdb_key_to_krb5_key_data(&s->keys.val[i],
301 s->kvno,
302 &k->key_data[i]);
303 if (ret) {
304 free_krb5_db_entry(context, k);
305 return ret;
308 k->n_key_data++;
312 return 0;
315 static int samba_kdc_kdb_entry_destructor(struct samba_kdc_entry *p)
317 krb5_db_entry *entry_ex = p->entry_ex;
318 krb5_error_code ret;
319 krb5_context context;
321 if (entry_ex->e_data != NULL) {
322 struct samba_kdc_entry *skdc_entry;
324 skdc_entry = talloc_get_type(entry_ex->e_data,
325 struct samba_kdc_entry);
326 talloc_set_destructor(skdc_entry, NULL);
327 entry_ex->e_data = NULL;
330 ret = smb_krb5_init_context_common(&context);
331 if (ret) {
332 DBG_ERR("kerberos init context failed (%s)\n",
333 error_message(ret));
334 return ret;
337 krb5_db_free_principal(context, entry_ex);
338 krb5_free_context(context);
340 return 0;
343 int sdb_entry_ex_to_kdb_entry_ex(krb5_context context,
344 const struct sdb_entry_ex *s,
345 krb5_db_entry *k)
347 ZERO_STRUCTP(k);
349 if (s->ctx != NULL) {
350 struct samba_kdc_entry *skdc_entry;
352 skdc_entry = talloc_get_type(s->ctx, struct samba_kdc_entry);
354 k->e_data = (void *)skdc_entry;
356 talloc_set_destructor(skdc_entry,
357 samba_kdc_kdb_entry_destructor);
360 return sdb_entry_ex_to_krb5_db_entry(context, &s->entry, k);