KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_store_creds(krb5_storage *sp, krb5_creds *creds) { int ret; ret = krb5_store_principal(sp, creds->client); if(ret) return ret; ret = krb5_store_principal(sp, creds->server); if(ret) return ret; ret = krb5_store_keyblock(sp, creds->session); if(ret) return ret; ret = krb5_store_times(sp, creds->times); if(ret) return ret; ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ if(ret) return ret; ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); if(ret) return ret; ret = krb5_store_addrs(sp, creds->addresses); if(ret) return ret; ret = krb5_store_authdata(sp, creds->authdata); if(ret) return ret; ret = krb5_store_data(sp, creds->ticket); if(ret) return ret; ret = krb5_store_data(sp, creds->second_ticket); return ret; }
static kadm5_ret_t store_principal_ent(krb5_storage *sp, kadm5_principal_ent_t princ, uint32_t mask) { int i; if (mask & KADM5_PRINCIPAL) krb5_store_principal(sp, princ->principal); if (mask & KADM5_PRINC_EXPIRE_TIME) krb5_store_int32(sp, princ->princ_expire_time); if (mask & KADM5_PW_EXPIRATION) krb5_store_int32(sp, princ->pw_expiration); if (mask & KADM5_LAST_PWD_CHANGE) krb5_store_int32(sp, princ->last_pwd_change); if (mask & KADM5_MAX_LIFE) krb5_store_int32(sp, princ->max_life); if (mask & KADM5_MOD_NAME) { krb5_store_int32(sp, princ->mod_name != NULL); if(princ->mod_name) krb5_store_principal(sp, princ->mod_name); } if (mask & KADM5_MOD_TIME) krb5_store_int32(sp, princ->mod_date); if (mask & KADM5_ATTRIBUTES) krb5_store_int32(sp, princ->attributes); if (mask & KADM5_KVNO) krb5_store_int32(sp, princ->kvno); if (mask & KADM5_MKVNO) krb5_store_int32(sp, princ->mkvno); if (mask & KADM5_POLICY) { krb5_store_int32(sp, princ->policy != NULL); if(princ->policy) krb5_store_string(sp, princ->policy); } if (mask & KADM5_AUX_ATTRIBUTES) krb5_store_int32(sp, princ->aux_attributes); if (mask & KADM5_MAX_RLIFE) krb5_store_int32(sp, princ->max_renewable_life); if (mask & KADM5_LAST_SUCCESS) krb5_store_int32(sp, princ->last_success); if (mask & KADM5_LAST_FAILED) krb5_store_int32(sp, princ->last_failed); if (mask & KADM5_FAIL_AUTH_COUNT) krb5_store_int32(sp, princ->fail_auth_count); if (mask & KADM5_KEY_DATA) { krb5_store_int32(sp, princ->n_key_data); for(i = 0; i < princ->n_key_data; i++) kadm5_store_key_data(sp, &princ->key_data[i]); } if (mask & KADM5_TL_DATA) { krb5_tl_data *tp; krb5_store_int32(sp, princ->n_tl_data); for(tp = princ->tl_data; tp; tp = tp->tl_data_next) kadm5_store_tl_data(sp, tp); } return 0; }
/* * Request: * NameZ * * Request: * NameZ * ClientPrincipal * ServerPrincipalPresent * ServerPrincipal OPTIONAL * Password * * Repsonse: * */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_kcm_get_initial_ticket(krb5_context context, krb5_ccache id, krb5_principal client, krb5_principal server, const char *password) { krb5_kcmcache *k = KCMCACHE(id); krb5_error_code ret; krb5_storage *request; if (id->ops != &krb5_kcm_ops && id->ops != &krb5_akcm_ops) { krb5_set_error_message(context, EINVAL, "Cache is not a KCM cache"); return EINVAL; } ret = krb5_kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request); if (ret) return ret; ret = krb5_store_stringz(request, k->name); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_principal(request, client); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_int8(request, (server == NULL) ? 0 : 1); if (ret) { krb5_storage_free(request); return ret; } if (server != NULL) { ret = krb5_store_principal(request, server); if (ret) { krb5_storage_free(request); return ret; } } ret = krb5_store_stringz(request, password); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_kcm_call(context, request, NULL, NULL); krb5_storage_free(request); return ret; }
/* * Request: * NameZ * Principal * * Response: * */ static krb5_error_code kcm_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { krb5_error_code ret; krb5_kcmcache *k = KCMCACHE(id); krb5_storage *request; ret = krb5_kcm_storage_request(context, KCM_OP_INITIALIZE, &request); if (ret) return ret; ret = krb5_store_stringz(request, k->name); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_principal(request, primary_principal); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_kcm_call(context, request, NULL, NULL); krb5_storage_free(request); if (context->kdc_sec_offset) kcm_set_kdc_offset(context, id, context->kdc_sec_offset); return ret; }
/* * Request: * NameZ * * Response: * Principal */ static krb5_error_code kcm_op_get_principal(krb5_context context, kcm_client *client, kcm_operation opcode, krb5_storage *request, krb5_storage *response) { krb5_error_code ret; kcm_ccache ccache; char *name; ret = krb5_ret_stringz(request, &name); if (ret) return ret; KCM_LOG_REQUEST_NAME(context, client, opcode, name); ret = kcm_ccache_resolve_client(context, client, opcode, name, &ccache); if (ret) { free(name); return ret; } if (ccache->client == NULL) ret = KRB5_CC_NOTFOUND; else ret = krb5_store_principal(response, ccache->client); free(name); kcm_release_ccache(context, ccache); return 0; }
kadm5_ret_t kadm5_c_chpass_principal(void *server_handle, krb5_principal princ, int keepold, int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, const char *password) { kadm5_client_context *context = server_handle; kadm5_ret_t ret; krb5_storage *sp; unsigned char buf[1024]; int32_t tmp; krb5_data reply; /* * We should get around to implementing this... At the moment, the * the server side API is implemented but the wire protocol has not * been updated. */ if (n_ks_tuple > 0) return KADM5_KS_TUPLE_NOSUPP; ret = _kadm5_connect(server_handle); if(ret) return ret; sp = krb5_storage_from_mem(buf, sizeof(buf)); if (sp == NULL) { krb5_clear_error_message(context->context); return ENOMEM; } krb5_store_int32(sp, kadm_chpass); krb5_store_principal(sp, princ); krb5_store_string(sp, password); krb5_store_int32(sp, keepold); /* extension */ ret = _kadm5_client_send(context, sp); krb5_storage_free(sp); if (ret) return ret; ret = _kadm5_client_recv(context, &reply); if(ret) return ret; sp = krb5_storage_from_data (&reply); if (sp == NULL) { krb5_clear_error_message(context->context); krb5_data_free (&reply); return ENOMEM; } krb5_ret_int32(sp, &tmp); krb5_clear_error_message(context->context); krb5_storage_free(sp); krb5_data_free (&reply); return tmp; }
static krb5_error_code fcc_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { krb5_fcache *f = FCACHE(id); int ret = 0; int fd; char *filename = f->filename; unlink (filename); ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); if(ret) return ret; { krb5_storage *sp; sp = krb5_storage_emem(); krb5_storage_set_eof_code(sp, KRB5_CC_END); if(context->fcache_vno != 0) f->version = context->fcache_vno; else f->version = KRB5_FCC_FVNO_4; ret |= krb5_store_int8(sp, 5); ret |= krb5_store_int8(sp, f->version); storage_set_flags(context, sp, f->version); if(f->version == KRB5_FCC_FVNO_4 && ret == 0) { /* V4 stuff */ if (context->kdc_sec_offset) { ret |= krb5_store_int16 (sp, 12); /* length */ ret |= krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */ ret |= krb5_store_int16 (sp, 8); /* length of data */ ret |= krb5_store_int32 (sp, context->kdc_sec_offset); ret |= krb5_store_int32 (sp, context->kdc_usec_offset); } else { ret |= krb5_store_int16 (sp, 0); } } ret |= krb5_store_principal(sp, primary_principal); ret |= write_storage(context, sp, fd); krb5_storage_free(sp); } fcc_unlock(context, fd); if (close(fd) < 0) if (ret == 0) { ret = errno; krb5_set_error_message (context, ret, N_("close %s: %s", ""), FILENAME(id), strerror(ret)); } return ret; }
kadm5_ret_t kadm5_c_rename_principal(void *server_handle, krb5_principal source, krb5_principal target) { kadm5_client_context *context = server_handle; kadm5_ret_t ret; krb5_storage *sp; unsigned char buf[1024]; int32_t tmp; krb5_data reply; ret = _kadm5_connect(server_handle); if(ret) return ret; sp = krb5_storage_from_mem(buf, sizeof(buf)); if (sp == NULL) return ENOMEM; krb5_store_int32(sp, kadm_rename); krb5_store_principal(sp, source); krb5_store_principal(sp, target); ret = _kadm5_client_send(context, sp); krb5_storage_free(sp); if (ret) return ret; ret = _kadm5_client_recv(context, &reply); if(ret) return ret; sp = krb5_storage_from_data (&reply); if (sp == NULL) { krb5_data_free (&reply); return ENOMEM; } krb5_ret_int32(sp, &tmp); ret = tmp; krb5_storage_free(sp); krb5_data_free (&reply); return ret; }
int main(int argc, char **argv) { int nerr = 0; krb5_storage *sp; krb5_context context; krb5_principal principal; krb5_init_context(&context); sp = krb5_storage_emem(); krb5_store_int32(sp, 0x01020304); nerr += compare("Integer", sp, "\x1\x2\x3\x4", 4); sp = krb5_storage_emem(); krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); krb5_store_int32(sp, 0x01020304); nerr += compare("Integer (LE)", sp, "\x4\x3\x2\x1", 4); sp = krb5_storage_emem(); krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); krb5_store_int32(sp, 0x01020304); nerr += compare("Integer (BE)", sp, "\x1\x2\x3\x4", 4); sp = krb5_storage_emem(); krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST); krb5_store_int32(sp, 0x01020304); { int test = 1; void *data; if(*(char*)&test) data = "\x4\x3\x2\x1"; else data = "\x1\x2\x3\x4"; nerr += compare("Integer (host)", sp, data, 4); } sp = krb5_storage_emem(); krb5_make_principal(context, &principal, "TEST", "foobar", NULL); krb5_store_principal(sp, principal); krb5_free_principal(context, principal); nerr += compare("Principal", sp, "\x0\x0\x0\x1" "\x0\x0\x0\x1" "\x0\x0\x0\x4TEST" "\x0\x0\x0\x6""foobar", 26); krb5_free_context(context); return nerr ? 1 : 0; }
kadm5_ret_t kadm5_c_chpass_principal_with_key(void *server_handle, krb5_principal princ, int keepold, int n_key_data, krb5_key_data *key_data) { kadm5_client_context *context = server_handle; kadm5_ret_t ret; krb5_storage *sp; unsigned char buf[1024]; int32_t tmp; krb5_data reply; int i; ret = _kadm5_connect(server_handle); if(ret) return ret; sp = krb5_storage_from_mem(buf, sizeof(buf)); if (sp == NULL) { krb5_clear_error_message(context->context); return ENOMEM; } krb5_store_int32(sp, kadm_chpass_with_key); krb5_store_principal(sp, princ); krb5_store_int32(sp, n_key_data); for (i = 0; i < n_key_data; ++i) kadm5_store_key_data (sp, &key_data[i]); krb5_store_int32(sp, keepold); /* extension */ ret = _kadm5_client_send(context, sp); krb5_storage_free(sp); if (ret) return ret; ret = _kadm5_client_recv(context, &reply); if(ret) return ret; sp = krb5_storage_from_data (&reply); if (sp == NULL) { krb5_clear_error_message(context->context); krb5_data_free (&reply); return ENOMEM; } krb5_ret_int32(sp, &tmp); krb5_clear_error_message(context->context); krb5_storage_free(sp); krb5_data_free (&reply); return tmp; }
kadm5_ret_t kadm5_c_get_principal(void *server_handle, krb5_principal princ, kadm5_principal_ent_t out, uint32_t mask) { kadm5_client_context *context = server_handle; kadm5_ret_t ret; krb5_storage *sp; unsigned char buf[1024]; int32_t tmp; krb5_data reply; ret = _kadm5_connect(server_handle); if(ret) return ret; sp = krb5_storage_from_mem(buf, sizeof(buf)); if (sp == NULL) { krb5_clear_error_message(context->context); return ENOMEM; } krb5_store_int32(sp, kadm_get); krb5_store_principal(sp, princ); krb5_store_int32(sp, mask); ret = _kadm5_client_send(context, sp); krb5_storage_free(sp); if(ret) return ret; ret = _kadm5_client_recv(context, &reply); if (ret) return ret; sp = krb5_storage_from_data (&reply); if (sp == NULL) { krb5_clear_error_message(context->context); krb5_data_free (&reply); return ENOMEM; } krb5_ret_int32(sp, &tmp); ret = tmp; krb5_clear_error_message(context->context); if(ret == 0) kadm5_ret_principal_ent(sp, out); krb5_storage_free(sp); krb5_data_free (&reply); return ret; }
/* * Request: * NameZ * ServerPrincipalPresent * ServerPrincipal OPTIONAL * Key * * Repsonse: * */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_kcm_get_initial_ticket(krb5_context context, krb5_ccache id, krb5_principal server, krb5_keyblock *key) { krb5_kcmcache *k = KCMCACHE(id); krb5_error_code ret; krb5_storage *request; ret = krb5_kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request); if (ret) return ret; ret = krb5_store_stringz(request, k->name); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_int8(request, (server == NULL) ? 0 : 1); if (ret) { krb5_storage_free(request); return ret; } if (server != NULL) { ret = krb5_store_principal(request, server); if (ret) { krb5_storage_free(request); return ret; } } ret = krb5_store_keyblock(request, *key); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_kcm_call(context, request, NULL, NULL); krb5_storage_free(request); return ret; }
/* * Request: * NameZ * KDCFlags * EncryptionType * ServerPrincipal * * Repsonse: * */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_kcm_get_ticket(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_enctype enctype, krb5_principal server) { krb5_error_code ret; krb5_kcmcache *k = KCMCACHE(id); krb5_storage *request; ret = krb5_kcm_storage_request(context, KCM_OP_GET_TICKET, &request); if (ret) return ret; ret = krb5_store_stringz(request, k->name); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_int32(request, flags.i); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_int32(request, enctype); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_store_principal(request, server); if (ret) { krb5_storage_free(request); return ret; } ret = krb5_kcm_call(context, request, NULL, NULL); krb5_storage_free(request); return ret; }
kadm5_ret_t kadm5_log_delete (kadm5_server_context *context, krb5_principal princ) { krb5_storage *sp; kadm5_ret_t ret; off_t off; off_t len; kadm5_log_context *log_context = &context->log_context; sp = krb5_storage_emem(); if (sp == NULL) return ENOMEM; ret = kadm5_log_preamble (context, sp, kadm_delete); if (ret) goto out; ret = krb5_store_int32 (sp, 0); if (ret) goto out; off = krb5_storage_seek (sp, 0, SEEK_CUR); ret = krb5_store_principal (sp, princ); if (ret) goto out; len = krb5_storage_seek (sp, 0, SEEK_CUR) - off; krb5_storage_seek(sp, -(len + 4), SEEK_CUR); ret = krb5_store_int32 (sp, len); if (ret) goto out; krb5_storage_seek(sp, len, SEEK_CUR); ret = krb5_store_int32 (sp, len); if (ret) goto out; ret = kadm5_log_postamble (log_context, sp); if (ret) goto out; ret = kadm5_log_flush (log_context, sp); if (ret) goto out; ret = kadm5_log_end (context); out: krb5_storage_free (sp); return ret; }
kadm5_ret_t kadm5_c_chpass_principal(void *server_handle, krb5_principal princ, const char *password) { kadm5_client_context *context = server_handle; kadm5_ret_t ret; krb5_storage *sp; unsigned char buf[1024]; int32_t tmp; krb5_data reply; ret = _kadm5_connect(server_handle); if(ret) return ret; sp = krb5_storage_from_mem(buf, sizeof(buf)); if (sp == NULL) { krb5_clear_error_message(context->context); return ENOMEM; } krb5_store_int32(sp, kadm_chpass); krb5_store_principal(sp, princ); krb5_store_string(sp, password); ret = _kadm5_client_send(context, sp); krb5_storage_free(sp); if (ret) return ret; ret = _kadm5_client_recv(context, &reply); if(ret) return ret; sp = krb5_storage_from_data (&reply); if (sp == NULL) { krb5_clear_error_message(context->context); krb5_data_free (&reply); return ENOMEM; } krb5_ret_int32(sp, &tmp); krb5_clear_error_message(context->context); krb5_storage_free(sp); krb5_data_free (&reply); return tmp; }
kadm5_ret_t kadm5_c_randkey_principal(void *server_handle, krb5_principal princ, krb5_boolean keepold, int n_ks_tuple, krb5_key_salt_tuple *ks_tuple, krb5_keyblock **new_keys, int *n_keys) { kadm5_client_context *context = server_handle; kadm5_ret_t ret; krb5_storage *sp; unsigned char buf[1536]; int32_t tmp; size_t i; krb5_data reply; ret = _kadm5_connect(server_handle); if(ret) return ret; sp = krb5_storage_from_mem(buf, sizeof(buf)); if (sp == NULL) { krb5_clear_error_message(context->context); return ENOMEM; } /* * NOTE WELL: This message is extensible. It currently consists of: * * - opcode (kadm_randkey) * - principal name (princ) * * followed by optional items, each of which must be present if * there are any items following them that are also present: * * - keepold boolean (whether to delete old kvnos) * - number of key/salt type tuples * - array of {enctype, salttype} * * Eventually we may add: * * - opaque string2key parameters (salt, rounds, ...) */ krb5_store_int32(sp, kadm_randkey); krb5_store_principal(sp, princ); if (keepold == TRUE || n_ks_tuple > 0) krb5_store_uint32(sp, keepold); if (n_ks_tuple > 0) krb5_store_uint32(sp, n_ks_tuple); for (i = 0; i < n_ks_tuple; i++) { krb5_store_int32(sp, ks_tuple[i].ks_enctype); krb5_store_int32(sp, ks_tuple[i].ks_salttype); } /* Future extensions go here */ ret = _kadm5_client_send(context, sp); krb5_storage_free(sp); if (ret) return ret; ret = _kadm5_client_recv(context, &reply); if(ret) return ret; sp = krb5_storage_from_data(&reply); if (sp == NULL) { krb5_clear_error_message(context->context); krb5_data_free (&reply); return ENOMEM; } krb5_clear_error_message(context->context); krb5_ret_int32(sp, &tmp); ret = tmp; if(ret == 0){ krb5_keyblock *k; krb5_ret_int32(sp, &tmp); if (tmp < 0) { ret = EOVERFLOW; goto out; } k = malloc(tmp * sizeof(*k)); if (k == NULL) { ret = ENOMEM; goto out; } for(i = 0; i < tmp; i++) krb5_ret_keyblock(sp, &k[i]); if (n_keys && new_keys) { *n_keys = tmp; *new_keys = k; } } out: krb5_storage_free(sp); krb5_data_free (&reply); return ret; }
kadm5_ret_t kadm5_log_rename (kadm5_server_context *context, krb5_principal source, hdb_entry *ent) { krb5_storage *sp; kadm5_ret_t ret; off_t off; off_t len; krb5_data value; kadm5_log_context *log_context = &context->log_context; krb5_data_zero(&value); sp = krb5_storage_emem(); ret = hdb_entry2value (context->context, ent, &value); if (ret) goto failed; ret = kadm5_log_preamble (context, sp, kadm_rename); if (ret) goto failed; ret = krb5_store_int32 (sp, 0); if (ret) goto failed; off = krb5_storage_seek (sp, 0, SEEK_CUR); ret = krb5_store_principal (sp, source); if (ret) goto failed; krb5_storage_write(sp, value.data, value.length); len = krb5_storage_seek (sp, 0, SEEK_CUR) - off; krb5_storage_seek(sp, -(len + 4), SEEK_CUR); ret = krb5_store_int32 (sp, len); if (ret) goto failed; krb5_storage_seek(sp, len, SEEK_CUR); ret = krb5_store_int32 (sp, len); if (ret) goto failed; ret = kadm5_log_postamble (log_context, sp); if (ret) goto failed; ret = kadm5_log_flush (log_context, sp); if (ret) goto failed; krb5_storage_free (sp); krb5_data_free (&value); return kadm5_log_end (context); failed: krb5_data_free(&value); krb5_storage_free(sp); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) { int ret; int32_t header = 0; if (creds->client) header |= SC_CLIENT_PRINCIPAL; if (creds->server) header |= SC_SERVER_PRINCIPAL; if (creds->session.keytype != ETYPE_NULL) header |= SC_SESSION_KEY; if (creds->ticket.data) header |= SC_TICKET; if (creds->second_ticket.length) header |= SC_SECOND_TICKET; if (creds->authdata.len) header |= SC_AUTHDATA; if (creds->addresses.len) header |= SC_ADDRESSES; ret = krb5_store_int32(sp, header); if (ret) return ret; if (creds->client) { ret = krb5_store_principal(sp, creds->client); if(ret) return ret; } if (creds->server) { ret = krb5_store_principal(sp, creds->server); if(ret) return ret; } if (creds->session.keytype != ETYPE_NULL) { ret = krb5_store_keyblock(sp, creds->session); if(ret) return ret; } ret = krb5_store_times(sp, creds->times); if(ret) return ret; ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ if(ret) return ret; ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); if(ret) return ret; if (creds->addresses.len) { ret = krb5_store_addrs(sp, creds->addresses); if(ret) return ret; } if (creds->authdata.len) { ret = krb5_store_authdata(sp, creds->authdata); if(ret) return ret; } if (creds->ticket.data) { ret = krb5_store_data(sp, creds->ticket); if(ret) return ret; } if (creds->second_ticket.data) { ret = krb5_store_data(sp, creds->second_ticket); if (ret) return ret; } return ret; }