Describe implication of upstream ICU-22610
[samba.git] / source4 / kdc / sdb_to_kdb.c
blob7214cbc317e1ba599eb5c938a107eef191987439
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 #undef DBGC_CLASS
32 #define DBGC_CLASS DBGC_KERBEROS
34 static int SDBFlags_to_kflags(const struct SDBFlags *s,
35 krb5_flags *k)
37 *k = 0;
39 if (s->initial) {
40 *k |= KRB5_KDB_DISALLOW_TGT_BASED;
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;
47 if (!s->proxiable) {
48 *k |= KRB5_KDB_DISALLOW_PROXIABLE;
50 if (s->renewable) {
53 if (s->postdate) {
56 if (s->server) {
59 if (s->client) {
62 if (s->invalid) {
63 *k |= KRB5_KDB_DISALLOW_ALL_TIX;
65 if (s->require_preauth) {
66 *k |= KRB5_KDB_REQUIRES_PRE_AUTH;
68 if (s->change_pw) {
69 *k |= KRB5_KDB_PWCHANGE_SERVICE;
71 #if 0
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.
77 if (s->require_hwauth) {
78 *k |= KRB5_KDB_REQUIRES_HW_AUTH;
80 #endif
81 if (s->ok_as_delegate) {
82 *k |= KRB5_KDB_OK_AS_DELEGATE;
84 if (s->user_to_user) {
87 if (s->immutable) {
90 if (s->trusted_for_delegation) {
91 *k |= KRB5_KDB_OK_TO_AUTH_AS_DELEGATE;
93 if (s->allow_kerberos4) {
96 if (s->allow_digest) {
99 if (s->no_auth_data_reqd) {
100 *k |= KRB5_KDB_NO_AUTH_DATA_REQUIRED;
103 return 0;
106 static int sdb_event_to_kmod(krb5_context context,
107 const struct sdb_event *s,
108 krb5_db_entry *k)
110 krb5_error_code ret;
111 krb5_principal principal = NULL;
113 if (s->principal != NULL) {
114 ret = krb5_copy_principal(context,
115 s->principal,
116 &principal);
117 if (ret != 0) {
118 return ret;
122 ret = krb5_dbe_update_mod_princ_data(context,
123 k, s->time,
124 principal);
126 krb5_free_principal(context, principal);
128 return ret;
131 /* sets up salt on the 2nd array position */
133 static int sdb_salt_to_krb5_key_data(const struct sdb_salt *s,
134 krb5_key_data *k)
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;
144 case hdb_afs3_salt:
145 k->key_data_type[1] = KRB5_KDB_SALTTYPE_AFS3;
146 break;
148 #endif
149 default:
150 k->key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
151 break;
154 k->key_data_contents[1] = malloc(s->salt.length);
155 if (k->key_data_contents[1] == NULL) {
156 return ENOMEM;
158 memcpy(k->key_data_contents[1],
159 s->salt.data,
160 s->salt.length);
161 k->key_data_length[1] = s->salt.length;
163 return 0;
166 static int sdb_key_to_krb5_key_data(const struct sdb_key *s,
167 int kvno,
168 krb5_key_data *k)
170 int ret = 0;
172 ZERO_STRUCTP(k);
174 k->key_data_ver = KRB5_KDB_V1_KEY_DATA_ARRAY;
175 k->key_data_kvno = kvno;
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;
184 memcpy(k->key_data_contents[0],
185 KRB5_KEY_DATA(&s->key),
186 k->key_data_length[0]);
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]);
196 return ret;
199 static void free_krb5_db_entry(krb5_context context,
200 krb5_db_entry *k)
202 krb5_tl_data *tl_data_next = NULL;
203 krb5_tl_data *tl_data = NULL;
204 int i, j;
206 if (k == NULL) {
207 return;
210 krb5_free_principal(context, k->princ);
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);
217 free(tl_data);
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]);
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;
234 free(k->key_data);
237 ZERO_STRUCTP(k);
240 int sdb_entry_to_krb5_db_entry(krb5_context context,
241 const struct sdb_entry *s,
242 krb5_db_entry *k)
244 struct samba_kdc_entry *ske = s->skdc_entry;
245 krb5_error_code ret;
246 int i;
248 ZERO_STRUCTP(k);
250 k->magic = KRB5_KDB_MAGIC_NUMBER;
251 k->len = KRB5_KDB_V1_BASE_LENGTH;
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;
261 ret = SDBFlags_to_kflags(&s->flags,
262 &k->attributes);
263 if (ret) {
264 free_krb5_db_entry(context, k);
265 return ret;
268 if (s->max_life != NULL) {
269 k->max_life = *s->max_life;
271 if (s->max_renew != NULL) {
272 k->max_renewable_life = *s->max_renew;
274 if (s->valid_end != NULL) {
275 k->expiration = *s->valid_end;
277 if (s->pw_end != NULL) {
278 k->pw_expiration = *s->pw_end;
281 /* last_success */
282 /* last_failed */
283 /* fail_auth_count */
284 /* n_tl_data */
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.
291 if (s->created_by.time != 0) {
292 ret = sdb_event_to_kmod(context,
293 s->modified_by ? s->modified_by : &s->created_by,
295 if (ret) {
296 free_krb5_db_entry(context, k);
297 return ret;
301 /* FIXME: TODO HDB Extensions */
304 * Don't copy keys (allow password auth) if s->flags.require_hwauth is
305 * set which translates to UF_SMARTCARD_REQUIRED.
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;
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;
323 k->n_key_data++;
327 k->e_data = (void *)ske;
328 if (ske != NULL) {
329 ske->kdc_entry = k;
331 return 0;