Line data Source code
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 92 : static int SDBFlags_to_kflags(const struct SDBFlags *s,
35 : krb5_flags *k)
36 : {
37 92 : *k = 0;
38 :
39 92 : if (s->initial) {
40 0 : *k |= KRB5_KDB_DISALLOW_TGT_BASED;
41 : }
42 : /* The forwardable and proxiable flags are set according to client and
43 : * server attributes. */
44 92 : if (!s->forwardable) {
45 0 : *k |= KRB5_KDB_DISALLOW_FORWARDABLE;
46 : }
47 92 : if (!s->proxiable) {
48 0 : *k |= KRB5_KDB_DISALLOW_PROXIABLE;
49 : }
50 92 : if (s->renewable) {
51 : ;
52 : }
53 92 : if (s->postdate) {
54 : ;
55 : }
56 92 : if (s->server) {
57 : ;
58 : }
59 92 : if (s->client) {
60 : ;
61 : }
62 92 : if (s->invalid) {
63 0 : *k |= KRB5_KDB_DISALLOW_ALL_TIX;
64 : }
65 92 : if (s->require_preauth) {
66 92 : *k |= KRB5_KDB_REQUIRES_PRE_AUTH;
67 : }
68 92 : if (s->change_pw) {
69 92 : *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 92 : if (s->ok_as_delegate) {
82 92 : *k |= KRB5_KDB_OK_AS_DELEGATE;
83 : }
84 92 : if (s->user_to_user) {
85 : ;
86 : }
87 92 : if (s->immutable) {
88 : ;
89 : }
90 92 : if (s->trusted_for_delegation) {
91 0 : *k |= KRB5_KDB_OK_TO_AUTH_AS_DELEGATE;
92 : }
93 92 : if (s->allow_kerberos4) {
94 : ;
95 : }
96 92 : if (s->allow_digest) {
97 : ;
98 : }
99 92 : if (s->no_auth_data_reqd) {
100 0 : *k |= KRB5_KDB_NO_AUTH_DATA_REQUIRED;
101 : }
102 :
103 92 : return 0;
104 : }
105 :
106 92 : 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 92 : krb5_principal principal = NULL;
112 :
113 92 : if (s->principal != NULL) {
114 92 : ret = krb5_copy_principal(context,
115 92 : s->principal,
116 : &principal);
117 92 : if (ret != 0) {
118 0 : return ret;
119 : }
120 : }
121 :
122 92 : ret = krb5_dbe_update_mod_princ_data(context,
123 92 : k, s->time,
124 : principal);
125 :
126 92 : krb5_free_principal(context, principal);
127 :
128 92 : return ret;
129 : }
130 :
131 : /* sets up salt on the 2nd array position */
132 :
133 176 : static int sdb_salt_to_krb5_key_data(const struct sdb_salt *s,
134 : krb5_key_data *k)
135 : {
136 176 : 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 176 : k->key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
151 176 : break;
152 : }
153 :
154 176 : k->key_data_contents[1] = malloc(s->salt.length);
155 176 : if (k->key_data_contents[1] == NULL) {
156 0 : return ENOMEM;
157 : }
158 176 : memcpy(k->key_data_contents[1],
159 176 : s->salt.data,
160 176 : s->salt.length);
161 176 : k->key_data_length[1] = s->salt.length;
162 :
163 176 : return 0;
164 : }
165 :
166 268 : static int sdb_key_to_krb5_key_data(const struct sdb_key *s,
167 : int kvno,
168 : krb5_key_data *k)
169 : {
170 268 : int ret = 0;
171 :
172 268 : ZERO_STRUCTP(k);
173 :
174 268 : k->key_data_ver = KRB5_KDB_V1_KEY_DATA_ARRAY;
175 268 : k->key_data_kvno = kvno;
176 :
177 268 : k->key_data_type[0] = KRB5_KEY_TYPE(&s->key);
178 268 : k->key_data_length[0] = KRB5_KEY_LENGTH(&s->key);
179 268 : k->key_data_contents[0] = malloc(k->key_data_length[0]);
180 268 : if (k->key_data_contents[0] == NULL) {
181 0 : return ENOMEM;
182 : }
183 :
184 268 : memcpy(k->key_data_contents[0],
185 268 : KRB5_KEY_DATA(&s->key),
186 268 : k->key_data_length[0]);
187 :
188 268 : if (s->salt != NULL) {
189 176 : ret = sdb_salt_to_krb5_key_data(s->salt, k);
190 176 : if (ret) {
191 0 : memset(k->key_data_contents[0], 0, k->key_data_length[0]);
192 0 : free(k->key_data_contents[0]);
193 : }
194 : }
195 :
196 268 : return ret;
197 : }
198 :
199 0 : static void free_krb5_db_entry(krb5_context context,
200 : krb5_db_entry *k)
201 : {
202 0 : krb5_tl_data *tl_data_next = NULL;
203 0 : krb5_tl_data *tl_data = NULL;
204 : int i, j;
205 :
206 0 : if (k == NULL) {
207 0 : return;
208 : }
209 :
210 0 : krb5_free_principal(context, k->princ);
211 :
212 0 : for (tl_data = k->tl_data; tl_data; tl_data = tl_data_next) {
213 0 : tl_data_next = tl_data->tl_data_next;
214 0 : if (tl_data->tl_data_contents != NULL) {
215 0 : free(tl_data->tl_data_contents);
216 : }
217 0 : free(tl_data);
218 : }
219 :
220 0 : if (k->key_data != NULL) {
221 0 : for (i = 0; i < k->n_key_data; i++) {
222 0 : for (j = 0; j < k->key_data[i].key_data_ver; j++) {
223 0 : if (k->key_data[i].key_data_length[j] != 0) {
224 0 : if (k->key_data[i].key_data_contents[j] != NULL) {
225 0 : BURN_PTR_SIZE(k->key_data[i].key_data_contents[j], k->key_data[i].key_data_length[j]);
226 0 : free(k->key_data[i].key_data_contents[j]);
227 : }
228 : }
229 0 : k->key_data[i].key_data_contents[j] = NULL;
230 0 : k->key_data[i].key_data_length[j] = 0;
231 0 : k->key_data[i].key_data_type[j] = 0;
232 : }
233 : }
234 0 : free(k->key_data);
235 : }
236 :
237 0 : ZERO_STRUCTP(k);
238 : }
239 :
240 92 : int sdb_entry_to_krb5_db_entry(krb5_context context,
241 : const struct sdb_entry *s,
242 : krb5_db_entry *k)
243 : {
244 92 : struct samba_kdc_entry *ske = s->skdc_entry;
245 : krb5_error_code ret;
246 : int i;
247 :
248 92 : ZERO_STRUCTP(k);
249 :
250 92 : k->magic = KRB5_KDB_MAGIC_NUMBER;
251 92 : k->len = KRB5_KDB_V1_BASE_LENGTH;
252 :
253 92 : ret = krb5_copy_principal(context,
254 92 : s->principal,
255 : &k->princ);
256 92 : if (ret) {
257 0 : free_krb5_db_entry(context, k);
258 0 : return ret;
259 : }
260 :
261 92 : ret = SDBFlags_to_kflags(&s->flags,
262 : &k->attributes);
263 92 : if (ret) {
264 0 : free_krb5_db_entry(context, k);
265 0 : return ret;
266 : }
267 :
268 92 : if (s->max_life != NULL) {
269 92 : k->max_life = *s->max_life;
270 : }
271 92 : if (s->max_renew != NULL) {
272 92 : k->max_renewable_life = *s->max_renew;
273 : }
274 92 : if (s->valid_end != NULL) {
275 0 : k->expiration = *s->valid_end;
276 : }
277 92 : if (s->pw_end != NULL) {
278 0 : 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 92 : if (s->created_by.time != 0) {
292 92 : ret = sdb_event_to_kmod(context,
293 92 : s->modified_by ? s->modified_by : &s->created_by,
294 : k);
295 92 : if (ret) {
296 0 : free_krb5_db_entry(context, k);
297 0 : 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 92 : if (s->keys.len > 0 && s->flags.require_hwauth == 0) {
308 92 : k->key_data = malloc(s->keys.len * sizeof(krb5_key_data));
309 92 : if (k->key_data == NULL) {
310 0 : free_krb5_db_entry(context, k);
311 0 : return ret;
312 : }
313 :
314 360 : for (i=0; i < s->keys.len; i++) {
315 268 : ret = sdb_key_to_krb5_key_data(&s->keys.val[i],
316 268 : s->kvno,
317 268 : &k->key_data[i]);
318 268 : if (ret) {
319 0 : free_krb5_db_entry(context, k);
320 0 : return ret;
321 : }
322 :
323 268 : k->n_key_data++;
324 : }
325 : }
326 :
327 92 : k->e_data = (void *)ske;
328 92 : if (ske != NULL) {
329 92 : ske->kdc_entry = k;
330 : }
331 92 : return 0;
332 : }
|