1 /* 2 * Copyright (c) 1997, 1998, 1999 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 the Institute nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #include "kadmin_locl.h" 35 #include <kadm5/private.h> 36 37 RCSID("$Id: load.c,v 1.34 1999/12/02 17:04:58 joda Exp $"); 38 39 struct entry{ 40 char *principal; 41 char *key; 42 char *max_life; 43 char *max_renew; 44 char *created; 45 char *modified; 46 char *valid_start; 47 char *valid_end; 48 char *pw_end; 49 char *flags; 50 char *etypes; 51 }; 52 53 static char * 54 skip_next(char *p) 55 { 56 while(*p && !isspace((unsigned char)*p)) 57 p++; 58 *p++ = 0; 59 while(*p && isspace((unsigned char)*p)) p++; 60 return p; 61 } 62 63 static time_t* 64 parse_time_string(time_t *t, char *s) 65 { 66 int year, month, date, hour, minute, second; 67 struct tm tm; 68 if(strcmp(s, "-") == 0) 69 return NULL; 70 if(t == NULL) 71 t = malloc(sizeof(*t)); 72 sscanf(s, "%04d%02d%02d%02d%02d%02d", 73 &year, &month, &date, &hour, &minute, &second); 74 tm.tm_year = year - 1900; 75 tm.tm_mon = month - 1; 76 tm.tm_mday = date; 77 tm.tm_hour = hour; 78 tm.tm_min = minute; 79 tm.tm_sec = second; 80 tm.tm_isdst = 0; 81 *t = timegm(&tm); 82 return t; 83 } 84 85 static unsigned* 86 parse_integer(unsigned *u, char *s) 87 { 88 if(strcmp(s, "-") == 0) 89 return NULL; 90 if(u == NULL) 91 u = malloc(sizeof(*u)); 92 sscanf(s, "%u", u); 93 return u; 94 } 95 96 static void 97 parse_keys(hdb_entry *ent, char *str) 98 { 99 int tmp; 100 char *p; 101 int i; 102 103 p = strsep(&str, ":"); 104 sscanf(p, "%d", &tmp); 105 ent->kvno = tmp; 106 p = strsep(&str, ":"); 107 while(p){ 108 Key *key; 109 key = realloc(ent->keys.val, 110 (ent->keys.len + 1) * sizeof(*ent->keys.val)); 111 if(key == NULL) 112 abort(); 113 ent->keys.val = key; 114 key = ent->keys.val + ent->keys.len; 115 ent->keys.len++; 116 memset(key, 0, sizeof(*key)); 117 if(sscanf(p, "%d", &tmp) == 1) { 118 key->mkvno = malloc(sizeof(*key->mkvno)); 119 *key->mkvno = tmp; 120 } else 121 key->mkvno = NULL; 122 p = strsep(&str, ":"); 123 sscanf(p, "%d", &tmp); 124 key->key.keytype = tmp; 125 p = strsep(&str, ":"); 126 krb5_data_alloc(&key->key.keyvalue, (strlen(p) - 1) / 2 + 1); 127 for(i = 0; i < strlen(p); i += 2){ 128 sscanf(p + i, "%02x", &tmp); 129 ((u_char*)key->key.keyvalue.data)[i / 2] = tmp; 130 } 131 p = strsep(&str, ":"); 132 if(strcmp(p, "-") != 0){ 133 unsigned type; 134 size_t p_len; 135 if(sscanf(p, "%u/", &type) != 1){ 136 abort (); 137 } 138 p = strchr(p, '/'); 139 if(p == NULL) 140 abort (); 141 p++; 142 p_len = strlen(p); 143 144 key->salt = malloc(sizeof(*key->salt)); 145 key->salt->type = type; 146 147 if (p_len) { 148 if(*p == '\"'){ 149 krb5_data_copy(&key->salt->salt, p + 1, p_len - 2); 150 }else{ 151 krb5_data_alloc(&key->salt->salt, (p_len - 1) / 2 + 1); 152 for(i = 0; i < p_len; i += 2){ 153 sscanf(p + i, "%02x", &tmp); 154 ((u_char*)key->salt->salt.data)[i / 2] = tmp; 155 } 156 } 157 } else 158 krb5_data_zero (&key->salt->salt); 159 } 160 p = strsep(&str, ":"); 161 } 162 } 163 164 static Event* 165 parse_event(Event *ev, char *str) 166 { 167 char *p; 168 if(strcmp(str, "-") == 0) 169 return NULL; 170 if(ev == NULL) 171 ev = malloc(sizeof(*ev)); 172 memset(ev, 0, sizeof(*ev)); 173 p = strsep(&str, ":"); 174 parse_time_string(&ev->time, p); 175 p = strsep(&str, ":"); 176 krb5_parse_name(context, p, &ev->principal); 177 return ev; 178 } 179 180 static HDBFlags 181 parse_hdbflags2int(char *str) 182 { 183 unsigned i; 184 parse_integer(&i, str); 185 186 return int2HDBFlags(i); 187 } 188 189 #if 0 190 static void 191 parse_etypes(char *str, unsigned **val, unsigned *len) 192 { 193 unsigned v; 194 195 *val = NULL; 196 *len = 0; 197 while(sscanf(str, "%u", &v) == 1) { 198 *val = realloc(*val, (*len+1) * sizeof(**val)); 199 (*val)[(*len)++] = v; 200 str = strchr(str, ':'); 201 if(str == NULL) 202 break; 203 str++; 204 } 205 } 206 #endif 207 208 static void 209 doit(char *filename, int merge) 210 { 211 krb5_error_code ret; 212 FILE *f; 213 char s[1024]; 214 char *p; 215 int line; 216 int flags = O_RDWR; 217 struct entry e; 218 hdb_entry ent; 219 HDB *db = _kadm5_s_get_db(kadm_handle); 220 221 f = fopen(filename, "r"); 222 if(f == NULL){ 223 krb5_warn(context, errno, "fopen(%s)", filename); 224 return; 225 } 226 if(!merge) 227 flags |= O_CREAT | O_TRUNC; 228 ret = db->open(context, db, flags, 0600); 229 if(ret){ 230 krb5_warn(context, ret, "hdb_open"); 231 fclose(f); 232 return; 233 } 234 line = 0; 235 while(fgets(s, sizeof(s), f)){ 236 line++; 237 e.principal = s; 238 for(p = s; *p; p++){ 239 if(*p == '\\') 240 p++; 241 else if(isspace((unsigned char)*p)) { 242 *p = 0; 243 break; 244 } 245 } 246 p = skip_next(p); 247 248 e.key = p; 249 p = skip_next(p); 250 251 e.created = p; 252 p = skip_next(p); 253 254 e.modified = p; 255 p = skip_next(p); 256 257 e.valid_start = p; 258 p = skip_next(p); 259 260 e.valid_end = p; 261 p = skip_next(p); 262 263 e.pw_end = p; 264 p = skip_next(p); 265 266 e.max_life = p; 267 p = skip_next(p); 268 269 e.max_renew = p; 270 p = skip_next(p); 271 272 e.flags = p; 273 p = skip_next(p); 274 275 e.etypes = p; 276 p = skip_next(p); 277 278 memset(&ent, 0, sizeof(ent)); 279 ret = krb5_parse_name(context, e.principal, &ent.principal); 280 if(ret){ 281 fprintf(stderr, "%s:%d:%s (%s)\n", 282 filename, 283 line, 284 krb5_get_err_text(context, ret), 285 e.principal); 286 continue; 287 } 288 289 parse_keys(&ent, e.key); 290 291 parse_event(&ent.created_by, e.created); 292 ent.modified_by = parse_event(NULL, e.modified); 293 ent.valid_start = parse_time_string(NULL, e.valid_start); 294 ent.valid_end = parse_time_string(NULL, e.valid_end); 295 ent.pw_end = parse_time_string(NULL, e.pw_end); 296 ent.max_life = parse_integer(NULL, e.max_life); 297 ent.max_renew = parse_integer(NULL, e.max_renew); 298 ent.flags = parse_hdbflags2int(e.flags); 299 #if 0 300 ALLOC(ent.etypes); 301 parse_etypes(e.etypes, &ent.etypes->val, &ent.etypes->len); 302 if(ent.etypes->len == 0) { 303 free(ent.etypes); 304 ent.etypes = NULL; 305 } 306 #endif 307 308 db->store(context, db, HDB_F_REPLACE, &ent); 309 hdb_free_entry (context, &ent); 310 } 311 db->close(context, db); 312 fclose(f); 313 } 314 315 int 316 load(int argc, char **argv) 317 { 318 if(argc < 2){ 319 krb5_warnx(context, "Usage: load filename"); 320 return 0; 321 } 322 doit(argv[1], 0); 323 return 0; 324 } 325 326 int 327 merge(int argc, char **argv) 328 { 329 if(argc < 2){ 330 krb5_warnx(context, "Usage: merge filename"); 331 return 0; 332 } 333 doit(argv[1], 1); 334 return 0; 335 } 336