Home | History | Annotate | Line # | Download | only in hdb
print.c revision 1.1.1.2.6.1
      1  1.1.1.2.6.1  pgoyette /*	$NetBSD: print.c,v 1.1.1.2.6.1 2017/03/20 06:51:44 pgoyette Exp $	*/
      2          1.1     elric 
      3          1.1     elric /*
      4          1.1     elric  * Copyright (c) 1999-2005 Kungliga Tekniska Hgskolan
      5          1.1     elric  * (Royal Institute of Technology, Stockholm, Sweden).
      6          1.1     elric  * All rights reserved.
      7          1.1     elric  *
      8          1.1     elric  * Redistribution and use in source and binary forms, with or without
      9          1.1     elric  * modification, are permitted provided that the following conditions
     10          1.1     elric  * are met:
     11          1.1     elric  *
     12          1.1     elric  * 1. Redistributions of source code must retain the above copyright
     13          1.1     elric  *    notice, this list of conditions and the following disclaimer.
     14          1.1     elric  *
     15          1.1     elric  * 2. Redistributions in binary form must reproduce the above copyright
     16          1.1     elric  *    notice, this list of conditions and the following disclaimer in the
     17          1.1     elric  *    documentation and/or other materials provided with the distribution.
     18          1.1     elric  *
     19          1.1     elric  * 3. Neither the name of KTH nor the names of its contributors may be
     20          1.1     elric  *    used to endorse or promote products derived from this software without
     21          1.1     elric  *    specific prior written permission.
     22          1.1     elric  *
     23          1.1     elric  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     24          1.1     elric  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25          1.1     elric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     26          1.1     elric  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
     27          1.1     elric  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     28          1.1     elric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     29          1.1     elric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     30          1.1     elric  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     31          1.1     elric  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     32          1.1     elric  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     33          1.1     elric  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
     34          1.1     elric 
     35          1.1     elric #include "hdb_locl.h"
     36          1.1     elric #include <krb5/hex.h>
     37          1.1     elric #include <ctype.h>
     38          1.1     elric 
     39          1.1     elric /*
     40          1.1     elric    This is the present contents of a dump line. This might change at
     41          1.1     elric    any time. Fields are separated by white space.
     42          1.1     elric 
     43          1.1     elric   principal
     44          1.1     elric   keyblock
     45          1.1     elric   	kvno
     46          1.1     elric 	keys...
     47          1.1     elric 		mkvno
     48          1.1     elric 		enctype
     49          1.1     elric 		keyvalue
     50          1.1     elric 		salt (- means use normal salt)
     51          1.1     elric   creation date and principal
     52          1.1     elric   modification date and principal
     53          1.1     elric   principal valid from date (not used)
     54          1.1     elric   principal valid end date (not used)
     55          1.1     elric   principal key expires (not used)
     56          1.1     elric   max ticket life
     57          1.1     elric   max renewable life
     58          1.1     elric   flags
     59          1.1     elric   generation number
     60          1.1     elric   */
     61          1.1     elric 
     62  1.1.1.2.6.1  pgoyette /*
     63  1.1.1.2.6.1  pgoyette  * These utility functions return the number of bytes written or -1, and
     64  1.1.1.2.6.1  pgoyette  * they set an error in the context.
     65  1.1.1.2.6.1  pgoyette  */
     66  1.1.1.2.6.1  pgoyette static ssize_t
     67          1.1     elric append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...)
     68          1.1     elric {
     69  1.1.1.2.6.1  pgoyette     ssize_t sz;
     70          1.1     elric     char *s;
     71  1.1.1.2.6.1  pgoyette     int rc;
     72          1.1     elric     va_list ap;
     73          1.1     elric     va_start(ap, fmt);
     74  1.1.1.2.6.1  pgoyette     rc = vasprintf(&s, fmt, ap);
     75          1.1     elric     va_end(ap);
     76  1.1.1.2.6.1  pgoyette     if(rc < 0) {
     77          1.1     elric 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
     78  1.1.1.2.6.1  pgoyette 	return -1;
     79          1.1     elric     }
     80  1.1.1.2.6.1  pgoyette     sz = krb5_storage_write(sp, s, strlen(s));
     81          1.1     elric     free(s);
     82  1.1.1.2.6.1  pgoyette     return sz;
     83          1.1     elric }
     84          1.1     elric 
     85          1.1     elric static krb5_error_code
     86  1.1.1.2.6.1  pgoyette append_hex(krb5_context context, krb5_storage *sp,
     87  1.1.1.2.6.1  pgoyette            int always_encode, int lower, krb5_data *data)
     88          1.1     elric {
     89  1.1.1.2.6.1  pgoyette     ssize_t sz;
     90      1.1.1.2    pettai     int printable = 1;
     91      1.1.1.2    pettai     size_t i;
     92          1.1     elric     char *p;
     93          1.1     elric 
     94          1.1     elric     p = data->data;
     95  1.1.1.2.6.1  pgoyette     if (!always_encode) {
     96  1.1.1.2.6.1  pgoyette         for (i = 0; i < data->length; i++) {
     97  1.1.1.2.6.1  pgoyette             if (!isalnum((unsigned char)p[i]) && p[i] != '.'){
     98  1.1.1.2.6.1  pgoyette                 printable = 0;
     99  1.1.1.2.6.1  pgoyette                 break;
    100  1.1.1.2.6.1  pgoyette             }
    101  1.1.1.2.6.1  pgoyette         }
    102  1.1.1.2.6.1  pgoyette     }
    103  1.1.1.2.6.1  pgoyette     if (printable && !always_encode)
    104          1.1     elric 	return append_string(context, sp, "\"%.*s\"",
    105          1.1     elric 			     data->length, data->data);
    106  1.1.1.2.6.1  pgoyette     sz = hex_encode(data->data, data->length, &p);
    107  1.1.1.2.6.1  pgoyette     if (sz == -1) return sz;
    108  1.1.1.2.6.1  pgoyette     if (lower)
    109  1.1.1.2.6.1  pgoyette         strlwr(p);
    110  1.1.1.2.6.1  pgoyette     sz = append_string(context, sp, "%s", p);
    111          1.1     elric     free(p);
    112  1.1.1.2.6.1  pgoyette     return sz;
    113          1.1     elric }
    114          1.1     elric 
    115          1.1     elric static char *
    116          1.1     elric time2str(time_t t)
    117          1.1     elric {
    118          1.1     elric     static char buf[128];
    119          1.1     elric     strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t));
    120          1.1     elric     return buf;
    121          1.1     elric }
    122          1.1     elric 
    123  1.1.1.2.6.1  pgoyette static ssize_t
    124          1.1     elric append_event(krb5_context context, krb5_storage *sp, Event *ev)
    125          1.1     elric {
    126          1.1     elric     krb5_error_code ret;
    127  1.1.1.2.6.1  pgoyette     ssize_t sz;
    128  1.1.1.2.6.1  pgoyette     char *pr = NULL;
    129          1.1     elric     if(ev == NULL)
    130          1.1     elric 	return append_string(context, sp, "- ");
    131          1.1     elric     if (ev->principal != NULL) {
    132          1.1     elric        ret = krb5_unparse_name(context, ev->principal, &pr);
    133  1.1.1.2.6.1  pgoyette        if (ret) return -1; /* krb5_unparse_name() sets error info */
    134          1.1     elric     }
    135  1.1.1.2.6.1  pgoyette     sz = append_string(context, sp, "%s:%s ", time2str(ev->time),
    136  1.1.1.2.6.1  pgoyette                        pr ? pr : "UNKNOWN");
    137          1.1     elric     free(pr);
    138  1.1.1.2.6.1  pgoyette     return sz;
    139  1.1.1.2.6.1  pgoyette }
    140  1.1.1.2.6.1  pgoyette 
    141  1.1.1.2.6.1  pgoyette #define KRB5_KDB_SALTTYPE_NORMAL        0
    142  1.1.1.2.6.1  pgoyette #define KRB5_KDB_SALTTYPE_V4            1
    143  1.1.1.2.6.1  pgoyette #define KRB5_KDB_SALTTYPE_NOREALM       2
    144  1.1.1.2.6.1  pgoyette #define KRB5_KDB_SALTTYPE_ONLYREALM     3
    145  1.1.1.2.6.1  pgoyette #define KRB5_KDB_SALTTYPE_SPECIAL       4
    146  1.1.1.2.6.1  pgoyette #define KRB5_KDB_SALTTYPE_AFS3          5
    147  1.1.1.2.6.1  pgoyette 
    148  1.1.1.2.6.1  pgoyette static ssize_t
    149  1.1.1.2.6.1  pgoyette append_mit_key(krb5_context context, krb5_storage *sp,
    150  1.1.1.2.6.1  pgoyette                krb5_const_principal princ,
    151  1.1.1.2.6.1  pgoyette                unsigned int kvno, Key *key)
    152  1.1.1.2.6.1  pgoyette {
    153  1.1.1.2.6.1  pgoyette     krb5_error_code ret;
    154  1.1.1.2.6.1  pgoyette     krb5_salt k5salt;
    155  1.1.1.2.6.1  pgoyette     ssize_t sz;
    156  1.1.1.2.6.1  pgoyette     size_t key_versions = key->salt ? 2 : 1;
    157  1.1.1.2.6.1  pgoyette     size_t decrypted_key_length;
    158  1.1.1.2.6.1  pgoyette     char buf[2];
    159  1.1.1.2.6.1  pgoyette     krb5_data keylenbytes;
    160  1.1.1.2.6.1  pgoyette     unsigned int salttype;
    161  1.1.1.2.6.1  pgoyette 
    162  1.1.1.2.6.1  pgoyette     sz = append_string(context, sp, "\t%u\t%u\t%d\t%d\t", key_versions, kvno,
    163  1.1.1.2.6.1  pgoyette                         key->key.keytype, key->key.keyvalue.length + 2);
    164  1.1.1.2.6.1  pgoyette     if (sz == -1) return sz;
    165  1.1.1.2.6.1  pgoyette     ret = krb5_enctype_keysize(context, key->key.keytype, &decrypted_key_length);
    166  1.1.1.2.6.1  pgoyette     if (ret) return -1; /* XXX we lose the error code */
    167  1.1.1.2.6.1  pgoyette     buf[0] = decrypted_key_length & 0xff;
    168  1.1.1.2.6.1  pgoyette     buf[1] = (decrypted_key_length & 0xff00) >> 8;
    169  1.1.1.2.6.1  pgoyette     keylenbytes.data = buf;
    170  1.1.1.2.6.1  pgoyette     keylenbytes.length = sizeof (buf);
    171  1.1.1.2.6.1  pgoyette     sz = append_hex(context, sp, 1, 1, &keylenbytes);
    172  1.1.1.2.6.1  pgoyette     if (sz == -1) return sz;
    173  1.1.1.2.6.1  pgoyette     sz = append_hex(context, sp, 1, 1, &key->key.keyvalue);
    174  1.1.1.2.6.1  pgoyette     if (!key->salt)
    175  1.1.1.2.6.1  pgoyette         return sz;
    176  1.1.1.2.6.1  pgoyette 
    177  1.1.1.2.6.1  pgoyette     /* Map salt to MIT KDB style */
    178  1.1.1.2.6.1  pgoyette     switch (key->salt->type) {
    179  1.1.1.2.6.1  pgoyette     case KRB5_PADATA_PW_SALT:
    180  1.1.1.2.6.1  pgoyette 
    181  1.1.1.2.6.1  pgoyette         /*
    182  1.1.1.2.6.1  pgoyette          * Compute normal salt and then see whether it matches the stored one
    183  1.1.1.2.6.1  pgoyette          */
    184  1.1.1.2.6.1  pgoyette         ret = krb5_get_pw_salt(context, princ, &k5salt);
    185  1.1.1.2.6.1  pgoyette         if (ret) return -1;
    186  1.1.1.2.6.1  pgoyette         if (k5salt.saltvalue.length == key->salt->salt.length &&
    187  1.1.1.2.6.1  pgoyette             memcmp(k5salt.saltvalue.data, key->salt->salt.data,
    188  1.1.1.2.6.1  pgoyette                    k5salt.saltvalue.length) == 0)
    189  1.1.1.2.6.1  pgoyette             salttype = KRB5_KDB_SALTTYPE_NORMAL; /* matches */
    190  1.1.1.2.6.1  pgoyette         else if (key->salt->salt.length == strlen(princ->realm) &&
    191  1.1.1.2.6.1  pgoyette                  memcmp(key->salt->salt.data, princ->realm,
    192  1.1.1.2.6.1  pgoyette                         key->salt->salt.length) == 0)
    193  1.1.1.2.6.1  pgoyette             salttype = KRB5_KDB_SALTTYPE_ONLYREALM; /* matches realm */
    194  1.1.1.2.6.1  pgoyette         else if (key->salt->salt.length ==
    195  1.1.1.2.6.1  pgoyette 		 k5salt.saltvalue.length - strlen(princ->realm) &&
    196  1.1.1.2.6.1  pgoyette                  memcmp((char *)k5salt.saltvalue.data + strlen(princ->realm),
    197  1.1.1.2.6.1  pgoyette                         key->salt->salt.data, key->salt->salt.length) == 0)
    198  1.1.1.2.6.1  pgoyette             salttype = KRB5_KDB_SALTTYPE_NOREALM; /* matches w/o realm */
    199  1.1.1.2.6.1  pgoyette         else
    200  1.1.1.2.6.1  pgoyette             salttype = KRB5_KDB_SALTTYPE_NORMAL;  /* hope for best */
    201  1.1.1.2.6.1  pgoyette 
    202  1.1.1.2.6.1  pgoyette 	break;
    203  1.1.1.2.6.1  pgoyette 
    204  1.1.1.2.6.1  pgoyette     case KRB5_PADATA_AFS3_SALT:
    205  1.1.1.2.6.1  pgoyette         salttype = KRB5_KDB_SALTTYPE_AFS3;
    206  1.1.1.2.6.1  pgoyette 	break;
    207  1.1.1.2.6.1  pgoyette 
    208  1.1.1.2.6.1  pgoyette     default:
    209  1.1.1.2.6.1  pgoyette 	return -1;
    210  1.1.1.2.6.1  pgoyette     }
    211  1.1.1.2.6.1  pgoyette 
    212  1.1.1.2.6.1  pgoyette     sz = append_string(context, sp, "\t%u\t%u\t", salttype,
    213  1.1.1.2.6.1  pgoyette                        key->salt->salt.length);
    214  1.1.1.2.6.1  pgoyette     if (sz == -1) return sz;
    215  1.1.1.2.6.1  pgoyette     return append_hex(context, sp, 1, 1, &key->salt->salt);
    216          1.1     elric }
    217          1.1     elric 
    218          1.1     elric static krb5_error_code
    219          1.1     elric entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
    220          1.1     elric {
    221          1.1     elric     char *p;
    222      1.1.1.2    pettai     size_t i;
    223          1.1     elric     krb5_error_code ret;
    224          1.1     elric 
    225          1.1     elric     /* --- principal */
    226          1.1     elric     ret = krb5_unparse_name(context, ent->principal, &p);
    227          1.1     elric     if(ret)
    228          1.1     elric 	return ret;
    229          1.1     elric     append_string(context, sp, "%s ", p);
    230          1.1     elric     free(p);
    231          1.1     elric     /* --- kvno */
    232          1.1     elric     append_string(context, sp, "%d", ent->kvno);
    233          1.1     elric     /* --- keys */
    234          1.1     elric     for(i = 0; i < ent->keys.len; i++){
    235          1.1     elric 	/* --- mkvno, keytype */
    236          1.1     elric 	if(ent->keys.val[i].mkvno)
    237          1.1     elric 	    append_string(context, sp, ":%d:%d:",
    238          1.1     elric 			  *ent->keys.val[i].mkvno,
    239          1.1     elric 			  ent->keys.val[i].key.keytype);
    240          1.1     elric 	else
    241          1.1     elric 	    append_string(context, sp, "::%d:",
    242          1.1     elric 			  ent->keys.val[i].key.keytype);
    243          1.1     elric 	/* --- keydata */
    244  1.1.1.2.6.1  pgoyette 	append_hex(context, sp, 0, 0, &ent->keys.val[i].key.keyvalue);
    245          1.1     elric 	append_string(context, sp, ":");
    246          1.1     elric 	/* --- salt */
    247          1.1     elric 	if(ent->keys.val[i].salt){
    248          1.1     elric 	    append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
    249  1.1.1.2.6.1  pgoyette 	    append_hex(context, sp, 0, 0, &ent->keys.val[i].salt->salt);
    250          1.1     elric 	}else
    251          1.1     elric 	    append_string(context, sp, "-");
    252          1.1     elric     }
    253          1.1     elric     append_string(context, sp, " ");
    254          1.1     elric     /* --- created by */
    255          1.1     elric     append_event(context, sp, &ent->created_by);
    256          1.1     elric     /* --- modified by */
    257          1.1     elric     append_event(context, sp, ent->modified_by);
    258          1.1     elric 
    259          1.1     elric     /* --- valid start */
    260          1.1     elric     if(ent->valid_start)
    261          1.1     elric 	append_string(context, sp, "%s ", time2str(*ent->valid_start));
    262          1.1     elric     else
    263          1.1     elric 	append_string(context, sp, "- ");
    264          1.1     elric 
    265          1.1     elric     /* --- valid end */
    266          1.1     elric     if(ent->valid_end)
    267          1.1     elric 	append_string(context, sp, "%s ", time2str(*ent->valid_end));
    268          1.1     elric     else
    269          1.1     elric 	append_string(context, sp, "- ");
    270          1.1     elric 
    271          1.1     elric     /* --- password ends */
    272          1.1     elric     if(ent->pw_end)
    273          1.1     elric 	append_string(context, sp, "%s ", time2str(*ent->pw_end));
    274          1.1     elric     else
    275          1.1     elric 	append_string(context, sp, "- ");
    276          1.1     elric 
    277          1.1     elric     /* --- max life */
    278          1.1     elric     if(ent->max_life)
    279          1.1     elric 	append_string(context, sp, "%d ", *ent->max_life);
    280          1.1     elric     else
    281          1.1     elric 	append_string(context, sp, "- ");
    282          1.1     elric 
    283          1.1     elric     /* --- max renewable life */
    284          1.1     elric     if(ent->max_renew)
    285          1.1     elric 	append_string(context, sp, "%d ", *ent->max_renew);
    286          1.1     elric     else
    287          1.1     elric 	append_string(context, sp, "- ");
    288          1.1     elric 
    289          1.1     elric     /* --- flags */
    290          1.1     elric     append_string(context, sp, "%d ", HDBFlags2int(ent->flags));
    291          1.1     elric 
    292          1.1     elric     /* --- generation number */
    293          1.1     elric     if(ent->generation) {
    294          1.1     elric 	append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time),
    295          1.1     elric 		      ent->generation->usec,
    296          1.1     elric 		      ent->generation->gen);
    297          1.1     elric     } else
    298          1.1     elric 	append_string(context, sp, "- ");
    299          1.1     elric 
    300          1.1     elric     /* --- extensions */
    301          1.1     elric     if(ent->extensions && ent->extensions->len > 0) {
    302          1.1     elric 	for(i = 0; i < ent->extensions->len; i++) {
    303          1.1     elric 	    void *d;
    304      1.1.1.2    pettai 	    size_t size, sz = 0;
    305          1.1     elric 
    306          1.1     elric 	    ASN1_MALLOC_ENCODE(HDB_extension, d, size,
    307          1.1     elric 			       &ent->extensions->val[i], &sz, ret);
    308          1.1     elric 	    if (ret) {
    309          1.1     elric 		krb5_clear_error_message(context);
    310          1.1     elric 		return ret;
    311          1.1     elric 	    }
    312          1.1     elric 	    if(size != sz)
    313          1.1     elric 		krb5_abortx(context, "internal asn.1 encoder error");
    314          1.1     elric 
    315          1.1     elric 	    if (hex_encode(d, size, &p) < 0) {
    316          1.1     elric 		free(d);
    317          1.1     elric 		krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
    318          1.1     elric 		return ENOMEM;
    319          1.1     elric 	    }
    320          1.1     elric 
    321          1.1     elric 	    free(d);
    322          1.1     elric 	    append_string(context, sp, "%s%s", p,
    323          1.1     elric 			  ent->extensions->len - 1 != i ? ":" : "");
    324          1.1     elric 	    free(p);
    325          1.1     elric 	}
    326          1.1     elric     } else
    327          1.1     elric 	append_string(context, sp, "-");
    328          1.1     elric 
    329  1.1.1.2.6.1  pgoyette     return 0;
    330  1.1.1.2.6.1  pgoyette }
    331          1.1     elric 
    332  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_POSTDATED     0x00000001
    333  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_FORWARDABLE   0x00000002
    334  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_TGT_BASED     0x00000004
    335  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_RENEWABLE     0x00000008
    336  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_PROXIABLE     0x00000010
    337  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_DUP_SKEY      0x00000020
    338  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_ALL_TIX       0x00000040
    339  1.1.1.2.6.1  pgoyette #define KRB5_KDB_REQUIRES_PRE_AUTH      0x00000080
    340  1.1.1.2.6.1  pgoyette #define KRB5_KDB_REQUIRES_HW_AUTH       0x00000100
    341  1.1.1.2.6.1  pgoyette #define KRB5_KDB_REQUIRES_PWCHANGE      0x00000200
    342  1.1.1.2.6.1  pgoyette #define KRB5_KDB_DISALLOW_SVR           0x00001000
    343  1.1.1.2.6.1  pgoyette #define KRB5_KDB_PWCHANGE_SERVICE       0x00002000
    344  1.1.1.2.6.1  pgoyette #define KRB5_KDB_SUPPORT_DESMD5         0x00004000
    345  1.1.1.2.6.1  pgoyette #define KRB5_KDB_NEW_PRINC              0x00008000
    346  1.1.1.2.6.1  pgoyette 
    347  1.1.1.2.6.1  pgoyette static int
    348  1.1.1.2.6.1  pgoyette flags_to_attr(HDBFlags flags)
    349  1.1.1.2.6.1  pgoyette {
    350  1.1.1.2.6.1  pgoyette     int a = 0;
    351  1.1.1.2.6.1  pgoyette 
    352  1.1.1.2.6.1  pgoyette     if (!flags.postdate)
    353  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_DISALLOW_POSTDATED;
    354  1.1.1.2.6.1  pgoyette     if (!flags.forwardable)
    355  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_DISALLOW_FORWARDABLE;
    356  1.1.1.2.6.1  pgoyette     if (flags.initial)
    357  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_DISALLOW_TGT_BASED;
    358  1.1.1.2.6.1  pgoyette     if (!flags.renewable)
    359  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_DISALLOW_RENEWABLE;
    360  1.1.1.2.6.1  pgoyette     if (!flags.proxiable)
    361  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_DISALLOW_PROXIABLE;
    362  1.1.1.2.6.1  pgoyette     if (flags.invalid)
    363  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_DISALLOW_ALL_TIX;
    364  1.1.1.2.6.1  pgoyette     if (flags.require_preauth)
    365  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_REQUIRES_PRE_AUTH;
    366  1.1.1.2.6.1  pgoyette     if (flags.require_hwauth)
    367  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_REQUIRES_HW_AUTH;
    368  1.1.1.2.6.1  pgoyette     if (!flags.server)
    369  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_DISALLOW_SVR;
    370  1.1.1.2.6.1  pgoyette     if (flags.change_pw)
    371  1.1.1.2.6.1  pgoyette         a |= KRB5_KDB_PWCHANGE_SERVICE;
    372  1.1.1.2.6.1  pgoyette     return a;
    373  1.1.1.2.6.1  pgoyette }
    374  1.1.1.2.6.1  pgoyette 
    375  1.1.1.2.6.1  pgoyette krb5_error_code
    376  1.1.1.2.6.1  pgoyette entry2mit_string_int(krb5_context context, krb5_storage *sp, hdb_entry *ent)
    377  1.1.1.2.6.1  pgoyette {
    378  1.1.1.2.6.1  pgoyette     krb5_error_code ret;
    379  1.1.1.2.6.1  pgoyette     ssize_t sz;
    380  1.1.1.2.6.1  pgoyette     size_t i, k;
    381  1.1.1.2.6.1  pgoyette     size_t num_tl_data = 0;
    382  1.1.1.2.6.1  pgoyette     size_t num_key_data = 0;
    383  1.1.1.2.6.1  pgoyette     char *p;
    384  1.1.1.2.6.1  pgoyette     HDB_Ext_KeySet *hist_keys = NULL;
    385  1.1.1.2.6.1  pgoyette     HDB_extension *extp;
    386  1.1.1.2.6.1  pgoyette     time_t last_pw_chg = 0;
    387  1.1.1.2.6.1  pgoyette     time_t exp = 0;
    388  1.1.1.2.6.1  pgoyette     time_t pwexp = 0;
    389  1.1.1.2.6.1  pgoyette     unsigned int max_life = 0;
    390  1.1.1.2.6.1  pgoyette     unsigned int max_renew = 0;
    391  1.1.1.2.6.1  pgoyette 
    392  1.1.1.2.6.1  pgoyette     if (ent->modified_by)
    393  1.1.1.2.6.1  pgoyette         num_tl_data++;
    394  1.1.1.2.6.1  pgoyette 
    395  1.1.1.2.6.1  pgoyette     ret = hdb_entry_get_pw_change_time(ent, &last_pw_chg);
    396  1.1.1.2.6.1  pgoyette     if (ret) return ret;
    397  1.1.1.2.6.1  pgoyette     if (last_pw_chg)
    398  1.1.1.2.6.1  pgoyette         num_tl_data++;
    399  1.1.1.2.6.1  pgoyette 
    400  1.1.1.2.6.1  pgoyette     extp = hdb_find_extension(ent, choice_HDB_extension_data_hist_keys);
    401  1.1.1.2.6.1  pgoyette     if (extp)
    402  1.1.1.2.6.1  pgoyette         hist_keys = &extp->data.u.hist_keys;
    403  1.1.1.2.6.1  pgoyette 
    404  1.1.1.2.6.1  pgoyette     for (i = 0; i < ent->keys.len;i++) {
    405  1.1.1.2.6.1  pgoyette         if (ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD4 ||
    406  1.1.1.2.6.1  pgoyette             ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD5)
    407  1.1.1.2.6.1  pgoyette             continue;
    408  1.1.1.2.6.1  pgoyette         num_key_data++;
    409  1.1.1.2.6.1  pgoyette     }
    410  1.1.1.2.6.1  pgoyette     if (hist_keys) {
    411  1.1.1.2.6.1  pgoyette         for (i = 0; i < hist_keys->len; i++) {
    412  1.1.1.2.6.1  pgoyette             /*
    413  1.1.1.2.6.1  pgoyette              * MIT uses the highest kvno as the current kvno instead of
    414  1.1.1.2.6.1  pgoyette              * tracking kvno separately, so we can't dump keysets with kvno
    415  1.1.1.2.6.1  pgoyette              * higher than the entry's kvno.
    416  1.1.1.2.6.1  pgoyette              */
    417  1.1.1.2.6.1  pgoyette             if (hist_keys->val[i].kvno >= ent->kvno)
    418  1.1.1.2.6.1  pgoyette                 continue;
    419  1.1.1.2.6.1  pgoyette             for (k = 0; k < hist_keys->val[i].keys.len; k++) {
    420  1.1.1.2.6.1  pgoyette                 if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 ||
    421  1.1.1.2.6.1  pgoyette                     ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5)
    422  1.1.1.2.6.1  pgoyette                     continue;
    423  1.1.1.2.6.1  pgoyette                 num_key_data++;
    424  1.1.1.2.6.1  pgoyette             }
    425  1.1.1.2.6.1  pgoyette         }
    426  1.1.1.2.6.1  pgoyette     }
    427  1.1.1.2.6.1  pgoyette 
    428  1.1.1.2.6.1  pgoyette     ret = krb5_unparse_name(context, ent->principal, &p);
    429  1.1.1.2.6.1  pgoyette     if (ret) return ret;
    430  1.1.1.2.6.1  pgoyette     sz = append_string(context, sp, "princ\t38\t%u\t%u\t%u\t0\t%s\t%d",
    431  1.1.1.2.6.1  pgoyette                        strlen(p), num_tl_data, num_key_data, p,
    432  1.1.1.2.6.1  pgoyette                        flags_to_attr(ent->flags));
    433  1.1.1.2.6.1  pgoyette     free(p);
    434  1.1.1.2.6.1  pgoyette     if (sz == -1) return ENOMEM;
    435  1.1.1.2.6.1  pgoyette 
    436  1.1.1.2.6.1  pgoyette     if (ent->max_life)
    437  1.1.1.2.6.1  pgoyette         max_life = *ent->max_life;
    438  1.1.1.2.6.1  pgoyette     if (ent->max_renew)
    439  1.1.1.2.6.1  pgoyette         max_renew = *ent->max_renew;
    440  1.1.1.2.6.1  pgoyette     if (ent->valid_end)
    441  1.1.1.2.6.1  pgoyette         exp = *ent->valid_end;
    442  1.1.1.2.6.1  pgoyette     if (ent->pw_end)
    443  1.1.1.2.6.1  pgoyette         pwexp = *ent->pw_end;
    444  1.1.1.2.6.1  pgoyette 
    445  1.1.1.2.6.1  pgoyette     sz = append_string(context, sp, "\t%u\t%u\t%u\t%u\t0\t0\t0",
    446  1.1.1.2.6.1  pgoyette                        max_life, max_renew, exp, pwexp);
    447  1.1.1.2.6.1  pgoyette     if (sz == -1) return ENOMEM;
    448  1.1.1.2.6.1  pgoyette 
    449  1.1.1.2.6.1  pgoyette     /* Dump TL data we know: last pw chg and modified_by */
    450  1.1.1.2.6.1  pgoyette #define mit_KRB5_TL_LAST_PWD_CHANGE     1
    451  1.1.1.2.6.1  pgoyette #define mit_KRB5_TL_MOD_PRINC           2
    452  1.1.1.2.6.1  pgoyette     if (last_pw_chg) {
    453  1.1.1.2.6.1  pgoyette         krb5_data d;
    454  1.1.1.2.6.1  pgoyette         time_t val;
    455  1.1.1.2.6.1  pgoyette         unsigned char *ptr;
    456  1.1.1.2.6.1  pgoyette 
    457  1.1.1.2.6.1  pgoyette         ptr = (unsigned char *)&last_pw_chg;
    458  1.1.1.2.6.1  pgoyette         val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
    459  1.1.1.2.6.1  pgoyette         d.data = &val;
    460  1.1.1.2.6.1  pgoyette         d.length = sizeof (last_pw_chg);
    461  1.1.1.2.6.1  pgoyette         sz = append_string(context, sp, "\t%u\t%u\t",
    462  1.1.1.2.6.1  pgoyette                            mit_KRB5_TL_LAST_PWD_CHANGE, d.length);
    463  1.1.1.2.6.1  pgoyette         if (sz == -1) return ENOMEM;
    464  1.1.1.2.6.1  pgoyette         sz = append_hex(context, sp, 1, 1, &d);
    465  1.1.1.2.6.1  pgoyette         if (sz == -1) return ENOMEM;
    466  1.1.1.2.6.1  pgoyette     }
    467  1.1.1.2.6.1  pgoyette     if (ent->modified_by) {
    468  1.1.1.2.6.1  pgoyette         krb5_data d;
    469  1.1.1.2.6.1  pgoyette         unsigned int val;
    470  1.1.1.2.6.1  pgoyette         size_t plen;
    471  1.1.1.2.6.1  pgoyette         unsigned char *ptr;
    472  1.1.1.2.6.1  pgoyette         char *modby_p;
    473  1.1.1.2.6.1  pgoyette 
    474  1.1.1.2.6.1  pgoyette         ptr = (unsigned char *)&ent->modified_by->time;
    475  1.1.1.2.6.1  pgoyette         val = ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
    476  1.1.1.2.6.1  pgoyette         d.data = &val;
    477  1.1.1.2.6.1  pgoyette         d.length = sizeof (ent->modified_by->time);
    478  1.1.1.2.6.1  pgoyette         ret = krb5_unparse_name(context, ent->modified_by->principal, &modby_p);
    479  1.1.1.2.6.1  pgoyette         if (ret) return ret;
    480  1.1.1.2.6.1  pgoyette         plen = strlen(modby_p);
    481  1.1.1.2.6.1  pgoyette         sz = append_string(context, sp, "\t%u\t%u\t",
    482  1.1.1.2.6.1  pgoyette                            mit_KRB5_TL_MOD_PRINC,
    483  1.1.1.2.6.1  pgoyette                            d.length + plen + 1 /* NULL counted */);
    484  1.1.1.2.6.1  pgoyette         if (sz == -1) return ENOMEM;
    485  1.1.1.2.6.1  pgoyette         sz = append_hex(context, sp, 1, 1, &d);
    486  1.1.1.2.6.1  pgoyette         if (sz == -1) {
    487  1.1.1.2.6.1  pgoyette             free(modby_p);
    488  1.1.1.2.6.1  pgoyette             return ENOMEM;
    489  1.1.1.2.6.1  pgoyette         }
    490  1.1.1.2.6.1  pgoyette         d.data = modby_p;
    491  1.1.1.2.6.1  pgoyette         d.length = plen + 1;
    492  1.1.1.2.6.1  pgoyette         sz = append_hex(context, sp, 1, 1, &d);
    493  1.1.1.2.6.1  pgoyette         free(modby_p);
    494  1.1.1.2.6.1  pgoyette         if (sz == -1) return ENOMEM;
    495  1.1.1.2.6.1  pgoyette     }
    496  1.1.1.2.6.1  pgoyette     /*
    497  1.1.1.2.6.1  pgoyette      * Dump keys (remembering to not include any with kvno higher than
    498  1.1.1.2.6.1  pgoyette      * the entry's because MIT doesn't track entry kvno separately from
    499  1.1.1.2.6.1  pgoyette      * the entry's keys -- max kvno is it)
    500  1.1.1.2.6.1  pgoyette      */
    501  1.1.1.2.6.1  pgoyette     for (i = 0; i < ent->keys.len; i++) {
    502  1.1.1.2.6.1  pgoyette         if (ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD4 ||
    503  1.1.1.2.6.1  pgoyette             ent->keys.val[i].key.keytype == ETYPE_DES_CBC_MD5)
    504  1.1.1.2.6.1  pgoyette             continue;
    505  1.1.1.2.6.1  pgoyette         sz = append_mit_key(context, sp, ent->principal, ent->kvno,
    506  1.1.1.2.6.1  pgoyette                             &ent->keys.val[i]);
    507  1.1.1.2.6.1  pgoyette         if (sz == -1) return ENOMEM;
    508  1.1.1.2.6.1  pgoyette     }
    509  1.1.1.2.6.1  pgoyette     for (i = 0; hist_keys && i < ent->kvno; i++) {
    510  1.1.1.2.6.1  pgoyette         size_t m;
    511  1.1.1.2.6.1  pgoyette 
    512  1.1.1.2.6.1  pgoyette         /* dump historical keys */
    513  1.1.1.2.6.1  pgoyette         for (k = 0; k < hist_keys->len; k++) {
    514  1.1.1.2.6.1  pgoyette             if (hist_keys->val[k].kvno != ent->kvno - i)
    515  1.1.1.2.6.1  pgoyette                 continue;
    516  1.1.1.2.6.1  pgoyette             for (m = 0; m < hist_keys->val[k].keys.len; m++) {
    517  1.1.1.2.6.1  pgoyette                 if (ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD4 ||
    518  1.1.1.2.6.1  pgoyette                     ent->keys.val[k].key.keytype == ETYPE_DES_CBC_MD5)
    519  1.1.1.2.6.1  pgoyette                     continue;
    520  1.1.1.2.6.1  pgoyette                 sz = append_mit_key(context, sp, ent->principal,
    521  1.1.1.2.6.1  pgoyette                                     hist_keys->val[k].kvno,
    522  1.1.1.2.6.1  pgoyette                                     &hist_keys->val[k].keys.val[m]);
    523  1.1.1.2.6.1  pgoyette                 if (sz == -1) return ENOMEM;
    524  1.1.1.2.6.1  pgoyette             }
    525  1.1.1.2.6.1  pgoyette         }
    526  1.1.1.2.6.1  pgoyette     }
    527  1.1.1.2.6.1  pgoyette     sz = append_string(context, sp, "\t-1;"); /* "extra data" */
    528  1.1.1.2.6.1  pgoyette     if (sz == -1) return ENOMEM;
    529          1.1     elric     return 0;
    530          1.1     elric }
    531          1.1     elric 
    532          1.1     elric krb5_error_code
    533  1.1.1.2.6.1  pgoyette hdb_entry2string(krb5_context context, hdb_entry *ent, char **str)
    534          1.1     elric {
    535          1.1     elric     krb5_error_code ret;
    536          1.1     elric     krb5_data data;
    537          1.1     elric     krb5_storage *sp;
    538          1.1     elric 
    539          1.1     elric     sp = krb5_storage_emem();
    540  1.1.1.2.6.1  pgoyette     if (sp == NULL) {
    541          1.1     elric 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
    542          1.1     elric 	return ENOMEM;
    543          1.1     elric     }
    544          1.1     elric 
    545          1.1     elric     ret = entry2string_int(context, sp, ent);
    546  1.1.1.2.6.1  pgoyette     if (ret) {
    547          1.1     elric 	krb5_storage_free(sp);
    548          1.1     elric 	return ret;
    549          1.1     elric     }
    550          1.1     elric 
    551          1.1     elric     krb5_storage_write(sp, "\0", 1);
    552          1.1     elric     krb5_storage_to_data(sp, &data);
    553          1.1     elric     krb5_storage_free(sp);
    554          1.1     elric     *str = data.data;
    555          1.1     elric     return 0;
    556          1.1     elric }
    557          1.1     elric 
    558          1.1     elric /* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */
    559          1.1     elric 
    560          1.1     elric krb5_error_code
    561  1.1.1.2.6.1  pgoyette hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry,
    562  1.1.1.2.6.1  pgoyette                 void *data)
    563          1.1     elric {
    564  1.1.1.2.6.1  pgoyette     struct hdb_print_entry_arg *parg = data;
    565          1.1     elric     krb5_error_code ret;
    566          1.1     elric     krb5_storage *sp;
    567          1.1     elric 
    568  1.1.1.2.6.1  pgoyette     fflush(parg->out);
    569  1.1.1.2.6.1  pgoyette     sp = krb5_storage_from_fd(fileno(parg->out));
    570  1.1.1.2.6.1  pgoyette     if (sp == NULL) {
    571          1.1     elric 	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
    572          1.1     elric 	return ENOMEM;
    573          1.1     elric     }
    574          1.1     elric 
    575  1.1.1.2.6.1  pgoyette     switch (parg->fmt) {
    576  1.1.1.2.6.1  pgoyette     case HDB_DUMP_HEIMDAL:
    577  1.1.1.2.6.1  pgoyette         ret = entry2string_int(context, sp, &entry->entry);
    578  1.1.1.2.6.1  pgoyette         break;
    579  1.1.1.2.6.1  pgoyette     case HDB_DUMP_MIT:
    580  1.1.1.2.6.1  pgoyette         ret = entry2mit_string_int(context, sp, &entry->entry);
    581  1.1.1.2.6.1  pgoyette         break;
    582  1.1.1.2.6.1  pgoyette     default:
    583  1.1.1.2.6.1  pgoyette         heim_abort("Only two dump formats supported: Heimdal and MIT");
    584  1.1.1.2.6.1  pgoyette     }
    585  1.1.1.2.6.1  pgoyette     if (ret) {
    586          1.1     elric 	krb5_storage_free(sp);
    587          1.1     elric 	return ret;
    588          1.1     elric     }
    589          1.1     elric 
    590          1.1     elric     krb5_storage_write(sp, "\n", 1);
    591          1.1     elric     krb5_storage_free(sp);
    592          1.1     elric     return 0;
    593          1.1     elric }
    594