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

📄 asn1.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   simple ASN1 routines   Copyright (C) Andrew Tridgell 2001      This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "lib/util/asn1.h"/* allocate an asn1 structure */struct asn1_data *asn1_init(TALLOC_CTX *mem_ctx){	struct asn1_data *ret = talloc_zero(mem_ctx, struct asn1_data);	if (ret == NULL) {		DEBUG(0,("asn1_init failed! out of memory\n"));	}	return ret;}/* free an asn1 structure */void asn1_free(struct asn1_data *data){	talloc_free(data);}/* write to the ASN1 buffer, advancing the buffer pointer */bool asn1_write(struct asn1_data *data, const void *p, int len){	if (data->has_error) return false;	if (data->length < data->ofs+len) {		uint8_t *newp;		newp = talloc_realloc(data, data->data, uint8_t, data->ofs+len);		if (!newp) {			asn1_free(data);			data->has_error = true;			return false;		}		data->data = newp;		data->length = data->ofs+len;	}	memcpy(data->data + data->ofs, p, len);	data->ofs += len;	return true;}/* useful fn for writing a uint8_t */bool asn1_write_uint8(struct asn1_data *data, uint8_t v){	return asn1_write(data, &v, 1);}/* push a tag onto the asn1 data buffer. Used for nested structures */bool asn1_push_tag(struct asn1_data *data, uint8_t tag){	struct nesting *nesting;	asn1_write_uint8(data, tag);	nesting = talloc(data, struct nesting);	if (!nesting) {		data->has_error = true;		return false;	}	nesting->start = data->ofs;	nesting->next = data->nesting;	data->nesting = nesting;	return asn1_write_uint8(data, 0xff);}/* pop a tag */bool asn1_pop_tag(struct asn1_data *data){	struct nesting *nesting;	size_t len;	nesting = data->nesting;	if (!nesting) {		data->has_error = true;		return false;	}	len = data->ofs - (nesting->start+1);	/* yes, this is ugly. We don't know in advance how many bytes the length	   of a tag will take, so we assumed 1 byte. If we were wrong then we 	   need to correct our mistake */	if (len > 0xFFFFFF) {		data->data[nesting->start] = 0x84;		if (!asn1_write_uint8(data, 0)) return false;		if (!asn1_write_uint8(data, 0)) return false;		if (!asn1_write_uint8(data, 0)) return false;		if (!asn1_write_uint8(data, 0)) return false;		memmove(data->data+nesting->start+5, data->data+nesting->start+1, len);		data->data[nesting->start+1] = (len>>24) & 0xFF;		data->data[nesting->start+2] = (len>>16) & 0xFF;		data->data[nesting->start+3] = (len>>8) & 0xFF;		data->data[nesting->start+4] = len&0xff;	} else if (len > 0xFFFF) {		data->data[nesting->start] = 0x83;		if (!asn1_write_uint8(data, 0)) return false;		if (!asn1_write_uint8(data, 0)) return false;		if (!asn1_write_uint8(data, 0)) return false;		memmove(data->data+nesting->start+4, data->data+nesting->start+1, len);		data->data[nesting->start+1] = (len>>16) & 0xFF;		data->data[nesting->start+2] = (len>>8) & 0xFF;		data->data[nesting->start+3] = len&0xff;	} else if (len > 255) {		data->data[nesting->start] = 0x82;		if (!asn1_write_uint8(data, 0)) return false;		if (!asn1_write_uint8(data, 0)) return false;		memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);		data->data[nesting->start+1] = len>>8;		data->data[nesting->start+2] = len&0xff;	} else if (len > 127) {		data->data[nesting->start] = 0x81;		if (!asn1_write_uint8(data, 0)) return false;		memmove(data->data+nesting->start+2, data->data+nesting->start+1, len);		data->data[nesting->start+1] = len;	} else {		data->data[nesting->start] = len;	}	data->nesting = nesting->next;	talloc_free(nesting);	return true;}/* "i" is the one's complement representation, as is the normal result of an * implicit signed->unsigned conversion */static bool push_int_bigendian(struct asn1_data *data, unsigned int i, bool negative){	uint8_t lowest = i & 0xFF;	i = i >> 8;	if (i != 0)		if (!push_int_bigendian(data, i, negative))			return false;	if (data->nesting->start+1 == data->ofs) {		/* We did not write anything yet, looking at the highest		 * valued byte */		if (negative) {			/* Don't write leading 0xff's */			if (lowest == 0xFF)				return true;			if ((lowest & 0x80) == 0) {				/* The only exception for a leading 0xff is if				 * the highest bit is 0, which would indicate				 * a positive value */				if (!asn1_write_uint8(data, 0xff))					return false;			}		} else {			if (lowest & 0x80) {				/* The highest bit of a positive integer is 1,				 * this would indicate a negative number. Push				 * a 0 to indicate a positive one */				if (!asn1_write_uint8(data, 0))					return false;			}		}	}	return asn1_write_uint8(data, lowest);}/* write an Integer without the tag framing. Needed for example for the LDAP * Abandon Operation */bool asn1_write_implicit_Integer(struct asn1_data *data, int i){	if (i == -1) {		/* -1 is special as it consists of all-0xff bytes. In                    push_int_bigendian this is the only case that is not                    properly handled, as all 0xff bytes would be handled as                    leading ones to be ignored. */		return asn1_write_uint8(data, 0xff);	} else {		return push_int_bigendian(data, i, i<0);	}}/* write an integer */bool asn1_write_Integer(struct asn1_data *data, int i){	if (!asn1_push_tag(data, ASN1_INTEGER)) return false;	if (!asn1_write_implicit_Integer(data, i)) return false;	return asn1_pop_tag(data);}bool ber_write_OID_String(DATA_BLOB *blob, const char *OID){	uint_t v, v2;	const char *p = (const char *)OID;	char *newp;	int i;	v = strtoul(p, &newp, 10);	if (newp[0] != '.') return false;	p = newp + 1;	v2 = strtoul(p, &newp, 10);	if (newp[0] != '.') return false;	p = newp + 1;	/*the ber representation can't use more space then the string one */	*blob = data_blob(NULL, strlen(OID));	if (!blob->data) return false;	blob->data[0] = 40*v + v2;	i = 1;	while (*p) {		v = strtoul(p, &newp, 10);		if (newp[0] == '.') {			p = newp + 1;		} else if (newp[0] == '\0') {			p = newp;		} else {			data_blob_free(blob);			return false;		}		if (v >= (1<<28)) blob->data[i++] = (0x80 | ((v>>28)&0x7f));		if (v >= (1<<21)) blob->data[i++] = (0x80 | ((v>>21)&0x7f));		if (v >= (1<<14)) blob->data[i++] = (0x80 | ((v>>14)&0x7f));		if (v >= (1<<7)) blob->data[i++] = (0x80 | ((v>>7)&0x7f));		blob->data[i++] = (v&0x7f);	}	blob->length = i;	return true;}/* write an object ID to a ASN1 buffer */bool asn1_write_OID(struct asn1_data *data, const char *OID){	DATA_BLOB blob;	if (!asn1_push_tag(data, ASN1_OID)) return false;	if (!ber_write_OID_String(&blob, OID)) {		data->has_error = true;		return false;	}	if (!asn1_write(data, blob.data, blob.length)) {		data->has_error = true;		return false;	}	data_blob_free(&blob);	return asn1_pop_tag(data);}/* write an octet string */bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length){	asn1_push_tag(data, ASN1_OCTET_STRING);	asn1_write(data, p, length);	asn1_pop_tag(data);	return !data->has_error;}/* write a LDAP string */bool asn1_write_LDAPString(struct asn1_data *data, const char *s){	asn1_write(data, s, strlen(s));	return !data->has_error;}/* write a LDAP string from a DATA_BLOB */bool asn1_write_DATA_BLOB_LDAPString(struct asn1_data *data, const DATA_BLOB *s){	asn1_write(data, s->data, s->length);	return !data->has_error;}/* write a general string */bool asn1_write_GeneralString(struct asn1_data *data, const char *s){	asn1_push_tag(data, ASN1_GENERAL_STRING);	asn1_write_LDAPString(data, s);	asn1_pop_tag(data);	return !data->has_error;}bool asn1_write_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob){	asn1_push_tag(data, ASN1_CONTEXT_SIMPLE(num));	asn1_write(data, blob->data, blob->length);	asn1_pop_tag(data);	return !data->has_error;}/* write a BOOLEAN */bool asn1_write_BOOLEAN(struct asn1_data *data, bool v){	asn1_push_tag(data, ASN1_BOOLEAN);	asn1_write_uint8(data, v ? 0xFF : 0);	asn1_pop_tag(data);	return !data->has_error;}bool asn1_read_BOOLEAN(struct asn1_data *data, bool *v){	uint8_t tmp = 0;	asn1_start_tag(data, ASN1_BOOLEAN);	asn1_read_uint8(data, &tmp);	if (tmp == 0xFF) {		*v = true;	} else {		*v = false;	}	asn1_end_tag(data);	return !data->has_error;}/* check a BOOLEAN */bool asn1_check_BOOLEAN(struct asn1_data *data, bool v){	uint8_t b = 0;	asn1_read_uint8(data, &b);	if (b != ASN1_BOOLEAN) {		data->has_error = true;		return false;	}	asn1_read_uint8(data, &b);	if (b != v) {		data->has_error = true;		return false;	}	return !data->has_error;}/* load a struct asn1_data structure with a lump of data, ready to be parsed */bool asn1_load(struct asn1_data *data, DATA_BLOB blob){	ZERO_STRUCTP(data);	data->data = talloc_memdup(data, blob.data, blob.length);	if (!data->data) {		data->has_error = true;		return false;	}	data->length = blob.length;	return true;}/* Peek into an ASN1 buffer, not advancing the pointer */bool asn1_peek(struct asn1_data *data, void *p, int len){	if (data->has_error)		return false;	if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len)		return false;	if (data->ofs + len > data->length) {		/* we need to mark the buffer as consumed, so the caller knows		   this was an out of data error, and not a decode error */		data->ofs = data->length;		return false;	}	memcpy(p, data->data + data->ofs, len);	return true;}

⌨️ 快捷键说明

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