int kt_remove(struct remove_options *opt, int argc, char **argv) { krb5_error_code ret = 0; krb5_keytab_entry entry; krb5_keytab keytab; krb5_principal principal = NULL; krb5_enctype enctype = 0; if(opt->principal_string) { ret = krb5_parse_name(context, opt->principal_string, &principal); if(ret) { krb5_warn(context, ret, "%s", opt->principal_string); return 1; } } if(opt->enctype_string) { ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype); if(ret) { int t; if(sscanf(opt->enctype_string, "%d", &t) == 1) enctype = t; else { krb5_warn(context, ret, "%s", opt->enctype_string); if(principal) krb5_free_principal(context, principal); return 1; } } } if (!principal && !enctype && !opt->kvno_integer) { krb5_warnx(context, "You must give at least one of " "principal, enctype or kvno."); ret = EINVAL; goto out; } if((keytab = ktutil_open_keytab()) == NULL) { ret = 1; goto out; } entry.principal = principal; entry.keyblock.keytype = enctype; entry.vno = opt->kvno_integer; ret = krb5_kt_remove_entry(context, keytab, &entry); krb5_kt_close(context, keytab); if(ret) krb5_warn(context, ret, "remove"); out: if(principal) krb5_free_principal(context, principal); return ret != 0; }
int kt_destroy (void *opt, int argc, char **argv) { krb5_error_code ret; krb5_keytab keytab; if((keytab = ktutil_open_keytab()) == NULL) return 1; ret = krb5_kt_destroy (context, keytab); if (ret) { krb5_warn (context, ret, "destroy keytab failed"); return 1; } return 0; }
int kt_get(struct get_options *opt, int argc, char **argv) { krb5_error_code ret = 0; krb5_keytab keytab; void *kadm_handle = NULL; krb5_enctype *etypes = NULL; size_t netypes = 0; size_t i; int a, j; unsigned int failed = 0; if((keytab = ktutil_open_keytab()) == NULL) return 1; if(opt->realm_string) krb5_set_default_realm(context, opt->realm_string); if (opt->enctypes_strings.num_strings != 0) { etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes)); if (etypes == NULL) { krb5_warnx(context, "malloc failed"); goto out; } netypes = opt->enctypes_strings.num_strings; for(i = 0; i < netypes; i++) { ret = krb5_string_to_enctype(context, opt->enctypes_strings.strings[i], &etypes[i]); if(ret) { krb5_warnx(context, "unrecognized enctype: %s", opt->enctypes_strings.strings[i]); goto out; } } } for(a = 0; a < argc; a++){ krb5_principal princ_ent; kadm5_principal_ent_rec princ; int mask = 0; krb5_keyblock *keys; int n_keys; int created = 0; krb5_keytab_entry entry; ret = krb5_parse_name(context, argv[a], &princ_ent); if (ret) { krb5_warn(context, ret, "can't parse principal %s", argv[a]); failed++; continue; } memset(&princ, 0, sizeof(princ)); princ.principal = princ_ent; mask |= KADM5_PRINCIPAL; princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; mask |= KADM5_ATTRIBUTES; princ.princ_expire_time = 0; mask |= KADM5_PRINC_EXPIRE_TIME; if(kadm_handle == NULL) { const char *r; if(opt->realm_string != NULL) r = opt->realm_string; else r = krb5_principal_get_realm(context, princ_ent); kadm_handle = open_kadmin_connection(opt->principal_string, r, opt->admin_server_string, opt->server_port_integer); if(kadm_handle == NULL) break; } ret = kadm5_create_principal(kadm_handle, &princ, mask, "x"); if(ret == 0) created = 1; else if(ret != KADM5_DUP) { krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[a]); krb5_free_principal(context, princ_ent); failed++; continue; } ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys); if (ret) { krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[a]); krb5_free_principal(context, princ_ent); failed++; continue; } ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES); if (ret) { krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[a]); for (j = 0; j < n_keys; j++) krb5_free_keyblock_contents(context, &keys[j]); krb5_free_principal(context, princ_ent); failed++; continue; } if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX)) krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[a]); princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX); mask = KADM5_ATTRIBUTES; if(created) { princ.kvno = 1; mask |= KADM5_KVNO; } ret = kadm5_modify_principal(kadm_handle, &princ, mask); if (ret) { krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[a]); for (j = 0; j < n_keys; j++) krb5_free_keyblock_contents(context, &keys[j]); krb5_free_principal(context, princ_ent); failed++; continue; } for(j = 0; j < n_keys; j++) { int do_add = TRUE; if (netypes) { size_t k; do_add = FALSE; for (k = 0; k < netypes; ++k) if (keys[j].keytype == etypes[k]) { do_add = TRUE; break; } } if (do_add) { entry.principal = princ_ent; entry.vno = princ.kvno; entry.keyblock = keys[j]; entry.timestamp = time (NULL); ret = krb5_kt_add_entry(context, keytab, &entry); if (ret) krb5_warn(context, ret, "krb5_kt_add_entry"); } krb5_free_keyblock_contents(context, &keys[j]); } kadm5_free_principal_ent(kadm_handle, &princ); krb5_free_principal(context, princ_ent); } out: free(etypes); if (kadm_handle) kadm5_destroy(kadm_handle); krb5_kt_close(context, keytab); return ret != 0 || failed > 0; }
int kt_purge(struct purge_options *opt, int argc, char **argv) { krb5_error_code ret = 0; krb5_kt_cursor cursor; krb5_keytab keytab; krb5_keytab_entry entry; int age; struct e *head = NULL; time_t judgement_day; age = parse_time(opt->age_string, "s"); if(age < 0) { krb5_warnx(context, "unparasable time `%s'", opt->age_string); return 1; } if((keytab = ktutil_open_keytab()) == NULL) return 1; ret = krb5_kt_start_seq_get(context, keytab, &cursor); if(ret){ krb5_warn(context, ret, "%s", keytab_string); goto out; } while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) { add_entry (entry.principal, entry.vno, entry.timestamp, &head); krb5_kt_free_entry(context, &entry); } krb5_kt_end_seq_get(context, keytab, &cursor); judgement_day = time (NULL); ret = krb5_kt_start_seq_get(context, keytab, &cursor); if(ret){ krb5_warn(context, ret, "%s", keytab_string); goto out; } while(krb5_kt_next_entry(context, keytab, &entry, &cursor) == 0) { struct e *e = get_entry (entry.principal, head); if (e == NULL) { krb5_warnx (context, "ignoring extra entry"); continue; } if (entry.vno < e->max_vno && judgement_day - e->timestamp > age) { if (verbose_flag) { char *name_str; krb5_unparse_name (context, entry.principal, &name_str); printf ("removing %s vno %d\n", name_str, entry.vno); free (name_str); } ret = krb5_kt_remove_entry (context, keytab, &entry); if (ret) krb5_warn (context, ret, "remove"); } krb5_kt_free_entry(context, &entry); } ret = krb5_kt_end_seq_get(context, keytab, &cursor); delete_list (head); out: krb5_kt_close (context, keytab); return ret != 0; }
int kt_rename(struct rename_options *opt, int argc, char **argv) { krb5_error_code ret = 0; krb5_keytab_entry entry; krb5_keytab keytab; krb5_kt_cursor cursor; krb5_principal from_princ, to_princ; ret = krb5_parse_name(context, argv[0], &from_princ); if(ret != 0) { krb5_warn(context, ret, "%s", argv[0]); return 1; } ret = krb5_parse_name(context, argv[1], &to_princ); if(ret != 0) { krb5_free_principal(context, from_princ); krb5_warn(context, ret, "%s", argv[1]); return 1; } if((keytab = ktutil_open_keytab()) == NULL) { krb5_free_principal(context, from_princ); krb5_free_principal(context, to_princ); return 1; } ret = krb5_kt_start_seq_get(context, keytab, &cursor); if(ret) { krb5_kt_close(context, keytab); krb5_free_principal(context, from_princ); krb5_free_principal(context, to_princ); return 1; } while(1) { ret = krb5_kt_next_entry(context, keytab, &entry, &cursor); if(ret != 0) { if(ret != KRB5_CC_END && ret != KRB5_KT_END) krb5_warn(context, ret, "getting entry from keytab"); else ret = 0; break; } if(krb5_principal_compare(context, entry.principal, from_princ)) { krb5_free_principal(context, entry.principal); entry.principal = to_princ; ret = krb5_kt_add_entry(context, keytab, &entry); if(ret) { entry.principal = NULL; krb5_kt_free_entry(context, &entry); krb5_warn(context, ret, "adding entry"); break; } if (opt->delete_flag) { entry.principal = from_princ; ret = krb5_kt_remove_entry(context, keytab, &entry); if(ret) { entry.principal = NULL; krb5_kt_free_entry(context, &entry); krb5_warn(context, ret, "removing entry"); break; } } entry.principal = NULL; } krb5_kt_free_entry(context, &entry); } krb5_kt_end_seq_get(context, keytab, &cursor); krb5_free_principal(context, from_princ); krb5_free_principal(context, to_princ); return ret != 0; }
int kt_change (struct change_options *opt, int argc, char **argv) { krb5_error_code ret; krb5_keytab keytab; krb5_kt_cursor cursor; krb5_keytab_entry entry; int i, j, max; struct change_set *changeset; int errors = 0; if((keytab = ktutil_open_keytab()) == NULL) return 1; j = 0; max = 0; changeset = NULL; ret = krb5_kt_start_seq_get(context, keytab, &cursor); if(ret){ krb5_warn(context, ret, "%s", keytab_string); goto out; } while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) { int add = 0; for (i = 0; i < j; ++i) { if (krb5_principal_compare (context, changeset[i].principal, entry.principal)) { if (changeset[i].kvno < entry.vno) changeset[i].kvno = entry.vno; break; } } if (i < j) { krb5_kt_free_entry (context, &entry); continue; } if (argc == 0) { add = 1; } else { for (i = 0; i < argc; ++i) { krb5_principal princ; ret = krb5_parse_name (context, argv[i], &princ); if (ret) { krb5_warn (context, ret, "%s", argv[i]); continue; } if (krb5_principal_compare (context, princ, entry.principal)) add = 1; krb5_free_principal (context, princ); } } if (add) { if (j >= max) { void *tmp; max = max(max * 2, 1); tmp = realloc (changeset, max * sizeof(*changeset)); if (tmp == NULL) { krb5_kt_free_entry (context, &entry); krb5_warnx (context, "realloc: out of memory"); ret = ENOMEM; break; } changeset = tmp; } ret = krb5_copy_principal (context, entry.principal, &changeset[j].principal); if (ret) { krb5_warn (context, ret, "krb5_copy_principal"); krb5_kt_free_entry (context, &entry); break; } changeset[j].kvno = entry.vno; ++j; } krb5_kt_free_entry (context, &entry); } krb5_kt_end_seq_get(context, keytab, &cursor); if (ret == KRB5_KT_END) { ret = 0; for (i = 0; i < j; i++) { if (verbose_flag) { char *client_name; ret = krb5_unparse_name (context, changeset[i].principal, &client_name); if (ret) { krb5_warn (context, ret, "krb5_unparse_name"); } else { printf("Changing %s kvno %d\n", client_name, changeset[i].kvno); free(client_name); } } ret = change_entry (keytab, changeset[i].principal, changeset[i].kvno, opt->realm_string, opt->admin_server_string, opt->server_port_integer); if (ret != 0) errors = 1; } } else errors = 1; for (i = 0; i < j; i++) krb5_free_principal (context, changeset[i].principal); free (changeset); out: krb5_kt_close(context, keytab); return errors; }
int kt_add(struct add_options *opt, int argc, char **argv) { krb5_error_code ret; krb5_keytab keytab; krb5_keytab_entry entry; char buf[1024]; krb5_enctype enctype; if((keytab = ktutil_open_keytab()) == NULL) return 1; memset(&entry, 0, sizeof(entry)); if(opt->principal_string == NULL) { if(readstring("Principal: ", buf, sizeof(buf)) == NULL) return 1; opt->principal_string = buf; } ret = krb5_parse_name(context, opt->principal_string, &entry.principal); if(ret) { krb5_warn(context, ret, "%s", opt->principal_string); goto out; } if(opt->enctype_string == NULL) { if(readstring("Encryption type: ", buf, sizeof(buf)) == NULL) { ret = 1; goto out; } opt->enctype_string = buf; } ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype); if(ret) { int t; if(sscanf(opt->enctype_string, "%d", &t) == 1) enctype = t; else { krb5_warn(context, ret, "%s", opt->enctype_string); goto out; } } if(opt->kvno_integer == -1) { if(readstring("Key version: ", buf, sizeof(buf)) == NULL) { ret = 1; goto out; } if(sscanf(buf, "%u", &opt->kvno_integer) != 1) goto out; } if(opt->password_string == NULL && opt->random_flag == 0) { if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: "******"malloc"); goto out; } if ((size_t)hex_decode(opt->password_string, data, len) != len) { free(data); krb5_warn(context, ENOMEM, "hex decode failed"); goto out; } ret = krb5_keyblock_init(context, enctype, data, len, &entry.keyblock); free(data); } else if (!opt->salt_flag) { krb5_salt salt; krb5_data pw; salt.salttype = KRB5_PW_SALT; salt.saltvalue.data = NULL; salt.saltvalue.length = 0; pw.data = (void*)opt->password_string; pw.length = strlen(opt->password_string); ret = krb5_string_to_key_data_salt(context, enctype, pw, salt, &entry.keyblock); } else { ret = krb5_string_to_key(context, enctype, opt->password_string, entry.principal, &entry.keyblock); } memset (opt->password_string, 0, strlen(opt->password_string)); } else { ret = krb5_generate_random_keyblock(context, enctype, &entry.keyblock); } if(ret) { krb5_warn(context, ret, "add"); goto out; } entry.vno = opt->kvno_integer; entry.timestamp = time (NULL); ret = krb5_kt_add_entry(context, keytab, &entry); if(ret) krb5_warn(context, ret, "add"); out: krb5_kt_free_entry(context, &entry); krb5_kt_close(context, keytab); return ret != 0; }