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
= calloc(1, sizeof(krb5_db_entry
));
86 kentry
->magic
= KRB5_KDB_MAGIC_NUMBER
;
87 kentry
->len
= KRB5_KDB_V1_BASE_LENGTH
;
88 kentry
->attributes
= KRB5_KDB_DISALLOW_ALL_TIX
;
91 code
= krb5_parse_name(context
, KRB5_KDB_M_NAME
, &kentry
->princ
);
93 code
= krb5_copy_principal(context
, princ
, &kentry
->princ
);
96 krb5_db_free_principal(context
, kentry
);
102 code
= krb5_dbe_update_mod_princ_data(context
, kentry
, now
, kentry
->princ
);
104 krb5_db_free_principal(context
, kentry
);
108 /* Return a dummy key */
109 kentry
->n_key_data
= 1;
110 kentry
->key_data
= calloc(1, sizeof(krb5_key_data
));
112 krb5_db_free_principal(context
, kentry
);
116 key_data
= &kentry
->key_data
[0];
118 key_data
->key_data_ver
= KRB5_KDB_V1_KEY_DATA_ARRAY
;
119 key_data
->key_data_kvno
= 1;
120 key_data
->key_data_type
[0] = ENCTYPE_UNKNOWN
;
122 krb5_db_free_principal(context
, kentry
);
126 *kentry_ptr
= kentry
;
131 static krb5_error_code
ks_create_principal(krb5_context context
,
132 krb5_const_principal princ
,
135 const char *password
,
136 krb5_db_entry
**kentry_ptr
)
138 krb5_error_code code
;
139 krb5_key_data
*key_data
;
141 krb5_db_entry
*kentry
;
145 int enctype
= ENCTYPE_AES256_CTS_HMAC_SHA1_96
;
146 int sts
= KRB5_KDB_SALTTYPE_SPECIAL
;
149 return KRB5_KDB_NOENTRY
;
154 kentry
= calloc(1, sizeof(krb5_db_entry
));
155 if (kentry
== NULL
) {
159 kentry
->magic
= KRB5_KDB_MAGIC_NUMBER
;
160 kentry
->len
= KRB5_KDB_V1_BASE_LENGTH
;
162 if (attributes
> 0) {
163 kentry
->attributes
= attributes
;
167 kentry
->max_life
= max_life
;
170 code
= krb5_copy_principal(context
, princ
, &kentry
->princ
);
172 krb5_db_free_principal(context
, kentry
);
178 code
= krb5_dbe_update_mod_princ_data(context
, kentry
, now
, kentry
->princ
);
180 krb5_db_free_principal(context
, kentry
);
184 code
= mit_samba_generate_salt(&salt
);
186 krb5_db_free_principal(context
, kentry
);
190 if (password
!= NULL
) {
191 pwd
.data
= strdup(password
);
192 pwd
.length
= strlen(password
);
194 /* create a random password */
195 code
= mit_samba_generate_random_password(&pwd
);
197 krb5_db_free_principal(context
, kentry
);
202 code
= krb5_c_string_to_key(context
, enctype
, &pwd
, &salt
, &key
);
205 krb5_db_free_principal(context
, kentry
);
209 kentry
->n_key_data
= 1;
210 kentry
->key_data
= calloc(1, sizeof(krb5_key_data
));
212 krb5_db_free_principal(context
, kentry
);
216 key_data
= &kentry
->key_data
[0];
218 key_data
->key_data_ver
= KRB5_KDB_V1_KEY_DATA_ARRAY
;
219 key_data
->key_data_kvno
= 1;
220 key_data
->key_data_type
[0] = key
.enctype
;
221 key_data
->key_data_length
[0] = key
.length
;
222 key_data
->key_data_contents
[0] = key
.contents
;
223 key_data
->key_data_type
[1] = sts
;
224 key_data
->key_data_length
[1] = salt
.length
;
225 key_data
->key_data_contents
[1] = (krb5_octet
*)salt
.data
;
227 *kentry_ptr
= kentry
;
232 static krb5_error_code
ks_get_admin_principal(krb5_context context
,
233 krb5_const_principal princ
,
234 krb5_db_entry
**kentry_ptr
)
236 krb5_error_code code
= EINVAL
;
238 code
= ks_create_principal(context
,
240 KRB5_KDB_DISALLOW_TGT_BASED
,
248 krb5_error_code
kdb_samba_db_get_principal(krb5_context context
,
249 krb5_const_principal princ
,
251 krb5_db_entry
**kentry
)
253 struct mit_samba_context
*mit_ctx
;
254 krb5_error_code code
;
256 mit_ctx
= ks_get_context(context
);
257 if (mit_ctx
== NULL
) {
258 return KRB5_KDB_DBNOTINITED
;
261 if (ks_is_master_key_principal(context
, princ
)) {
262 return ks_get_master_key_principal(context
, princ
, kentry
);
266 * Fake a kadmin/admin and kadmin/history principal so that kadmindd can
269 if (ks_is_kadmin_admin(context
, princ
) ||
270 ks_is_kadmin_history(context
, princ
)) {
271 return ks_get_admin_principal(context
, princ
, kentry
);
274 code
= ks_get_principal(context
, princ
, kflags
, kentry
);
277 * This restricts the changepw account so it isn't able to request a
278 * service ticket. It also marks the principal as the changepw service.
280 if (ks_is_kadmin_changepw(context
, princ
)) {
281 /* FIXME: shouldn't we also set KRB5_KDB_DISALLOW_TGT_BASED ?
282 * testing showed that setpw kpasswd command fails then on the
283 * server though... */
284 (*kentry
)->attributes
|= KRB5_KDB_PWCHANGE_SERVICE
;
285 (*kentry
)->max_life
= CHANGEPW_LIFETIME
;
291 krb5_error_code
kdb_samba_db_put_principal(krb5_context context
,
292 krb5_db_entry
*entry
,
296 /* NOTE: deferred, samba does not allow the KDC to store
297 * principals for now. We should not return KRB5_KDB_DB_INUSE as this
298 * would result in confusing error messages after password changes. */
302 krb5_error_code
kdb_samba_db_delete_principal(krb5_context context
,
303 krb5_const_principal princ
)
306 /* NOTE: deferred, samba does not allow the KDC to delete
307 * principals for now */
308 return KRB5_KDB_DB_INUSE
;
311 #if KRB5_KDB_API_VERSION == 8
312 krb5_error_code
kdb_samba_db_iterate(krb5_context context
,
314 int (*func
)(krb5_pointer
, krb5_db_entry
*),
315 krb5_pointer func_arg
,
316 krb5_flags iterflags
)
318 krb5_error_code
kdb_samba_db_iterate(krb5_context context
,
320 int (*func
)(krb5_pointer
, krb5_db_entry
*),
321 krb5_pointer func_arg
)
324 struct mit_samba_context
*mit_ctx
;
325 krb5_db_entry
*kentry
= NULL
;
326 krb5_error_code code
;
329 mit_ctx
= ks_get_context(context
);
330 if (mit_ctx
== NULL
) {
331 return KRB5_KDB_DBNOTINITED
;
334 code
= mit_samba_get_firstkey(mit_ctx
, &kentry
);
336 code
= (*func
)(func_arg
, kentry
);
341 code
= mit_samba_get_nextkey(mit_ctx
, &kentry
);
344 if (code
== KRB5_KDB_NOENTRY
) {