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 60 static krb5_error_code 61 append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...) 62 { 63 krb5_error_code ret; 64 char *s; 65 va_list ap; 66 va_start(ap, fmt); 67 vasprintf(&s, fmt, ap); 68 va_end(ap); 69 if(s == NULL) { 70 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 71 return ENOMEM; 72 } 73 ret = krb5_storage_write(sp, s, strlen(s)); 74 free(s); 75 return ret; 76 } 77 78 static krb5_error_code 79 append_hex(krb5_context context, krb5_storage *sp, krb5_data *data) 80 { 81 int printable = 1; 82 size_t i; 83 char *p; 84 85 p = data->data; 86 for(i = 0; i < data->length; i++) 87 if(!isalnum((unsigned char)p[i]) && p[i] != '.'){ 88 printable = 0; 89 break; 90 } 91 if(printable) 92 return append_string(context, sp, "\"%.*s\"", 93 data->length, data->data); 94 hex_encode(data->data, data->length, &p); 95 append_string(context, sp, "%s", p); 96 free(p); 97 return 0; 98 } 99 100 static char * 101 time2str(time_t t) 102 { 103 static char buf[128]; 104 strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t)); 105 return buf; 106 } 107 108 static krb5_error_code 109 append_event(krb5_context context, krb5_storage *sp, Event *ev) 110 { 111 char *pr = NULL; 112 krb5_error_code ret; 113 if(ev == NULL) 114 return append_string(context, sp, "- "); 115 if (ev->principal != NULL) { 116 ret = krb5_unparse_name(context, ev->principal, &pr); 117 if(ret) 118 return ret; 119 } 120 ret = append_string(context, sp, "%s:%s ", 121 time2str(ev->time), pr ? pr : "UNKNOWN"); 122 free(pr); 123 return ret; 124 } 125 126 static krb5_error_code 127 entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent) 128 { 129 char *p; 130 size_t i; 131 krb5_error_code ret; 132 133 /* --- principal */ 134 ret = krb5_unparse_name(context, ent->principal, &p); 135 if(ret) 136 return ret; 137 append_string(context, sp, "%s ", p); 138 free(p); 139 /* --- kvno */ 140 append_string(context, sp, "%d", ent->kvno); 141 /* --- keys */ 142 for(i = 0; i < ent->keys.len; i++){ 143 /* --- mkvno, keytype */ 144 if(ent->keys.val[i].mkvno) 145 append_string(context, sp, ":%d:%d:", 146 *ent->keys.val[i].mkvno, 147 ent->keys.val[i].key.keytype); 148 else 149 append_string(context, sp, "::%d:", 150 ent->keys.val[i].key.keytype); 151 /* --- keydata */ 152 append_hex(context, sp, &ent->keys.val[i].key.keyvalue); 153 append_string(context, sp, ":"); 154 /* --- salt */ 155 if(ent->keys.val[i].salt){ 156 append_string(context, sp, "%u/", ent->keys.val[i].salt->type); 157 append_hex(context, sp, &ent->keys.val[i].salt->salt); 158 }else 159 append_string(context, sp, "-"); 160 } 161 append_string(context, sp, " "); 162 /* --- created by */ 163 append_event(context, sp, &ent->created_by); 164 /* --- modified by */ 165 append_event(context, sp, ent->modified_by); 166 167 /* --- valid start */ 168 if(ent->valid_start) 169 append_string(context, sp, "%s ", time2str(*ent->valid_start)); 170 else 171 append_string(context, sp, "- "); 172 173 /* --- valid end */ 174 if(ent->valid_end) 175 append_string(context, sp, "%s ", time2str(*ent->valid_end)); 176 else 177 append_string(context, sp, "- "); 178 179 /* --- password ends */ 180 if(ent->pw_end) 181 append_string(context, sp, "%s ", time2str(*ent->pw_end)); 182 else 183 append_string(context, sp, "- "); 184 185 /* --- max life */ 186 if(ent->max_life) 187 append_string(context, sp, "%d ", *ent->max_life); 188 else 189 append_string(context, sp, "- "); 190 191 /* --- max renewable life */ 192 if(ent->max_renew) 193 append_string(context, sp, "%d ", *ent->max_renew); 194 else 195 append_string(context, sp, "- "); 196 197 /* --- flags */ 198 append_string(context, sp, "%d ", HDBFlags2int(ent->flags)); 199 200 /* --- generation number */ 201 if(ent->generation) { 202 append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time), 203 ent->generation->usec, 204 ent->generation->gen); 205 } else 206 append_string(context, sp, "- "); 207 208 /* --- extensions */ 209 if(ent->extensions && ent->extensions->len > 0) { 210 for(i = 0; i < ent->extensions->len; i++) { 211 void *d; 212 size_t size, sz = 0; 213 214 ASN1_MALLOC_ENCODE(HDB_extension, d, size, 215 &ent->extensions->val[i], &sz, ret); 216 if (ret) { 217 krb5_clear_error_message(context); 218 return ret; 219 } 220 if(size != sz) 221 krb5_abortx(context, "internal asn.1 encoder error"); 222 223 if (hex_encode(d, size, &p) < 0) { 224 free(d); 225 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 226 return ENOMEM; 227 } 228 229 free(d); 230 append_string(context, sp, "%s%s", p, 231 ent->extensions->len - 1 != i ? ":" : ""); 232 free(p); 233 } 234 } else 235 append_string(context, sp, "-"); 236 237 238 return 0; 239 } 240 241 krb5_error_code 242 hdb_entry2string (krb5_context context, hdb_entry *ent, char **str) 243 { 244 krb5_error_code ret; 245 krb5_data data; 246 krb5_storage *sp; 247 248 sp = krb5_storage_emem(); 249 if(sp == NULL) { 250 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 251 return ENOMEM; 252 } 253 254 ret = entry2string_int(context, sp, ent); 255 if(ret) { 256 krb5_storage_free(sp); 257 return ret; 258 } 259 260 krb5_storage_write(sp, "\0", 1); 261 krb5_storage_to_data(sp, &data); 262 krb5_storage_free(sp); 263 *str = data.data; 264 return 0; 265 } 266 267 /* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */ 268 269 krb5_error_code 270 hdb_print_entry(krb5_context context, HDB *db, hdb_entry_ex *entry, void *data) 271 { 272 krb5_error_code ret; 273 krb5_storage *sp; 274 275 FILE *f = data; 276 277 fflush(f); 278 sp = krb5_storage_from_fd(fileno(f)); 279 if(sp == NULL) { 280 krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 281 return ENOMEM; 282 } 283 284 ret = entry2string_int(context, sp, &entry->entry); 285 if(ret) { 286 krb5_storage_free(sp); 287 return ret; 288 } 289 290 krb5_storage_write(sp, "\n", 1); 291 krb5_storage_free(sp); 292 return 0; 293 } 294