155682Smarkm/* 2233294Sstas * Copyright (c) 1997-2005 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadmin_locl.h" 35178825Sdfr#include "kadmin-commands.h" 3655682Smarkm#include <kadm5/private.h> 3755682Smarkm 3857416Smarkmstruct entry { 3955682Smarkm char *principal; 4055682Smarkm char *key; 4155682Smarkm char *max_life; 4255682Smarkm char *max_renew; 4355682Smarkm char *created; 4455682Smarkm char *modified; 4555682Smarkm char *valid_start; 4655682Smarkm char *valid_end; 4755682Smarkm char *pw_end; 4855682Smarkm char *flags; 4990926Snectar char *generation; 50178825Sdfr char *extensions; 5155682Smarkm}; 5255682Smarkm 5355682Smarkmstatic char * 5455682Smarkmskip_next(char *p) 5555682Smarkm{ 56233294Sstas while(*p && !isspace((unsigned char)*p)) 5755682Smarkm p++; 5855682Smarkm *p++ = 0; 5957416Smarkm while(*p && isspace((unsigned char)*p)) 6057416Smarkm p++; 6155682Smarkm return p; 6255682Smarkm} 6355682Smarkm 6457416Smarkm/* 6557416Smarkm * Parse the time in `s', returning: 6657416Smarkm * -1 if error parsing 6757416Smarkm * 0 if none present 6857416Smarkm * 1 if parsed ok 6957416Smarkm */ 7057416Smarkm 7157416Smarkmstatic int 7257416Smarkmparse_time_string(time_t *t, const char *s) 7355682Smarkm{ 7455682Smarkm int year, month, date, hour, minute, second; 7555682Smarkm struct tm tm; 7657416Smarkm 7755682Smarkm if(strcmp(s, "-") == 0) 7857416Smarkm return 0; 79233294Sstas if(sscanf(s, "%04d%02d%02d%02d%02d%02d", 8057416Smarkm &year, &month, &date, &hour, &minute, &second) != 6) 8157416Smarkm return -1; 8257416Smarkm tm.tm_year = year - 1900; 8357416Smarkm tm.tm_mon = month - 1; 8457416Smarkm tm.tm_mday = date; 8557416Smarkm tm.tm_hour = hour; 8657416Smarkm tm.tm_min = minute; 8757416Smarkm tm.tm_sec = second; 8855682Smarkm tm.tm_isdst = 0; 8955682Smarkm *t = timegm(&tm); 9057416Smarkm return 1; 9155682Smarkm} 9255682Smarkm 9357416Smarkm/* 9457416Smarkm * parse time, allocating space in *t if it's there 9557416Smarkm */ 9657416Smarkm 9757416Smarkmstatic int 9857416Smarkmparse_time_string_alloc (time_t **t, const char *s) 9955682Smarkm{ 10057416Smarkm time_t tmp; 10157416Smarkm int ret; 10257416Smarkm 10357416Smarkm *t = NULL; 10457416Smarkm ret = parse_time_string (&tmp, s); 10557416Smarkm if (ret == 1) { 10657416Smarkm *t = malloc (sizeof (**t)); 10757416Smarkm if (*t == NULL) 10857416Smarkm krb5_errx (context, 1, "malloc: out of memory"); 10957416Smarkm **t = tmp; 11057416Smarkm } 11157416Smarkm return ret; 11257416Smarkm} 11357416Smarkm 11457416Smarkm/* 11557416Smarkm * see parse_time_string for calling convention 11657416Smarkm */ 11757416Smarkm 11857416Smarkmstatic int 119178825Sdfrparse_integer(unsigned int *u, const char *s) 12057416Smarkm{ 12155682Smarkm if(strcmp(s, "-") == 0) 12257416Smarkm return 0; 12357416Smarkm if (sscanf(s, "%u", u) != 1) 12457416Smarkm return -1; 12557416Smarkm return 1; 12655682Smarkm} 12755682Smarkm 12857416Smarkmstatic int 129178825Sdfrparse_integer_alloc (unsigned int **u, const char *s) 13057416Smarkm{ 131178825Sdfr unsigned int tmp; 13257416Smarkm int ret; 13357416Smarkm 13457416Smarkm *u = NULL; 13557416Smarkm ret = parse_integer (&tmp, s); 13657416Smarkm if (ret == 1) { 13757416Smarkm *u = malloc (sizeof (**u)); 13857416Smarkm if (*u == NULL) 13957416Smarkm krb5_errx (context, 1, "malloc: out of memory"); 14057416Smarkm **u = tmp; 14157416Smarkm } 14257416Smarkm return ret; 14357416Smarkm} 14457416Smarkm 14557416Smarkm/* 14657416Smarkm * Parse dumped keys in `str' and store them in `ent' 14757416Smarkm * return -1 if parsing failed 14857416Smarkm */ 14957416Smarkm 15057416Smarkmstatic int 15155682Smarkmparse_keys(hdb_entry *ent, char *str) 15255682Smarkm{ 15357416Smarkm krb5_error_code ret; 15455682Smarkm int tmp; 15555682Smarkm char *p; 156233294Sstas size_t i; 157233294Sstas 15855682Smarkm p = strsep(&str, ":"); 15957416Smarkm if (sscanf(p, "%d", &tmp) != 1) 16057416Smarkm return 1; 16155682Smarkm ent->kvno = tmp; 16255682Smarkm p = strsep(&str, ":"); 16355682Smarkm while(p){ 16455682Smarkm Key *key; 165233294Sstas key = realloc(ent->keys.val, 16655682Smarkm (ent->keys.len + 1) * sizeof(*ent->keys.val)); 16755682Smarkm if(key == NULL) 16857416Smarkm krb5_errx (context, 1, "realloc: out of memory"); 16955682Smarkm ent->keys.val = key; 17055682Smarkm key = ent->keys.val + ent->keys.len; 17155682Smarkm ent->keys.len++; 17255682Smarkm memset(key, 0, sizeof(*key)); 17355682Smarkm if(sscanf(p, "%d", &tmp) == 1) { 17455682Smarkm key->mkvno = malloc(sizeof(*key->mkvno)); 17555682Smarkm *key->mkvno = tmp; 17655682Smarkm } else 17755682Smarkm key->mkvno = NULL; 17855682Smarkm p = strsep(&str, ":"); 17957416Smarkm if (sscanf(p, "%d", &tmp) != 1) 18057416Smarkm return 1; 18155682Smarkm key->key.keytype = tmp; 18255682Smarkm p = strsep(&str, ":"); 18357416Smarkm ret = krb5_data_alloc(&key->key.keyvalue, (strlen(p) - 1) / 2 + 1); 18457416Smarkm if (ret) 18557416Smarkm krb5_err (context, 1, ret, "krb5_data_alloc"); 18657416Smarkm for(i = 0; i < strlen(p); i += 2) { 18757416Smarkm if(sscanf(p + i, "%02x", &tmp) != 1) 18857416Smarkm return 1; 18955682Smarkm ((u_char*)key->key.keyvalue.data)[i / 2] = tmp; 19055682Smarkm } 19155682Smarkm p = strsep(&str, ":"); 19255682Smarkm if(strcmp(p, "-") != 0){ 19355682Smarkm unsigned type; 19455682Smarkm size_t p_len; 19557416Smarkm 19657416Smarkm if(sscanf(p, "%u/", &type) != 1) 19757416Smarkm return 1; 19855682Smarkm p = strchr(p, '/'); 19955682Smarkm if(p == NULL) 20057416Smarkm return 1; 20155682Smarkm p++; 20255682Smarkm p_len = strlen(p); 20355682Smarkm 204233294Sstas key->salt = calloc(1, sizeof(*key->salt)); 20557416Smarkm if (key->salt == NULL) 20657416Smarkm krb5_errx (context, 1, "malloc: out of memory"); 20755682Smarkm key->salt->type = type; 208233294Sstas 20955682Smarkm if (p_len) { 21057416Smarkm if(*p == '\"') { 21157416Smarkm ret = krb5_data_copy(&key->salt->salt, p + 1, p_len - 2); 21257416Smarkm if (ret) 21357416Smarkm krb5_err (context, 1, ret, "krb5_data_copy"); 21457416Smarkm } else { 21557416Smarkm ret = krb5_data_alloc(&key->salt->salt, 21657416Smarkm (p_len - 1) / 2 + 1); 21757416Smarkm if (ret) 21857416Smarkm krb5_err (context, 1, ret, "krb5_data_alloc"); 21955682Smarkm for(i = 0; i < p_len; i += 2){ 22057416Smarkm if (sscanf(p + i, "%02x", &tmp) != 1) 22157416Smarkm return 1; 22255682Smarkm ((u_char*)key->salt->salt.data)[i / 2] = tmp; 22355682Smarkm } 22455682Smarkm } 22555682Smarkm } else 22655682Smarkm krb5_data_zero (&key->salt->salt); 22755682Smarkm } 22855682Smarkm p = strsep(&str, ":"); 22955682Smarkm } 23057416Smarkm return 0; 23155682Smarkm} 23255682Smarkm 23357416Smarkm/* 23457416Smarkm * see parse_time_string for calling convention 23557416Smarkm */ 23657416Smarkm 23757416Smarkmstatic int 23857416Smarkmparse_event(Event *ev, char *s) 23955682Smarkm{ 24057416Smarkm krb5_error_code ret; 24155682Smarkm char *p; 24257416Smarkm 24357416Smarkm if(strcmp(s, "-") == 0) 24457416Smarkm return 0; 24555682Smarkm memset(ev, 0, sizeof(*ev)); 24657416Smarkm p = strsep(&s, ":"); 24757416Smarkm if(parse_time_string(&ev->time, p) != 1) 24857416Smarkm return -1; 24957416Smarkm p = strsep(&s, ":"); 25057416Smarkm ret = krb5_parse_name(context, p, &ev->principal); 25157416Smarkm if (ret) 25257416Smarkm return -1; 25357416Smarkm return 1; 25455682Smarkm} 25555682Smarkm 25657416Smarkmstatic int 25757416Smarkmparse_event_alloc (Event **ev, char *s) 25855682Smarkm{ 25957416Smarkm Event tmp; 26057416Smarkm int ret; 26155682Smarkm 26257416Smarkm *ev = NULL; 26357416Smarkm ret = parse_event (&tmp, s); 26457416Smarkm if (ret == 1) { 26557416Smarkm *ev = malloc (sizeof (**ev)); 26657416Smarkm if (*ev == NULL) 26757416Smarkm krb5_errx (context, 1, "malloc: out of memory"); 26857416Smarkm **ev = tmp; 26957416Smarkm } 27057416Smarkm return ret; 27155682Smarkm} 27255682Smarkm 27357416Smarkmstatic int 27457416Smarkmparse_hdbflags2int(HDBFlags *f, const char *s) 27557416Smarkm{ 27657416Smarkm int ret; 277178825Sdfr unsigned int tmp; 27857416Smarkm 27957416Smarkm ret = parse_integer (&tmp, s); 28057416Smarkm if (ret == 1) 28157416Smarkm *f = int2HDBFlags (tmp); 28257416Smarkm return ret; 28357416Smarkm} 28457416Smarkm 28590926Snectarstatic int 28690926Snectarparse_generation(char *str, GENERATION **gen) 28755682Smarkm{ 28890926Snectar char *p; 28990926Snectar int v; 29090926Snectar 291103423Snectar if(strcmp(str, "-") == 0 || *str == '\0') { 29290926Snectar *gen = NULL; 293103423Snectar return 0; 294103423Snectar } 29590926Snectar *gen = calloc(1, sizeof(**gen)); 29690926Snectar 29790926Snectar p = strsep(&str, ":"); 29890926Snectar if(parse_time_string(&(*gen)->time, p) != 1) 29990926Snectar return -1; 30090926Snectar p = strsep(&str, ":"); 30190926Snectar if(sscanf(p, "%d", &v) != 1) 30290926Snectar return -1; 30390926Snectar (*gen)->usec = v; 30490926Snectar p = strsep(&str, ":"); 30590926Snectar if(sscanf(p, "%d", &v) != 1) 30690926Snectar return -1; 30790926Snectar (*gen)->gen = v - 1; /* XXX gets bumped in _hdb_store */ 30890926Snectar return 0; 30955682Smarkm} 31055682Smarkm 311178825Sdfrstatic int 312178825Sdfrparse_extensions(char *str, HDB_extensions **e) 313178825Sdfr{ 314178825Sdfr char *p; 315178825Sdfr int ret; 31690926Snectar 317178825Sdfr if(strcmp(str, "-") == 0 || *str == '\0') { 318178825Sdfr *e = NULL; 319178825Sdfr return 0; 320178825Sdfr } 321178825Sdfr *e = calloc(1, sizeof(**e)); 322178825Sdfr 323178825Sdfr p = strsep(&str, ":"); 324178825Sdfr 325178825Sdfr while (p) { 326178825Sdfr HDB_extension ext; 327178825Sdfr ssize_t len; 328178825Sdfr void *d; 329178825Sdfr 330178825Sdfr len = strlen(p); 331178825Sdfr d = malloc(len); 332178825Sdfr 333178825Sdfr len = hex_decode(p, d, len); 334233294Sstas if (len < 0) { 335233294Sstas free(d); 336178825Sdfr return -1; 337233294Sstas } 338178825Sdfr 339178825Sdfr ret = decode_HDB_extension(d, len, &ext, NULL); 340178825Sdfr free(d); 341178825Sdfr if (ret) 342178825Sdfr return -1; 343178825Sdfr d = realloc((*e)->val, ((*e)->len + 1) * sizeof((*e)->val[0])); 344178825Sdfr if (d == NULL) 345178825Sdfr abort(); 346178825Sdfr (*e)->val = d; 347178825Sdfr (*e)->val[(*e)->len] = ext; 348178825Sdfr (*e)->len++; 349178825Sdfr 350178825Sdfr p = strsep(&str, ":"); 351178825Sdfr } 352178825Sdfr 353178825Sdfr return 0; 354178825Sdfr} 355178825Sdfr 356178825Sdfr 35757416Smarkm/* 35857416Smarkm * Parse the dump file in `filename' and create the database (merging 35957416Smarkm * iff merge) 36057416Smarkm */ 36157416Smarkm 36257416Smarkmstatic int 363178825Sdfrdoit(const char *filename, int mergep) 36455682Smarkm{ 36555682Smarkm krb5_error_code ret; 36655682Smarkm FILE *f; 36790926Snectar char s[8192]; /* XXX should fix this properly */ 36855682Smarkm char *p; 36955682Smarkm int line; 37055682Smarkm int flags = O_RDWR; 37155682Smarkm struct entry e; 372178825Sdfr hdb_entry_ex ent; 37355682Smarkm HDB *db = _kadm5_s_get_db(kadm_handle); 37455682Smarkm 37555682Smarkm f = fopen(filename, "r"); 37655682Smarkm if(f == NULL){ 37755682Smarkm krb5_warn(context, errno, "fopen(%s)", filename); 37857416Smarkm return 1; 37955682Smarkm } 38072445Sassar ret = kadm5_log_truncate (kadm_handle); 38172445Sassar if (ret) { 38272445Sassar fclose (f); 38372445Sassar krb5_warn(context, ret, "kadm5_log_truncate"); 38472445Sassar return 1; 38572445Sassar } 38672445Sassar 387178825Sdfr if(!mergep) 38855682Smarkm flags |= O_CREAT | O_TRUNC; 389178825Sdfr ret = db->hdb_open(context, db, flags, 0600); 39055682Smarkm if(ret){ 39155682Smarkm krb5_warn(context, ret, "hdb_open"); 39255682Smarkm fclose(f); 39357416Smarkm return 1; 39455682Smarkm } 39555682Smarkm line = 0; 39672445Sassar ret = 0; 39772445Sassar while(fgets(s, sizeof(s), f) != NULL) { 39855682Smarkm line++; 399178825Sdfr 400178825Sdfr p = s; 401178825Sdfr while (isspace((unsigned char)*p)) 402178825Sdfr p++; 403178825Sdfr 404178825Sdfr e.principal = p; 40555682Smarkm for(p = s; *p; p++){ 40655682Smarkm if(*p == '\\') 40755682Smarkm p++; 40855682Smarkm else if(isspace((unsigned char)*p)) { 40955682Smarkm *p = 0; 41055682Smarkm break; 41155682Smarkm } 41255682Smarkm } 41355682Smarkm p = skip_next(p); 414233294Sstas 41555682Smarkm e.key = p; 41655682Smarkm p = skip_next(p); 41755682Smarkm 41855682Smarkm e.created = p; 41955682Smarkm p = skip_next(p); 42055682Smarkm 42155682Smarkm e.modified = p; 42255682Smarkm p = skip_next(p); 42355682Smarkm 42455682Smarkm e.valid_start = p; 42555682Smarkm p = skip_next(p); 42655682Smarkm 42755682Smarkm e.valid_end = p; 42855682Smarkm p = skip_next(p); 42955682Smarkm 43055682Smarkm e.pw_end = p; 43155682Smarkm p = skip_next(p); 43255682Smarkm 43355682Smarkm e.max_life = p; 43455682Smarkm p = skip_next(p); 43555682Smarkm 43655682Smarkm e.max_renew = p; 43755682Smarkm p = skip_next(p); 43855682Smarkm 43955682Smarkm e.flags = p; 44055682Smarkm p = skip_next(p); 44155682Smarkm 44290926Snectar e.generation = p; 44355682Smarkm p = skip_next(p); 44455682Smarkm 445178825Sdfr e.extensions = p; 446233294Sstas skip_next(p); 447178825Sdfr 44855682Smarkm memset(&ent, 0, sizeof(ent)); 449178825Sdfr ret = krb5_parse_name(context, e.principal, &ent.entry.principal); 45057416Smarkm if(ret) { 451233294Sstas const char *msg = krb5_get_error_message(context, ret); 452233294Sstas fprintf(stderr, "%s:%d:%s (%s)\n", 453233294Sstas filename, line, msg, e.principal); 454233294Sstas krb5_free_error_message(context, msg); 45555682Smarkm continue; 45655682Smarkm } 457233294Sstas 458178825Sdfr if (parse_keys(&ent.entry, e.key)) { 45957416Smarkm fprintf (stderr, "%s:%d:error parsing keys (%s)\n", 46057416Smarkm filename, line, e.key); 46157416Smarkm hdb_free_entry (context, &ent); 46257416Smarkm continue; 46357416Smarkm } 464233294Sstas 465178825Sdfr if (parse_event(&ent.entry.created_by, e.created) == -1) { 46657416Smarkm fprintf (stderr, "%s:%d:error parsing created event (%s)\n", 46757416Smarkm filename, line, e.created); 46857416Smarkm hdb_free_entry (context, &ent); 46957416Smarkm continue; 47057416Smarkm } 471178825Sdfr if (parse_event_alloc (&ent.entry.modified_by, e.modified) == -1) { 47257416Smarkm fprintf (stderr, "%s:%d:error parsing event (%s)\n", 47357416Smarkm filename, line, e.modified); 47457416Smarkm hdb_free_entry (context, &ent); 47557416Smarkm continue; 47657416Smarkm } 477178825Sdfr if (parse_time_string_alloc (&ent.entry.valid_start, e.valid_start) == -1) { 47857416Smarkm fprintf (stderr, "%s:%d:error parsing time (%s)\n", 47957416Smarkm filename, line, e.valid_start); 48057416Smarkm hdb_free_entry (context, &ent); 48157416Smarkm continue; 48257416Smarkm } 483178825Sdfr if (parse_time_string_alloc (&ent.entry.valid_end, e.valid_end) == -1) { 48457416Smarkm fprintf (stderr, "%s:%d:error parsing time (%s)\n", 48557416Smarkm filename, line, e.valid_end); 48657416Smarkm hdb_free_entry (context, &ent); 48757416Smarkm continue; 48857416Smarkm } 489178825Sdfr if (parse_time_string_alloc (&ent.entry.pw_end, e.pw_end) == -1) { 49057416Smarkm fprintf (stderr, "%s:%d:error parsing time (%s)\n", 49157416Smarkm filename, line, e.pw_end); 49257416Smarkm hdb_free_entry (context, &ent); 49357416Smarkm continue; 49457416Smarkm } 49557416Smarkm 496178825Sdfr if (parse_integer_alloc (&ent.entry.max_life, e.max_life) == -1) { 49757416Smarkm fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n", 49857416Smarkm filename, line, e.max_life); 49957416Smarkm hdb_free_entry (context, &ent); 50057416Smarkm continue; 50157416Smarkm 50257416Smarkm } 503178825Sdfr if (parse_integer_alloc (&ent.entry.max_renew, e.max_renew) == -1) { 50457416Smarkm fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n", 50557416Smarkm filename, line, e.max_renew); 50657416Smarkm hdb_free_entry (context, &ent); 50757416Smarkm continue; 50857416Smarkm } 50957416Smarkm 510178825Sdfr if (parse_hdbflags2int (&ent.entry.flags, e.flags) != 1) { 51157416Smarkm fprintf (stderr, "%s:%d:error parsing flags (%s)\n", 51257416Smarkm filename, line, e.flags); 51357416Smarkm hdb_free_entry (context, &ent); 51457416Smarkm continue; 51557416Smarkm } 51690926Snectar 517178825Sdfr if(parse_generation(e.generation, &ent.entry.generation) == -1) { 51890926Snectar fprintf (stderr, "%s:%d:error parsing generation (%s)\n", 51990926Snectar filename, line, e.generation); 52090926Snectar hdb_free_entry (context, &ent); 52190926Snectar continue; 52255682Smarkm } 52355682Smarkm 524178825Sdfr if(parse_extensions(e.extensions, &ent.entry.extensions) == -1) { 525178825Sdfr fprintf (stderr, "%s:%d:error parsing extension (%s)\n", 526178825Sdfr filename, line, e.extensions); 527178825Sdfr hdb_free_entry (context, &ent); 528178825Sdfr continue; 529178825Sdfr } 530178825Sdfr 531178825Sdfr ret = db->hdb_store(context, db, HDB_F_REPLACE, &ent); 53255682Smarkm hdb_free_entry (context, &ent); 53372445Sassar if (ret) { 53472445Sassar krb5_warn(context, ret, "db_store"); 53572445Sassar break; 53672445Sassar } 53755682Smarkm } 538178825Sdfr db->hdb_close(context, db); 53955682Smarkm fclose(f); 54072445Sassar return ret != 0; 54155682Smarkm} 54255682Smarkm 54372445Sassar 544178825Sdfrextern int local_flag; 54572445Sassar 546178825Sdfrstatic int 547178825Sdfrloadit(int mergep, const char *name, int argc, char **argv) 54872445Sassar{ 549178825Sdfr if(!local_flag) { 550178825Sdfr krb5_warnx(context, "%s is only available in local (-l) mode", name); 55155682Smarkm return 0; 55255682Smarkm } 55372445Sassar 554178825Sdfr return doit(argv[0], mergep); 55555682Smarkm} 556233294Sstas 55755682Smarkmint 558178825Sdfrload(void *opt, int argc, char **argv) 55955682Smarkm{ 560178825Sdfr return loadit(0, "load", argc, argv); 56155682Smarkm} 562233294Sstas 563178825Sdfrint 564178825Sdfrmerge(void *opt, int argc, char **argv) 565178825Sdfr{ 566178825Sdfr return loadit(1, "merge", argc, argv); 567178825Sdfr} 568