Path: blob/main/crypto/krb5/src/plugins/kdb/lmdb/marshal.c
34914 views
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */1/* lib/kdb/kdb_xdr.c */2/*3* Copyright (C) 2018 by the Massachusetts Institute of Technology.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9*10* * Redistributions of source code must retain the above copyright11* notice, this list of conditions and the following disclaimer.12*13* * Redistributions in binary form must reproduce the above copyright14* notice, this list of conditions and the following disclaimer in15* the documentation and/or other materials provided with the16* distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS19* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT20* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS21* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE22* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,23* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES24* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR25* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)26* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,27* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)28* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED29* OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132#include "k5-int.h"33#include "k5-input.h"34#include <kdb.h>35#include "klmdb-int.h"3637static void38put_tl_data(struct k5buf *buf, const krb5_tl_data *tl)39{40for (; tl != NULL; tl = tl->tl_data_next) {41k5_buf_add_uint16_le(buf, tl->tl_data_type);42k5_buf_add_uint16_le(buf, tl->tl_data_length);43k5_buf_add_len(buf, tl->tl_data_contents, tl->tl_data_length);44}45}4647krb5_error_code48klmdb_encode_princ(krb5_context context, const krb5_db_entry *entry,49uint8_t **enc_out, size_t *len_out)50{51struct k5buf buf;52const krb5_key_data *kd;53int i, j;5455*enc_out = NULL;56*len_out = 0;5758k5_buf_init_dynamic(&buf);5960k5_buf_add_uint32_le(&buf, entry->attributes);61k5_buf_add_uint32_le(&buf, entry->max_life);62k5_buf_add_uint32_le(&buf, entry->max_renewable_life);63k5_buf_add_uint32_le(&buf, entry->expiration);64k5_buf_add_uint32_le(&buf, entry->pw_expiration);65k5_buf_add_uint16_le(&buf, entry->n_tl_data);66k5_buf_add_uint16_le(&buf, entry->n_key_data);67put_tl_data(&buf, entry->tl_data);68for (i = 0; i < entry->n_key_data; i++) {69kd = &entry->key_data[i];70k5_buf_add_uint16_le(&buf, kd->key_data_ver);71k5_buf_add_uint16_le(&buf, kd->key_data_kvno);72for (j = 0; j < kd->key_data_ver; j++) {73k5_buf_add_uint16_le(&buf, kd->key_data_type[j]);74k5_buf_add_uint16_le(&buf, kd->key_data_length[j]);75if (kd->key_data_length[j] > 0) {76k5_buf_add_len(&buf, kd->key_data_contents[j],77kd->key_data_length[j]);78}79}80}8182if (k5_buf_status(&buf) != 0)83return ENOMEM;8485*enc_out = buf.data;86*len_out = buf.len;87return 0;88}8990void91klmdb_encode_princ_lockout(krb5_context context, const krb5_db_entry *entry,92uint8_t buf[LOCKOUT_RECORD_LEN])93{94store_32_le(entry->last_success, buf);95store_32_le(entry->last_failed, buf + 4);96store_32_le(entry->fail_auth_count, buf + 8);97}9899krb5_error_code100klmdb_encode_policy(krb5_context context, const osa_policy_ent_rec *pol,101uint8_t **enc_out, size_t *len_out)102{103struct k5buf buf;104105*enc_out = NULL;106*len_out = 0;107108k5_buf_init_dynamic(&buf);109k5_buf_add_uint32_le(&buf, pol->pw_min_life);110k5_buf_add_uint32_le(&buf, pol->pw_max_life);111k5_buf_add_uint32_le(&buf, pol->pw_min_length);112k5_buf_add_uint32_le(&buf, pol->pw_min_classes);113k5_buf_add_uint32_le(&buf, pol->pw_history_num);114k5_buf_add_uint32_le(&buf, pol->pw_max_fail);115k5_buf_add_uint32_le(&buf, pol->pw_failcnt_interval);116k5_buf_add_uint32_le(&buf, pol->pw_lockout_duration);117k5_buf_add_uint32_le(&buf, pol->attributes);118k5_buf_add_uint32_le(&buf, pol->max_life);119k5_buf_add_uint32_le(&buf, pol->max_renewable_life);120121if (pol->allowed_keysalts == NULL) {122k5_buf_add_uint32_le(&buf, 0);123} else {124k5_buf_add_uint32_le(&buf, strlen(pol->allowed_keysalts));125k5_buf_add(&buf, pol->allowed_keysalts);126}127128k5_buf_add_uint16_le(&buf, pol->n_tl_data);129put_tl_data(&buf, pol->tl_data);130131if (k5_buf_status(&buf) != 0)132return ENOMEM;133134*enc_out = buf.data;135*len_out = buf.len;136return 0;137}138139static krb5_error_code140get_tl_data(struct k5input *in, size_t count, krb5_tl_data **tl)141{142krb5_error_code ret;143const uint8_t *contents;144size_t i, len;145146for (i = 0; i < count; i++) {147*tl = k5alloc(sizeof(**tl), &ret);148if (*tl == NULL)149return ret;150(*tl)->tl_data_type = k5_input_get_uint16_le(in);151len = (*tl)->tl_data_length = k5_input_get_uint16_le(in);152contents = k5_input_get_bytes(in, len);153if (contents == NULL)154return KRB5_KDB_TRUNCATED_RECORD;155(*tl)->tl_data_contents = k5memdup(contents, len, &ret);156if ((*tl)->tl_data_contents == NULL)157return ret;158tl = &(*tl)->tl_data_next;159}160161return 0;162}163164krb5_error_code165klmdb_decode_princ(krb5_context context, const void *key, size_t key_len,166const void *enc, size_t enc_len, krb5_db_entry **entry_out)167{168krb5_error_code ret;169struct k5input in;170krb5_db_entry *entry = NULL;171char *princname = NULL;172const uint8_t *contents;173int i, j;174size_t len;175krb5_key_data *kd;176177*entry_out = NULL;178179entry = k5alloc(sizeof(*entry), &ret);180if (entry == NULL)181goto cleanup;182183princname = k5memdup0(key, key_len, &ret);184if (princname == NULL)185goto cleanup;186ret = krb5_parse_name(context, princname, &entry->princ);187if (ret)188goto cleanup;189190k5_input_init(&in, enc, enc_len);191entry->attributes = k5_input_get_uint32_le(&in);192entry->max_life = k5_input_get_uint32_le(&in);193entry->max_renewable_life = k5_input_get_uint32_le(&in);194entry->expiration = k5_input_get_uint32_le(&in);195entry->pw_expiration = k5_input_get_uint32_le(&in);196entry->n_tl_data = k5_input_get_uint16_le(&in);197entry->n_key_data = k5_input_get_uint16_le(&in);198if (entry->n_tl_data < 0 || entry->n_key_data < 0) {199ret = KRB5_KDB_TRUNCATED_RECORD;200goto cleanup;201}202203ret = get_tl_data(&in, entry->n_tl_data, &entry->tl_data);204if (ret)205goto cleanup;206207if (entry->n_key_data > 0) {208entry->key_data = k5calloc(entry->n_key_data, sizeof(*entry->key_data),209&ret);210if (entry->key_data == NULL)211goto cleanup;212}213for (i = 0; i < entry->n_key_data; i++) {214kd = &entry->key_data[i];215kd->key_data_ver = k5_input_get_uint16_le(&in);216kd->key_data_kvno = k5_input_get_uint16_le(&in);217if (kd->key_data_ver < 0 &&218kd->key_data_ver > KRB5_KDB_V1_KEY_DATA_ARRAY) {219ret = KRB5_KDB_BAD_VERSION;220goto cleanup;221}222for (j = 0; j < kd->key_data_ver; j++) {223kd->key_data_type[j] = k5_input_get_uint16_le(&in);224len = kd->key_data_length[j] = k5_input_get_uint16_le(&in);225contents = k5_input_get_bytes(&in, len);226if (contents == NULL) {227ret = KRB5_KDB_TRUNCATED_RECORD;228goto cleanup;229}230if (len > 0) {231kd->key_data_contents[j] = k5memdup(contents, len, &ret);232if (kd->key_data_contents[j] == NULL)233goto cleanup;234}235}236}237238ret = in.status;239if (ret)240goto cleanup;241242entry->len = KRB5_KDB_V1_BASE_LENGTH;243*entry_out = entry;244entry = NULL;245246cleanup:247free(princname);248krb5_db_free_principal(context, entry);249return ret;250}251252void253klmdb_decode_princ_lockout(krb5_context context, krb5_db_entry *entry,254const uint8_t buf[LOCKOUT_RECORD_LEN])255{256entry->last_success = load_32_le(buf);257entry->last_failed = load_32_le(buf + 4);258entry->fail_auth_count = load_32_le(buf + 8);259}260261krb5_error_code262klmdb_decode_policy(krb5_context context, const void *key, size_t key_len,263const void *enc, size_t enc_len, osa_policy_ent_t *pol_out)264{265krb5_error_code ret;266osa_policy_ent_t pol = NULL;267struct k5input in;268const char *str;269size_t len;270271*pol_out = NULL;272pol = k5alloc(sizeof(*pol), &ret);273if (pol == NULL)274goto error;275276pol->name = k5memdup0(key, key_len, &ret);277if (pol->name == NULL)278goto error;279280k5_input_init(&in, enc, enc_len);281pol->pw_min_life = k5_input_get_uint32_le(&in);282pol->pw_max_life = k5_input_get_uint32_le(&in);283pol->pw_min_length = k5_input_get_uint32_le(&in);284pol->pw_min_classes = k5_input_get_uint32_le(&in);285pol->pw_history_num = k5_input_get_uint32_le(&in);286pol->pw_max_fail = k5_input_get_uint32_le(&in);287pol->pw_failcnt_interval = k5_input_get_uint32_le(&in);288pol->pw_lockout_duration = k5_input_get_uint32_le(&in);289pol->attributes = k5_input_get_uint32_le(&in);290pol->max_life = k5_input_get_uint32_le(&in);291pol->max_renewable_life = k5_input_get_uint32_le(&in);292293len = k5_input_get_uint32_le(&in);294if (len > 0) {295str = (char *)k5_input_get_bytes(&in, len);296if (str == NULL) {297ret = KRB5_KDB_TRUNCATED_RECORD;298goto error;299}300pol->allowed_keysalts = k5memdup0(str, len, &ret);301if (pol->allowed_keysalts == NULL)302goto error;303}304305pol->n_tl_data = k5_input_get_uint16_le(&in);306ret = get_tl_data(&in, pol->n_tl_data, &pol->tl_data);307if (ret)308goto error;309310ret = in.status;311if (ret)312goto error;313314*pol_out = pol;315return 0;316317error:318krb5_db_free_policy(context, pol);319return ret;320}321322323