📄 asn1.c
字号:
/* read from a ASN1 buffer, advancing the buffer pointer */bool asn1_read(struct asn1_data *data, void *p, int len){ if (!asn1_peek(data, p, len)) { data->has_error = true; return false; } data->ofs += len; return true;}/* read a uint8_t from a ASN1 buffer */bool asn1_read_uint8(struct asn1_data *data, uint8_t *v){ return asn1_read(data, v, 1);}bool asn1_peek_uint8(struct asn1_data *data, uint8_t *v){ return asn1_peek(data, v, 1);}bool asn1_peek_tag(struct asn1_data *data, uint8_t tag){ uint8_t b; if (asn1_tag_remaining(data) <= 0) { return false; } if (!asn1_peek_uint8(data, &b)) return false; return (b == tag);}/* start reading a nested asn1 structure */bool asn1_start_tag(struct asn1_data *data, uint8_t tag){ uint8_t b; struct nesting *nesting; if (!asn1_read_uint8(data, &b)) return false; if (b != tag) { data->has_error = true; return false; } nesting = talloc(data, struct nesting); if (!nesting) { data->has_error = true; return false; } if (!asn1_read_uint8(data, &b)) { return false; } if (b & 0x80) { int n = b & 0x7f; if (!asn1_read_uint8(data, &b)) return false; nesting->taglen = b; while (n > 1) { if (!asn1_read_uint8(data, &b)) return false; nesting->taglen = (nesting->taglen << 8) | b; n--; } } else { nesting->taglen = b; } nesting->start = data->ofs; nesting->next = data->nesting; data->nesting = nesting; if (asn1_tag_remaining(data) == -1) { return false; } return !data->has_error;}/* stop reading a tag */bool asn1_end_tag(struct asn1_data *data){ struct nesting *nesting; /* make sure we read it all */ if (asn1_tag_remaining(data) != 0) { data->has_error = true; return false; } nesting = data->nesting; if (!nesting) { data->has_error = true; return false; } data->nesting = nesting->next; talloc_free(nesting); return true;}/* work out how many bytes are left in this nested tag */int asn1_tag_remaining(struct asn1_data *data){ int remaining; if (data->has_error) { return -1; } if (!data->nesting) { data->has_error = true; return -1; } remaining = data->nesting->taglen - (data->ofs - data->nesting->start); if (remaining > (data->length - data->ofs)) { data->has_error = true; return -1; } return remaining;}/* read an object ID from a data blob */bool ber_read_OID_String(TALLOC_CTX *mem_ctx, DATA_BLOB blob, const char **OID){ int i; uint8_t *b; uint_t v; char *tmp_oid = NULL; if (blob.length < 2) return false; b = blob.data; tmp_oid = talloc_asprintf(mem_ctx, "%u", b[0]/40); if (!tmp_oid) goto nomem; tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", b[0]%40); if (!tmp_oid) goto nomem; for(i = 1, v = 0; i < blob.length; i++) { v = (v<<7) | (b[i]&0x7f); if ( ! (b[i] & 0x80)) { tmp_oid = talloc_asprintf_append_buffer(tmp_oid, ".%u", v); v = 0; } if (!tmp_oid) goto nomem; } if (v != 0) { talloc_free(tmp_oid); return false; } *OID = tmp_oid; return true;nomem: return false;}/* read an object ID from a ASN1 buffer */bool asn1_read_OID(struct asn1_data *data, TALLOC_CTX *mem_ctx, const char **OID){ DATA_BLOB blob; int len; if (!asn1_start_tag(data, ASN1_OID)) return false; len = asn1_tag_remaining(data); if (len < 0) { data->has_error = true; return false; } blob = data_blob(NULL, len); if (!blob.data) { data->has_error = true; return false; } asn1_read(data, blob.data, len); asn1_end_tag(data); if (data->has_error) { data_blob_free(&blob); return false; } if (!ber_read_OID_String(mem_ctx, blob, OID)) { data->has_error = true; data_blob_free(&blob); return false; } data_blob_free(&blob); return true;}/* check that the next object ID is correct */bool asn1_check_OID(struct asn1_data *data, const char *OID){ const char *id; if (!asn1_read_OID(data, data, &id)) return false; if (strcmp(id, OID) != 0) { talloc_free(discard_const(id)); data->has_error = true; return false; } talloc_free(discard_const(id)); return true;}/* read a LDAPString from a ASN1 buffer */bool asn1_read_LDAPString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s){ int len; len = asn1_tag_remaining(data); if (len < 0) { data->has_error = true; return false; } *s = talloc_array(mem_ctx, char, len+1); if (! *s) { data->has_error = true; return false; } asn1_read(data, *s, len); (*s)[len] = 0; return !data->has_error;}/* read a GeneralString from a ASN1 buffer */bool asn1_read_GeneralString(struct asn1_data *data, TALLOC_CTX *mem_ctx, char **s){ if (!asn1_start_tag(data, ASN1_GENERAL_STRING)) return false; if (!asn1_read_LDAPString(data, mem_ctx, s)) return false; return asn1_end_tag(data);}/* read a octet string blob */bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob){ int len; ZERO_STRUCTP(blob); if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return false; len = asn1_tag_remaining(data); if (len < 0) { data->has_error = true; return false; } *blob = data_blob_talloc(mem_ctx, NULL, len+1); if (!blob->data) { data->has_error = true; return false; } asn1_read(data, blob->data, len); asn1_end_tag(data); blob->length--; blob->data[len] = 0; if (data->has_error) { data_blob_free(blob); *blob = data_blob(NULL, 0); return false; } return true;}bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob){ int len; ZERO_STRUCTP(blob); if (!asn1_start_tag(data, ASN1_CONTEXT_SIMPLE(num))) return false; len = asn1_tag_remaining(data); if (len < 0) { data->has_error = true; return false; } *blob = data_blob(NULL, len); if ((len != 0) && (!blob->data)) { data->has_error = true; return false; } asn1_read(data, blob->data, len); asn1_end_tag(data); return !data->has_error;}/* read an integer without tag*/bool asn1_read_implicit_Integer(struct asn1_data *data, int *i){ uint8_t b; *i = 0; while (!data->has_error && asn1_tag_remaining(data)>0) { if (!asn1_read_uint8(data, &b)) return false; *i = (*i << 8) + b; } return !data->has_error; }/* read an integer */bool asn1_read_Integer(struct asn1_data *data, int *i){ *i = 0; if (!asn1_start_tag(data, ASN1_INTEGER)) return false; if (!asn1_read_implicit_Integer(data, i)) return false; return asn1_end_tag(data); }/* read an integer */bool asn1_read_enumerated(struct asn1_data *data, int *v){ *v = 0; if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; while (!data->has_error && asn1_tag_remaining(data)>0) { uint8_t b; asn1_read_uint8(data, &b); *v = (*v << 8) + b; } return asn1_end_tag(data); }/* check a enumerated value is correct */bool asn1_check_enumerated(struct asn1_data *data, int v){ uint8_t b; if (!asn1_start_tag(data, ASN1_ENUMERATED)) return false; asn1_read_uint8(data, &b); asn1_end_tag(data); if (v != b) data->has_error = false; return !data->has_error;}/* write an enumerated value to the stream */bool asn1_write_enumerated(struct asn1_data *data, uint8_t v){ if (!asn1_push_tag(data, ASN1_ENUMERATED)) return false; asn1_write_uint8(data, v); asn1_pop_tag(data); return !data->has_error;}/* check if a ASN.1 blob is a full tag*/NTSTATUS asn1_full_tag(DATA_BLOB blob, uint8_t tag, size_t *packet_size){ struct asn1_data *asn1 = asn1_init(NULL); int size; NT_STATUS_HAVE_NO_MEMORY(asn1); asn1->data = blob.data; asn1->length = blob.length; asn1_start_tag(asn1, tag); if (asn1->has_error) { talloc_free(asn1); return STATUS_MORE_ENTRIES; } size = asn1_tag_remaining(asn1) + asn1->ofs; talloc_free(asn1); if (size > blob.length) { return STATUS_MORE_ENTRIES; } *packet_size = size; return NT_STATUS_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -