static krb5_error_code check_compat(OM_uint32 *minor_status, krb5_context context, krb5_const_principal name, const char *option, krb5_boolean *compat, krb5_boolean match_val) { krb5_error_code ret = 0; char **p, **q; krb5_principal match; p = krb5_config_get_strings(context, NULL, "gssapi", option, NULL); if(p == NULL) return 0; match = NULL; for(q = p; *q; q++) { ret = krb5_parse_name(context, *q, &match); if (ret) break; if (krb5_principal_match(context, name, match)) { *compat = match_val; break; } krb5_free_principal(context, match); match = NULL; } if (match) krb5_free_principal(context, match); krb5_config_free_strings(p); if (ret) { if (minor_status) *minor_status = ret; return GSS_S_FAILURE; } return 0; }
static kadm5_ret_t fetch_acl (kadm5_server_context *context, krb5_const_principal princ, unsigned *ret_flags) { FILE *f; krb5_error_code ret = 0; char buf[256]; *ret_flags = 0; /* no acl file -> no rights */ f = fopen(context->config.acl_file, "r"); if (f == NULL) return 0; while(fgets(buf, sizeof(buf), f) != NULL) { char *foo = NULL, *p; krb5_principal this_princ; unsigned flags = 0; p = strtok_r(buf, " \t\n", &foo); if(p == NULL) continue; if (*p == '#') /* comment */ continue; ret = krb5_parse_name(context->context, p, &this_princ); if(ret) break; if(!krb5_principal_compare(context->context, context->caller, this_princ)) { krb5_free_principal(context->context, this_princ); continue; } krb5_free_principal(context->context, this_princ); p = strtok_r(NULL, " \t\n", &foo); if(p == NULL) continue; ret = _kadm5_string_to_privs(p, &flags); if (ret) break; p = strtok_r(NULL, " \t\n", &foo); if (p == NULL) { *ret_flags = flags; break; } if (princ != NULL) { krb5_principal pattern_princ; krb5_boolean match; ret = krb5_parse_name (context->context, p, &pattern_princ); if (ret) break; match = krb5_principal_match (context->context, princ, pattern_princ); krb5_free_principal (context->context, pattern_princ); if (match) { *ret_flags = flags; break; } } } fclose(f); return ret; }
int kt_copy (struct copy_options *opt, int argc, char **argv) { krb5_keytab src_keytab = NULL, dst_keytab = NULL; krb5_principal match_principal = NULL; krb5_keytab_entry entry, dummy; const char *from = argv[0]; const char *to = argv[1]; krb5_kt_cursor cursor; krb5_error_code ret; ret = krb5_kt_resolve (context, from, &src_keytab); if (ret) { krb5_warn (context, ret, "resolving src keytab `%s'", from); goto out; } ret = krb5_kt_resolve (context, to, &dst_keytab); if (ret) { krb5_warn (context, ret, "resolving dst keytab `%s'", to); goto out; } if (opt->match_principal_string) { ret = krb5_parse_name(context, opt->match_principal_string, &match_principal); if (ret) { krb5_warn (context, ret, "failed parsing match principal `%s'", opt->match_principal_string); goto out; } if (verbose_flag) { char *str = NULL; ret = krb5_unparse_name(context, match_principal, &str); if (ret == 0) { fprintf(stderr, "matching on principal %s\n", str); krb5_xfree(str); } } } ret = krb5_kt_start_seq_get (context, src_keytab, &cursor); if (ret) { krb5_warn (context, ret, "krb5_kt_start_seq_get %s", keytab_string); goto out; } if (verbose_flag) fprintf(stderr, "copying %s to %s\n", from, to); while((ret = krb5_kt_next_entry(context, src_keytab, &entry, &cursor)) == 0) { char *name_str; char *etype_str; ret = krb5_unparse_name (context, entry.principal, &name_str); if(ret) { krb5_warn(context, ret, "krb5_unparse_name"); name_str = NULL; /* XXX */ } ret = krb5_enctype_to_string(context, entry.keyblock.keytype, &etype_str); if(ret) { krb5_warn(context, ret, "krb5_enctype_to_string"); etype_str = NULL; /* XXX */ } if (match_principal && !krb5_principal_match(context, entry.principal, match_principal)) { if (verbose_flag) { krb5_warnx(context, "skipping %s, keytype %s, kvno %d", name_str, etype_str, entry.vno); } free(name_str); free(etype_str); continue; } ret = krb5_kt_get_entry(context, dst_keytab, entry.principal, entry.vno, entry.keyblock.keytype, &dummy); if(ret == 0) { /* this entry is already in the new keytab, so no need to copy it; if the keyblocks are not the same, something is weird, so complain about that */ if(!compare_keyblock(&entry.keyblock, &dummy.keyblock)) { krb5_warnx(context, "entry with different keyvalue " "already exists for %s, keytype %s, kvno %d", name_str, etype_str, entry.vno); } krb5_kt_free_entry(context, &dummy); krb5_kt_free_entry (context, &entry); free(name_str); free(etype_str); continue; } else if(ret != KRB5_KT_NOTFOUND) { krb5_warn (context, ret, "%s: fetching %s/%s/%u", to, name_str, etype_str, entry.vno); krb5_kt_free_entry (context, &entry); free(name_str); free(etype_str); break; } if (verbose_flag) fprintf (stderr, "copying %s, keytype %s, kvno %d\n", name_str, etype_str, entry.vno); ret = krb5_kt_add_entry (context, dst_keytab, &entry); krb5_kt_free_entry (context, &entry); if (ret) { krb5_warn (context, ret, "%s: adding %s/%s/%u", to, name_str, etype_str, entry.vno); free(name_str); free(etype_str); break; } free(name_str); free(etype_str); } krb5_kt_end_seq_get (context, src_keytab, &cursor); out: if (match_principal) krb5_free_principal(context, match_principal); if (src_keytab) krb5_kt_close (context, src_keytab); if (dst_keytab) krb5_kt_close (context, dst_keytab); return ret != 0; }