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