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

📄 pac.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2006 - 2007 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 "krb5_locl.h"#include <wind.h>RCSID("$Id: pac.c 22562 2008-02-03 17:38:35Z lha $");struct PAC_INFO_BUFFER {    uint32_t type;    uint32_t buffersize;    uint32_t offset_hi;    uint32_t offset_lo;};struct PACTYPE {    uint32_t numbuffers;    uint32_t version;                             struct PAC_INFO_BUFFER buffers[1];};struct krb5_pac_data {    struct PACTYPE *pac;    krb5_data data;    struct PAC_INFO_BUFFER *server_checksum;    struct PAC_INFO_BUFFER *privsvr_checksum;    struct PAC_INFO_BUFFER *logon_name;};#define PAC_ALIGNMENT			8#define PACTYPE_SIZE			8#define PAC_INFO_BUFFER_SIZE		16#define PAC_SERVER_CHECKSUM		6#define PAC_PRIVSVR_CHECKSUM		7#define PAC_LOGON_NAME			10#define PAC_CONSTRAINED_DELEGATION	11#define CHECK(r,f,l)						\	do {							\		if (((r) = f ) != 0) {				\			krb5_clear_error_string(context);	\			goto l;					\		}						\	} while(0)static const char zeros[PAC_ALIGNMENT] = { 0 };/* * */krb5_error_codekrb5_pac_parse(krb5_context context, const void *ptr, size_t len,	       krb5_pac *pac){    krb5_error_code ret;    krb5_pac p;    krb5_storage *sp = NULL;    uint32_t i, tmp, tmp2, header_end;    p = calloc(1, sizeof(*p));    if (p == NULL) {	ret = ENOMEM;	krb5_set_error_string(context, "out of memory");	goto out;    }    sp = krb5_storage_from_readonly_mem(ptr, len);    if (sp == NULL) {	ret = ENOMEM;	krb5_set_error_string(context, "out of memory");	goto out;    }    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);    CHECK(ret, krb5_ret_uint32(sp, &tmp), out);    CHECK(ret, krb5_ret_uint32(sp, &tmp2), out);    if (tmp < 1) {	krb5_set_error_string(context, "PAC have too few buffer");	ret = EINVAL; /* Too few buffers */	goto out;    }    if (tmp2 != 0) {	krb5_set_error_string(context, "PAC have wrong version");	ret = EINVAL; /* Wrong version */	goto out;    }    p->pac = calloc(1, 		    sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1)));    if (p->pac == NULL) {	krb5_set_error_string(context, "out of memory");	ret = ENOMEM;	goto out;    }    p->pac->numbuffers = tmp;    p->pac->version = tmp2;    header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);    if (header_end > len) {	ret = EINVAL;	goto out;    }    for (i = 0; i < p->pac->numbuffers; i++) {	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].type), out);	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].buffersize), out);	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_lo), out);	CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_hi), out);	/* consistency checks */	if (p->pac->buffers[i].offset_lo & (PAC_ALIGNMENT - 1)) {	    krb5_set_error_string(context, "PAC out of allignment");	    ret = EINVAL;	    goto out;	}	if (p->pac->buffers[i].offset_hi) {	    krb5_set_error_string(context, "PAC high offset set");	    ret = EINVAL;	    goto out;	}	if (p->pac->buffers[i].offset_lo > len) {	    krb5_set_error_string(context, "PAC offset off end");	    ret = EINVAL;	    goto out;	}	if (p->pac->buffers[i].offset_lo < header_end) {	    krb5_set_error_string(context, "PAC offset inside header: %d %d",				  p->pac->buffers[i].offset_lo, header_end);	    ret = EINVAL;	    goto out;	}	if (p->pac->buffers[i].buffersize > len - p->pac->buffers[i].offset_lo){	    krb5_set_error_string(context, "PAC length off end");	    ret = EINVAL;	    goto out;	}	/* let save pointer to data we need later */	if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) {	    if (p->server_checksum) {		krb5_set_error_string(context, "PAC have two server checksums");		ret = EINVAL;		goto out;	    }	    p->server_checksum = &p->pac->buffers[i];	} else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) {	    if (p->privsvr_checksum) {		krb5_set_error_string(context, "PAC have two KDC checksums");		ret = EINVAL;		goto out;	    }	    p->privsvr_checksum = &p->pac->buffers[i];	} else if (p->pac->buffers[i].type == PAC_LOGON_NAME) {	    if (p->logon_name) {		krb5_set_error_string(context, "PAC have two logon names");		ret = EINVAL;		goto out;	    }	    p->logon_name = &p->pac->buffers[i];	}    }    ret = krb5_data_copy(&p->data, ptr, len);    if (ret)	goto out;    krb5_storage_free(sp);    *pac = p;    return 0;out:    if (sp)	krb5_storage_free(sp);    if (p) {	if (p->pac)	    free(p->pac);	free(p);    }    *pac = NULL;    return ret;}krb5_error_codekrb5_pac_init(krb5_context context, krb5_pac *pac){    krb5_error_code ret;    krb5_pac p;    p = calloc(1, sizeof(*p));    if (p == NULL) {	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    p->pac = calloc(1, sizeof(*p->pac));    if (p->pac == NULL) {	free(p);	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    ret = krb5_data_alloc(&p->data, PACTYPE_SIZE);    if (ret) {	free (p->pac);	free(p);	krb5_set_error_string(context, "out of memory");	return ret;    }    *pac = p;    return 0;}krb5_error_codekrb5_pac_add_buffer(krb5_context context, krb5_pac p,		    uint32_t type, const krb5_data *data){    krb5_error_code ret;    void *ptr;    size_t len, offset, header_end, old_end;    uint32_t i;    len = p->pac->numbuffers;    ptr = realloc(p->pac,		  sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len));    if (ptr == NULL) {	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    p->pac = ptr;    for (i = 0; i < len; i++)	p->pac->buffers[i].offset_lo += PAC_INFO_BUFFER_SIZE;    offset = p->data.length + PAC_INFO_BUFFER_SIZE;    p->pac->buffers[len].type = type;    p->pac->buffers[len].buffersize = data->length;    p->pac->buffers[len].offset_lo = offset;    p->pac->buffers[len].offset_hi = 0;    old_end = p->data.length;    len = p->data.length + data->length + PAC_INFO_BUFFER_SIZE;    if (len < p->data.length) {	krb5_set_error_string(context, "integer overrun");	return EINVAL;    }        /* align to PAC_ALIGNMENT */    len = ((len + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT;    ret = krb5_data_realloc(&p->data, len);    if (ret) {	krb5_set_error_string(context, "out of memory");	return ret;    }    /*      * make place for new PAC INFO BUFFER header     */    header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);    memmove((unsigned char *)p->data.data + header_end + PAC_INFO_BUFFER_SIZE,	    (unsigned char *)p->data.data + header_end ,	    old_end - header_end);    memset((unsigned char *)p->data.data + header_end, 0, PAC_INFO_BUFFER_SIZE);    /*     * copy in new data part     */    memcpy((unsigned char *)p->data.data + offset,	   data->data, data->length);    memset((unsigned char *)p->data.data + offset + data->length,	   0, p->data.length - offset - data->length);    p->pac->numbuffers += 1;    return 0;}krb5_error_codekrb5_pac_get_buffer(krb5_context context, krb5_pac p,		    uint32_t type, krb5_data *data){    krb5_error_code ret;    uint32_t i;    /*     * Hide the checksums from external consumers     */    if (type == PAC_PRIVSVR_CHECKSUM || type == PAC_SERVER_CHECKSUM) {	ret = krb5_data_alloc(data, 16);	if (ret) {	    krb5_set_error_string(context, "out of memory");	    return ret;	}	memset(data->data, 0, data->length);	return 0;    }    for (i = 0; i < p->pac->numbuffers; i++) {	size_t len = p->pac->buffers[i].buffersize;	size_t offset = p->pac->buffers[i].offset_lo;	if (p->pac->buffers[i].type != type)	    continue;	ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len);	if (ret) {	    krb5_set_error_string(context, "Out of memory");	    return ret;	}	return 0;    }    krb5_set_error_string(context, "No PAC buffer of type %lu was found",			  (unsigned long)type);    return ENOENT;}/* * */krb5_error_codekrb5_pac_get_types(krb5_context context,		   krb5_pac p,		   size_t *len,		   uint32_t **types){    size_t i;    *types = calloc(p->pac->numbuffers, sizeof(*types));    if (*types == NULL) {	*len = 0;	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    for (i = 0; i < p->pac->numbuffers; i++)	(*types)[i] = p->pac->buffers[i].type;    *len = p->pac->numbuffers;    return 0;}/* * */voidkrb5_pac_free(krb5_context context, krb5_pac pac){    krb5_data_free(&pac->data);    free(pac->pac);    free(pac);}/* * */static krb5_error_codeverify_checksum(krb5_context context,		const struct PAC_INFO_BUFFER *sig,		const krb5_data *data,		void *ptr, size_t len,		const krb5_keyblock *key){    krb5_crypto crypto = NULL;    krb5_storage *sp = NULL;    uint32_t type;    krb5_error_code ret;    Checksum cksum;    memset(&cksum, 0, sizeof(cksum));    sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo,			       sig->buffersize);    if (sp == NULL) {	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);    CHECK(ret, krb5_ret_uint32(sp, &type), out);    cksum.cksumtype = type;    cksum.checksum.length = 	sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR);    cksum.checksum.data = malloc(cksum.checksum.length);    if (cksum.checksum.data == NULL) {	krb5_set_error_string(context, "out of memory");	ret = ENOMEM;	goto out;    }    ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length);    if (ret != cksum.checksum.length) {	krb5_set_error_string(context, "PAC checksum missing checksum");	ret = EINVAL;	goto out;    }    if (!krb5_checksum_is_keyed(context, cksum.cksumtype)) {	krb5_set_error_string (context, "Checksum type %d not keyed",			       cksum.cksumtype);	ret = EINVAL;	goto out;    }    ret = krb5_crypto_init(context, key, 0, &crypto);    if (ret)	goto out;    ret = krb5_verify_checksum(context, crypto, KRB5_KU_OTHER_CKSUM,			       ptr, len, &cksum);    free(cksum.checksum.data);    krb5_crypto_destroy(context, crypto);    krb5_storage_free(sp);    return ret;out:    if (cksum.checksum.data)	free(cksum.checksum.data);    if (sp)	krb5_storage_free(sp);    if (crypto)	krb5_crypto_destroy(context, crypto);    return ret;}static krb5_error_codecreate_checksum(krb5_context context,		const krb5_keyblock *key,		void *data, size_t datalen,		void *sig, size_t siglen){    krb5_crypto crypto = NULL;    krb5_error_code ret;    Checksum cksum;    ret = krb5_crypto_init(context, key, 0, &crypto);    if (ret)	return ret;    ret = krb5_create_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, 0,			       data, datalen, &cksum);    krb5_crypto_destroy(context, crypto);    if (ret)	return ret;    if (cksum.checksum.length != siglen) {	krb5_set_error_string(context, "pac checksum wrong length");	free_Checksum(&cksum);	return EINVAL;    }    memcpy(sig, cksum.checksum.data, siglen);    free_Checksum(&cksum);    return 0;}/* * */#define NTTIME_EPOCH 0x019DB1DED53E8000LLstatic uint64_tunix2nttime(time_t unix_time){    long long wt;    wt = unix_time * (uint64_t)10000000 + (uint64_t)NTTIME_EPOCH;    return wt;}static krb5_error_codeverify_logonname(krb5_context context,		 const struct PAC_INFO_BUFFER *logon_name,		 const krb5_data *data,		 time_t authtime,

⌨️ 快捷键说明

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