1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* plugins/kdb/hdb/kdb_marshal.c */
4 * Copyright 2009 by the Massachusetts Institute of Technology.
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
41 kh_free_Principal(krb5_context context,
44 kh_db_context *kh = KH_DB_CONTEXT(context);
46 if (principal != NULL)
47 (*kh->heim_free_principal)(kh->hcontext, principal);
51 kh_free_Event(krb5_context context,
54 kh_free_Principal(context, event->principal);
58 kh_free_HostAddresses(krb5_context context,
61 kh_db_context *kh = KH_DB_CONTEXT(context);
64 (*kh->heim_free_addresses)(kh->hcontext, addrs);
68 static krb5_error_code
69 kh_marshal_octet_string(krb5_context context,
70 const krb5_data *in_data,
71 heim_octet_string *out_data)
73 out_data->data = malloc(in_data->length);
74 if (out_data->data == NULL)
77 memcpy(out_data->data, in_data->data, in_data->length);
79 out_data->length = in_data->length;
84 static krb5_error_code
85 kh_unmarshal_octet_string_contents(krb5_context context,
86 const heim_octet_string *in_data,
89 out_data->magic = KV5M_DATA;
90 out_data->data = malloc(in_data->length);
91 if (out_data->data == NULL)
94 memcpy(out_data->data, in_data->data, in_data->length);
96 out_data->length = in_data->length;
101 static krb5_error_code
102 kh_unmarshal_octet_string(krb5_context context,
103 heim_octet_string *in_data,
104 krb5_data **out_data)
106 krb5_error_code code;
108 *out_data = k5alloc(sizeof(krb5_data), &code);
112 code = kh_unmarshal_octet_string_contents(context, in_data, *out_data);
123 static krb5_error_code
124 kh_marshal_general_string(krb5_context context,
125 const krb5_data *in_data,
126 heim_general_string *out_str)
128 *out_str = malloc(in_data->length + 1);
129 if (*out_str == NULL)
132 memcpy(*out_str, in_data->data, in_data->length);
133 (*out_str)[in_data->length] = '\0';
138 static krb5_error_code
139 kh_unmarshal_general_string_contents(krb5_context context,
140 const heim_general_string in_str,
143 out_data->magic = KV5M_DATA;
144 out_data->length = strlen(in_str);
145 out_data->data = malloc(out_data->length);
146 if (out_data->data == NULL)
149 memcpy(out_data->data, in_str, out_data->length);
154 static krb5_error_code
155 kh_unmarshal_general_string(krb5_context context,
156 const heim_general_string in_str,
157 krb5_data **out_data)
159 krb5_error_code code;
161 *out_data = k5alloc(sizeof(krb5_data), &code);
165 code = kh_unmarshal_general_string_contents(context, in_str, *out_data);
177 kh_marshal_Principal(krb5_context context,
178 krb5_const_principal kprinc,
179 Principal **out_hprinc)
181 krb5_error_code code;
185 hprinc = k5alloc(sizeof(*hprinc), &code);
189 hprinc->name.name_type = kprinc->type;
190 hprinc->name.name_string.val = k5alloc(kprinc->length *
191 sizeof(heim_general_string),
194 kh_free_Principal(context, hprinc);
197 for (i = 0; i < kprinc->length; i++) {
198 code = kh_marshal_general_string(context, &kprinc->data[i],
199 &hprinc->name.name_string.val[i]);
201 kh_free_Principal(context, hprinc);
204 hprinc->name.name_string.len++;
206 code = kh_marshal_general_string(context, &kprinc->realm, &hprinc->realm);
208 kh_free_Principal(context, hprinc);
212 *out_hprinc = hprinc;
218 kh_unmarshal_Principal(krb5_context context,
219 const Principal *hprinc,
220 krb5_principal *out_kprinc)
222 krb5_error_code code;
223 krb5_principal kprinc;
226 kprinc = k5alloc(sizeof(*kprinc), &code);
230 kprinc->magic = KV5M_PRINCIPAL;
231 kprinc->type = hprinc->name.name_type;
232 kprinc->data = k5alloc(hprinc->name.name_string.len * sizeof(krb5_data),
235 krb5_free_principal(context, kprinc);
238 for (i = 0; i < hprinc->name.name_string.len; i++) {
239 code = kh_unmarshal_general_string_contents(context,
240 hprinc->name.name_string.val[i],
243 krb5_free_principal(context, kprinc);
248 code = kh_unmarshal_general_string_contents(context,
252 krb5_free_principal(context, kprinc);
256 *out_kprinc = kprinc;
261 static krb5_error_code
262 kh_marshal_Event(krb5_context context,
263 const krb5_db_entry *kentry,
266 krb5_error_code code;
267 krb5_timestamp mod_time = 0;
268 krb5_principal mod_princ = NULL;
270 memset(event, 0, sizeof(*event));
272 code = krb5_dbe_lookup_mod_princ_data(context, (krb5_db_entry *)kentry,
273 &mod_time, &mod_princ);
277 event->time = mod_time;
279 if (mod_princ != NULL) {
280 code = kh_marshal_Principal(context, mod_princ, &event->principal);
282 krb5_free_principal(context, mod_princ);
287 krb5_free_principal(context, mod_princ);
292 static krb5_error_code
293 kh_unmarshal_Event(krb5_context context,
295 krb5_db_entry *kentry)
297 krb5_error_code code;
298 krb5_principal princ = NULL;
300 if (event->principal != NULL) {
301 code = kh_unmarshal_Principal(context, event->principal, &princ);
306 code = krb5_dbe_update_mod_princ_data(context, kentry,
309 krb5_free_principal(context, princ);
314 static krb5_error_code
315 kh_marshal_HDBFlags(krb5_context context,
319 memset(hflags, 0, sizeof(*hflags));
321 if (kflags & KRB5_KDB_DISALLOW_TGT_BASED)
323 if ((kflags & KRB5_KDB_DISALLOW_FORWARDABLE) == 0)
324 hflags->forwardable = 1;
325 if ((kflags & KRB5_KDB_DISALLOW_PROXIABLE) == 0)
326 hflags->proxiable = 1;
327 if ((kflags & KRB5_KDB_DISALLOW_RENEWABLE) == 0)
328 hflags->renewable = 1;
329 if ((kflags & KRB5_KDB_DISALLOW_POSTDATED) == 0)
330 hflags->postdate = 1;
331 if ((kflags & KRB5_KDB_DISALLOW_SVR) == 0)
334 if (kflags & KRB5_KDB_DISALLOW_ALL_TIX)
336 if (kflags & KRB5_KDB_REQUIRES_PRE_AUTH)
337 hflags->require_preauth = 1;
338 if (kflags & KRB5_KDB_PWCHANGE_SERVICE)
339 hflags->change_pw = 1;
340 if (kflags & KRB5_KDB_REQUIRES_HW_AUTH)
341 hflags->require_hwauth = 1;
342 if (kflags & KRB5_KDB_OK_AS_DELEGATE)
343 hflags->ok_as_delegate = 1;
344 /* hflags->user_to_user */
345 /* hflags->immutable */
346 if (kflags & KRB5_KDB_OK_TO_AUTH_AS_DELEGATE)
347 hflags->trusted_for_delegation = 1;
348 /* hflags->allow_kerberos4 */
349 /* hflags->allow_digest */
354 static krb5_error_code
355 kh_unmarshal_HDBFlags(krb5_context context,
362 *kflags |= KRB5_KDB_DISALLOW_TGT_BASED;
363 if (!hflags.forwardable)
364 *kflags |= KRB5_KDB_DISALLOW_FORWARDABLE;
365 if (!hflags.proxiable)
366 *kflags |= KRB5_KDB_DISALLOW_PROXIABLE;
367 if (!hflags.renewable)
368 *kflags |= KRB5_KDB_DISALLOW_RENEWABLE;
369 if (!hflags.postdate)
370 *kflags |= KRB5_KDB_DISALLOW_POSTDATED;
372 *kflags |= KRB5_KDB_DISALLOW_SVR;
376 *kflags |= KRB5_KDB_DISALLOW_ALL_TIX;
377 if (hflags.require_preauth)
378 *kflags |= KRB5_KDB_REQUIRES_PRE_AUTH;
379 if (hflags.change_pw)
380 *kflags |= KRB5_KDB_PWCHANGE_SERVICE;
381 if (hflags.require_hwauth)
382 *kflags |= KRB5_KDB_REQUIRES_HW_AUTH;
383 if (hflags.ok_as_delegate)
384 *kflags |= KRB5_KDB_OK_AS_DELEGATE;
385 if (hflags.user_to_user)
387 if (hflags.immutable)
389 if (hflags.trusted_for_delegation)
390 *kflags |= KRB5_KDB_OK_TO_AUTH_AS_DELEGATE;
391 if (hflags.allow_kerberos4)
393 if (hflags.allow_digest)
398 static krb5_error_code
399 kh_marshal_Key(krb5_context context,
400 const krb5_key_data *kkey,
403 krb5_error_code code;
405 memset(hkey, 0, sizeof(*hkey));
407 hkey->key.keytype = kkey->key_data_type[0];
408 hkey->key.keyvalue.data = k5alloc(kkey->key_data_length[0], &code);
411 memcpy(hkey->key.keyvalue.data, kkey->key_data_contents[0],
412 kkey->key_data_length[0]);
413 hkey->key.keyvalue.length = kkey->key_data_length[0];
415 if (kkey->key_data_contents[1] != NULL) {
418 salt = k5alloc(sizeof(*salt), &code);
422 switch (kkey->key_data_type[1]) {
423 case KRB5_KDB_SALTTYPE_NORMAL:
424 salt->type = hdb_pw_salt;
426 case KRB5_KDB_SALTTYPE_AFS3:
427 salt->type = hdb_afs3_salt;
434 salt->salt.data = k5alloc(kkey->key_data_length[1], &code);
439 memcpy(salt->salt.data, kkey->key_data_contents[1],
440 kkey->key_data_length[1]);
441 salt->salt.length = kkey->key_data_length[1];
447 if (code != 0 && hkey->key.keyvalue.data != NULL)
448 free(hkey->key.keyvalue.data);
453 static krb5_error_code
454 kh_unmarshal_Key(krb5_context context,
455 const hdb_entry *hentry,
459 memset(kkey, 0, sizeof(*kkey));
461 kkey->key_data_ver = KRB5_KDB_V1_KEY_DATA_ARRAY;
462 kkey->key_data_kvno = hentry->kvno;
464 kkey->key_data_type[0] = hkey->key.keytype;
465 kkey->key_data_contents[0] = malloc(hkey->key.keyvalue.length);
466 if (kkey->key_data_contents[0] == NULL)
469 memcpy(kkey->key_data_contents[0], hkey->key.keyvalue.data,
470 hkey->key.keyvalue.length);
471 kkey->key_data_length[0] = hkey->key.keyvalue.length;
473 if (hkey->salt != NULL) {
474 switch (hkey->salt->type) {
476 kkey->key_data_type[1] = KRB5_KDB_SALTTYPE_NORMAL;
479 kkey->key_data_type[1] = KRB5_KDB_SALTTYPE_AFS3;
482 kkey->key_data_type[1] = KRB5_KDB_SALTTYPE_SPECIAL;
486 kkey->key_data_contents[1] = malloc(hkey->salt->salt.length);
487 if (kkey->key_data_contents[1] == NULL) {
488 memset(kkey->key_data_contents[0], 0, kkey->key_data_length[0]);
489 free(kkey->key_data_contents[0]);
492 memcpy(kkey->key_data_contents[1], hkey->salt->salt.data,
493 hkey->salt->salt.length);
494 kkey->key_data_length[1] = hkey->salt->salt.length;
501 * Extension marshalers
504 static krb5_error_code
505 kh_marshal_HDB_extension_data_last_pw_change(krb5_context context,
506 const krb5_db_entry *kentry,
509 krb5_timestamp stamp;
510 krb5_error_code code;
512 code = krb5_dbe_lookup_last_pwd_change(context,
513 (krb5_db_entry *)kentry, &stamp);
517 hext->data.u.last_pw_change = stamp;
522 static krb5_error_code
523 kh_unmarshal_HDB_extension_data_last_pw_change(krb5_context context,
525 krb5_db_entry *kentry)
527 return krb5_dbe_update_last_pwd_change(context, kentry,
528 hext->data.u.last_pw_change);
531 typedef krb5_error_code (*kh_hdb_marshal_extension_fn)(krb5_context,
532 const krb5_db_entry *,
535 typedef krb5_error_code (*kh_hdb_unmarshal_extension_fn)(krb5_context,
540 kh_hdb_marshal_extension_fn marshal;
541 kh_hdb_unmarshal_extension_fn unmarshal;
542 } kh_hdb_extension_vtable[] = {
543 { NULL, NULL }, /* choice_HDB_extension_data_asn1_ellipsis */
544 { NULL, NULL }, /* choice_HDB_extension_data_pkinit_acl */
545 { NULL, NULL }, /* choice_HDB_extension_data_pkinit_cert_hash */
546 { NULL, NULL }, /* choice_HDB_extension_data_allowed_to_delegate_to */
547 { NULL, NULL }, /* choice_HDB_extension_data_lm_owf */
548 { NULL, NULL }, /* choice_HDB_extension_data_password */
549 { NULL, NULL }, /* choice_HDB_extension_data_aliases */
550 { kh_marshal_HDB_extension_data_last_pw_change,
551 kh_unmarshal_HDB_extension_data_last_pw_change }
554 static const size_t kh_hdb_extension_count =
555 sizeof(kh_hdb_extension_vtable) / sizeof(kh_hdb_extension_vtable[0]);
557 static krb5_error_code
558 kh_marshal_HDB_extension(krb5_context context,
559 const krb5_db_entry *kentry,
562 kh_hdb_marshal_extension_fn marshal = NULL;
564 if (hext->data.element < kh_hdb_extension_count)
565 marshal = kh_hdb_extension_vtable[hext->data.element].marshal;
568 return KRB5_KDB_DBTYPE_NOSUP;
570 return (*marshal)(context, kentry, hext);
573 static krb5_error_code
574 kh_unmarshal_HDB_extension(krb5_context context,
576 krb5_db_entry *kentry)
578 kh_hdb_unmarshal_extension_fn unmarshal = NULL;
580 if (hext->data.element < kh_hdb_extension_count)
581 unmarshal = kh_hdb_extension_vtable[hext->data.element].unmarshal;
583 if (unmarshal == NULL)
584 return hext->mandatory ? KRB5_KDB_DBTYPE_NOSUP : 0;
586 return (*unmarshal)(context, hext, kentry);
589 static krb5_error_code
590 kh_marshal_HDB_extensions(krb5_context context,
591 const krb5_db_entry *kentry,
592 HDB_extensions *hexts)
595 krb5_error_code code;
597 hexts->val = k5alloc(kh_hdb_extension_count * sizeof(HDB_extension), &code);
603 for (i = 0; i < kh_hdb_extension_count; i++) {
604 HDB_extension *hext = &hexts->val[hexts->len];
606 hext->data.element = i;
608 code = kh_marshal_HDB_extension(context, kentry, hext);
609 if (code == KRB5_KDB_DBTYPE_NOSUP)
620 static krb5_error_code
621 kh_unmarshal_HDB_extensions(krb5_context context,
622 HDB_extensions *hexts,
623 krb5_db_entry *kentry)
626 krb5_error_code code = 0;
628 for (i = 0; i < hexts->len; i++) {
629 code = kh_unmarshal_HDB_extension(context, &hexts->val[i], kentry);
638 kh_marshal_hdb_entry(krb5_context context,
639 const krb5_db_entry *kentry,
642 kh_db_context *kh = KH_DB_CONTEXT(context);
643 krb5_error_code code;
647 memset(hentry, 0, sizeof(*hentry));
649 code = kh_marshal_Principal(context, kentry->princ, &hentry->principal);
653 code = kh_marshal_HDBFlags(context, kentry->attributes, &hentry->flags);
657 if (kentry->expiration) {
658 hentry->valid_end = k5alloc(sizeof(KerberosTime), &code);
661 *(hentry->valid_end) = kentry->expiration;
663 if (kentry->pw_expiration) {
664 hentry->pw_end = k5alloc(sizeof(KerberosTime), &code);
667 *(hentry->pw_end) = kentry->pw_expiration;
669 if (kentry->max_life) {
670 hentry->max_life = k5alloc(sizeof(unsigned int), &code);
673 *(hentry->max_life) = kentry->max_life;
675 if (kentry->max_renewable_life) {
676 hentry->max_renew = k5alloc(sizeof(unsigned int), &code);
679 *(hentry->max_renew) = kentry->max_renewable_life;
684 /* fail_auth_count */
687 if ((kentry->attributes & KRB5_KDB_NEW_PRINC) == 0) {
688 hentry->modified_by = k5alloc(sizeof(Event), &code);
691 code = kh_marshal_Event(context, kentry, hentry->modified_by);
693 code = kh_marshal_Event(context, kentry, &hentry->created_by);
698 hentry->extensions = k5alloc(sizeof(HDB_extensions), &code);
702 code = kh_marshal_HDB_extensions(context, kentry, hentry->extensions);
706 hentry->keys.len = 0;
707 hentry->keys.val = k5alloc(kentry->n_key_data * sizeof(Key), &code);
711 for (i = 0; i < kentry->n_key_data; i++) {
712 code = kh_marshal_Key(context,
713 &kentry->key_data[i],
714 &hentry->keys.val[hentry->keys.len]);
718 if (kentry->key_data[i].key_data_kvno > kvno)
719 kvno = kentry->key_data[i].key_data_kvno;
731 hext.entry = *hentry;
732 hext.free_entry = NULL;
734 kh_hdb_free_entry(context, kh, &hext);
735 memset(hentry, 0, sizeof(*hentry));
742 kh_unmarshal_hdb_entry(krb5_context context,
743 const hdb_entry *hentry,
744 krb5_db_entry **kentry_ptr)
746 kh_db_context *kh = KH_DB_CONTEXT(context);
747 krb5_db_entry *kentry;
748 krb5_error_code code;
751 kentry = k5alloc(sizeof(*kentry), &code);
755 kentry->magic = KRB5_KDB_MAGIC_NUMBER;
756 kentry->len = KRB5_KDB_V1_BASE_LENGTH;
758 code = kh_unmarshal_Principal(context, hentry->principal, &kentry->princ);
762 code = kh_unmarshal_HDBFlags(context, hentry->flags, &kentry->attributes);
766 if (hentry->max_life != NULL)
767 kentry->max_life = *(hentry->max_life);
768 if (hentry->max_renew != NULL)
769 kentry->max_renewable_life = *(hentry->max_renew);
770 if (hentry->valid_end != NULL)
771 kentry->expiration = *(hentry->valid_end);
772 if (hentry->pw_end != NULL)
773 kentry->pw_expiration = *(hentry->pw_end);
777 /* fail_auth_count */
780 code = kh_unmarshal_Event(context,
781 hentry->modified_by ? hentry->modified_by :
787 code = kh_unmarshal_HDB_extensions(context, hentry->extensions, kentry);
791 kentry->key_data = k5alloc(hentry->keys.len * sizeof(krb5_key_data), &code);
795 for (i = 0; i < hentry->keys.len; i++) {
796 code = kh_unmarshal_Key(context, hentry,
797 &hentry->keys.val[i],
798 &kentry->key_data[i]);
802 kentry->n_key_data++;
805 *kentry_ptr = kentry;
809 kh_kdb_free_entry(context, kh, kentry);