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