static kadm5_ret_t kadm5_log_flush (kadm5_log_context *log_context, krb5_storage *sp) { krb5_data data; size_t len; int ret; krb5_storage_to_data(sp, &data); len = data.length; ret = write (log_context->log_fd, data.data, len); if (ret != len) { krb5_data_free(&data); return errno; } if (fsync (log_context->log_fd) < 0) { krb5_data_free(&data); return errno; } /* * Try to send a signal to any running `ipropd-master' */ sendto (log_context->socket_fd, (void *)&log_context->version, sizeof(log_context->version), 0, (struct sockaddr *)&log_context->socket_name, sizeof(log_context->socket_name)); krb5_data_free(&data); return 0; }
krb5_error_code hdb_entry2string (krb5_context context, hdb_entry *ent, char **str) { krb5_error_code ret; krb5_data data; krb5_storage *sp; sp = krb5_storage_emem(); if(sp == NULL) { krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = entry2string_int(context, sp, ent); if(ret) { krb5_storage_free(sp); return ret; } krb5_storage_write(sp, "\0", 1); krb5_storage_to_data(sp, &data); krb5_storage_free(sp); *str = data.data; return 0; }
static krb5_error_code kcm_send_request(krb5_context context, krb5_storage *request, krb5_data *response_data) { static heim_base_once_t init_once = HEIM_BASE_ONCE_INIT; krb5_error_code ret = 0; krb5_data request_data; heim_base_once_f(&init_once, NULL, kcm_init_ipc); if (kcm_ipc == NULL) { krb5_set_error_message(context, ENOENT, "Failed to open kcm init"); return ENOENT; } ret = krb5_storage_to_data(request, &request_data); if (ret) { krb5_clear_error_message(context); return KRB5_CC_NOMEM; } ret = heim_ipc_call(kcm_ipc, &request_data, response_data, NULL); krb5_data_free(&request_data); if (ret) { krb5_clear_error_message(context); ret = KRB5_CC_NOSUPP; } return ret; }
static krb5_error_code kcm_send_request(krb5_context context, krb5_storage *request, krb5_data *response_data) { krb5_error_code ret = 0; krb5_data request_data; HEIMDAL_MUTEX_lock(&kcm_mutex); if (kcm_ipc == NULL) ret = heim_ipc_init_context(kcm_ipc_name, &kcm_ipc); HEIMDAL_MUTEX_unlock(&kcm_mutex); if (ret) return KRB5_CC_NOSUPP; ret = krb5_storage_to_data(request, &request_data); if (ret) { krb5_clear_error_message(context); return KRB5_CC_NOMEM; } ret = heim_ipc_call(kcm_ipc, &request_data, response_data, NULL); krb5_data_free(&request_data); if (ret) { krb5_clear_error_message(context); ret = KRB5_CC_NOSUPP; } return ret; }
static int make_result (krb5_data *data, uint16_t result_code, const char *expl) { krb5_error_code ret; krb5_storage *sp; sp = krb5_storage_emem(); if (sp == NULL) goto out; ret = krb5_store_uint16(sp, result_code); if (ret) goto out; ret = krb5_store_stringz(sp, expl); if (ret) goto out; ret = krb5_storage_to_data(sp, data); if (ret) goto out; krb5_storage_free(sp); return 0; out: if (sp) krb5_storage_free(sp); krb5_warnx (context, "Out of memory generating error reply"); return 1; }
static krb5_error_code encode_creds(krb5_context context, krb5_creds *creds, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; krb5_data_zero(data); sp = krb5_storage_emem(); if (sp == NULL) return krb5_enomem(context); ret = krb5_store_creds(sp, creds); if (ret) { krb5_set_error_message(context, ret, N_("Failed to store credential in scache", "")); krb5_storage_free(sp); return ret; } ret = krb5_storage_to_data(sp, data); krb5_storage_free(sp); if (ret) krb5_set_error_message(context, ret, N_("Failed to encode credential in scache", "")); return ret; }
static krb5_error_code encode_creds(krb5_context context, krb5_creds *creds, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; sp = krb5_storage_emem(); if (sp == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); return ENOMEM; } ret = krb5_store_creds(sp, creds); if (ret) { krb5_set_error_message(context, ret, N_("Failed to store credential in scache", "")); krb5_storage_free(sp); return ret; } ret = krb5_storage_to_data(sp, data); krb5_storage_free(sp); if (ret) krb5_set_error_message(context, ret, N_("Failed to encode credential in scache", "")); return ret; }
static OM_uint32 get_service_keyblock (OM_uint32 *minor_status, gsskrb5_ctx ctx, gss_buffer_set_t *data_set) { krb5_storage *sp = NULL; krb5_data data; OM_uint32 maj_stat = GSS_S_COMPLETE; krb5_error_code ret = EINVAL; sp = krb5_storage_emem(); if (sp == NULL) { _gsskrb5_clear_status(); *minor_status = ENOMEM; return GSS_S_FAILURE; } HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); if (ctx->service_keyblock == NULL) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); _gsskrb5_set_status(EINVAL, "No service keyblock on gssapi context"); *minor_status = EINVAL; return GSS_S_FAILURE; } krb5_data_zero(&data); ret = krb5_store_keyblock(sp, *ctx->service_keyblock); HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) goto out; ret = krb5_storage_to_data(sp, &data); if (ret) goto out; { gss_buffer_desc value; value.length = data.length; value.value = data.data; maj_stat = gss_add_buffer_set_member(minor_status, &value, data_set); } out: krb5_data_free(&data); if (sp) krb5_storage_free(sp); if (ret) { *minor_status = ret; maj_stat = GSS_S_FAILURE; } return maj_stat; }
krb5_error_code kcm_dispatch(krb5_context context, kcm_client *client, krb5_data *req_data, krb5_data *resp_data) { krb5_error_code ret; kcm_method method; krb5_storage *req_sp = NULL; krb5_storage *resp_sp = NULL; u_int16_t opcode; resp_sp = krb5_storage_emem(); if (resp_sp == NULL) { return ENOMEM; } if (client->pid == -1) { kcm_log(0, "Client had invalid process number"); ret = KRB5_FCC_INTERNAL; goto out; } req_sp = krb5_storage_from_data(req_data); if (req_sp == NULL) { kcm_log(0, "Process %d: failed to initialize storage from data", client->pid); ret = KRB5_CC_IO; goto out; } krb5_ret_int16(req_sp, &opcode); if (opcode >= sizeof(kcm_ops)/sizeof(kcm_ops[0])) { kcm_log(0, "Process %d: invalid operation code %d", client->pid, opcode); ret = KRB5_FCC_INTERNAL; goto out; } method = kcm_ops[opcode].method; /* seek past place for status code */ krb5_storage_seek(resp_sp, 4, SEEK_SET); ret = (*method)(context, client, opcode, req_sp, resp_sp); out: if (req_sp != NULL) { krb5_storage_free(req_sp); } krb5_storage_seek(resp_sp, 0, SEEK_SET); krb5_store_int32(resp_sp, ret); ret = krb5_storage_to_data(resp_sp, resp_data); krb5_storage_free(resp_sp); return ret; }
int krb_mk_req(KTEXT authent, char *service, char *instance, char *realm, int32_t checksum) #endif { CREDENTIALS cr; KTEXT_ST req; krb5_storage *sp; int code; /* XXX get user realm */ const char *myrealm = realm; krb5_data a; code = krb_get_cred(service, instance, realm, &cr); if(code || time(NULL) > krb_life_to_time(cr.issue_date, cr.lifetime)){ code = get_ad_tkt((char *)service, (char *)instance, (char *)realm, lifetime); if(code == KSUCCESS) code = krb_get_cred(service, instance, realm, &cr); } if(code) return code; sp = krb5_storage_emem(); krb5_store_int8(sp, KRB_PROT_VERSION); krb5_store_int8(sp, AUTH_MSG_APPL_REQUEST); krb5_store_int8(sp, cr.kvno); krb5_store_stringz(sp, realm); krb5_store_int8(sp, cr.ticket_st.length); build_request(&req, cr.pname, cr.pinst, myrealm, checksum); encrypt_ktext(&req, &cr.session, DES_ENCRYPT); krb5_store_int8(sp, req.length); krb5_storage_write(sp, cr.ticket_st.dat, cr.ticket_st.length); krb5_storage_write(sp, req.dat, req.length); krb5_storage_to_data(sp, &a); krb5_storage_free(sp); memcpy(authent->dat, a.data, a.length); authent->length = a.length; krb5_data_free(&a); memset(&cr, 0, sizeof(cr)); memset(&req, 0, sizeof(req)); return KSUCCESS; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_s4u2self_to_checksumdata(krb5_context context, const PA_S4U2Self *self, krb5_data *data) { krb5_error_code ret; krb5_ssize_t ssize; krb5_storage *sp; size_t size; size_t i; sp = krb5_storage_emem(); if (sp == NULL) { krb5_clear_error_message(context); return ENOMEM; } krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); ret = krb5_store_int32(sp, self->name.name_type); if (ret) goto out; for (i = 0; i < self->name.name_string.len; i++) { size = strlen(self->name.name_string.val[i]); ssize = krb5_storage_write(sp, self->name.name_string.val[i], size); if (ssize != (krb5_ssize_t)size) { ret = ENOMEM; goto out; } } size = strlen(self->realm); ssize = krb5_storage_write(sp, self->realm, size); if (ssize != (krb5_ssize_t)size) { ret = ENOMEM; goto out; } size = strlen(self->auth); ssize = krb5_storage_write(sp, self->auth, size); if (ssize != (krb5_ssize_t)size) { ret = ENOMEM; goto out; } ret = krb5_storage_to_data(sp, data); krb5_storage_free(sp); return ret; out: krb5_clear_error_message(context); return ret; }
OM_uint32 gss_krb5_set_allowable_enctypes(OM_uint32 *minor_status, gss_cred_id_t cred, OM_uint32 num_enctypes, int32_t *enctypes) { krb5_error_code ret; OM_uint32 maj_status; gss_buffer_desc buffer; krb5_storage *sp; krb5_data data; int i; sp = krb5_storage_emem(); if (sp == NULL) { *minor_status = ENOMEM; maj_status = GSS_S_FAILURE; goto out; } for (i = 0; i < num_enctypes; i++) { ret = krb5_store_int32(sp, enctypes[i]); if (ret) { *minor_status = ret; maj_status = GSS_S_FAILURE; goto out; } } ret = krb5_storage_to_data(sp, &data); if (ret) { *minor_status = ret; maj_status = GSS_S_FAILURE; goto out; } buffer.value = data.data; buffer.length = data.length; maj_status = gss_set_cred_option(minor_status, &cred, GSS_KRB5_SET_ALLOWABLE_ENCTYPES_X, &buffer); krb5_data_free(&data); out: if (sp) krb5_storage_free(sp); return maj_status; }
kadm5_ret_t _kadm5_marshal_params(krb5_context context, kadm5_config_params *params, krb5_data *out) { krb5_storage *sp = krb5_storage_emem(); krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM)); if(params->mask & KADM5_CONFIG_REALM) krb5_store_string(sp, params->realm); krb5_storage_to_data(sp, out); krb5_storage_free(sp); return 0; }
krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_create_auth_reply(krb5_context context, const char *pname, const char *pinst, const char *prealm, int32_t time_ws, int n, uint32_t x_date, unsigned char kvno, const krb5_data *cipher, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; krb5_data_zero(data); sp = krb5_storage_emem(); if (sp == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_KDC_REPLY), error); RCHECK(ret, put_nir(sp, pname, pinst, prealm), error); RCHECK(ret, krb5_store_int32(sp, time_ws), error); RCHECK(ret, krb5_store_int8(sp, n), error); RCHECK(ret, krb5_store_int32(sp, x_date), error); RCHECK(ret, krb5_store_int8(sp, kvno), error); RCHECK(ret, krb5_store_int16(sp, cipher->length), error); ret = krb5_storage_write(sp, cipher->data, cipher->length); if (ret != cipher->length) { ret = EINVAL; goto error; } ret = krb5_storage_to_data(sp, data); error: krb5_storage_free(sp); if (ret) krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); return ret; }
static int compare(const char *name, krb5_storage *sp, void *expected, size_t len) { int ret = 0; krb5_data data; if (krb5_storage_to_data(sp, &data)) errx(1, "krb5_storage_to_data failed"); krb5_storage_free(sp); if(data.length != len || memcmp(data.data, expected, len) != 0) { printf("%s mismatch\n", name); printf(" Expected: "); print_data(expected, len); printf(" Actual: "); print_data(data.data, data.length); ret++; } krb5_data_free(&data); return ret; }
krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_cr_err_reply(krb5_context context, const char *name, const char *inst, const char *realm, uint32_t time_ws, uint32_t e, const char *e_string, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; krb5_data_zero(data); if (name == NULL) name = ""; if (inst == NULL) inst = ""; if (realm == NULL) realm = ""; if (e_string == NULL) e_string = ""; sp = krb5_storage_emem(); if (sp == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error); RCHECK(ret, put_nir(sp, name, inst, realm), error); RCHECK(ret, krb5_store_int32(sp, time_ws), error); RCHECK(ret, krb5_store_int32(sp, e), error); RCHECK(ret, krb5_store_stringz(sp, e_string), error); ret = krb5_storage_to_data(sp, data); error: krb5_storage_free(sp); if (ret) krb5_set_error_string(context, "Failed to encode kerberos 4 error"); return 0; }
static kadm5_ret_t kadm5_log_flush (kadm5_log_context *log_context, krb5_storage *sp) { krb5_data data; size_t len; ssize_t ret; krb5_storage_to_data(sp, &data); len = data.length; ret = write (log_context->log_fd, data.data, len); if (ret < 0 || (size_t)ret != len) { krb5_data_free(&data); return errno; } if (fsync (log_context->log_fd) < 0) { krb5_data_free(&data); return errno; } /* * Try to send a signal to any running `ipropd-master' */ #ifndef NO_UNIX_SOCKETS sendto (log_context->socket_fd, (void *)&log_context->version, sizeof(log_context->version), 0, (struct sockaddr *)&log_context->socket_name, sizeof(log_context->socket_name)); #else sendto (log_context->socket_fd, (void *)&log_context->version, sizeof(log_context->version), 0, log_context->socket_info->ai_addr, log_context->socket_info->ai_addrlen); #endif krb5_data_free(&data); return 0; }
/* * Create an error `reply´ using for the packet `hdr' with the error * `error´ code. */ static void make_error_reply (struct rx_header *hdr, uint32_t error, krb5_data *reply) { struct rx_header reply_hdr; krb5_error_code ret; krb5_storage *sp; init_reply_header (hdr, &reply_hdr, HT_ABORT, HF_LAST); sp = krb5_storage_emem(); if (sp == NULL) return; ret = encode_rx_header (&reply_hdr, sp); if (ret) return; krb5_store_int32(sp, error); krb5_storage_to_data (sp, reply); krb5_storage_free (sp); }
static void build_request(KTEXT req, const char *name, const char *inst, const char *realm, u_int32_t checksum) { struct timeval tv; krb5_storage *sp; krb5_data data; sp = krb5_storage_emem(); krb5_store_stringz(sp, name); krb5_store_stringz(sp, inst); krb5_store_stringz(sp, realm); krb5_store_int32(sp, checksum); gettimeofday(&tv, NULL); krb5_store_int8(sp, tv.tv_usec / 5000); krb5_store_int32(sp, tv.tv_sec); krb5_storage_to_data(sp, &data); krb5_storage_free(sp); memcpy(req->dat, data.data, data.length); req->length = (data.length + 7) & ~7; krb5_data_free(&data); }
static krb5_error_code storage_to_etext(krb5_context context, krb5_storage *sp, const krb5_keyblock *key, krb5_data *enc_data) { krb5_error_code ret; krb5_crypto crypto; krb5_ssize_t size; krb5_data data; /* multiple of eight bytes */ size = krb5_storage_seek(sp, 0, SEEK_END); if (size < 0) return EINVAL; size = 8 - (size & 7); ret = krb5_storage_write(sp, eightzeros, size); if (ret != size) return EINVAL; ret = krb5_storage_to_data(sp, &data); if (ret) return ret; ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto); if (ret) { krb5_data_free(&data); return ret; } ret = krb5_encrypt(context, crypto, 0, data.data, data.length, enc_data); krb5_data_free(&data); krb5_crypto_destroy(context, crypto); return ret; }
krb5_error_code _kadm5_xdr_store_gcred(struct _kadm5_xdr_gcred *gcred, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; krb5_data_zero(data); sp = krb5_storage_emem(); INSIST(sp != NULL); CHECK(krb5_store_uint32(sp, gcred->version)); CHECK(krb5_store_uint32(sp, gcred->proc)); CHECK(krb5_store_uint32(sp, gcred->seq_num)); CHECK(krb5_store_uint32(sp, gcred->service)); CHECK(_kadm5_xdr_store_data_xdr(sp, gcred->handle)); ret = krb5_storage_to_data(sp, data); krb5_storage_free(sp); return ret; }
static krb5_error_code kcm_send_request(krb5_context context, krb5_kcmcache *k, krb5_storage *request, krb5_data *response_data) { krb5_error_code ret; krb5_data request_data; int i; response_data->data = NULL; response_data->length = 0; ret = krb5_storage_to_data(request, &request_data); if (ret) { krb5_clear_error_string(context); return KRB5_CC_NOMEM; } ret = KRB5_CC_IO; for (i = 0; i < context->max_retries; i++) { ret = try_door(context, k, &request_data, response_data); if (ret == 0 && response_data->length != 0) break; ret = try_unix_socket(context, k, &request_data, response_data); if (ret == 0 && response_data->length != 0) break; } krb5_data_free(&request_data); if (ret) { krb5_clear_error_string(context); ret = KRB5_CC_IO; } return ret; }
static krb5_error_code write_storage(krb5_context context, krb5_storage *sp, int fd) { krb5_error_code ret; krb5_data data; ssize_t sret; ret = krb5_storage_to_data(sp, &data); if (ret) { krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); return ret; } sret = write(fd, data.data, data.length); ret = (sret != data.length); krb5_data_free(&data); if (ret) { ret = errno; krb5_set_error_message(context, ret, N_("Failed to write FILE credential data", "")); return ret; } return 0; }
krb5_error_code _kdc_do_524(krb5_context context, krb5_kdc_configuration *config, const Ticket *t, krb5_data *reply, const char *from, struct sockaddr *addr) { krb5_error_code ret = 0; krb5_crypto crypto; hdb_entry_ex *server = NULL; Key *skey; krb5_data et_data; EncTicketPart et; EncryptedData ticket; krb5_storage *sp; char *spn = NULL; unsigned char buf[MAX_KTXT_LEN + 4 * 4]; size_t len; int kvno = 0; if(!config->enable_524) { ret = KRB5KDC_ERR_POLICY; kdc_log(context, config, 0, "Rejected ticket conversion request from %s", from); goto out; } ret = fetch_server (context, config, t, &spn, &server, from); if (ret) { goto out; } ret = hdb_enctype2key(context, &server->entry, t->enc_part.etype, &skey); if(ret){ kdc_log(context, config, 0, "No suitable key found for server (%s) from %s", spn, from); goto out; } ret = krb5_crypto_init(context, &skey->key, 0, &crypto); if (ret) { kdc_log(context, config, 0, "krb5_crypto_init failed: %s", krb5_get_err_text(context, ret)); goto out; } ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET, &t->enc_part, &et_data); krb5_crypto_destroy(context, crypto); if(ret){ kdc_log(context, config, 0, "Failed to decrypt ticket from %s for %s", from, spn); goto out; } ret = krb5_decode_EncTicketPart(context, et_data.data, et_data.length, &et, &len); krb5_data_free(&et_data); if(ret){ kdc_log(context, config, 0, "Failed to decode ticket from %s for %s", from, spn); goto out; } ret = log_524 (context, config, &et, from, spn); if (ret) { free_EncTicketPart(&et); goto out; } ret = verify_flags (context, config, &et, spn); if (ret) { free_EncTicketPart(&et); goto out; } ret = set_address (context, config, &et, addr, from); if (ret) { free_EncTicketPart(&et); goto out; } ret = encode_524_response(context, config, spn, et, t, server, &ticket, &kvno); free_EncTicketPart(&et); out: /* make reply */ memset(buf, 0, sizeof(buf)); sp = krb5_storage_from_mem(buf, sizeof(buf)); if (sp) { krb5_store_int32(sp, ret); if(ret == 0){ krb5_store_int32(sp, kvno); krb5_store_data(sp, ticket.cipher); /* Aargh! This is coded as a KTEXT_ST. */ krb5_storage_seek(sp, MAX_KTXT_LEN - ticket.cipher.length, SEEK_CUR); krb5_store_int32(sp, 0); /* mbz */ free_EncryptedData(&ticket); } ret = krb5_storage_to_data(sp, reply); reply->length = krb5_storage_seek(sp, 0, SEEK_CUR); krb5_storage_free(sp); } else krb5_data_zero(reply); if(spn) free(spn); if(server) _kdc_free_ent (context, server); return ret; }
static krb5_error_code create_reply_ticket (krb5_context context, struct rx_header *hdr, Key *skey, char *name, char *instance, char *realm, struct sockaddr_in *addr, int life, int kvno, int32_t max_seq_len, const char *sname, const char *sinstance, uint32_t challenge, const char *label, krb5_keyblock *key, krb5_data *reply) { krb5_error_code ret; krb5_data ticket; krb5_keyblock session; krb5_storage *sp; krb5_data enc_data; struct rx_header reply_hdr; char zero[8]; size_t pad; unsigned fyrtiosjuelva; /* create the ticket */ krb5_generate_random_keyblock(context, ETYPE_DES_PCBC_NONE, &session); _krb5_krb_create_ticket(context, 0, name, instance, realm, addr->sin_addr.s_addr, &session, life, kdc_time, sname, sinstance, &skey->key, &ticket); /* create the encrypted part of the reply */ sp = krb5_storage_emem (); krb5_generate_random_block(&fyrtiosjuelva, sizeof(fyrtiosjuelva)); fyrtiosjuelva &= 0xffffffff; krb5_store_int32 (sp, fyrtiosjuelva); krb5_store_int32 (sp, challenge); krb5_storage_write (sp, session.keyvalue.data, 8); krb5_free_keyblock_contents(context, &session); krb5_store_int32 (sp, kdc_time); krb5_store_int32 (sp, kdc_time + _krb5_krb_life_to_time (0, life)); krb5_store_int32 (sp, kvno); krb5_store_int32 (sp, ticket.length); krb5_store_stringz (sp, name); krb5_store_stringz (sp, instance); #if 1 /* XXX - Why shouldn't the realm go here? */ krb5_store_stringz (sp, ""); #else krb5_store_stringz (sp, realm); #endif krb5_store_stringz (sp, sname); krb5_store_stringz (sp, sinstance); krb5_storage_write (sp, ticket.data, ticket.length); krb5_storage_write (sp, label, strlen(label)); /* pad to DES block */ memset (zero, 0, sizeof(zero)); pad = (8 - krb5_storage_seek (sp, 0, SEEK_CUR) % 8) % 8; krb5_storage_write (sp, zero, pad); krb5_storage_to_data (sp, &enc_data); krb5_storage_free (sp); if (enc_data.length > max_seq_len) { krb5_data_free (&enc_data); make_error_reply (hdr, KAANSWERTOOLONG, reply); return 0; } /* encrypt it */ { DES_key_schedule schedule; DES_cblock deskey; memcpy (&deskey, key->keyvalue.data, sizeof(deskey)); DES_set_key_unchecked (&deskey, &schedule); DES_pcbc_encrypt (enc_data.data, enc_data.data, enc_data.length, &schedule, &deskey, DES_ENCRYPT); memset (&schedule, 0, sizeof(schedule)); memset (&deskey, 0, sizeof(deskey)); } /* create the reply packet */ init_reply_header (hdr, &reply_hdr, HT_DATA, HF_LAST); sp = krb5_storage_emem (); ret = encode_rx_header (&reply_hdr, sp); krb5_store_int32 (sp, max_seq_len); krb5_store_xdr_data (sp, enc_data); krb5_data_free (&enc_data); krb5_storage_to_data (sp, reply); krb5_storage_free (sp); return 0; }
OM_uint32 GSSAPI_CALLCONV _gsskrb5_export_sec_context ( OM_uint32 * minor_status, gss_ctx_id_t * context_handle, gss_buffer_t interprocess_token ) { krb5_context context; const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle; krb5_storage *sp; krb5_auth_context ac; OM_uint32 ret = GSS_S_COMPLETE; krb5_data data; gss_buffer_desc buffer; int flags; OM_uint32 minor; krb5_error_code kret; GSSAPI_KRB5_INIT (&context); HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); if (!(ctx->flags & GSS_C_TRANS_FLAG)) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); *minor_status = 0; return GSS_S_UNAVAILABLE; } sp = krb5_storage_emem (); if (sp == NULL) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); *minor_status = ENOMEM; return GSS_S_FAILURE; } ac = ctx->auth_context; /* flagging included fields */ flags = 0; if (ac->local_address) flags |= SC_LOCAL_ADDRESS; if (ac->remote_address) flags |= SC_REMOTE_ADDRESS; if (ac->keyblock) flags |= SC_KEYBLOCK; if (ac->local_subkey) flags |= SC_LOCAL_SUBKEY; if (ac->remote_subkey) flags |= SC_REMOTE_SUBKEY; kret = krb5_store_int32 (sp, flags); if (kret) { *minor_status = kret; goto failure; } /* marshall auth context */ kret = krb5_store_int32 (sp, ac->flags); if (kret) { *minor_status = kret; goto failure; } if (ac->local_address) { kret = krb5_store_address (sp, *ac->local_address); if (kret) { *minor_status = kret; goto failure; } } if (ac->remote_address) { kret = krb5_store_address (sp, *ac->remote_address); if (kret) { *minor_status = kret; goto failure; } } kret = krb5_store_int16 (sp, ac->local_port); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int16 (sp, ac->remote_port); if (kret) { *minor_status = kret; goto failure; } if (ac->keyblock) { kret = krb5_store_keyblock (sp, *ac->keyblock); if (kret) { *minor_status = kret; goto failure; } } if (ac->local_subkey) { kret = krb5_store_keyblock (sp, *ac->local_subkey); if (kret) { *minor_status = kret; goto failure; } } if (ac->remote_subkey) { kret = krb5_store_keyblock (sp, *ac->remote_subkey); if (kret) { *minor_status = kret; goto failure; } } kret = krb5_store_int32 (sp, ac->local_seqnumber); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ac->remote_seqnumber); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ac->keytype); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ac->cksumtype); if (kret) { *minor_status = kret; goto failure; } /* names */ ret = _gsskrb5_export_name (minor_status, (gss_name_t)ctx->source, &buffer); if (ret) goto failure; data.data = buffer.value; data.length = buffer.length; kret = krb5_store_data (sp, data); _gsskrb5_release_buffer (&minor, &buffer); if (kret) { *minor_status = kret; goto failure; } ret = _gsskrb5_export_name (minor_status, (gss_name_t)ctx->target, &buffer); if (ret) goto failure; data.data = buffer.value; data.length = buffer.length; ret = GSS_S_FAILURE; kret = krb5_store_data (sp, data); _gsskrb5_release_buffer (&minor, &buffer); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ctx->flags); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ctx->more_flags); if (kret) { *minor_status = kret; goto failure; } kret = krb5_store_int32 (sp, ctx->lifetime); if (kret) { *minor_status = kret; goto failure; } kret = _gssapi_msg_order_export(sp, ctx->order); if (kret ) { *minor_status = kret; goto failure; } kret = krb5_storage_to_data (sp, &data); krb5_storage_free (sp); if (kret) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); *minor_status = kret; return GSS_S_FAILURE; } interprocess_token->length = data.length; interprocess_token->value = data.data; HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); ret = _gsskrb5_delete_sec_context (minor_status, context_handle, GSS_C_NO_BUFFER); if (ret != GSS_S_COMPLETE) _gsskrb5_release_buffer (NULL, interprocess_token); *minor_status = 0; return ret; failure: HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); krb5_storage_free (sp); return ret; }
static krb5_error_code KRB5_CALLCONV fkt_add_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) { int ret; int fd; krb5_storage *sp; struct fkt_data *d = id->data; krb5_data keytab; int32_t len; fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC); if (fd < 0) { fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); if (fd < 0) { ret = errno; krb5_set_error_message(context, ret, N_("open(%s): %s", ""), d->filename, strerror(ret)); return ret; } rk_cloexec(fd); ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = fkt_setup_keytab(context, id, sp); if(ret) { goto out; } storage_set_flags(context, sp, id->version); } else { int8_t pvno, tag; rk_cloexec(fd); ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); return ret; } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb5_ret_int8(sp, &pvno); if(ret) { /* we probably have a zero byte file, so try to set it up properly */ ret = fkt_setup_keytab(context, id, sp); if(ret) { krb5_set_error_message(context, ret, N_("%s: keytab is corrupted: %s", ""), d->filename, strerror(ret)); goto out; } storage_set_flags(context, sp, id->version); } else { if(pvno != 5) { ret = KRB5_KEYTAB_BADVNO; krb5_set_error_message(context, ret, N_("Bad version in keytab %s", ""), d->filename); goto out; } ret = krb5_ret_int8 (sp, &tag); if (ret) { krb5_set_error_message(context, ret, N_("failed reading tag from " "keytab %s", ""), d->filename); goto out; } id->version = tag; storage_set_flags(context, sp, id->version); } } { krb5_storage *emem; emem = krb5_storage_emem(); if(emem == NULL) { ret = krb5_enomem(context); goto out; } ret = krb5_kt_store_principal(context, emem, entry->principal); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing principal " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_int32 (emem, entry->timestamp); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing timpstamp " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_int8 (emem, entry->vno % 256); if(ret) { krb5_set_error_message(context, ret, N_("Failed storing kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_kt_store_keyblock (context, d, emem, &entry->keyblock); if(ret) { krb5_storage_free(emem); goto out; } if ((d->flags & KRB5_KT_FL_JAVA) == 0) { ret = krb5_store_int32 (emem, entry->vno); if (ret) { krb5_set_error_message(context, ret, N_("Failed storing extended kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } ret = krb5_store_uint32 (emem, entry->flags); if (ret) { krb5_set_error_message(context, ret, N_("Failed storing extended kvno " "in keytab %s", ""), d->filename); krb5_storage_free(emem); goto out; } } ret = krb5_storage_to_data(emem, &keytab); krb5_storage_free(emem); if(ret) { krb5_set_error_message(context, ret, N_("Failed converting keytab entry " "to memory block for keytab %s", ""), d->filename); goto out; } } while(1) { ret = krb5_ret_int32(sp, &len); if(ret == KRB5_KT_END) { len = keytab.length; break; } if(len < 0) { len = -len; if(len >= (int)keytab.length) { krb5_storage_seek(sp, -4, SEEK_CUR); break; } } krb5_storage_seek(sp, len, SEEK_CUR); } ret = krb5_store_int32(sp, len); if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) { ret = errno; krb5_set_error_message(context, ret, N_("Failed writing keytab block " "in keytab %s: %s", ""), d->filename, strerror(ret)); } memset(keytab.data, 0, keytab.length); krb5_data_free(&keytab); out: krb5_storage_free(sp); _krb5_xunlock(context, fd); close(fd); return ret; }
krb5_error_code _krb5_pac_sign(krb5_context context, krb5_pac p, time_t authtime, krb5_principal principal, const krb5_keyblock *server_key, const krb5_keyblock *priv_key, krb5_data *data) { krb5_error_code ret; krb5_storage *sp = NULL, *spdata = NULL; uint32_t end; size_t server_size, priv_size; uint32_t server_offset = 0, priv_offset = 0; uint32_t server_cksumtype = 0, priv_cksumtype = 0; int i, num = 0; krb5_data logon, d; krb5_data_zero(&logon); if (p->logon_name == NULL) num++; if (p->server_checksum == NULL) num++; if (p->privsvr_checksum == NULL) num++; if (num) { void *ptr; ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1))); if (ptr == NULL) return krb5_enomem(context); p->pac = ptr; if (p->logon_name == NULL) { p->logon_name = &p->pac->buffers[p->pac->numbuffers++]; memset(p->logon_name, 0, sizeof(*p->logon_name)); p->logon_name->type = PAC_LOGON_NAME; } if (p->server_checksum == NULL) { p->server_checksum = &p->pac->buffers[p->pac->numbuffers++]; memset(p->server_checksum, 0, sizeof(*p->server_checksum)); p->server_checksum->type = PAC_SERVER_CHECKSUM; } if (p->privsvr_checksum == NULL) { p->privsvr_checksum = &p->pac->buffers[p->pac->numbuffers++]; memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum)); p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM; } } /* Calculate LOGON NAME */ ret = build_logon_name(context, authtime, principal, &logon); if (ret) goto out; /* Set lengths for checksum */ ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); if (ret) goto out; ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size); if (ret) goto out; /* Encode PAC */ sp = krb5_storage_emem(); if (sp == NULL) return krb5_enomem(context); krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); spdata = krb5_storage_emem(); if (spdata == NULL) { krb5_storage_free(sp); return krb5_enomem(context); } krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE); CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out); CHECK(ret, krb5_store_uint32(sp, p->pac->version), out); end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); for (i = 0; i < p->pac->numbuffers; i++) { uint32_t len; size_t sret; void *ptr = NULL; /* store data */ if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) { len = server_size + 4; server_offset = end + 4; CHECK(ret, krb5_store_uint32(spdata, server_cksumtype), out); CHECK(ret, fill_zeros(context, spdata, server_size), out); } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { len = priv_size + 4; priv_offset = end + 4; CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out); CHECK(ret, fill_zeros(context, spdata, priv_size), out); } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { len = krb5_storage_write(spdata, logon.data, logon.length); if (logon.length != len) { ret = EINVAL; goto out; } } else { len = p->pac->buffers[i].buffersize; ptr = (char *)p->data.data + p->pac->buffers[i].offset_lo; sret = krb5_storage_write(spdata, ptr, len); if (sret != len) { ret = krb5_enomem(context); goto out; } /* XXX if not aligned, fill_zeros */ } /* write header */ CHECK(ret, krb5_store_uint32(sp, p->pac->buffers[i].type), out); CHECK(ret, krb5_store_uint32(sp, len), out); CHECK(ret, krb5_store_uint32(sp, end), out); CHECK(ret, krb5_store_uint32(sp, 0), out); /* advance data endpointer and align */ { int32_t e; end += len; e = ((end + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT; if (end != e) { CHECK(ret, fill_zeros(context, spdata, e - end), out); } end = e; } } /* assert (server_offset != 0 && priv_offset != 0); */ /* export PAC */ ret = krb5_storage_to_data(spdata, &d); if (ret) { krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); goto out; } ret = krb5_storage_write(sp, d.data, d.length); if (ret != d.length) { krb5_data_free(&d); ret = krb5_enomem(context); goto out; } krb5_data_free(&d); ret = krb5_storage_to_data(sp, &d); if (ret) { ret = krb5_enomem(context); goto out; } /* sign */ ret = create_checksum(context, server_key, server_cksumtype, d.data, d.length, (char *)d.data + server_offset, server_size); if (ret) { krb5_data_free(&d); goto out; } ret = create_checksum(context, priv_key, priv_cksumtype, (char *)d.data + server_offset, server_size, (char *)d.data + priv_offset, priv_size); if (ret) { krb5_data_free(&d); goto out; } /* done */ *data = d; krb5_data_free(&logon); krb5_storage_free(sp); krb5_storage_free(spdata); return 0; out: krb5_data_free(&logon); if (sp) krb5_storage_free(sp); if (spdata) krb5_storage_free(spdata); return ret; }
static krb5_error_code build_logon_name(krb5_context context, time_t authtime, krb5_const_principal principal, krb5_data *logon) { krb5_error_code ret; krb5_storage *sp; uint64_t t; char *s, *s2; size_t i, len; t = unix2nttime(authtime); krb5_data_zero(logon); sp = krb5_storage_emem(); if (sp == NULL) return krb5_enomem(context); krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); CHECK(ret, krb5_store_uint32(sp, t & 0xffffffff), out); CHECK(ret, krb5_store_uint32(sp, t >> 32), out); ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &s); if (ret) goto out; len = strlen(s); CHECK(ret, krb5_store_uint16(sp, len * 2), out); #if 1 /* cheat for now */ s2 = malloc(len * 2); if (s2 == NULL) { ret = krb5_enomem(context); free(s); goto out; } for (i = 0; i < len; i++) { s2[i * 2] = s[i]; s2[i * 2 + 1] = 0; } free(s); #else /* write libwind code here */ #endif ret = krb5_storage_write(sp, s2, len * 2); free(s2); if (ret != len * 2) { ret = krb5_enomem(context); goto out; } ret = krb5_storage_to_data(sp, logon); if (ret) goto out; krb5_storage_free(sp); return 0; out: krb5_storage_free(sp); return ret; }
static krb5_error_code write_v4_cc(krb5_context context, const char *tkfile, krb5_storage *sp, int append) { krb5_error_code ret; struct stat sb; krb5_data data; char *path; int fd, i; ret = get_krb4_cc_name(tkfile, &path); if (ret) { krb5_set_error_string(context, "krb5_krb_tf_setup: failed getting " "the krb4 credentials cache name"); return ret; } fd = open(path, O_WRONLY|O_CREAT, 0600); if (fd < 0) { ret = errno; krb5_set_error_string(context, "krb5_krb_tf_setup: error opening file %s", path); free(path); return ret; } if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) { krb5_set_error_string(context, "krb5_krb_tf_setup: tktfile %s is not a file", path); free(path); close(fd); return KRB5_FCC_PERM; } for (i = 0; i < KRB5_TF_LCK_RETRY_COUNT; i++) { if (flock(fd, LOCK_EX | LOCK_NB) < 0) { sleep(KRB5_TF_LCK_RETRY); } else break; } if (i == KRB5_TF_LCK_RETRY_COUNT) { krb5_set_error_string(context, "krb5_krb_tf_setup: failed to lock %s", path); free(path); close(fd); return KRB5_FCC_PERM; } if (!append) { ret = ftruncate(fd, 0); if (ret < 0) { flock(fd, LOCK_UN); krb5_set_error_string(context, "krb5_krb_tf_setup: failed to truncate %s", path); free(path); close(fd); return KRB5_FCC_PERM; } } ret = lseek(fd, 0L, SEEK_END); if (ret < 0) { ret = errno; flock(fd, LOCK_UN); free(path); close(fd); return ret; } krb5_storage_to_data(sp, &data); ret = write(fd, data.data, data.length); if (ret != data.length) ret = KRB5_CC_IO; krb5_free_data_contents(context, &data); flock(fd, LOCK_UN); free(path); close(fd); return 0; }