KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_get_creds_opt_set_ticket(krb5_context context, krb5_get_creds_opt opt, const Ticket *ticket) { if (opt->ticket) { free_Ticket(opt->ticket); free(opt->ticket); opt->ticket = NULL; } if (ticket) { krb5_error_code ret; opt->ticket = malloc(sizeof(*ticket)); if (opt->ticket == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } ret = copy_Ticket(ticket, opt->ticket); if (ret) { free(opt->ticket); opt->ticket = NULL; krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); return ret; } } return 0; }
KRB5_LIB_FUNCTION void KRB5_LIB_CALL krb5_get_creds_opt_free(krb5_context context, krb5_get_creds_opt opt) { if (opt->self) krb5_free_principal(context, opt->self); if (opt->ticket) { free_Ticket(opt->ticket); free(opt->ticket); } memset(opt, 0, sizeof(*opt)); free(opt); }
int krb5_kdc_process_request(krb5_context context, krb5_kdc_configuration *config, unsigned char *buf, size_t len, krb5_data *reply, krb5_boolean *prependlength, const char *from, struct sockaddr *addr, int datagram_reply) { KDC_REQ req; Ticket ticket; DigestREQ digestreq; krb5_error_code ret; size_t i; gettimeofday(&_kdc_now, NULL); if(decode_AS_REQ(buf, len, &req, &i) == 0){ krb5_data req_buffer; req_buffer.data = buf; req_buffer.length = len; ret = _kdc_as_rep(context, config, &req, &req_buffer, reply, from, addr, datagram_reply); free_AS_REQ(&req); return ret; }else if(decode_TGS_REQ(buf, len, &req, &i) == 0){ ret = _kdc_tgs_rep(context, config, &req, reply, from, addr); free_TGS_REQ(&req); return ret; }else if(decode_Ticket(buf, len, &ticket, &i) == 0){ ret = _kdc_do_524(context, config, &ticket, reply, from, addr); free_Ticket(&ticket); return ret; }else if(decode_DigestREQ(buf, len, &digestreq, &i) == 0){ ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr); free_DigestREQ(&digestreq); return ret; } else if(_kdc_maybe_version4(buf, len)){ *prependlength = FALSE; /* elbitapmoc sdrawkcab XXX */ _kdc_do_version4(context, config, buf, len, reply, from, (struct sockaddr_in*)addr); return 0; } else if (config->enable_kaserver) { ret = _kdc_do_kaserver(context, config, buf, len, reply, from, (struct sockaddr_in*)addr); return ret; } return -1; }
void free_KRB_CRED(KRB_CRED *data) { free_MESSAGE_TYPE(&(data)->msg_type); while((&(data)->tickets)->len){ free_Ticket(&(&(data)->tickets)->val[(&(data)->tickets)->len-1]); (&(data)->tickets)->len--; } free((&(data)->tickets)->val); (&(data)->tickets)->val = NULL; free_EncryptedData(&(data)->enc_part); }
static void copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) { Ticket ticket; size_t len; int ret; ret = decode_Ticket(v5cred->ticket.data, v5cred->ticket.length, &ticket, &len); if (ret == 0) { strncpy(dest, ticket.realm, destlen - 1); dest[destlen - 1] = '\0'; free_Ticket(&ticket); } }
krb5_error_code KRB5_LIB_FUNCTION krb5_build_ap_req (krb5_context context, krb5_enctype enctype, krb5_creds *cred, krb5_flags ap_options, krb5_data authenticator, krb5_data *retdata) { krb5_error_code ret = 0; AP_REQ ap; Ticket t; size_t len; ap.pvno = 5; ap.msg_type = krb_ap_req; memset(&ap.ap_options, 0, sizeof(ap.ap_options)); ap.ap_options.use_session_key = (ap_options & AP_OPTS_USE_SESSION_KEY) > 0; ap.ap_options.mutual_required = (ap_options & AP_OPTS_MUTUAL_REQUIRED) > 0; ap.ticket.tkt_vno = 5; copy_Realm(&cred->server->realm, &ap.ticket.realm); copy_PrincipalName(&cred->server->name, &ap.ticket.sname); decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len); copy_EncryptedData(&t.enc_part, &ap.ticket.enc_part); free_Ticket(&t); ap.authenticator.etype = enctype; ap.authenticator.kvno = NULL; ap.authenticator.cipher = authenticator; ASN1_MALLOC_ENCODE(AP_REQ, retdata->data, retdata->length, &ap, &len, ret); if(ret == 0 && retdata->length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); free_AP_REQ(&ap); return ret; }
static void print_cred_verbose(krb5_context context, krb5_creds *cred) { int j; char *str; krb5_error_code ret; krb5_timestamp sec; krb5_timeofday (context, &sec); ret = krb5_unparse_name(context, cred->server, &str); if(ret) exit(1); printf(N_("Server: %s\n", ""), str); free (str); ret = krb5_unparse_name(context, cred->client, &str); if(ret) exit(1); printf(N_("Client: %s\n", ""), str); free (str); { Ticket t; size_t len; char *s; decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len); ret = krb5_enctype_to_string(context, t.enc_part.etype, &s); printf(N_("Ticket etype: ", "")); if (ret == 0) { printf("%s", s); free(s); } else { printf(N_("unknown-enctype(%d)", ""), t.enc_part.etype); } if(t.enc_part.kvno) printf(N_(", kvno %d", ""), *t.enc_part.kvno); printf("\n"); if(cred->session.keytype != t.enc_part.etype) { ret = krb5_enctype_to_string(context, cred->session.keytype, &str); if(ret) krb5_warn(context, ret, "session keytype"); else { printf(N_("Session key: %s\n", "enctype"), str); free(str); } } free_Ticket(&t); printf(N_("Ticket length: %lu\n", ""), (unsigned long)cred->ticket.length); } printf(N_("Auth time: %s\n", ""), printable_time_long(cred->times.authtime)); if(cred->times.authtime != cred->times.starttime) printf(N_("Start time: %s\n", ""), printable_time_long(cred->times.starttime)); printf(N_("End time: %s", ""), printable_time_long(cred->times.endtime)); if(sec > cred->times.endtime) printf(N_(" (expired)", "")); printf("\n"); if(cred->flags.b.renewable) printf(N_("Renew till: %s\n", ""), printable_time_long(cred->times.renew_till)); { char flags[1024]; unparse_flags(TicketFlags2int(cred->flags.b), asn1_TicketFlags_units(), flags, sizeof(flags)); printf(N_("Ticket flags: %s\n", ""), flags); } printf(N_("Addresses: ", "")); if (cred->addresses.len != 0) { for(j = 0; j < cred->addresses.len; j++){ char buf[128]; size_t len; if(j) printf(", "); ret = krb5_print_address(&cred->addresses.val[j], buf, sizeof(buf), &len); if(ret == 0) printf("%s", buf); } } else { printf(N_("addressless", "")); } printf("\n\n"); }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache cache; krb5_creds *out; int optidx = 0; krb5_get_creds_opt opt; krb5_principal server; krb5_principal impersonate = NULL; setprogname (argv[0]); ret = krb5_init_context (&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if(version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (argc != 1) usage (1); if(cache_str) { ret = krb5_cc_resolve(context, cache_str, &cache); if (ret) krb5_err (context, 1, ret, "%s", cache_str); } else { ret = krb5_cc_default (context, &cache); if (ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); } ret = krb5_get_creds_opt_alloc(context, &opt); if (ret) krb5_err (context, 1, ret, "krb5_get_creds_opt_alloc"); if (etype_str) { krb5_enctype enctype; ret = krb5_string_to_enctype(context, etype_str, &enctype); if (ret) krb5_errx (context, 1, N_("unrecognized enctype: %s", ""), etype_str); krb5_get_creds_opt_set_enctype(context, opt, enctype); } if (impersonate_str) { ret = krb5_parse_name(context, impersonate_str, &impersonate); if (ret) krb5_err (context, 1, ret, "krb5_parse_name %s", impersonate_str); krb5_get_creds_opt_set_impersonate(context, opt, impersonate); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); } if (out_cache_str) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); if (forwardable_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE); if (!transit_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK); if (canonicalize_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE); if (delegation_cred_str) { krb5_ccache id; krb5_creds c, mc; Ticket ticket; krb5_cc_clear_mcred(&mc); ret = krb5_cc_get_principal(context, cache, &mc.server); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_principal"); ret = krb5_cc_resolve(context, delegation_cred_str, &id); if(ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c); if(ret) krb5_err (context, 1, ret, "krb5_cc_retrieve_cred"); ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL); if (ret) { krb5_clear_error_message(context); krb5_err (context, 1, ret, "decode_Ticket"); } krb5_free_cred_contents(context, &c); ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket); if(ret) krb5_err (context, 1, ret, "krb5_get_creds_opt_set_ticket"); free_Ticket(&ticket); krb5_cc_close (context, id); krb5_free_principal(context, mc.server); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CONSTRAINED_DELEGATION); } ret = krb5_parse_name(context, argv[0], &server); if (ret) krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]); if (nametype_str) { int32_t nametype; ret = krb5_parse_nametype(context, nametype_str, &nametype); if (ret) krb5_err(context, 1, ret, "krb5_parse_nametype"); server->name.name_type = (NAME_TYPE)nametype; } ret = krb5_get_creds(context, opt, cache, server, &out); if (ret) krb5_err (context, 1, ret, "krb5_get_creds"); if (out_cache_str) { krb5_ccache id; ret = krb5_cc_resolve(context, out_cache_str, &id); if(ret) krb5_err (context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_initialize(context, id, out->client); if(ret) krb5_err (context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred(context, id, out); if(ret) krb5_err (context, 1, ret, "krb5_cc_store_cred"); krb5_cc_close (context, id); } krb5_free_creds(context, out); krb5_free_principal(context, server); krb5_get_creds_opt_free(context, opt); krb5_cc_close (context, cache); krb5_free_context (context); return 0; }
static int v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524) { int kvno, ret; kt->ticket = NULL; /* check if des key */ if (cred->session.keyvalue.length != 8) return EINVAL; if (local524) { Ticket t; unsigned char *buf; size_t buf_len; size_t len; kvno = KAFS_RXKAD_2B_KVNO; ret = decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len); if (ret) return ret; if (t.tkt_vno != 5) return -1; ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_len, &t.enc_part, &len, ret); free_Ticket(&t); if (ret) return ret; if(buf_len != len) { free(buf); return KRB5KRB_ERR_GENERIC; } kt->ticket = buf; kt->ticket_len = buf_len; } else { kvno = KAFS_RXKAD_K5_KVNO; kt->ticket = malloc(cred->ticket.length); if (kt->ticket == NULL) return ENOMEM; kt->ticket_len = cred->ticket.length; memcpy(kt->ticket, cred->ticket.data, kt->ticket_len); ret = 0; } /* * Build a struct ClearToken */ kt->ct.AuthHandle = kvno; memcpy(kt->ct.HandShakeKey, cred->session.keyvalue.data, 8); kt->ct.ViceId = uid; kt->ct.BeginTimestamp = cred->times.starttime; kt->ct.EndTimestamp = cred->times.endtime; _kafs_fixup_viceid(&kt->ct, uid); return 0; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache cache; krb5_creds *out; int optidx = 0; int32_t nametype = KRB5_NT_UNKNOWN; krb5_get_creds_opt opt; krb5_principal server = NULL; krb5_principal impersonate; setprogname(argv[0]); ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) usage(1); if (help_flag) usage (0); if (version_flag) { print_version(NULL); exit(0); } argc -= optidx; argv += optidx; if (debug_flag) { ret = krb5_set_debug_dest(context, getprogname(), "STDERR"); if (ret) krb5_warn(context, ret, "krb5_set_debug_dest"); } if (cache_str) { ret = krb5_cc_resolve(context, cache_str, &cache); if (ret) krb5_err(context, 1, ret, "%s", cache_str); } else { ret = krb5_cc_default (context, &cache); if (ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); } ret = krb5_get_creds_opt_alloc(context, &opt); if (ret) krb5_err(context, 1, ret, "krb5_get_creds_opt_alloc"); if (etype_str) { krb5_enctype enctype; ret = krb5_string_to_enctype(context, etype_str, &enctype); if (ret) krb5_errx(context, 1, N_("unrecognized enctype: %s", ""), etype_str); krb5_get_creds_opt_set_enctype(context, opt, enctype); } if (impersonate_str) { ret = krb5_parse_name(context, impersonate_str, &impersonate); if (ret) krb5_err(context, 1, ret, "krb5_parse_name %s", impersonate_str); krb5_get_creds_opt_set_impersonate(context, opt, impersonate); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); krb5_free_principal(context, impersonate); } if (out_cache_str) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); if (forwardable_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE); if (!transit_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK); if (canonicalize_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE); if (!store_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE); if (cached_only_flag) krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CACHED); if (delegation_cred_str) { krb5_ccache id; krb5_creds c, mc; Ticket ticket; krb5_cc_clear_mcred(&mc); ret = krb5_cc_get_principal(context, cache, &mc.server); if (ret) krb5_err(context, 1, ret, "krb5_cc_get_principal"); ret = krb5_cc_resolve(context, delegation_cred_str, &id); if(ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c); if(ret) krb5_err(context, 1, ret, "krb5_cc_retrieve_cred"); ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL); if (ret) { krb5_clear_error_message(context); krb5_err(context, 1, ret, "decode_Ticket"); } krb5_free_cred_contents(context, &c); ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket); if(ret) krb5_err(context, 1, ret, "krb5_get_creds_opt_set_ticket"); free_Ticket(&ticket); krb5_cc_close(context, id); krb5_free_principal(context, mc.server); krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CONSTRAINED_DELEGATION); } if (nametype_str != NULL) { ret = krb5_parse_nametype(context, nametype_str, &nametype); if (ret) krb5_err(context, 1, ret, "krb5_parse_nametype"); } if (nametype == KRB5_NT_SRV_HST || nametype == KRB5_NT_SRV_HST_NEEDS_CANON) is_hostbased_flag = 1; if (is_hostbased_flag) { const char *sname = NULL; const char *hname = NULL; if (nametype_str != NULL && nametype != KRB5_NT_SRV_HST && nametype != KRB5_NT_SRV_HST_NEEDS_CANON) krb5_errx(context, 1, "--hostbased not compatible with " "non-hostbased --name-type"); if (is_canonical_flag) nametype = KRB5_NT_SRV_HST; else nametype = KRB5_NT_SRV_HST_NEEDS_CANON; /* * Host-based service names can have more than one component. * * RFC5179 did not, but should have, assign a Kerberos name-type * corresponding to GSS_C_NT_DOMAINBASED. But it's basically a * host-based service name type with one additional component. * * So that's how we're treating host-based service names here: * two or more components. */ if (argc == 0) { usage(1); } else if (argc == 1) { krb5_principal server2; /* * In this case the one argument is a principal name, not the * service name. * * We parse the argument as a principal name, extract the service * and hostname components, use krb5_sname_to_principal(), then * extract the service and hostname components from that. */ ret = krb5_parse_name(context, argv[0], &server); if (ret) krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]); sname = krb5_principal_get_comp_string(context, server, 0); /* * If a single-component principal name is given, then we'll * default the hostname, as krb5_principal_get_comp_string() * returns NULL in this case. */ hname = krb5_principal_get_comp_string(context, server, 1); ret = krb5_sname_to_principal(context, hname, sname, KRB5_NT_SRV_HST, &server2); sname = krb5_principal_get_comp_string(context, server2, 0); hname = krb5_principal_get_comp_string(context, server2, 1); /* * Modify the original with the new sname/hname. This way we * retain any additional principal name components from the given * principal name. * * The name-type is set further below. */ ret = krb5_principal_set_comp_string(context, server, 0, sname); if (ret) krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]); ret = krb5_principal_set_comp_string(context, server, 1, hname); if (ret) krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]); krb5_free_principal(context, server2); } else { size_t i; /* * In this case the arguments are principal name components. * * The service and hostname components can be defaulted by passing * empty strings. */ sname = argv[0]; if (*sname == '\0') sname = NULL; hname = argv[1]; if (hname == NULL || *hname == '\0') hname = NULL; ret = krb5_sname_to_principal(context, hname, sname, KRB5_NT_SRV_HST, &server); if (ret) krb5_err(context, 1, ret, "krb5_sname_to_principal"); for (i = 2; i < argc; i++) { ret = krb5_principal_set_comp_string(context, server, i, argv[i]); if (ret) krb5_err(context, 1, ret, "krb5_principal_set_comp_string"); } } } else if (argc == 1) { ret = krb5_parse_name(context, argv[0], &server); if (ret) krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]); } else { usage(1); } if (nametype != KRB5_NT_UNKNOWN) server->name.name_type = (NAME_TYPE)nametype; ret = krb5_get_creds(context, opt, cache, server, &out); if (ret) krb5_err(context, 1, ret, "krb5_get_creds"); if (out_cache_str) { krb5_ccache id; ret = krb5_cc_resolve(context, out_cache_str, &id); if(ret) krb5_err(context, 1, ret, "krb5_cc_resolve"); ret = krb5_cc_initialize(context, id, out->client); if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize"); ret = krb5_cc_store_cred(context, id, out); if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred"); krb5_cc_close(context, id); } krb5_free_creds(context, out); krb5_free_principal(context, server); krb5_get_creds_opt_free(context, opt); krb5_cc_close (context, cache); krb5_free_context (context); return 0; }
krb5_error_code _krb5_mk_req_internal(krb5_context context, krb5_auth_context *auth_context, const krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_data *outbuf, krb5_key_usage checksum_usage, krb5_key_usage encrypt_usage) { krb5_error_code ret; krb5_data authenticator; Checksum c; Checksum *c_opt; krb5_auth_context ac; if(auth_context) { if(*auth_context == NULL) ret = krb5_auth_con_init(context, auth_context); else ret = 0; ac = *auth_context; } else ret = krb5_auth_con_init(context, &ac); if(ret) return ret; if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) { ret = krb5_auth_con_generatelocalsubkey(context, ac, &in_creds->session); if(ret) goto out; } #if 0 { /* This is somewhat bogus since we're possibly overwriting a value specified by the user, but it's the easiest way to make the code use a compatible enctype */ Ticket ticket; krb5_keytype ticket_keytype; ret = decode_Ticket(in_creds->ticket.data, in_creds->ticket.length, &ticket, NULL); krb5_enctype_to_keytype (context, ticket.enc_part.etype, &ticket_keytype); if (ticket_keytype == in_creds->session.keytype) krb5_auth_setenctype(context, ac, ticket.enc_part.etype); free_Ticket(&ticket); } #endif krb5_free_keyblock(context, ac->keyblock); ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock); if (ret) goto out; /* it's unclear what type of checksum we can use. try the best one, except: * a) if it's configured differently for the current realm, or * b) if the session key is des-cbc-crc */ if (in_data) { if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) { /* this is to make DCE secd (and older MIT kdcs?) happy */ ret = krb5_create_checksum(context, NULL, 0, CKSUMTYPE_RSA_MD4, in_data->data, in_data->length, &c); } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 || ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) { /* this is to make MS kdc happy */ ret = krb5_create_checksum(context, NULL, 0, CKSUMTYPE_RSA_MD5, in_data->data, in_data->length, &c); } else { krb5_crypto crypto; ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto); if (ret) goto out; ret = krb5_create_checksum(context, crypto, checksum_usage, 0, in_data->data, in_data->length, &c); krb5_crypto_destroy(context, crypto); } c_opt = &c; } else { c_opt = NULL; } if (ret) goto out; ret = krb5_build_authenticator (context, ac, ac->keyblock->keytype, in_creds, c_opt, NULL, &authenticator, encrypt_usage); if (c_opt) free_Checksum (c_opt); if (ret) goto out; ret = krb5_build_ap_req (context, ac->keyblock->keytype, in_creds, ap_req_options, authenticator, outbuf); out: if(auth_context == NULL) krb5_auth_con_free(context, ac); return ret; }
static krb5_error_code get_cred_kdc_usage(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_addresses *addresses, krb5_creds *in_creds, krb5_creds *krbtgt, krb5_creds *out_creds, krb5_key_usage usage) { TGS_REQ req; krb5_data enc; krb5_data resp; krb5_kdc_rep rep; KRB_ERROR error; krb5_error_code ret; unsigned nonce; krb5_keyblock *subkey = NULL; size_t len; Ticket second_ticket; int send_to_kdc_flags = 0; krb5_data_zero(&resp); krb5_data_zero(&enc); krb5_generate_random_block(&nonce, sizeof(nonce)); nonce &= 0xffffffff; if(flags.b.enc_tkt_in_skey){ ret = decode_Ticket(in_creds->second_ticket.data, in_creds->second_ticket.length, &second_ticket, &len); if(ret) return ret; } ret = init_tgs_req (context, id, addresses, flags, flags.b.enc_tkt_in_skey ? &second_ticket : NULL, in_creds, krbtgt, nonce, &subkey, &req, usage); if(flags.b.enc_tkt_in_skey) free_Ticket(&second_ticket); if (ret) goto out; ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret); if (ret) goto out; if(enc.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); /* don't free addresses */ req.req_body.addresses = NULL; free_TGS_REQ(&req); /* * Send and receive */ again: ret = krb5_sendto_kdc_flags (context, &enc, &krbtgt->server->name.name_string.val[1], &resp, send_to_kdc_flags); if(ret) goto out; memset(&rep, 0, sizeof(rep)); if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0){ ret = krb5_copy_principal(context, in_creds->client, &out_creds->client); if(ret) goto out; ret = krb5_copy_principal(context, in_creds->server, &out_creds->server); if(ret) goto out; /* this should go someplace else */ out_creds->times.endtime = in_creds->times.endtime; ret = _krb5_extract_ticket(context, &rep, out_creds, &krbtgt->session, NULL, KRB5_KU_TGS_REP_ENC_PART_SESSION, &krbtgt->addresses, nonce, TRUE, flags.b.request_anonymous, decrypt_tkt_with_subkey, subkey); krb5_free_kdc_rep(context, &rep); } else if(krb5_rd_error(context, &resp, &error) == 0) { ret = krb5_error_from_rd_error(context, &error, in_creds); krb5_free_error_contents(context, &error); if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) { send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; krb5_data_free(&resp); goto again; } } else if(resp.data && ((char*)resp.data)[0] == 4) { ret = KRB5KRB_AP_ERR_V4_REPLY; krb5_clear_error_string(context); } else { ret = KRB5KRB_AP_ERR_MSG_TYPE; krb5_clear_error_string(context); } out: krb5_data_free(&resp); krb5_data_free(&enc); if(subkey){ krb5_free_keyblock_contents(context, subkey); free(subkey); } return ret; }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context context; krb5_ccache src_cc = NULL; krb5_ccache dst_cc = NULL; krb5_cc_cursor cursor; krb5_principal me = NULL; krb5_creds cred; const char *during; Ticket t; size_t len; int make_kvno_absent = 0; int opt; memset(&cred, 0, sizeof (cred)); during = "init_context"; ret = krb5_init_context(&context); if (ret) goto err; while ((opt = getopt(argc, argv, "c:n")) != -1) { switch (opt) { case 'c': during = "cc_resolve of source ccache"; ret = krb5_cc_resolve(context, optarg, &src_cc); if (ret) goto err; break; case 'n': make_kvno_absent++; break; case 'h': default: fprintf(stderr, "Usage: %s [-n] [-c ccache]\n" "\tThis utility edits a ccache, setting all ticket\n" "\tenc_part kvnos to zero or absent (if -n is set).\n", argv[0]); return 1; } } if (!src_cc) { during = "cc_default"; ret = krb5_cc_default(context, &src_cc); if (ret) goto err; } during = "cc_get_principal"; ret = krb5_cc_get_principal(context, src_cc, &me); if (ret) goto err; if (optind != argc) { fprintf(stderr, "Usage: %s [-n] [-c ccache]\n" "\tThis utility edits a ccache, setting all ticket\n" "\tenc_part kvnos to zero or absent (if -n is set).\n", argv[0]); return 1; } during = "cc_new_unique of temporary ccache"; ret = krb5_cc_new_unique(context, krb5_cc_get_type(context, src_cc), NULL, &dst_cc); during = "cc_initialize of temporary ccache"; ret = krb5_cc_initialize(context, dst_cc, me); if (ret) goto err; during = "cc_start_seq_get"; ret = krb5_cc_start_seq_get(context, src_cc, &cursor); if (ret) goto err; while ((ret = krb5_cc_next_cred(context, src_cc, &cursor, &cred)) == 0) { krb5_data data; during = "decode_Ticket"; memset(&t, 0, sizeof (t)); ret = decode_Ticket(cred.ticket.data, cred.ticket.length, &t, &len); if (ret == ASN1_MISSING_FIELD) continue; if (ret) goto err; if (t.enc_part.kvno) { *t.enc_part.kvno = 0; if (make_kvno_absent) { free(t.enc_part.kvno); t.enc_part.kvno = NULL; } /* * The new Ticket has to need less or same space as before, so * we reuse cred->icket.data. */ during = "encode_Ticket"; ASN1_MALLOC_ENCODE(Ticket, data.data, data.length, &t, &len, ret); if (ret) { free_Ticket(&t); goto err; } krb5_data_free(&cred.ticket); cred.ticket = data; } free_Ticket(&t); during = "cc_store_cred"; ret = krb5_cc_store_cred(context, dst_cc, &cred); if (ret) goto err; krb5_free_cred_contents(context, &cred); memset(&cred, 0, sizeof (cred)); } during = "cc_next_cred"; if (ret != KRB5_CC_END) goto err; during = "cc_end_seq_get"; ret = krb5_cc_end_seq_get(context, src_cc, &cursor); if (ret) goto err; during = "cc_move"; ret = krb5_cc_move(context, dst_cc, src_cc); if (ret) goto err; dst_cc = NULL; during = "cc_switch"; ret = krb5_cc_switch(context, src_cc); if (ret) goto err; err: (void) krb5_free_principal(context, me); if (src_cc) (void) krb5_cc_close(context, src_cc); if (dst_cc) (void) krb5_cc_destroy(context, dst_cc); if (ret) { fprintf(stderr, "Failed while doing %s (%d)\n", during, ret); ret = 1; } return (ret); }
static void do_v5_kvno (int count, char *names[], char * ccache_name, char *etype_str, char *keytab_name, char *sname) { krb5_error_code ret; krb5_context context = 0; int i, errors; krb5_enctype etype; krb5_ccache ccache; krb5_principal me; krb5_creds in_creds, *out_creds = NULL; Ticket ticket; size_t len; char *princ = NULL; krb5_keytab keytab = NULL; ret = krb5_init_context(&context); if (ret) errx(1, "krb5_init_context failed: %d", ret); if (etype_str) { ret = krb5_string_to_enctype(context, etype_str, &etype); if (ret) krb5_err(context, 1, ret, "Failed to convert encryption type %s", etype_str); } else { etype = 0; } if (ccache_name) ret = krb5_cc_resolve(context, ccache_name, &ccache); else ret = krb5_cc_default(context, &ccache); if (ret) krb5_err(context, 1, ret, "Failed to open credentials cache %s", (ccache_name) ? ccache_name : "(Default)"); if (keytab_name) { ret = krb5_kt_resolve(context, keytab_name, &keytab); if (ret) krb5_err(context, 1, ret, "Can't resolve keytab %s", keytab_name); } ret = krb5_cc_get_principal(context, ccache, &me); if (ret) krb5_err(context, 1, ret, "krb5_cc_get_principal"); errors = 0; for (i = 0; i < count; i++) { memset(&in_creds, 0, sizeof(in_creds)); memset(&ticket, 0, sizeof(ticket)); in_creds.client = me; if (sname != NULL) { ret = krb5_sname_to_principal(context, names[i], sname, KRB5_NT_SRV_HST, &in_creds.server); } else { ret = krb5_parse_name(context, names[i], &in_creds.server); } if (ret) { if (!quiet_flag) krb5_warn(context, ret, "Couldn't parse principal name %s", names[i]); errors++; continue; } ret = krb5_unparse_name(context, in_creds.server, &princ); if (ret) { krb5_warn(context, ret, "Couldn't format parsed principal name for '%s'", names[i]); errors++; goto next; } in_creds.session.keytype = etype; ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds); if (ret) { krb5_warn(context, ret, "Couldn't get credentials for %s", princ); errors++; goto next; } ret = decode_Ticket(out_creds->ticket.data, out_creds->ticket.length, &ticket, &len); if (ret) { krb5_err(context, 1, ret, "Can't decode ticket for %s", princ); errors++; goto next; continue; } if (keytab) { krb5_keytab_entry kte; krb5_crypto crypto; krb5_data dec_data; EncTicketPart decr_part; ret = krb5_kt_get_entry(context, keytab, in_creds.server, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0, ticket.enc_part.etype, &kte); if (ret) { krb5_warn(context, ret, "Can't decrypt ticket for %s", princ); if (!quiet_flag) printf("%s: kvno = %d, keytab entry invalid", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); errors ++; goto next; } ret = krb5_crypto_init(context, &kte.keyblock, 0, &crypto); if (ret) { krb5_warn(context, ret, "krb5_crypto_init"); errors ++; krb5_kt_free_entry(context, &kte); goto next; } ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET, &ticket.enc_part, &dec_data); krb5_crypto_destroy(context, crypto); krb5_kt_free_entry(context, &kte); if (ret) { krb5_warn(context, ret, "krb5_decrypt_EncryptedData"); errors ++; goto next; } ret = decode_EncTicketPart(dec_data.data, dec_data.length, &decr_part, &len); krb5_data_free(&dec_data); if (ret) { krb5_warn(context, ret, "decode_EncTicketPart"); errors ++; goto next; } if (!quiet_flag) printf("%s: kvno = %d, keytab entry valid\n", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); free_EncTicketPart(&decr_part); } else { if (!quiet_flag) printf("%s: kvno = %d\n", princ, (ticket.enc_part.kvno != NULL)? *ticket.enc_part.kvno : 0); } next: if (out_creds) { krb5_free_creds(context, out_creds); out_creds = NULL; } if (princ) { krb5_free_unparsed_name(context, princ); princ = NULL; } krb5_free_principal(context, in_creds.server); free_Ticket(&ticket); } if (keytab) krb5_kt_close(context, keytab); krb5_free_principal(context, me); krb5_cc_close(context, ccache); krb5_free_context(context); if (errors) exit(1); exit(0); }
static void test_dh2key(krb5_context context, int i, struct testcase *c) { krb5_error_code ret; krb5_keyblock key; krb5_principal client, server; Ticket ticket; AlgorithmIdentifier ai; size_t size; memset(&ticket, 0, sizeof(&ticket)); ai.algorithm = *c->oid; ai.parameters = NULL; ret = decode_Ticket(c->ticket.data, c->ticket.length, &ticket, &size); if (ret) krb5_errx(context, 1, "decode ticket: %d", ret); ret = krb5_parse_name(context, c->client, &client); if (ret) krb5_err(context, 1, ret, "parse_name: %s", c->client); ret = krb5_parse_name(context, c->server, &server); if (ret) krb5_err(context, 1, ret, "parse_name: %s", c->server); if (verbose_flag) { char *str; hex_encode(c->Z.data, c->Z.length, &str); printf("Z: %s\n", str); free(str); printf("client: %s\n", c->client); printf("server: %s\n", c->server); printf("enctype: %d\n", (int)c->enctype); hex_encode(c->as_req.data, c->as_req.length, &str); printf("as-req: %s\n", str); free(str); hex_encode(c->pk_as_rep.data, c->pk_as_rep.length, &str); printf("pk-as-rep: %s\n", str); free(str); hex_encode(c->ticket.data, c->ticket.length, &str); printf("ticket: %s\n", str); free(str); } ret = _krb5_pk_kdf(context, &ai, c->Z.data, c->Z.length, client, server, c->enctype, &c->as_req, &c->pk_as_rep, &ticket, &key); krb5_free_principal(context, client); krb5_free_principal(context, server); if (ret) krb5_err(context, 1, ret, "_krb5_pk_kdf: %d", i); if (verbose_flag) { char *str; hex_encode(key.keyvalue.data, key.keyvalue.length, &str); printf("key: %s\n", str); free(str); } if (key.keyvalue.length != c->key.length || memcmp(key.keyvalue.data, c->key.data, c->key.length) != 0) krb5_errx(context, 1, "resulting key wrong: %d", i); krb5_free_keyblock_contents(context, &key); free_Ticket(&ticket); }
static krb5_error_code get_cred_kdc(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_addresses *addresses, krb5_creds *in_creds, krb5_creds *krbtgt, krb5_principal impersonate_principal, Ticket *second_ticket, krb5_creds *out_creds) { TGS_REQ req; krb5_data enc; krb5_data resp; krb5_kdc_rep rep; KRB_ERROR error; krb5_error_code ret; unsigned nonce; krb5_keyblock *subkey = NULL; size_t len; Ticket second_ticket_data; METHOD_DATA padata; krb5_data_zero(&resp); krb5_data_zero(&enc); padata.val = NULL; padata.len = 0; krb5_generate_random_block(&nonce, sizeof(nonce)); nonce &= 0xffffffff; if(flags.b.enc_tkt_in_skey && second_ticket == NULL){ ret = decode_Ticket(in_creds->second_ticket.data, in_creds->second_ticket.length, &second_ticket_data, &len); if(ret) return ret; second_ticket = &second_ticket_data; } if (impersonate_principal) { krb5_crypto crypto; PA_S4U2Self self; krb5_data data; void *buf; size_t size; self.name = impersonate_principal->name; self.realm = impersonate_principal->realm; self.auth = estrdup("Kerberos"); ret = _krb5_s4u2self_to_checksumdata(context, &self, &data); if (ret) { free(self.auth); goto out; } ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto); if (ret) { free(self.auth); krb5_data_free(&data); goto out; } ret = krb5_create_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, 0, data.data, data.length, &self.cksum); krb5_crypto_destroy(context, crypto); krb5_data_free(&data); if (ret) { free(self.auth); goto out; } ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret); free(self.auth); free_Checksum(&self.cksum); if (ret) goto out; if (len != size) krb5_abortx(context, "internal asn1 error"); ret = krb5_padata_add(context, &padata, KRB5_PADATA_FOR_USER, buf, len); if (ret) goto out; } ret = init_tgs_req (context, id, addresses, flags, second_ticket, in_creds, krbtgt, nonce, &padata, &subkey, &req); if (ret) goto out; ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret); if (ret) goto out; if(enc.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); /* don't free addresses */ req.req_body.addresses = NULL; free_TGS_REQ(&req); /* * Send and receive */ { krb5_sendto_ctx stctx; ret = krb5_sendto_ctx_alloc(context, &stctx); if (ret) return ret; krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); ret = krb5_sendto_context (context, stctx, &enc, krbtgt->server->name.name_string.val[1], &resp); krb5_sendto_ctx_free(context, stctx); } if(ret) goto out; memset(&rep, 0, sizeof(rep)); if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0) { unsigned eflags = 0; ret = krb5_copy_principal(context, in_creds->client, &out_creds->client); if(ret) goto out2; ret = krb5_copy_principal(context, in_creds->server, &out_creds->server); if(ret) goto out2; /* this should go someplace else */ out_creds->times.endtime = in_creds->times.endtime; /* XXX should do better testing */ if (flags.b.constrained_delegation || impersonate_principal) eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; ret = _krb5_extract_ticket(context, &rep, out_creds, &krbtgt->session, NULL, 0, &krbtgt->addresses, nonce, eflags, decrypt_tkt_with_subkey, subkey); out2: krb5_free_kdc_rep(context, &rep); } else if(krb5_rd_error(context, &resp, &error) == 0) { ret = krb5_error_from_rd_error(context, &error, in_creds); krb5_free_error_contents(context, &error); } else if(resp.length > 0 && ((char*)resp.data)[0] == 4) { ret = KRB5KRB_AP_ERR_V4_REPLY; krb5_clear_error_message(context); } else { ret = KRB5KRB_AP_ERR_MSG_TYPE; krb5_clear_error_message(context); } out: if (second_ticket == &second_ticket_data) free_Ticket(&second_ticket_data); free_METHOD_DATA(&padata); krb5_data_free(&resp); krb5_data_free(&enc); if(subkey) krb5_free_keyblock(context, subkey); return ret; }
static krb5_error_code KRB5_CALLCONV scc_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { sqlite_uint64 credid; krb5_scache *s = SCACHE(id); krb5_error_code ret; krb5_data data; ret = make_database(context, s); if (ret) return ret; ret = encode_creds(context, creds, &data); if (ret) return ret; sqlite3_bind_int(s->icred, 1, s->cid); { krb5_enctype etype = 0; int kvno = 0; Ticket t; size_t len; ret = decode_Ticket(creds->ticket.data, creds->ticket.length, &t, &len); if (ret == 0) { if(t.enc_part.kvno) kvno = *t.enc_part.kvno; etype = t.enc_part.etype; free_Ticket(&t); } sqlite3_bind_int(s->icred, 2, kvno); sqlite3_bind_int(s->icred, 3, etype); } sqlite3_bind_blob(s->icred, 4, data.data, data.length, free_data); sqlite3_bind_int(s->icred, 5, time(NULL)); ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO); if (ret) return ret; do { ret = sqlite3_step(s->icred); } while (ret == SQLITE_ROW); sqlite3_reset(s->icred); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to add credential: %s", ""), sqlite3_errmsg(s->db)); goto rollback; } credid = sqlite3_last_insert_rowid(s->db); { bind_principal(context, s->db, s->iprincipal, 1, creds->server); sqlite3_bind_int(s->iprincipal, 2, 1); sqlite3_bind_int(s->iprincipal, 3, credid); do { ret = sqlite3_step(s->iprincipal); } while (ret == SQLITE_ROW); sqlite3_reset(s->iprincipal); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to add principal: %s", ""), sqlite3_errmsg(s->db)); goto rollback; } } { bind_principal(context, s->db, s->iprincipal, 1, creds->client); sqlite3_bind_int(s->iprincipal, 2, 0); sqlite3_bind_int(s->iprincipal, 3, credid); do { ret = sqlite3_step(s->iprincipal); } while (ret == SQLITE_ROW); sqlite3_reset(s->iprincipal); if (ret != SQLITE_DONE) { ret = KRB5_CC_IO; krb5_set_error_message(context, ret, N_("Failed to add principal: %s", ""), sqlite3_errmsg(s->db)); goto rollback; } } ret = exec_stmt(context, s->db, "COMMIT", KRB5_CC_IO); if (ret) return ret; return 0; rollback: exec_stmt(context, s->db, "ROLLBACK", 0); return ret; }