2 Unix SMB/CIFS implementation.
4 Samba KDB plugin for MIT Kerberos
6 Copyright (c) 2010 Simo Sorce <idra@samba.org>.
7 Copyright (c) 2014 Andreas Schneider <asn@samba.org>
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.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "system/kerberos.h"
30 #include "kdc/mit_samba.h"
31 #include "kdb_samba.h"
33 #define ADMIN_LIFETIME 60*60*3 /* 3 hours */
34 #define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
36 static krb5_error_code
ks_get_principal(krb5_context context
,
37 krb5_const_principal principal
,
39 krb5_db_entry
**kentry
)
41 struct mit_samba_context
*mit_ctx
;
44 mit_ctx
= ks_get_context(context
);
45 if (mit_ctx
== NULL
) {
46 return KRB5_KDB_DBNOTINITED
;
49 code
= mit_samba_get_principal(mit_ctx
,
62 static krb5_boolean
ks_is_master_key_principal(krb5_context context
,
63 krb5_const_principal princ
)
65 return krb5_princ_size(context
, princ
) == 2 &&
66 ks_data_eq_string(princ
->data
[0], "K") &&
67 ks_data_eq_string(princ
->data
[1], "M");
70 static krb5_error_code
ks_get_master_key_principal(krb5_context context
,
71 krb5_const_principal princ
,
72 krb5_db_entry
**kentry_ptr
)
75 krb5_key_data
*key_data
;
77 krb5_db_entry
*kentry
;
81 kentry
= malloc(sizeof(krb5_db_entry
));
88 kentry
->magic
= KRB5_KDB_MAGIC_NUMBER
;
89 kentry
->len
= KRB5_KDB_V1_BASE_LENGTH
;
90 kentry
->attributes
= KRB5_KDB_DISALLOW_ALL_TIX
;
93 code
= krb5_parse_name(context
, KRB5_KDB_M_NAME
, &kentry
->princ
);
95 code
= krb5_copy_principal(context
, princ
, &kentry
->princ
);
98 ks_free_krb5_db_entry(context
, kentry
);
104 code
= krb5_dbe_update_mod_princ_data(context
, kentry
, now
, kentry
->princ
);
106 ks_free_krb5_db_entry(context
, kentry
);
110 /* Return a dummy key */
111 kentry
->n_key_data
= 1;
112 kentry
->key_data
= calloc(1, sizeof(krb5_key_data
));
114 ks_free_krb5_db_entry(context
, kentry
);
118 key_data
= &kentry
->key_data
[0];
120 key_data
->key_data_ver
= KRB5_KDB_V1_KEY_DATA_ARRAY
;
121 key_data
->key_data_kvno
= 1;
122 key_data
->key_data_type
[0] = ENCTYPE_UNKNOWN
;
124 ks_free_krb5_db_entry(context
, kentry
);
128 *kentry_ptr
= kentry
;
133 static krb5_error_code
ks_create_principal(krb5_context context
,
134 krb5_const_principal princ
,
137 const char *password
,
138 krb5_db_entry
**kentry_ptr
)
140 krb5_error_code code
;
141 krb5_key_data
*key_data
;
143 krb5_db_entry
*kentry
;
147 int enctype
= ENCTYPE_AES256_CTS_HMAC_SHA1_96
;
148 int sts
= KRB5_KDB_SALTTYPE_SPECIAL
;
151 return KRB5_KDB_NOENTRY
;
156 kentry
= calloc(1, sizeof(krb5_db_entry
));
157 if (kentry
== NULL
) {
161 ZERO_STRUCTP(kentry
);
163 kentry
->magic
= KRB5_KDB_MAGIC_NUMBER
;
164 kentry
->len
= KRB5_KDB_V1_BASE_LENGTH
;
166 if (attributes
> 0) {
167 kentry
->attributes
= attributes
;
171 kentry
->max_life
= max_life
;
174 code
= krb5_copy_principal(context
, princ
, &kentry
->princ
);
176 ks_free_krb5_db_entry(context
, kentry
);
182 code
= krb5_dbe_update_mod_princ_data(context
, kentry
, now
, kentry
->princ
);
184 ks_free_krb5_db_entry(context
, kentry
);
188 code
= mit_samba_generate_salt(&salt
);
190 ks_free_krb5_db_entry(context
, kentry
);
194 if (password
!= NULL
) {
195 pwd
.data
= strdup(password
);
196 pwd
.length
= strlen(password
);
198 /* create a random password */
199 code
= mit_samba_generate_random_password(&pwd
);
201 ks_free_krb5_db_entry(context
, kentry
);
206 code
= krb5_c_string_to_key(context
, enctype
, &pwd
, &salt
, &key
);
209 ks_free_krb5_db_entry(context
, kentry
);
213 kentry
->n_key_data
= 1;
214 kentry
->key_data
= calloc(1, sizeof(krb5_key_data
));
216 ks_free_krb5_db_entry(context
, kentry
);
220 key_data
= &kentry
->key_data
[0];
222 key_data
->key_data_ver
= KRB5_KDB_V1_KEY_DATA_ARRAY
;
223 key_data
->key_data_kvno
= 1;
224 key_data
->key_data_type
[0] = key
.enctype
;
225 key_data
->key_data_length
[0] = key
.length
;
226 key_data
->key_data_contents
[0] = key
.contents
;
227 key_data
->key_data_type
[1] = sts
;
228 key_data
->key_data_length
[1] = salt
.length
;
229 key_data
->key_data_contents
[1] = (krb5_octet
*)salt
.data
;
231 *kentry_ptr
= kentry
;
236 static krb5_error_code
ks_get_admin_principal(krb5_context context
,
237 krb5_const_principal princ
,
238 krb5_db_entry
**kentry_ptr
)
240 krb5_error_code code
= EINVAL
;
242 code
= ks_create_principal(context
,
244 KRB5_KDB_DISALLOW_TGT_BASED
,
252 krb5_error_code
kdb_samba_db_get_principal(krb5_context context
,
253 krb5_const_principal princ
,
255 krb5_db_entry
**kentry
)
257 struct mit_samba_context
*mit_ctx
;
258 krb5_error_code code
;
260 mit_ctx
= ks_get_context(context
);
261 if (mit_ctx
== NULL
) {
262 return KRB5_KDB_DBNOTINITED
;
265 if (ks_is_master_key_principal(context
, princ
)) {
266 return ks_get_master_key_principal(context
, princ
, kentry
);
270 * Fake a kadmin/admin and kadmin/history principal so that kadmindd can
273 if (ks_is_kadmin_admin(context
, princ
) ||
274 ks_is_kadmin_history(context
, princ
)) {
275 return ks_get_admin_principal(context
, princ
, kentry
);
278 code
= ks_get_principal(context
, princ
, kflags
, kentry
);
283 void kdb_samba_db_free_principal(krb5_context context
,
284 krb5_db_entry
*entry
)
286 struct mit_samba_context
*mit_ctx
;
288 mit_ctx
= ks_get_context(context
);
289 if (mit_ctx
== NULL
) {
293 ks_free_krb5_db_entry(context
, entry
);
296 krb5_error_code
kdb_samba_db_put_principal(krb5_context context
,
297 krb5_db_entry
*entry
,
301 /* NOTE: deferred, samba does not allow the KDC to store
302 * principals for now. We should not return KRB5_KDB_DB_INUSE as this
303 * would result in confusing error messages after password changes. */
307 krb5_error_code
kdb_samba_db_delete_principal(krb5_context context
,
308 krb5_const_principal princ
)
311 /* NOTE: deferred, samba does not allow the KDC to delete
312 * principals for now */
313 return KRB5_KDB_DB_INUSE
;
316 krb5_error_code
kdb_samba_db_iterate(krb5_context context
,
318 int (*func
)(krb5_pointer
, krb5_db_entry
*),
319 krb5_pointer func_arg
)
321 struct mit_samba_context
*mit_ctx
;
322 krb5_db_entry
*kentry
= NULL
;
323 krb5_error_code code
;
326 mit_ctx
= ks_get_context(context
);
327 if (mit_ctx
== NULL
) {
328 return KRB5_KDB_DBNOTINITED
;
331 code
= mit_samba_get_firstkey(mit_ctx
, &kentry
);
333 code
= (*func
)(func_arg
, kentry
);
338 code
= mit_samba_get_nextkey(mit_ctx
, &kentry
);
341 if (code
== KRB5_KDB_NOENTRY
) {