⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mkey.c

📁 samba最新软件
💻 C
字号:
/* * Copyright (c) 2000 - 2004 Kungliga Tekniska H鰃skolan * (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 the Institute 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 THE INSTITUTE AND 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 THE INSTITUTE OR 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 "hdb_locl.h"#ifndef O_BINARY#define O_BINARY 0#endifRCSID("$Id: mkey.c 21745 2007-07-31 16:11:25Z lha $");struct hdb_master_key_data {    krb5_keytab_entry keytab;    krb5_crypto crypto;    struct hdb_master_key_data *next;};voidhdb_free_master_key(krb5_context context, hdb_master_key mkey){    struct hdb_master_key_data *ptr;    while(mkey) {	krb5_kt_free_entry(context, &mkey->keytab);	if (mkey->crypto)	    krb5_crypto_destroy(context, mkey->crypto);	ptr = mkey;	mkey = mkey->next;	free(ptr);    }}krb5_error_codehdb_process_master_key(krb5_context context,		       int kvno, krb5_keyblock *key, krb5_enctype etype,		       hdb_master_key *mkey){    krb5_error_code ret;    *mkey = calloc(1, sizeof(**mkey));    if(*mkey == NULL) {	krb5_set_error_string(context, "malloc: out of memory");	return ENOMEM;    }    (*mkey)->keytab.vno = kvno;    ret = krb5_parse_name(context, "K/M", &(*mkey)->keytab.principal);    if(ret)	goto fail;    ret = krb5_copy_keyblock_contents(context, key, &(*mkey)->keytab.keyblock);    if(ret)	goto fail;    if(etype != 0)	(*mkey)->keytab.keyblock.keytype = etype;    (*mkey)->keytab.timestamp = time(NULL);    ret = krb5_crypto_init(context, key, etype, &(*mkey)->crypto);    if(ret)	goto fail;    return 0; fail:    hdb_free_master_key(context, *mkey);    *mkey = NULL;    return ret;}krb5_error_codehdb_add_master_key(krb5_context context, krb5_keyblock *key,		   hdb_master_key *inout){    int vno = 0;    hdb_master_key p;    krb5_error_code ret;    for(p = *inout; p; p = p->next)	vno = max(vno, p->keytab.vno);    vno++;    ret = hdb_process_master_key(context, vno, key, 0, &p);    if(ret)	return ret;    p->next = *inout;    *inout = p;    return 0;}static krb5_error_coderead_master_keytab(krb5_context context, const char *filename, 		   hdb_master_key *mkey){    krb5_error_code ret;    krb5_keytab id;    krb5_kt_cursor cursor;    krb5_keytab_entry entry;    hdb_master_key p;        ret = krb5_kt_resolve(context, filename, &id);    if(ret)	return ret;    ret = krb5_kt_start_seq_get(context, id, &cursor);    if(ret)	goto out;    *mkey = NULL;    while(krb5_kt_next_entry(context, id, &entry, &cursor) == 0) {	p = calloc(1, sizeof(*p));	if(p == NULL) {	    krb5_kt_end_seq_get(context, id, &cursor);	    ret = ENOMEM;	    goto out;	}	p->keytab = entry;	ret = krb5_crypto_init(context, &p->keytab.keyblock, 0, &p->crypto);	p->next = *mkey;	*mkey = p;    }    krb5_kt_end_seq_get(context, id, &cursor);  out:    krb5_kt_close(context, id);    return ret;}/* read a MIT master keyfile */static krb5_error_coderead_master_mit(krb5_context context, const char *filename, 		hdb_master_key *mkey){    int fd;    krb5_error_code ret;    krb5_storage *sp;    int16_t enctype;    krb5_keyblock key;	           fd = open(filename, O_RDONLY | O_BINARY);    if(fd < 0) {	int save_errno = errno;	krb5_set_error_string(context, "failed to open %s: %s", filename,			      strerror(save_errno));	return save_errno;    }    sp = krb5_storage_from_fd(fd);    if(sp == NULL) {	close(fd);	return errno;    }    krb5_storage_set_flags(sp, KRB5_STORAGE_HOST_BYTEORDER);#if 0    /* could possibly use ret_keyblock here, but do it with more       checks for now */    ret = krb5_ret_keyblock(sp, &key);#else    ret = krb5_ret_int16(sp, &enctype);    if((htons(enctype) & 0xff00) == 0x3000) {	krb5_set_error_string(context, "unknown keytype in %s: %#x, expected %#x", 			      filename, htons(enctype), 0x3000);	ret = HEIM_ERR_BAD_MKEY;	goto out;    }    key.keytype = enctype;    ret = krb5_ret_data(sp, &key.keyvalue);    if(ret)	goto out;#endif    ret = hdb_process_master_key(context, 0, &key, 0, mkey);    krb5_free_keyblock_contents(context, &key);  out:    krb5_storage_free(sp);    close(fd);    return ret;}/* read an old master key file */static krb5_error_coderead_master_encryptionkey(krb5_context context, const char *filename, 			  hdb_master_key *mkey){    int fd;    krb5_keyblock key;    krb5_error_code ret;    unsigned char buf[256];    ssize_t len;    size_t ret_len;	           fd = open(filename, O_RDONLY | O_BINARY);    if(fd < 0) {	int save_errno = errno;	krb5_set_error_string(context, "failed to open %s: %s", 			      filename, strerror(save_errno));	return save_errno;    }        len = read(fd, buf, sizeof(buf));    close(fd);    if(len < 0) {	int save_errno = errno;	krb5_set_error_string(context, "error reading %s: %s", 			      filename, strerror(save_errno));	return save_errno;    }    ret = decode_EncryptionKey(buf, len, &key, &ret_len);    memset(buf, 0, sizeof(buf));    if(ret)	return ret;    /* Originally, the keytype was just that, and later it got changed       to des-cbc-md5, but we always used des in cfb64 mode. This       should cover all cases, but will break if someone has hacked       this code to really use des-cbc-md5 -- but then that's not my       problem. */    if(key.keytype == KEYTYPE_DES || key.keytype == ETYPE_DES_CBC_MD5)	key.keytype = ETYPE_DES_CFB64_NONE;        ret = hdb_process_master_key(context, 0, &key, 0, mkey);    krb5_free_keyblock_contents(context, &key);    return ret;}/* read a krb4 /.k style file */static krb5_error_coderead_master_krb4(krb5_context context, const char *filename, 		 hdb_master_key *mkey){    int fd;    krb5_keyblock key;    krb5_error_code ret;    unsigned char buf[256];    ssize_t len;	           fd = open(filename, O_RDONLY | O_BINARY);    if(fd < 0) {	int save_errno = errno;	krb5_set_error_string(context, "failed to open %s: %s", 			      filename, strerror(save_errno));	return save_errno;    }        len = read(fd, buf, sizeof(buf));    close(fd);    if(len < 0) {	int save_errno = errno;	krb5_set_error_string(context, "error reading %s: %s", 			      filename, strerror(save_errno));	return save_errno;    }    if(len != 8) {	krb5_set_error_string(context, "bad contents of %s", filename);	return HEIM_ERR_EOF; /* XXX file might be too large */    }    memset(&key, 0, sizeof(key));    key.keytype = ETYPE_DES_PCBC_NONE;    ret = krb5_data_copy(&key.keyvalue, buf, len);    memset(buf, 0, sizeof(buf));    if(ret) 	return ret;    ret = hdb_process_master_key(context, 0, &key, 0, mkey);    krb5_free_keyblock_contents(context, &key);    return ret;}krb5_error_codehdb_read_master_key(krb5_context context, const char *filename, 		    hdb_master_key *mkey){    FILE *f;    unsigned char buf[16];    krb5_error_code ret;    off_t len;    *mkey = NULL;    if(filename == NULL)	filename = HDB_DB_DIR "/m-key";    f = fopen(filename, "r");    if(f == NULL) {	int save_errno = errno;	krb5_set_error_string(context, "failed to open %s: %s", 			      filename, strerror(save_errno));	return save_errno;    }        if(fread(buf, 1, 2, f) != 2) {	krb5_set_error_string(context, "end of file reading %s", filename);	fclose(f);	return HEIM_ERR_EOF;    }        fseek(f, 0, SEEK_END);    len = ftell(f);    if(fclose(f) != 0)	return errno;        if(len < 0)	return errno;        if(len == 8) {	ret = read_master_krb4(context, filename, mkey);    } else if(buf[0] == 0x30 && len <= 127 && buf[1] == len - 2) {	ret = read_master_encryptionkey(context, filename, mkey);    } else if(buf[0] == 5 && buf[1] >= 1 && buf[1] <= 2) {	ret = read_master_keytab(context, filename, mkey);    } else {	ret = read_master_mit(context, filename, mkey);    }    return ret;}krb5_error_codehdb_write_master_key(krb5_context context, const char *filename, 		     hdb_master_key mkey){    krb5_error_code ret;    hdb_master_key p;    krb5_keytab kt;    if(filename == NULL)	filename = HDB_DB_DIR "/m-key";    ret = krb5_kt_resolve(context, filename, &kt);    if(ret)	return ret;    for(p = mkey; p; p = p->next) {	ret = krb5_kt_add_entry(context, kt, &p->keytab);    }    krb5_kt_close(context, kt);    return ret;}hdb_master_key_hdb_find_master_key(uint32_t *mkvno, hdb_master_key mkey){    hdb_master_key ret = NULL;    while(mkey) {	if(ret == NULL && mkey->keytab.vno == 0)	    ret = mkey;	if(mkvno == NULL) {	    if(ret == NULL || mkey->keytab.vno > ret->keytab.vno)		ret = mkey;	} else if(mkey->keytab.vno == *mkvno)	    return mkey;	mkey = mkey->next;    }    return ret;}int_hdb_mkey_version(hdb_master_key mkey){    return mkey->keytab.vno;}int_hdb_mkey_decrypt(krb5_context context, hdb_master_key key,		  krb5_key_usage usage,		  void *ptr, size_t size, krb5_data *res){    return krb5_decrypt(context, key->crypto, usage,			ptr, size, res);}int_hdb_mkey_encrypt(krb5_context context, hdb_master_key key,		  krb5_key_usage usage,		  const void *ptr, size_t size, krb5_data *res){    return krb5_encrypt(context, key->crypto, usage,			ptr, size, res);}krb5_error_codehdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey) {	    krb5_error_code ret;    krb5_data res;    size_t keysize;    hdb_master_key key;    if(k->mkvno == NULL)	return 0;	    key = _hdb_find_master_key(k->mkvno, mkey);    if (key == NULL)	return HDB_ERR_NO_MKEY;    ret = _hdb_mkey_decrypt(context, key, HDB_KU_MKEY,			    k->key.keyvalue.data,			    k->key.keyvalue.length,			    &res);    if(ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {	/* try to decrypt with MIT key usage */	ret = _hdb_mkey_decrypt(context, key, 0,				k->key.keyvalue.data,				k->key.keyvalue.length,				&res);    }        if (ret)	return ret;    /* fixup keylength if the key got padded when encrypting it */    ret = krb5_enctype_keysize(context, k->key.keytype, &keysize);    if (ret) {	krb5_data_free(&res);	return ret;    }    if (keysize > res.length) {	krb5_data_free(&res);	return KRB5_BAD_KEYSIZE;    }    memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);    free(k->key.keyvalue.data);    k->key.keyvalue = res;    k->key.keyvalue.length = keysize;    free(k->mkvno);    k->mkvno = NULL;    return 0;}krb5_error_codehdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey){    int i;    for(i = 0; i < ent->keys.len; i++){	krb5_error_code ret;	ret = hdb_unseal_key_mkey(context, &ent->keys.val[i], mkey);	if (ret) 	    return ret;    }    return 0;}krb5_error_codehdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent){    if (db->hdb_master_key_set == 0)	return 0;    return hdb_unseal_keys_mkey(context, ent, db->hdb_master_key);}krb5_error_codehdb_unseal_key(krb5_context context, HDB *db, Key *k){    if (db->hdb_master_key_set == 0)	return 0;    return hdb_unseal_key_mkey(context, k, db->hdb_master_key);}krb5_error_codehdb_seal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey){    krb5_error_code ret;    krb5_data res;    hdb_master_key key;    if(k->mkvno != NULL)	return 0;    key = _hdb_find_master_key(k->mkvno, mkey);    if (key == NULL)	return HDB_ERR_NO_MKEY;    ret = _hdb_mkey_encrypt(context, key, HDB_KU_MKEY,			    k->key.keyvalue.data,			    k->key.keyvalue.length,			    &res);    if (ret)	return ret;    memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);    free(k->key.keyvalue.data);    k->key.keyvalue = res;    if (k->mkvno == NULL) {	k->mkvno = malloc(sizeof(*k->mkvno));	if (k->mkvno == NULL)	    return ENOMEM;    }    *k->mkvno = key->keytab.vno;	    return 0;}krb5_error_codehdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey){    int i;    for(i = 0; i < ent->keys.len; i++){	krb5_error_code ret;	ret = hdb_seal_key_mkey(context, &ent->keys.val[i], mkey);	if (ret)	    return ret;    }    return 0;}krb5_error_codehdb_seal_keys(krb5_context context, HDB *db, hdb_entry *ent){    if (db->hdb_master_key_set == 0)	return 0;        return hdb_seal_keys_mkey(context, ent, db->hdb_master_key);}krb5_error_codehdb_seal_key(krb5_context context, HDB *db, Key *k){    if (db->hdb_master_key_set == 0)	return 0;        return hdb_seal_key_mkey(context, k, db->hdb_master_key);}krb5_error_codehdb_set_master_key (krb5_context context,		    HDB *db,		    krb5_keyblock *key){    krb5_error_code ret;    hdb_master_key mkey;    ret = hdb_process_master_key(context, 0, key, 0, &mkey);    if (ret)	return ret;    db->hdb_master_key = mkey;#if 0 /* XXX - why? */    des_set_random_generator_seed(key.keyvalue.data);#endif    db->hdb_master_key_set = 1;    return 0;}krb5_error_codehdb_set_master_keyfile (krb5_context context,			HDB *db,			const char *keyfile){    hdb_master_key key;    krb5_error_code ret;    ret = hdb_read_master_key(context, keyfile, &key);    if (ret) {	if (ret != ENOENT)	    return ret;	krb5_clear_error_string(context);	return 0;    }    db->hdb_master_key = key;    db->hdb_master_key_set = 1;    return ret;}krb5_error_codehdb_clear_master_key (krb5_context context,		      HDB *db){    if (db->hdb_master_key_set) {	hdb_free_master_key(context, db->hdb_master_key);	db->hdb_master_key_set = 0;    }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -