155682Smarkm/*
2233294Sstas * Copyright (c) 1999-2005 Kungliga Tekniska H��gskolan
3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4233294Sstas * All rights reserved.
555682Smarkm *
6233294Sstas * Redistribution and use in source and binary forms, with or without
7233294Sstas * modification, are permitted provided that the following conditions
8233294Sstas * are met:
955682Smarkm *
10233294Sstas * 1. Redistributions of source code must retain the above copyright
11233294Sstas *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright
14233294Sstas *    notice, this list of conditions and the following disclaimer in the
15233294Sstas *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of KTH nor the names of its contributors may be
1855682Smarkm *    used to endorse or promote products derived from this software without
1955682Smarkm *    specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
2255682Smarkm * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2455682Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
2555682Smarkm * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2655682Smarkm * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2755682Smarkm * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
2855682Smarkm * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2955682Smarkm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3055682Smarkm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3155682Smarkm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
3255682Smarkm
3355682Smarkm#include "hdb_locl.h"
34178825Sdfr#include <hex.h>
3555682Smarkm#include <ctype.h>
3655682Smarkm
37233294Sstas/*
3855682Smarkm   This is the present contents of a dump line. This might change at
3955682Smarkm   any time. Fields are separated by white space.
4055682Smarkm
4155682Smarkm  principal
4255682Smarkm  keyblock
4355682Smarkm  	kvno
4455682Smarkm	keys...
4555682Smarkm		mkvno
4655682Smarkm		enctype
4755682Smarkm		keyvalue
4855682Smarkm		salt (- means use normal salt)
4955682Smarkm  creation date and principal
5055682Smarkm  modification date and principal
5155682Smarkm  principal valid from date (not used)
5255682Smarkm  principal valid end date (not used)
5355682Smarkm  principal key expires (not used)
5455682Smarkm  max ticket life
5555682Smarkm  max renewable life
5655682Smarkm  flags
5790926Snectar  generation number
5855682Smarkm  */
5955682Smarkm
6090926Snectarstatic krb5_error_code
6190926Snectarappend_string(krb5_context context, krb5_storage *sp, const char *fmt, ...)
6255682Smarkm{
6390926Snectar    krb5_error_code ret;
6490926Snectar    char *s;
6590926Snectar    va_list ap;
6690926Snectar    va_start(ap, fmt);
6790926Snectar    vasprintf(&s, fmt, ap);
6890926Snectar    va_end(ap);
6990926Snectar    if(s == NULL) {
70233294Sstas	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
7190926Snectar	return ENOMEM;
7290926Snectar    }
73102644Snectar    ret = krb5_storage_write(sp, s, strlen(s));
7490926Snectar    free(s);
7590926Snectar    return ret;
7690926Snectar}
7790926Snectar
7890926Snectarstatic krb5_error_code
7990926Snectarappend_hex(krb5_context context, krb5_storage *sp, krb5_data *data)
8090926Snectar{
81233294Sstas    int printable = 1;
82233294Sstas    size_t i;
8355682Smarkm    char *p;
8455682Smarkm
8555682Smarkm    p = data->data;
8655682Smarkm    for(i = 0; i < data->length; i++)
8755682Smarkm	if(!isalnum((unsigned char)p[i]) && p[i] != '.'){
8890926Snectar	    printable = 0;
8955682Smarkm	    break;
9055682Smarkm	}
9190926Snectar    if(printable)
9290926Snectar	return append_string(context, sp, "\"%.*s\"",
9390926Snectar			     data->length, data->data);
94178825Sdfr    hex_encode(data->data, data->length, &p);
95178825Sdfr    append_string(context, sp, "%s", p);
96178825Sdfr    free(p);
9790926Snectar    return 0;
9855682Smarkm}
9955682Smarkm
10055682Smarkmstatic char *
10155682Smarkmtime2str(time_t t)
10255682Smarkm{
10355682Smarkm    static char buf[128];
10455682Smarkm    strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t));
10555682Smarkm    return buf;
10655682Smarkm}
10755682Smarkm
10855682Smarkmstatic krb5_error_code
10990926Snectarappend_event(krb5_context context, krb5_storage *sp, Event *ev)
11055682Smarkm{
11190926Snectar    char *pr = NULL;
11255682Smarkm    krb5_error_code ret;
11390926Snectar    if(ev == NULL)
11490926Snectar	return append_string(context, sp, "- ");
11590926Snectar    if (ev->principal != NULL) {
11655682Smarkm       ret = krb5_unparse_name(context, ev->principal, &pr);
11755682Smarkm       if(ret)
11855682Smarkm           return ret;
11955682Smarkm    }
12090926Snectar    ret = append_string(context, sp, "%s:%s ",
12190926Snectar			time2str(ev->time), pr ? pr : "UNKNOWN");
12255682Smarkm    free(pr);
12390926Snectar    return ret;
12455682Smarkm}
12555682Smarkm
12690926Snectarstatic krb5_error_code
12790926Snectarentry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
12855682Smarkm{
12955682Smarkm    char *p;
130233294Sstas    size_t i;
13155682Smarkm    krb5_error_code ret;
13255682Smarkm
13355682Smarkm    /* --- principal */
13455682Smarkm    ret = krb5_unparse_name(context, ent->principal, &p);
13555682Smarkm    if(ret)
13655682Smarkm	return ret;
13790926Snectar    append_string(context, sp, "%s ", p);
13855682Smarkm    free(p);
13955682Smarkm    /* --- kvno */
14090926Snectar    append_string(context, sp, "%d", ent->kvno);
14155682Smarkm    /* --- keys */
14255682Smarkm    for(i = 0; i < ent->keys.len; i++){
14355682Smarkm	/* --- mkvno, keytype */
14455682Smarkm	if(ent->keys.val[i].mkvno)
145233294Sstas	    append_string(context, sp, ":%d:%d:",
146233294Sstas			  *ent->keys.val[i].mkvno,
14790926Snectar			  ent->keys.val[i].key.keytype);
14855682Smarkm	else
149233294Sstas	    append_string(context, sp, "::%d:",
15090926Snectar			  ent->keys.val[i].key.keytype);
15155682Smarkm	/* --- keydata */
15290926Snectar	append_hex(context, sp, &ent->keys.val[i].key.keyvalue);
15390926Snectar	append_string(context, sp, ":");
15455682Smarkm	/* --- salt */
15555682Smarkm	if(ent->keys.val[i].salt){
15690926Snectar	    append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
15790926Snectar	    append_hex(context, sp, &ent->keys.val[i].salt->salt);
15855682Smarkm	}else
15990926Snectar	    append_string(context, sp, "-");
16055682Smarkm    }
16190926Snectar    append_string(context, sp, " ");
16255682Smarkm    /* --- created by */
16390926Snectar    append_event(context, sp, &ent->created_by);
16455682Smarkm    /* --- modified by */
16590926Snectar    append_event(context, sp, ent->modified_by);
16655682Smarkm
16755682Smarkm    /* --- valid start */
16855682Smarkm    if(ent->valid_start)
16990926Snectar	append_string(context, sp, "%s ", time2str(*ent->valid_start));
17055682Smarkm    else
17190926Snectar	append_string(context, sp, "- ");
17255682Smarkm
17355682Smarkm    /* --- valid end */
17455682Smarkm    if(ent->valid_end)
17590926Snectar	append_string(context, sp, "%s ", time2str(*ent->valid_end));
17655682Smarkm    else
17790926Snectar	append_string(context, sp, "- ");
178233294Sstas
17955682Smarkm    /* --- password ends */
18055682Smarkm    if(ent->pw_end)
18190926Snectar	append_string(context, sp, "%s ", time2str(*ent->pw_end));
18255682Smarkm    else
18390926Snectar	append_string(context, sp, "- ");
18455682Smarkm
18555682Smarkm    /* --- max life */
18690926Snectar    if(ent->max_life)
18790926Snectar	append_string(context, sp, "%d ", *ent->max_life);
18890926Snectar    else
18990926Snectar	append_string(context, sp, "- ");
19055682Smarkm
19155682Smarkm    /* --- max renewable life */
19290926Snectar    if(ent->max_renew)
19390926Snectar	append_string(context, sp, "%d ", *ent->max_renew);
19490926Snectar    else
19590926Snectar	append_string(context, sp, "- ");
196233294Sstas
19790926Snectar    /* --- flags */
19890926Snectar    append_string(context, sp, "%d ", HDBFlags2int(ent->flags));
19955682Smarkm
20090926Snectar    /* --- generation number */
20190926Snectar    if(ent->generation) {
202178825Sdfr	append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time),
20390926Snectar		      ent->generation->usec,
20490926Snectar		      ent->generation->gen);
20590926Snectar    } else
206178825Sdfr	append_string(context, sp, "- ");
207178825Sdfr
208178825Sdfr    /* --- extensions */
209178825Sdfr    if(ent->extensions && ent->extensions->len > 0) {
210178825Sdfr	for(i = 0; i < ent->extensions->len; i++) {
211178825Sdfr	    void *d;
212233294Sstas	    size_t size, sz = 0;
213178825Sdfr
214178825Sdfr	    ASN1_MALLOC_ENCODE(HDB_extension, d, size,
215178825Sdfr			       &ent->extensions->val[i], &sz, ret);
216178825Sdfr	    if (ret) {
217233294Sstas		krb5_clear_error_message(context);
218178825Sdfr		return ret;
219178825Sdfr	    }
220178825Sdfr	    if(size != sz)
221178825Sdfr		krb5_abortx(context, "internal asn.1 encoder error");
222178825Sdfr
223178825Sdfr	    if (hex_encode(d, size, &p) < 0) {
224178825Sdfr		free(d);
225233294Sstas		krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
226178825Sdfr		return ENOMEM;
227178825Sdfr	    }
228178825Sdfr
229178825Sdfr	    free(d);
230233294Sstas	    append_string(context, sp, "%s%s", p,
231178825Sdfr			  ent->extensions->len - 1 != i ? ":" : "");
232178825Sdfr	    free(p);
233178825Sdfr	}
234178825Sdfr    } else
23590926Snectar	append_string(context, sp, "-");
236178825Sdfr
237233294Sstas
23890926Snectar    return 0;
23990926Snectar}
24090926Snectar
24190926Snectarkrb5_error_code
24290926Snectarhdb_entry2string (krb5_context context, hdb_entry *ent, char **str)
24390926Snectar{
24490926Snectar    krb5_error_code ret;
24590926Snectar    krb5_data data;
24690926Snectar    krb5_storage *sp;
24790926Snectar
24890926Snectar    sp = krb5_storage_emem();
24990926Snectar    if(sp == NULL) {
250233294Sstas	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
25190926Snectar	return ENOMEM;
25290926Snectar    }
253233294Sstas
25490926Snectar    ret = entry2string_int(context, sp, ent);
25590926Snectar    if(ret) {
25690926Snectar	krb5_storage_free(sp);
25790926Snectar	return ret;
25890926Snectar    }
25990926Snectar
260102644Snectar    krb5_storage_write(sp, "\0", 1);
26190926Snectar    krb5_storage_to_data(sp, &data);
26290926Snectar    krb5_storage_free(sp);
26390926Snectar    *str = data.data;
26455682Smarkm    return 0;
26555682Smarkm}
26655682Smarkm
26755682Smarkm/* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */
26855682Smarkm
26955682Smarkmkrb5_error_code
270178825Sdfrhdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, void *data)
27155682Smarkm{
27290926Snectar    krb5_error_code ret;
27390926Snectar    krb5_storage *sp;
27490926Snectar
27590926Snectar    FILE *f = data;
27690926Snectar
27790926Snectar    fflush(f);
27890926Snectar    sp = krb5_storage_from_fd(fileno(f));
27990926Snectar    if(sp == NULL) {
280233294Sstas	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
28190926Snectar	return ENOMEM;
28290926Snectar    }
283233294Sstas
284178825Sdfr    ret = entry2string_int(context, sp, &entry->entry);
28590926Snectar    if(ret) {
28690926Snectar	krb5_storage_free(sp);
28790926Snectar	return ret;
28890926Snectar    }
28990926Snectar
290102644Snectar    krb5_storage_write(sp, "\n", 1);
29190926Snectar    krb5_storage_free(sp);
29255682Smarkm    return 0;
29355682Smarkm}
294