1 /* $NetBSD: mit_dump.c,v 1.3 2019/12/15 22:50:46 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2000 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hprop.h" 37 38 extern krb5_error_code _hdb_mdb_value2entry(krb5_context context, 39 krb5_data *data, 40 krb5_kvno target_kvno, 41 hdb_entry *entry); 42 43 extern int _hdb_mit_dump2mitdb_entry(krb5_context context, 44 char *line, 45 krb5_storage *sp); 46 47 48 49 /* 50 can have any number of princ stanzas. 51 format is as follows (only \n indicates newlines) 52 princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38) 53 %d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU) 54 %d\t (number of tl_data) 55 %d\t (number of key data, e.g. how many keys for this user) 56 %d\t (extra data length) 57 %s\t (principal name) 58 %d\t (attributes) 59 %d\t (max lifetime, seconds) 60 %d\t (max renewable life, seconds) 61 %d\t (expiration, seconds since epoch or 2145830400 for never) 62 %d\t (password expiration, seconds, 0 for never) 63 %d\t (last successful auth, seconds since epoch) 64 %d\t (last failed auth, per above) 65 %d\t (failed auth count) 66 foreach tl_data 0 to number of tl_data - 1 as above 67 %d\t%d\t (data type, data length) 68 foreach tl_data 0 to length-1 69 %02x (tl data contents[element n]) 70 except if tl_data length is 0 71 %d (always -1) 72 \t 73 foreach key 0 to number of keys - 1 as above 74 %d\t%d\t (key data version, kvno) 75 foreach version 0 to key data version - 1 (a key or a salt) 76 %d\t%d\t(data type for this key, data length for this key) 77 foreach key data length 0 to length-1 78 %02x (key data contents[element n]) 79 except if key_data length is 0 80 %d (always -1) 81 \t 82 foreach extra data length 0 to length - 1 83 %02x (extra data part) 84 unless no extra data 85 %d (always -1) 86 ;\n 87 88 */ 89 90 static char * 91 nexttoken(char **p) 92 { 93 char *q; 94 do { 95 q = strsep(p, " \t"); 96 } while(q && *q == '\0'); 97 return q; 98 } 99 100 #include <kadm5/admin.h> 101 102 /* XXX: Principal names with '\n' cannot be dumped or loaded */ 103 static int 104 my_fgetln(FILE *f, char **bufp, size_t *szp, size_t *lenp) 105 { 106 size_t len; 107 size_t sz = *szp; 108 char *buf = *bufp; 109 char *p, *n; 110 111 if (!buf) { 112 buf = malloc(sz ? sz : 8192); 113 if (!buf) 114 return ENOMEM; 115 if (!sz) 116 sz = 8192; 117 } 118 119 len = 0; 120 while ((p = fgets(&buf[len], sz-len, f)) != NULL) { 121 len += strlen(&buf[len]); 122 if (buf[len-1] == '\n') 123 break; 124 if (feof(f)) 125 break; 126 if (sz > SIZE_MAX/2 || 127 (n = realloc(buf, sz += 1 + (sz >> 1))) == NULL) { 128 free(buf); 129 *bufp = NULL; 130 *szp = 0; 131 *lenp = 0; 132 return ENOMEM; 133 } 134 buf = n; 135 } 136 *bufp = buf; 137 *szp = sz; 138 *lenp = len; 139 return 0; /* *len == 0 || no EOL -> EOF */ 140 } 141 142 int 143 mit_prop_dump(void *arg, const char *file) 144 { 145 krb5_error_code ret; 146 size_t line_bufsz = 0; 147 size_t line_len = 0; 148 char *line = NULL; 149 int lineno = 0; 150 FILE *f; 151 struct hdb_entry_ex ent; 152 struct prop_data *pd = arg; 153 krb5_storage *sp = NULL; 154 krb5_data kdb_ent; 155 156 memset(&ent, 0, sizeof (ent)); 157 f = fopen(file, "r"); 158 if (f == NULL) 159 return errno; 160 161 ret = ENOMEM; 162 sp = krb5_storage_emem(); 163 if (!sp) 164 goto out; 165 while ((ret = my_fgetln(f, &line, &line_bufsz, &line_len)) == 0 && 166 line_len > 0) { 167 char *p = line; 168 char *q; 169 170 lineno++; 171 if(strncmp(line, "kdb5_util", strlen("kdb5_util")) == 0) { 172 int major; 173 q = nexttoken(&p); 174 if (strcmp(q, "kdb5_util")) 175 errx(1, "line %d: unknown version", lineno); 176 q = nexttoken(&p); /* load_dump */ 177 if (strcmp(q, "load_dump")) 178 errx(1, "line %d: unknown version", lineno); 179 q = nexttoken(&p); /* load_dump */ 180 if (strcmp(q, "version")) 181 errx(1, "line %d: unknown version", lineno); 182 q = nexttoken(&p); /* x.0 */ 183 if (sscanf(q, "%d", &major) != 1) 184 errx(1, "line %d: unknown version", lineno); 185 if (major != 4 && major != 5 && major != 6) 186 errx(1, "unknown dump file format, got %d, expected 4-6", 187 major); 188 continue; 189 } else if(strncmp(p, "policy", strlen("policy")) == 0) { 190 warnx("line: %d: ignoring policy (not supported)", lineno); 191 continue; 192 } else if(strncmp(p, "princ", strlen("princ")) != 0) { 193 warnx("line %d: not a principal", lineno); 194 continue; 195 } 196 krb5_storage_truncate(sp, 0); 197 ret = _hdb_mit_dump2mitdb_entry(pd->context, line, sp); 198 if (ret) { 199 if (ret > 0) 200 warn("line: %d: failed to parse; ignoring", lineno); 201 else 202 warnx("line: %d: failed to parse; ignoring", lineno); 203 continue; 204 } 205 ret = krb5_storage_to_data(sp, &kdb_ent); 206 if (ret) break; 207 ret = _hdb_mdb_value2entry(pd->context, &kdb_ent, 0, &ent.entry); 208 krb5_data_free(&kdb_ent); 209 if (ret) { 210 warnx("line: %d: failed to store; ignoring", lineno); 211 continue; 212 } 213 ret = v5_prop(pd->context, NULL, &ent, arg); 214 hdb_free_entry(pd->context, &ent); 215 if (ret) break; 216 } 217 218 out: 219 fclose(f); 220 free(line); 221 if (sp) 222 krb5_storage_free(sp); 223 if (ret && ret == ENOMEM) 224 errx(1, "out of memory"); 225 if (ret) 226 errx(1, "line %d: problem parsing dump line", lineno); 227 return ret; 228 } 229 230