static int base2json(heim_object_t obj, struct twojson *j) { heim_tid_t type; if (obj == NULL) { indent(j); j->out(j->ctx, "<NULL>\n"); } type = heim_get_tid(obj); switch (type) { case HEIM_TID_ARRAY: indent(j); j->out(j->ctx, "[\n"); j->indent++; heim_array_iterate_f(obj, j, array2json); j->indent--; indent(j); j->out(j->ctx, "]\n"); break; case HEIM_TID_DICT: indent(j); j->out(j->ctx, "{\n"); j->indent++; heim_dict_iterate_f(obj, j, dict2json); j->indent--; indent(j); j->out(j->ctx, "}\n"); break; case HEIM_TID_STRING: indent(j); j->out(j->ctx, "\""); j->out(j->ctx, heim_string_get_utf8(obj)); j->out(j->ctx, "\""); break; case HEIM_TID_NUMBER: { char num[16]; indent(j); snprintf(num, sizeof(num), "%d", heim_number_get_int(obj)); j->out(j->ctx, num); break; } case HEIM_TID_NULL: indent(j); j->out(j->ctx, "null"); break; case HEIM_TID_BOOL: indent(j); j->out(j->ctx, heim_bool_val(obj) ? "true" : "false"); break; default: return 1; } return 0; }
static void eval_kgetcred(heim_dict_t o) { heim_string_t server, ccache; krb5_get_creds_opt opt; heim_bool_t nostore; krb5_error_code ret; krb5_ccache cc = NULL; krb5_principal s; krb5_creds *out = NULL; if (ptop) ptop->tgs_req++; server = heim_dict_get_value(o, HSTR("server")); if (server == NULL) krb5_errx(kdc_context, 1, "no server"); ccache = heim_dict_get_value(o, HSTR("ccache")); if (ccache == NULL) krb5_errx(kdc_context, 1, "no ccache"); nostore = heim_dict_get_value(o, HSTR("nostore")); if (nostore == NULL) nostore = heim_bool_create(1); ret = krb5_cc_resolve(kdc_context, heim_string_get_utf8(ccache), &cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_cc_resolve"); ret = krb5_parse_name(kdc_context, heim_string_get_utf8(server), &s); if (ret) krb5_err(kdc_context, 1, ret, "krb5_parse_name"); ret = krb5_get_creds_opt_alloc(kdc_context, &opt); if (ret) krb5_err(kdc_context, 1, ret, "krb5_get_creds_opt_alloc"); if (heim_bool_val(nostore)) krb5_get_creds_opt_add_options(kdc_context, opt, KRB5_GC_NO_STORE); ret = krb5_get_creds(kdc_context, opt, cc, s, &out); if (ret) krb5_err(kdc_context, 1, ret, "krb5_get_creds"); krb5_free_creds(kdc_context, out); krb5_free_principal(kdc_context, s); krb5_get_creds_opt_free(kdc_context, opt); krb5_cc_close(kdc_context, cc); }
static int base2json(heim_object_t obj, struct twojson *j) { heim_tid_t type; int first = 0; if (obj == NULL) { if (j->flags & HEIM_JSON_F_CNULL2JSNULL) { obj = heim_null_create(); } else if (j->flags & HEIM_JSON_F_NO_C_NULL) { return EINVAL; } else { indent(j); j->out(j->ctx, "<NULL>\n"); /* This is NOT valid JSON! */ return 0; } } type = heim_get_tid(obj); switch (type) { case HEIM_TID_ARRAY: indent(j); j->out(j->ctx, "[\n"); j->indent++; first = j->first; j->first = 1; heim_array_iterate_f(obj, j, array2json); j->indent--; if (!j->first) j->out(j->ctx, "\n"); indent(j); j->out(j->ctx, "]\n"); j->first = first; break; case HEIM_TID_DICT: indent(j); j->out(j->ctx, "{\n"); j->indent++; first = j->first; j->first = 1; heim_dict_iterate_f(obj, j, dict2json); j->indent--; if (!j->first) j->out(j->ctx, "\n"); indent(j); j->out(j->ctx, "}\n"); j->first = first; break; case HEIM_TID_STRING: indent(j); j->out(j->ctx, "\""); j->out(j->ctx, heim_string_get_utf8(obj)); j->out(j->ctx, "\""); break; case HEIM_TID_DATA: { heim_dict_t d; heim_string_t v; const heim_octet_string *data; char *b64 = NULL; int ret; if (j->flags & HEIM_JSON_F_NO_DATA) return EINVAL; /* JSON doesn't do binary */ data = heim_data_get_data(obj); ret = base64_encode(data->data, data->length, &b64); if (ret < 0 || b64 == NULL) return ENOMEM; if (j->flags & HEIM_JSON_F_NO_DATA_DICT) { indent(j); j->out(j->ctx, "\""); j->out(j->ctx, b64); /* base64-encode; hope there's no aliasing */ j->out(j->ctx, "\""); free(b64); } else { /* * JSON has no way to represent binary data, therefore the * following is a Heimdal-specific convention. * * We encode binary data as a dict with a single very magic * key with a base64-encoded value. The magic key includes * a uuid, so we're not likely to alias accidentally. */ d = heim_dict_create(2); if (d == NULL) { free(b64); return ENOMEM; } v = heim_string_ref_create(b64, free); if (v == NULL) { free(b64); heim_release(d); return ENOMEM; } ret = heim_dict_set_value(d, heim_tid_data_uuid_key, v); heim_release(v); if (ret) { heim_release(d); return ENOMEM; } ret = base2json(d, j); heim_release(d); if (ret) return ret; } break; } case HEIM_TID_NUMBER: { char num[32]; indent(j); snprintf(num, sizeof (num), "%d", heim_number_get_int(obj)); j->out(j->ctx, num); break; } case HEIM_TID_NULL: indent(j); j->out(j->ctx, "null"); break; case HEIM_TID_BOOL: indent(j); j->out(j->ctx, heim_bool_val(obj) ? "true" : "false"); break; default: return 1; } return 0; }
static void eval_kinit(heim_dict_t o) { heim_string_t user, password, keytab, fast_armor_cc, pk_user_id, ccache; krb5_get_init_creds_opt *opt; krb5_init_creds_context ctx; krb5_principal client; krb5_keytab ktmem = NULL; krb5_ccache fast_cc = NULL; krb5_error_code ret; if (ptop) ptop->as_req++; user = heim_dict_get_value(o, HSTR("client")); if (user == NULL) krb5_errx(kdc_context, 1, "no client"); password = heim_dict_get_value(o, HSTR("password")); keytab = heim_dict_get_value(o, HSTR("keytab")); pk_user_id = heim_dict_get_value(o, HSTR("pkinit-user-cert-id")); if (password == NULL && keytab == NULL && pk_user_id == NULL) krb5_errx(kdc_context, 1, "password, keytab, nor PKINIT user cert ID"); ccache = heim_dict_get_value(o, HSTR("ccache")); ret = krb5_parse_name(kdc_context, heim_string_get_utf8(user), &client); if (ret) krb5_err(kdc_context, 1, ret, "krb5_unparse_name"); /* PKINIT parts */ ret = krb5_get_init_creds_opt_alloc (kdc_context, &opt); if (ret) krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_alloc"); if (pk_user_id) { heim_bool_t rsaobj = heim_dict_get_value(o, HSTR("pkinit-use-rsa")); int use_rsa = rsaobj ? heim_bool_val(rsaobj) : 0; ret = krb5_get_init_creds_opt_set_pkinit(kdc_context, opt, client, heim_string_get_utf8(pk_user_id), NULL, NULL, NULL, use_rsa ? 2 : 0, NULL, NULL, NULL); if (ret) krb5_err(kdc_context, 1, ret, "krb5_get_init_creds_opt_set_pkinit"); } ret = krb5_init_creds_init(kdc_context, client, NULL, NULL, 0, opt, &ctx); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_init"); fast_armor_cc = heim_dict_get_value(o, HSTR("fast-armor-cc")); if (fast_armor_cc) { ret = krb5_cc_resolve(kdc_context, heim_string_get_utf8(fast_armor_cc), &fast_cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_cc_resolve"); ret = krb5_init_creds_set_fast_ccache(kdc_context, ctx, fast_cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_fast_ccache"); } if (password) { ret = krb5_init_creds_set_password(kdc_context, ctx, heim_string_get_utf8(password)); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_password"); } if (keytab) { krb5_keytab kt = NULL; ret = krb5_kt_resolve(kdc_context, heim_string_get_utf8(keytab), &kt); if (ret) krb5_err(kdc_context, 1, ret, "krb5_kt_resolve"); ret = krb5_kt_resolve(kdc_context, "MEMORY:keytab", &ktmem); if (ret) krb5_err(kdc_context, 1, ret, "krb5_kt_resolve(MEMORY)"); ret = copy_keytab(kdc_context, kt, ktmem); if (ret) krb5_err(kdc_context, 1, ret, "copy_keytab"); krb5_kt_close(kdc_context, kt); ret = krb5_init_creds_set_keytab(kdc_context, ctx, ktmem); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_set_keytab"); } ret = krb5_init_creds_get(kdc_context, ctx); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_get"); if (ccache) { const char *name = heim_string_get_utf8(ccache); krb5_creds cred; krb5_ccache cc; ret = krb5_init_creds_get_creds(kdc_context, ctx, &cred); if (ret) krb5_err(kdc_context, 1, ret, "krb5_init_creds_get_creds"); ret = krb5_cc_resolve(kdc_context, name, &cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_cc_resolve"); krb5_init_creds_store(kdc_context, ctx, cc); ret = krb5_cc_close(kdc_context, cc); if (ret) krb5_err(kdc_context, 1, ret, "krb5_cc_close"); krb5_free_cred_contents(kdc_context, &cred); } krb5_init_creds_free(kdc_context, ctx); if (ktmem) krb5_kt_close(kdc_context, ktmem); if (fast_cc) krb5_cc_close(kdc_context, fast_cc); }