summaryrefslogtreecommitdiffstats
path: root/crypto/heimdal/kadmin/version4.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/heimdal/kadmin/version4.c')
-rw-r--r--crypto/heimdal/kadmin/version4.c1016
1 files changed, 0 insertions, 1016 deletions
diff --git a/crypto/heimdal/kadmin/version4.c b/crypto/heimdal/kadmin/version4.c
deleted file mode 100644
index ffa9c07..0000000
--- a/crypto/heimdal/kadmin/version4.c
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of KTH nor the names of its contributors may be
- * used to endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-#include "kadmin_locl.h"
-#include <krb5-private.h>
-
-#define Principal krb4_Principal
-#define kadm_get krb4_kadm_get
-#undef ALLOC
-#include <krb.h>
-#include <kadm.h>
-#include <krb_err.h>
-#include <kadm_err.h>
-
-RCSID("$Id: version4.c,v 1.29.2.1 2004/04/29 12:29:23 lha Exp $");
-
-#define KADM_NO_OPCODE -1
-#define KADM_NO_ENCRYPT -2
-
-/*
- * make an error packet if we fail encrypting
- */
-
-static void
-make_you_lose_packet(int code, krb5_data *reply)
-{
- krb5_data_alloc(reply, KADM_VERSIZE + 4);
- memcpy(reply->data, KADM_ULOSE, KADM_VERSIZE);
- _krb5_put_int((char*)reply->data + KADM_VERSIZE, code, 4);
-}
-
-static int
-ret_fields(krb5_storage *sp, char *fields)
-{
- return krb5_storage_read(sp, fields, FLDSZ);
-}
-
-static int
-store_fields(krb5_storage *sp, char *fields)
-{
- return krb5_storage_write(sp, fields, FLDSZ);
-}
-
-static void
-ret_vals(krb5_storage *sp, Kadm_vals *vals)
-{
- int field;
- char *tmp_string;
-
- memset(vals, 0, sizeof(*vals));
-
- ret_fields(sp, vals->fields);
-
- for(field = 31; field >= 0; field--) {
- if(IS_FIELD(field, vals->fields)) {
- switch(field) {
- case KADM_NAME:
- krb5_ret_stringz(sp, &tmp_string);
- strlcpy(vals->name, tmp_string, sizeof(vals->name));
- free(tmp_string);
- break;
- case KADM_INST:
- krb5_ret_stringz(sp, &tmp_string);
- strlcpy(vals->instance, tmp_string,
- sizeof(vals->instance));
- free(tmp_string);
- break;
- case KADM_EXPDATE:
- krb5_ret_int32(sp, &vals->exp_date);
- break;
- case KADM_ATTR:
- krb5_ret_int16(sp, &vals->attributes);
- break;
- case KADM_MAXLIFE:
- krb5_ret_int8(sp, &vals->max_life);
- break;
- case KADM_DESKEY:
- krb5_ret_int32(sp, &vals->key_high);
- krb5_ret_int32(sp, &vals->key_low);
- break;
-#ifdef EXTENDED_KADM
- case KADM_MODDATE:
- krb5_ret_int32(sp, &vals->mod_date);
- break;
- case KADM_MODNAME:
- krb5_ret_stringz(sp, &tmp_string);
- strlcpy(vals->mod_name, tmp_string,
- sizeof(vals->mod_name));
- free(tmp_string);
- break;
- case KADM_MODINST:
- krb5_ret_stringz(sp, &tmp_string);
- strlcpy(vals->mod_instance, tmp_string,
- sizeof(vals->mod_instance));
- free(tmp_string);
- break;
- case KADM_KVNO:
- krb5_ret_int8(sp, &vals->key_version);
- break;
-#endif
- default:
- break;
- }
- }
- }
-}
-
-static void
-store_vals(krb5_storage *sp, Kadm_vals *vals)
-{
- int field;
-
- store_fields(sp, vals->fields);
-
- for(field = 31; field >= 0; field--) {
- if(IS_FIELD(field, vals->fields)) {
- switch(field) {
- case KADM_NAME:
- krb5_store_stringz(sp, vals->name);
- break;
- case KADM_INST:
- krb5_store_stringz(sp, vals->instance);
- break;
- case KADM_EXPDATE:
- krb5_store_int32(sp, vals->exp_date);
- break;
- case KADM_ATTR:
- krb5_store_int16(sp, vals->attributes);
- break;
- case KADM_MAXLIFE:
- krb5_store_int8(sp, vals->max_life);
- break;
- case KADM_DESKEY:
- krb5_store_int32(sp, vals->key_high);
- krb5_store_int32(sp, vals->key_low);
- break;
-#ifdef EXTENDED_KADM
- case KADM_MODDATE:
- krb5_store_int32(sp, vals->mod_date);
- break;
- case KADM_MODNAME:
- krb5_store_stringz(sp, vals->mod_name);
- break;
- case KADM_MODINST:
- krb5_store_stringz(sp, vals->mod_instance);
- break;
- case KADM_KVNO:
- krb5_store_int8(sp, vals->key_version);
- break;
-#endif
- default:
- break;
- }
- }
- }
-}
-
-static int
-flags_4_to_5(char *flags)
-{
- int i;
- int32_t mask = 0;
- for(i = 31; i >= 0; i--) {
- if(IS_FIELD(i, flags))
- switch(i) {
- case KADM_NAME:
- case KADM_INST:
- mask |= KADM5_PRINCIPAL;
- case KADM_EXPDATE:
- mask |= KADM5_PRINC_EXPIRE_TIME;
- case KADM_MAXLIFE:
- mask |= KADM5_MAX_LIFE;
-#ifdef EXTENDED_KADM
- case KADM_KVNO:
- mask |= KADM5_KEY_DATA;
- case KADM_MODDATE:
- mask |= KADM5_MOD_TIME;
- case KADM_MODNAME:
- case KADM_MODINST:
- mask |= KADM5_MOD_NAME;
-#endif
- }
- }
- return mask;
-}
-
-static void
-ent_to_values(krb5_context context,
- kadm5_principal_ent_t ent,
- int32_t mask,
- Kadm_vals *vals)
-{
- krb5_error_code ret;
- char realm[REALM_SZ];
- time_t exp = 0;
-
- memset(vals, 0, sizeof(*vals));
- if(mask & KADM5_PRINCIPAL) {
- ret = krb5_524_conv_principal(context, ent->principal,
- vals->name, vals->instance, realm);
- SET_FIELD(KADM_NAME, vals->fields);
- SET_FIELD(KADM_INST, vals->fields);
- }
- if(mask & KADM5_PRINC_EXPIRE_TIME) {
- if(ent->princ_expire_time != 0)
- exp = ent->princ_expire_time;
- }
- if(mask & KADM5_PW_EXPIRATION) {
- if(ent->pw_expiration != 0 && (exp == 0 || exp > ent->pw_expiration))
- exp = ent->pw_expiration;
- }
- if(exp) {
- vals->exp_date = exp;
- SET_FIELD(KADM_EXPDATE, vals->fields);
- }
- if(mask & KADM5_MAX_LIFE) {
- if(ent->max_life == 0)
- vals->max_life = 255;
- else
- vals->max_life = krb_time_to_life(0, ent->max_life);
- SET_FIELD(KADM_MAXLIFE, vals->fields);
- }
- if(mask & KADM5_KEY_DATA) {
- if(ent->n_key_data > 0) {
-#ifdef EXTENDED_KADM
- vals->key_version = ent->key_data[0].key_data_kvno;
- SET_FIELD(KADM_KVNO, vals->fields);
-#endif
- }
- /* XXX the key itself? */
- }
-#ifdef EXTENDED_KADM
- if(mask & KADM5_MOD_TIME) {
- vals->mod_date = ent->mod_date;
- SET_FIELD(KADM_MODDATE, vals->fields);
- }
- if(mask & KADM5_MOD_NAME) {
- krb5_524_conv_principal(context, ent->mod_name,
- vals->mod_name, vals->mod_instance, realm);
- SET_FIELD(KADM_MODNAME, vals->fields);
- SET_FIELD(KADM_MODINST, vals->fields);
- }
-#endif
-}
-
-/*
- * convert the kadm4 values in `vals' to `ent' (and `mask')
- */
-
-static krb5_error_code
-values_to_ent(krb5_context context,
- Kadm_vals *vals,
- kadm5_principal_ent_t ent,
- int32_t *mask)
-{
- krb5_error_code ret;
- *mask = 0;
- memset(ent, 0, sizeof(*ent));
-
- if(IS_FIELD(KADM_NAME, vals->fields)) {
- char *inst = NULL;
- if(IS_FIELD(KADM_INST, vals->fields))
- inst = vals->instance;
- ret = krb5_425_conv_principal(context,
- vals->name,
- inst,
- NULL,
- &ent->principal);
- if(ret)
- return ret;
- *mask |= KADM5_PRINCIPAL;
- }
- if(IS_FIELD(KADM_EXPDATE, vals->fields)) {
- ent->princ_expire_time = vals->exp_date;
- *mask |= KADM5_PRINC_EXPIRE_TIME;
- }
- if(IS_FIELD(KADM_MAXLIFE, vals->fields)) {
- ent->max_life = krb_life_to_time(0, vals->max_life);
- *mask |= KADM5_MAX_LIFE;
- }
-
- if(IS_FIELD(KADM_DESKEY, vals->fields)) {
- int i;
- ent->key_data = calloc(3, sizeof(*ent->key_data));
- if(ent->key_data == NULL)
- return ENOMEM;
- for(i = 0; i < 3; i++) {
- u_int32_t key_low, key_high;
-
- ent->key_data[i].key_data_ver = 2;
-#ifdef EXTENDED_KADM
- if(IS_FIELD(KADM_KVNO, vals->fields))
- ent->key_data[i].key_data_kvno = vals->key_version;
-#endif
- ent->key_data[i].key_data_type[0] = ETYPE_DES_CBC_MD5;
- ent->key_data[i].key_data_length[0] = 8;
- if((ent->key_data[i].key_data_contents[0] = malloc(8)) == NULL)
- return ENOMEM;
-
- key_low = ntohl(vals->key_low);
- key_high = ntohl(vals->key_high);
- memcpy(ent->key_data[i].key_data_contents[0],
- &key_low, 4);
- memcpy((char*)ent->key_data[i].key_data_contents[0] + 4,
- &key_high, 4);
- ent->key_data[i].key_data_type[1] = KRB5_PW_SALT;
- ent->key_data[i].key_data_length[1] = 0;
- ent->key_data[i].key_data_contents[1] = NULL;
- }
- ent->key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4;
- ent->key_data[2].key_data_type[0] = ETYPE_DES_CBC_CRC;
- ent->n_key_data = 3;
- *mask |= KADM5_KEY_DATA;
- }
-
-#ifdef EXTENDED_KADM
- if(IS_FIELD(KADM_MODDATE, vals->fields)) {
- ent->mod_date = vals->mod_date;
- *mask |= KADM5_MOD_TIME;
- }
- if(IS_FIELD(KADM_MODNAME, vals->fields)) {
- char *inst = NULL;
- if(IS_FIELD(KADM_MODINST, vals->fields))
- inst = vals->mod_instance;
- ret = krb5_425_conv_principal(context,
- vals->mod_name,
- inst,
- NULL,
- &ent->mod_name);
- if(ret)
- return ret;
- *mask |= KADM5_MOD_NAME;
- }
-#endif
- return 0;
-}
-
-/*
- * Try to translate a KADM5 error code into a v4 kadmin one.
- */
-
-static int
-error_code(int ret)
-{
- switch (ret) {
- case 0:
- return 0;
- case KADM5_FAILURE :
- case KADM5_AUTH_GET :
- case KADM5_AUTH_ADD :
- case KADM5_AUTH_MODIFY :
- case KADM5_AUTH_DELETE :
- case KADM5_AUTH_INSUFFICIENT :
- return KADM_UNAUTH;
- case KADM5_BAD_DB :
- return KADM_UK_RERROR;
- case KADM5_DUP :
- return KADM_INUSE;
- case KADM5_RPC_ERROR :
- case KADM5_NO_SRV :
- return KADM_NO_SERV;
- case KADM5_NOT_INIT :
- return KADM_NO_CONN;
- case KADM5_UNK_PRINC :
- return KADM_NOENTRY;
- case KADM5_PASS_Q_TOOSHORT :
-#ifdef KADM_PASS_Q_TOOSHORT
- return KADM_PASS_Q_TOOSHORT;
-#else
- return KADM_INSECURE_PW;
-#endif
- case KADM5_PASS_Q_CLASS :
-#ifdef KADM_PASS_Q_CLASS
- return KADM_PASS_Q_CLASS;
-#else
- return KADM_INSECURE_PW;
-#endif
- case KADM5_PASS_Q_DICT :
-#ifdef KADM_PASS_Q_DICT
- return KADM_PASS_Q_DICT;
-#else
- return KADM_INSECURE_PW;
-#endif
- case KADM5_PASS_REUSE :
- case KADM5_PASS_TOOSOON :
- case KADM5_BAD_PASSWORD :
- return KADM_INSECURE_PW;
- case KADM5_PROTECT_PRINCIPAL :
- return KADM_IMMUTABLE;
- case KADM5_POLICY_REF :
- case KADM5_INIT :
- case KADM5_BAD_HIST_KEY :
- case KADM5_UNK_POLICY :
- case KADM5_BAD_MASK :
- case KADM5_BAD_CLASS :
- case KADM5_BAD_LENGTH :
- case KADM5_BAD_POLICY :
- case KADM5_BAD_PRINCIPAL :
- case KADM5_BAD_AUX_ATTR :
- case KADM5_BAD_HISTORY :
- case KADM5_BAD_MIN_PASS_LIFE :
- case KADM5_BAD_SERVER_HANDLE :
- case KADM5_BAD_STRUCT_VERSION :
- case KADM5_OLD_STRUCT_VERSION :
- case KADM5_NEW_STRUCT_VERSION :
- case KADM5_BAD_API_VERSION :
- case KADM5_OLD_LIB_API_VERSION :
- case KADM5_OLD_SERVER_API_VERSION :
- case KADM5_NEW_LIB_API_VERSION :
- case KADM5_NEW_SERVER_API_VERSION :
- case KADM5_SECURE_PRINC_MISSING :
- case KADM5_NO_RENAME_SALT :
- case KADM5_BAD_CLIENT_PARAMS :
- case KADM5_BAD_SERVER_PARAMS :
- case KADM5_AUTH_LIST :
- case KADM5_AUTH_CHANGEPW :
- case KADM5_BAD_TL_TYPE :
- case KADM5_MISSING_CONF_PARAMS :
- case KADM5_BAD_SERVER_NAME :
- default :
- return KADM_UNAUTH; /* XXX */
- }
-}
-
-/*
- * server functions
- */
-
-static int
-kadm_ser_cpw(krb5_context context,
- void *kadm_handle,
- krb5_principal principal,
- const char *principal_string,
- krb5_storage *message,
- krb5_storage *reply)
-{
- char key[8];
- char *password = NULL;
- krb5_error_code ret;
-
- krb5_warnx(context, "v4-compat %s: CHPASS %s",
- principal_string, principal_string);
-
- ret = krb5_storage_read(message, key + 4, 4);
- ret = krb5_storage_read(message, key, 4);
- ret = krb5_ret_stringz(message, &password);
-
- if(password) {
- krb5_data pwd_data;
- const char *tmp;
-
- pwd_data.data = password;
- pwd_data.length = strlen(password);
-
- tmp = kadm5_check_password_quality (context, principal, &pwd_data);
-
- if (tmp != NULL) {
- krb5_store_stringz (reply, (char *)tmp);
- ret = KADM5_PASS_Q_DICT;
- goto fail;
- }
- ret = kadm5_chpass_principal(kadm_handle, principal, password);
- } else {
- krb5_key_data key_data[3];
- int i;
- for(i = 0; i < 3; i++) {
- key_data[i].key_data_ver = 2;
- key_data[i].key_data_kvno = 0;
- /* key */
- key_data[i].key_data_type[0] = ETYPE_DES_CBC_CRC;
- key_data[i].key_data_length[0] = 8;
- key_data[i].key_data_contents[0] = malloc(8);
- memcpy(key_data[i].key_data_contents[0], &key, 8);
- /* salt */
- key_data[i].key_data_type[1] = KRB5_PW_SALT;
- key_data[i].key_data_length[1] = 0;
- key_data[i].key_data_contents[1] = NULL;
- }
- key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5;
- key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4;
- ret = kadm5_s_chpass_principal_with_key(kadm_handle,
- principal, 3, key_data);
- }
-
- if(ret != 0) {
- krb5_store_stringz(reply, (char*)krb5_get_err_text(context, ret));
- goto fail;
- }
- return 0;
-fail:
- krb5_warn(context, ret, "v4-compat CHPASS");
- return error_code(ret);
-}
-
-static int
-kadm_ser_add(krb5_context context,
- void *kadm_handle,
- krb5_principal principal,
- const char *principal_string,
- krb5_storage *message,
- krb5_storage *reply)
-{
- int32_t mask;
- kadm5_principal_ent_rec ent, out;
- Kadm_vals values;
- krb5_error_code ret;
- char name[128];
-
- ret_vals(message, &values);
-
- ret = values_to_ent(context, &values, &ent, &mask);
- if(ret)
- goto fail;
-
- krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
- krb5_warnx(context, "v4-compat %s: ADD %s",
- principal_string, name);
-
- ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_ADD,
- ent.principal);
- if (ret)
- goto fail;
-
- ret = kadm5_s_create_principal_with_key(kadm_handle, &ent, mask);
- if(ret) {
- kadm5_free_principal_ent(kadm_handle, &ent);
- goto fail;
- }
-
- mask = KADM5_PRINCIPAL | KADM5_PRINC_EXPIRE_TIME | KADM5_MAX_LIFE |
- KADM5_KEY_DATA | KADM5_MOD_TIME | KADM5_MOD_NAME;
-
- kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
- ent_to_values(context, &out, mask, &values);
- kadm5_free_principal_ent(kadm_handle, &ent);
- kadm5_free_principal_ent(kadm_handle, &out);
- store_vals(reply, &values);
- return 0;
-fail:
- krb5_warn(context, ret, "v4-compat ADD");
- return error_code(ret);
-}
-
-static int
-kadm_ser_get(krb5_context context,
- void *kadm_handle,
- krb5_principal principal,
- const char *principal_string,
- krb5_storage *message,
- krb5_storage *reply)
-{
- krb5_error_code ret;
- Kadm_vals values;
- kadm5_principal_ent_rec ent, out;
- int32_t mask;
- char flags[FLDSZ];
- char name[128];
-
- ret_vals(message, &values);
- /* XXX BRAIN DAMAGE! these flags are not stored in the same order
- as in the header */
- krb5_ret_int8(message, &flags[3]);
- krb5_ret_int8(message, &flags[2]);
- krb5_ret_int8(message, &flags[1]);
- krb5_ret_int8(message, &flags[0]);
- ret = values_to_ent(context, &values, &ent, &mask);
- if(ret)
- goto fail;
-
- krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
- krb5_warnx(context, "v4-compat %s: GET %s",
- principal_string, name);
-
- ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_GET,
- ent.principal);
- if (ret)
- goto fail;
-
- mask = flags_4_to_5(flags);
-
- ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
- kadm5_free_principal_ent(kadm_handle, &ent);
-
- if (ret)
- goto fail;
-
- ent_to_values(context, &out, mask, &values);
-
- kadm5_free_principal_ent(kadm_handle, &out);
-
- store_vals(reply, &values);
- return 0;
-fail:
- krb5_warn(context, ret, "v4-compat GET");
- return error_code(ret);
-}
-
-static int
-kadm_ser_mod(krb5_context context,
- void *kadm_handle,
- krb5_principal principal,
- const char *principal_string,
- krb5_storage *message,
- krb5_storage *reply)
-{
- Kadm_vals values1, values2;
- kadm5_principal_ent_rec ent, out;
- int32_t mask;
- krb5_error_code ret;
- char name[128];
-
- ret_vals(message, &values1);
- /* why are the old values sent? is the mask the same in the old and
- the new entry? */
- ret_vals(message, &values2);
-
- ret = values_to_ent(context, &values2, &ent, &mask);
- if(ret)
- goto fail;
-
- krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
- krb5_warnx(context, "v4-compat %s: MOD %s",
- principal_string, name);
-
- ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_MODIFY,
- ent.principal);
- if (ret)
- goto fail;
-
- ret = kadm5_s_modify_principal(kadm_handle, &ent, mask);
- if(ret) {
- kadm5_free_principal_ent(kadm_handle, &ent);
- krb5_warn(context, ret, "kadm5_s_modify_principal");
- goto fail;
- }
-
- ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
- if(ret) {
- kadm5_free_principal_ent(kadm_handle, &ent);
- krb5_warn(context, ret, "kadm5_s_modify_principal");
- goto fail;
- }
-
- ent_to_values(context, &out, mask, &values1);
-
- kadm5_free_principal_ent(kadm_handle, &ent);
- kadm5_free_principal_ent(kadm_handle, &out);
-
- store_vals(reply, &values1);
- return 0;
-fail:
- krb5_warn(context, ret, "v4-compat MOD");
- return error_code(ret);
-}
-
-static int
-kadm_ser_del(krb5_context context,
- void *kadm_handle,
- krb5_principal principal,
- const char *principal_string,
- krb5_storage *message,
- krb5_storage *reply)
-{
- Kadm_vals values;
- kadm5_principal_ent_rec ent;
- int32_t mask;
- krb5_error_code ret;
- char name[128];
-
- ret_vals(message, &values);
-
- ret = values_to_ent(context, &values, &ent, &mask);
- if(ret)
- goto fail;
-
- krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
- krb5_warnx(context, "v4-compat %s: DEL %s",
- principal_string, name);
-
- ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_DELETE,
- ent.principal);
- if (ret)
- goto fail;
-
- ret = kadm5_delete_principal(kadm_handle, ent.principal);
-
- kadm5_free_principal_ent(kadm_handle, &ent);
-
- if (ret)
- goto fail;
-
- return 0;
-fail:
- krb5_warn(context, ret, "v4-compat ADD");
- return error_code(ret);
-}
-
-static int
-dispatch(krb5_context context,
- void *kadm_handle,
- krb5_principal principal,
- const char *principal_string,
- krb5_data msg,
- krb5_data *reply)
-{
- int retval;
- int8_t command;
- krb5_storage *sp_in, *sp_out;
-
- sp_in = krb5_storage_from_data(&msg);
- krb5_ret_int8(sp_in, &command);
-
- sp_out = krb5_storage_emem();
- krb5_storage_write(sp_out, KADM_VERSTR, KADM_VERSIZE);
- krb5_store_int32(sp_out, 0);
-
- switch(command) {
- case CHANGE_PW:
- retval = kadm_ser_cpw(context, kadm_handle, principal,
- principal_string,
- sp_in, sp_out);
- break;
- case ADD_ENT:
- retval = kadm_ser_add(context, kadm_handle, principal,
- principal_string,
- sp_in, sp_out);
- break;
- case GET_ENT:
- retval = kadm_ser_get(context, kadm_handle, principal,
- principal_string,
- sp_in, sp_out);
- break;
- case MOD_ENT:
- retval = kadm_ser_mod(context, kadm_handle, principal,
- principal_string,
- sp_in, sp_out);
- break;
- case DEL_ENT:
- retval = kadm_ser_del(context, kadm_handle, principal,
- principal_string,
- sp_in, sp_out);
- break;
- default:
- krb5_warnx(context, "v4-compat %s: unknown opcode: %d",
- principal_string, command);
- retval = KADM_NO_OPCODE;
- break;
- }
- krb5_storage_free(sp_in);
- if(retval) {
- krb5_storage_seek(sp_out, KADM_VERSIZE, SEEK_SET);
- krb5_store_int32(sp_out, retval);
- }
- krb5_storage_to_data(sp_out, reply);
- krb5_storage_free(sp_out);
- return retval;
-}
-
-/*
- * Decode a v4 kadmin packet in `message' and create a reply in `reply'
- */
-
-static void
-decode_packet(krb5_context context,
- krb5_keytab keytab,
- struct sockaddr_in *admin_addr,
- struct sockaddr_in *client_addr,
- krb5_data message,
- krb5_data *reply)
-{
- int ret;
- KTEXT_ST authent;
- AUTH_DAT ad;
- MSG_DAT msg_dat;
- off_t off = 0;
- unsigned long rlen;
- char sname[] = "changepw", sinst[] = "kerberos";
- unsigned long checksum;
- des_key_schedule schedule;
- char *msg = message.data;
- void *kadm_handle;
- krb5_principal client;
- char *client_str;
- krb5_keytab_entry entry;
-
- if(message.length < KADM_VERSIZE + 4
- || strncmp(msg, KADM_VERSTR, KADM_VERSIZE) != 0) {
- make_you_lose_packet (KADM_BAD_VER, reply);
- return;
- }
-
- off = KADM_VERSIZE;
- off += _krb5_get_int(msg + off, &rlen, 4);
- memset(&authent, 0, sizeof(authent));
- authent.length = message.length - rlen - KADM_VERSIZE - 4;
-
- if(rlen > message.length - KADM_VERSIZE - 4
- || authent.length > MAX_KTXT_LEN) {
- krb5_warnx(context, "received bad rlen (%lu)", (unsigned long)rlen);
- make_you_lose_packet (KADM_LENGTH_ERROR, reply);
- return;
- }
-
- memcpy(authent.dat, (char*)msg + off, authent.length);
- off += authent.length;
-
- {
- krb5_principal principal;
- krb5_keyblock *key;
-
- ret = krb5_make_principal(context, &principal, NULL,
- "changepw", "kerberos", NULL);
- if (ret) {
- krb5_warn (context, ret, "krb5_make_principal");
- make_you_lose_packet (KADM_NOMEM, reply);
- return;
- }
- ret = krb5_kt_get_entry (context, keytab, principal, 0,
- ETYPE_DES_CBC_MD5, &entry);
- krb5_kt_close (context, keytab);
- if (ret) {
- krb5_free_principal(context, principal);
- make_you_lose_packet (KADM_NO_AUTH, reply);
- return;
- }
- ret = krb5_copy_keyblock (context, &entry.keyblock,& key);
- krb5_kt_free_entry(context, &entry);
- krb5_free_principal(context, principal);
- if(ret) {
- if(ret == KRB5_KT_NOTFOUND)
- make_you_lose_packet(KADM_NO_AUTH, reply);
- else
- /* XXX */
- make_you_lose_packet(KADM_NO_AUTH, reply);
- krb5_warn(context, ret, "krb5_kt_read_service_key");
- return;
- }
-
- if(key->keyvalue.length != 8)
- krb5_abortx(context, "key has wrong length (%lu)",
- (unsigned long)key->keyvalue.length);
- krb_set_key(key->keyvalue.data, 0);
- krb5_free_keyblock(context, key);
- }
-
- ret = krb_rd_req(&authent, sname, sinst,
- client_addr->sin_addr.s_addr, &ad, NULL);
-
- if(ret) {
- make_you_lose_packet(ERROR_TABLE_BASE_krb + ret, reply);
- krb5_warnx(context, "krb_rd_req: %d", ret);
- return;
- }
-
- ret = krb5_425_conv_principal(context, ad.pname, ad.pinst, ad.prealm,
- &client);
- if (ret) {
- krb5_warnx (context, "krb5_425_conv_principal: %d", ret);
- make_you_lose_packet (KADM_NOMEM, reply);
- return;
- }
-
- krb5_unparse_name(context, client, &client_str);
-
- ret = kadm5_init_with_password_ctx(context,
- client_str,
- NULL,
- KADM5_ADMIN_SERVICE,
- NULL, 0, 0,
- &kadm_handle);
- if (ret) {
- krb5_warn (context, ret, "kadm5_init_with_password_ctx");
- make_you_lose_packet (KADM_NOMEM, reply);
- goto out;
- }
-
- checksum = des_quad_cksum((void *)(msg + off), NULL, rlen, 0, &ad.session);
- if(checksum != ad.checksum) {
- krb5_warnx(context, "decode_packet: bad checksum");
- make_you_lose_packet (KADM_BAD_CHK, reply);
- goto out;
- }
- des_set_key(&ad.session, schedule);
- ret = krb_rd_priv(msg + off, rlen, schedule, &ad.session,
- client_addr, admin_addr, &msg_dat);
- if (ret) {
- make_you_lose_packet (ERROR_TABLE_BASE_krb + ret, reply);
- krb5_warnx(context, "krb_rd_priv: %d", ret);
- goto out;
- }
-
- {
- krb5_data d, r;
- int retval;
-
- d.data = msg_dat.app_data;
- d.length = msg_dat.app_length;
-
- retval = dispatch(context, kadm_handle,
- client, client_str, d, &r);
- krb5_data_alloc(reply, r.length + 26);
- reply->length = krb_mk_priv(r.data, reply->data, r.length,
- schedule, &ad.session,
- admin_addr, client_addr);
- if((ssize_t)reply->length < 0) {
- make_you_lose_packet(KADM_NO_ENCRYPT, reply);
- goto out;
- }
- }
-out:
- krb5_free_principal(context, client);
- free(client_str);
-}
-
-void
-handle_v4(krb5_context context,
- krb5_keytab keytab,
- int len,
- int fd)
-{
- int first = 1;
- struct sockaddr_in admin_addr, client_addr;
- socklen_t addr_len;
- krb5_data message, reply;
- ssize_t n;
-
- addr_len = sizeof(client_addr);
- if (getsockname(fd, (struct sockaddr*)&admin_addr, &addr_len) < 0)
- krb5_errx (context, 1, "getsockname");
- addr_len = sizeof(client_addr);
- if (getpeername(fd, (struct sockaddr*)&client_addr, &addr_len) < 0)
- krb5_errx (context, 1, "getpeername");
-
- while(1) {
- doing_useful_work = 0;
- if(term_flag)
- exit(0);
- if(first) {
- if (len < 2)
- krb5_errx(context, 1, "received too short len (%d < 2)", len);
- /* first time around, we have already read len, and two
- bytes of the version string */
- krb5_data_alloc(&message, len);
- memcpy(message.data, "KA", 2);
- n = krb5_net_read(context, &fd, (char*)message.data + 2,
- len - 2);
- if (n == 0)
- exit (0);
- if (n < 0)
- krb5_err (context, 1, errno, "krb5_net_read");
- first = 0;
- } else {
- char buf[2];
- unsigned long tmp;
- ssize_t n;
-
- n = krb5_net_read(context, &fd, buf, sizeof(2));
- if (n == 0)
- exit (0);
- if (n < 0)
- krb5_err (context, 1, errno, "krb5_net_read");
- _krb5_get_int(buf, &tmp, 2);
- krb5_data_alloc(&message, tmp);
- n = krb5_net_read(context, &fd, message.data, message.length);
- if (n == 0)
- krb5_errx (context, 1, "EOF in krb5_net_read");
- if (n < 0)
- krb5_err (context, 1, errno, "krb5_net_read");
- }
- doing_useful_work = 1;
- decode_packet(context, keytab, &admin_addr, &client_addr,
- message, &reply);
- krb5_data_free(&message);
- {
- char buf[2];
-
- _krb5_put_int(buf, reply.length, sizeof(buf));
- n = krb5_net_write(context, &fd, buf, sizeof(buf));
- if (n < 0)
- krb5_err (context, 1, errno, "krb5_net_write");
- n = krb5_net_write(context, &fd, reply.data, reply.length);
- if (n < 0)
- krb5_err (context, 1, errno, "krb5_net_write");
- krb5_data_free(&reply);
- }
- }
-}
OpenPOWER on IntegriCloud