1/* 2 * Copyright (c) 1999-2005 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * 3. Neither the name of KTH nor the names of its contributors may be 18 * used to endorse or promote products derived from this software without 19 * specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE 25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 32 33#include "hdb_locl.h" 34#include <hex.h> 35#include <ctype.h> 36 37/* 38 This is the present contents of a dump line. This might change at 39 any time. Fields are separated by white space. 40 41 principal 42 keyblock 43 kvno 44 keys... 45 mkvno 46 enctype 47 keyvalue 48 salt (- means use normal salt) 49 creation date and principal 50 modification date and principal 51 principal valid from date (not used) 52 principal valid end date (not used) 53 principal key expires (not used) 54 max ticket life 55 max renewable life 56 flags 57 generation number 58 */ 59 60static krb5_error_code 61append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...) 62{ 63 krb5_ssize_t sret; 64 char *s; 65 int rc; 66 va_list ap; 67 va_start(ap, fmt); 68 rc = vasprintf(&s, fmt, ap); 69 va_end(ap); 70 if(rc < 0) { 71 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 72 return ENOMEM; 73 } 74 sret = krb5_storage_write(sp, s, strlen(s)); 75 free(s); 76 if (sret != strlen(s)) 77 return ENOMEM; 78 return 0; 79} 80 81static krb5_error_code 82append_hex(krb5_context context, krb5_storage *sp, krb5_data *data) 83{ 84 int printable = 1; 85 size_t i; 86 char *p; 87 88 p = data->data; 89 for(i = 0; i < data->length; i++) 90 if(!isalnum((unsigned char)p[i]) && p[i] != '.'){ 91 printable = 0; 92 break; 93 } 94 if(printable) 95 return append_string(context, sp, "\"%.*s\"", 96 data->length, data->data); 97 hex_encode(data->data, data->length, &p); 98 append_string(context, sp, "%s", p); 99 free(p); 100 return 0; 101} 102 103static char * 104time2str(time_t t) 105{ 106 static char buf[128]; 107 strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t)); 108 return buf; 109} 110 111static krb5_error_code 112append_event(krb5_context context, krb5_storage *sp, Event *ev) 113{ 114 char *pr = NULL; 115 krb5_error_code ret; 116 if(ev == NULL) 117 return append_string(context, sp, "- "); 118 if (ev->principal != NULL) { 119 ret = krb5_unparse_name(context, ev->principal, &pr); 120 if(ret) 121 return ret; 122 } 123 ret = append_string(context, sp, "%s:%s ", 124 time2str(ev->time), pr ? pr : "UNKNOWN"); 125 free(pr); 126 return ret; 127} 128 129static krb5_error_code 130entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent) 131{ 132 char *p; 133 size_t i; 134 krb5_error_code ret; 135 136 /* --- principal */ 137 ret = krb5_unparse_name(context, ent->principal, &p); 138 if(ret) 139 return ret; 140 append_string(context, sp, "%s ", p); 141 free(p); 142 /* --- kvno */ 143 append_string(context, sp, "%d", ent->kvno); 144 /* --- keys */ 145 for(i = 0; i < ent->keys.len; i++){ 146 /* --- mkvno, keytype */ 147 if(ent->keys.val[i].mkvno) 148 append_string(context, sp, ":%d:%d:", 149 *ent->keys.val[i].mkvno, 150 ent->keys.val[i].key.keytype); 151 else 152 append_string(context, sp, "::%d:", 153 ent->keys.val[i].key.keytype); 154 /* --- keydata */ 155 append_hex(context, sp, &ent->keys.val[i].key.keyvalue); 156 append_string(context, sp, ":"); 157 /* --- salt */ 158 if(ent->keys.val[i].salt){ 159 append_string(context, sp, "%u/", ent->keys.val[i].salt->type); 160 append_hex(context, sp, &ent->keys.val[i].salt->salt); 161 }else 162 append_string(context, sp, "-"); 163 } 164 append_string(context, sp, " "); 165 /* --- created by */ 166 append_event(context, sp, &ent->created_by); 167 /* --- modified by */ 168 append_event(context, sp, ent->modified_by); 169 170 /* --- valid start */ 171 if(ent->valid_start) 172 append_string(context, sp, "%s ", time2str(*ent->valid_start)); 173 else 174 append_string(context, sp, "- "); 175 176 /* --- valid end */ 177 if(ent->valid_end) 178 append_string(context, sp, "%s ", time2str(*ent->valid_end)); 179 else 180 append_string(context, sp, "- "); 181 182 /* --- password ends */ 183 if(ent->pw_end) 184 append_string(context, sp, "%s ", time2str(*ent->pw_end)); 185 else 186 append_string(context, sp, "- "); 187 188 /* --- max life */ 189 if(ent->max_life) 190 append_string(context, sp, "%d ", *ent->max_life); 191 else 192 append_string(context, sp, "- "); 193 194 /* --- max renewable life */ 195 if(ent->max_renew) 196 append_string(context, sp, "%d ", *ent->max_renew); 197 else 198 append_string(context, sp, "- "); 199 200 /* --- flags */ 201 append_string(context, sp, "%d ", HDBFlags2int(ent->flags)); 202 203 /* --- generation number */ 204 if(ent->generation) { 205 append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time), 206 ent->generation->usec, 207 ent->generation->gen); 208 } else 209 append_string(context, sp, "- "); 210 211 /* --- extensions */ 212 if(ent->extensions && ent->extensions->len > 0) { 213 for(i = 0; i < ent->extensions->len; i++) { 214 void *d; 215 size_t size, sz = 0; 216 217 ASN1_MALLOC_ENCODE(HDB_extension, d, size, 218 &ent->extensions->val[i], &sz, ret); 219 if (ret) { 220 krb5_clear_error_message(context); 221 return ret; 222 } 223 if(size != sz) 224 krb5_abortx(context, "internal asn.1 encoder error"); 225 226 if (hex_encode(d, size, &p) < 0) { 227 free(d); 228 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 229 return ENOMEM; 230 } 231 232 free(d); 233 append_string(context, sp, "%s%s", p, 234 ent->extensions->len - 1 != i ? ":" : ""); 235 free(p); 236 } 237 } else 238 append_string(context, sp, "-"); 239 240 return 0; 241} 242 243krb5_error_code 244hdb_entry2string (krb5_context context, hdb_entry *ent, char **str) 245{ 246 krb5_error_code ret; 247 krb5_data data; 248 krb5_storage *sp; 249 250 sp = krb5_storage_emem(); 251 if(sp == NULL) { 252 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 253 return ENOMEM; 254 } 255 256 ret = entry2string_int(context, sp, ent); 257 if(ret) { 258 krb5_storage_free(sp); 259 return ret; 260 } 261 262 krb5_storage_write(sp, "\0", 1); 263 krb5_storage_to_data(sp, &data); 264 krb5_storage_free(sp); 265 *str = data.data; 266 return 0; 267} 268 269/* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */ 270 271krb5_error_code 272hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, void *data) 273{ 274 krb5_error_code ret; 275 krb5_storage *sp; 276 277 FILE *f = data; 278 279 fflush(f); 280 sp = krb5_storage_from_fd(fileno(f)); 281 if(sp == NULL) { 282 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 283 return ENOMEM; 284 } 285 286 ret = entry2string_int(context, sp, &entry->entry); 287 if(ret) { 288 krb5_storage_free(sp); 289 return ret; 290 } 291 292 krb5_storage_write(sp, "\n", 1); 293 krb5_storage_free(sp); 294 return 0; 295} 296