#define MAX_PROTSEQ 10
+struct dcerpc_binding_pointer_ref;
+
+struct dcerpc_binding_pointer {
+ struct dcerpc_binding *b;
+ struct dcerpc_binding_pointer_ref *r;
+ const char *name;
+ const char *type;
+ const void *pointer;
+};
+
+struct dcerpc_binding_pointer_ref {
+ struct dcerpc_binding_pointer *p;
+};
+
struct dcerpc_binding {
enum dcerpc_transport_t transport;
struct GUID object;
uint32_t flags;
uint32_t assoc_group_id;
char assoc_group_string[11]; /* 0x3456789a + '\0' */
+ uint8_t num_pointers;
+ struct dcerpc_binding_pointer **pointers;
};
static const struct {
/*
form a binding string from a binding structure
+ TODO
*/
-_PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b)
+static char *dcerpc_binding_string_ex(TALLOC_CTX *mem_ctx,
+ const struct dcerpc_binding *b,
+ uint64_t flags)
{
char *s = talloc_strdup(mem_ctx, "");
char *o = s;
option_section = true;
} else if (b->options) {
option_section = true;
+ } else if (b->num_pointers != 0) {
+ option_section = true;
} else if (b->flags) {
option_section = true;
}
}
}
+ for (i=0; b->num_pointers; i++) {
+ struct dcerpc_binding_pointer *p = b->pointers[i];
+ char tsbuf[512];
+
+ snprintf(tsbuf, sizeof(tsbuf),
+ "pointer(%d:%p):%s=(%s *)%p",
+ getpid(), p->pointer,
+ p->name, p->type, p->pointer);
+
+ o = s;
+ s = talloc_asprintf_append_buffer(s, ",%s", tsbuf);
+ if (s == NULL) {
+ talloc_free(o);
+ return NULL;
+ }
+ }
+
o = s;
s = talloc_asprintf_append_buffer(s, "]");
if (s == NULL) {
return s;
}
+/*
+ form a binding string from a binding structure
+*/
+_PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b)
+{
+ return dcerpc_binding_string_ex(mem_ctx, b, 0);
+}
+
/*
parse a binding string into a dcerpc_binding structure
*/
* value != NULL means add or reset.
*/
+ ret = strncmp(name, "pointer(", 8);
+ if (ret == 0) {
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
+
ret = strcmp(name, "transport");
if (ret == 0) {
enum dcerpc_transport_t t = dcerpc_transport_by_name(value);
return NT_STATUS_OK;
}
-_PUBLIC_ void *_dcerpc_binding_get_pointer_option(const struct dcerpc_binding *b,
- const char *name, const char *type)
+static uint8_t dcerpc_binding_find_pointer_idx(const struct dcerpc_binding *b,
+ const char *name,
+ const char *type)
{
- char tsbuf[256];
- const char *vs;
- char *end = NULL;
- unsigned long long vl;
- uintptr_t vp;
+ uint8_t i;
- if (strlen(name) > 100) {
- return NULL;
+ for (i = 0; i < b->num_pointers; i++) {
+ struct dcerpc_binding_pointer *p = b->pointers[i];
+ int ret;
+
+ ret = strcmp(p->name, name);
+ if (ret != 0) {
+ continue;
+ }
+
+ ret = strcmp(p->type, type);
+ if (ret != 0) {
+ continue;
+ }
+
+ return i;
}
- if (strlen(type) > 100) {
- return NULL;
+ return UINT8_MAX;
+}
+
+static int dcerpc_binding_pointer_destructor(struct dcerpc_binding_pointer *p)
+{
+ struct dcerpc_binding *b = p->b;
+ uint8_t i;
+ uint8_t idx = UINT8_MAX;
+
+ if (p->r != NULL) {
+ p->r->p = NULL;
+ TALLOC_FREE(p->r);
}
- snprintf(tsbuf, sizeof(tsbuf), "%s:pointer:%d:%s", name, getpid(), type);
+ for (i = 0; i < b->num_pointers; i++) {
+ if (p != b->pointers[i]) {
+ continue;
+ }
- vs = dcerpc_binding_get_string_option(b, tsbuf);
- if (vs == NULL) {
- return NULL;
+ idx = i;
+ break;
}
- errno = 0;
- vl = strtoull(vs, &end, 16);
- if (errno != 0) {
- return NULL;
+ if (idx == UINT8_MAX) {
+ return 0;
}
- if (end == NULL) {
- return NULL;
+
+ for (i = idx + 1; i < b->num_pointers; i++) {
+ b->pointers[i - 1] = b->pointers[i];
}
- if (end[0] != '\0') {
- return NULL;
+
+ b->num_pointers -= 1;
+ b->pointers = talloc_realloc(b, b->pointers,
+ struct dcerpc_binding_pointer *,
+ b->num_pointers);
+
+ return 0;
+}
+
+static int dcerpc_binding_pointer_ref_destructor(struct dcerpc_binding_pointer_ref *r)
+{
+ if (r->p == NULL) {
+ return 0;
}
- vp = vl;
- if (vp != vl) {
+ r->p->r = NULL;
+ TALLOC_FREE(r->p);
+ return 0;
+}
+
+_PUBLIC_ void *_dcerpc_binding_get_pointer_option(const struct dcerpc_binding *b,
+ const char *name, const char *type)
+{
+ struct dcerpc_binding_pointer *p;
+ uint8_t idx;
+
+ idx = dcerpc_binding_find_pointer_idx(b, name, type);
+ if (idx == UINT8_MAX) {
return NULL;
}
- return (void *)vp;
+ p = b->pointers[idx];
+
+ return discard_const(p->pointer);
+}
+
+#if 0
+_PUBLIC_ void dcerpc_binding_clear_pointer_options(struct dcerpc_binding *b,
+ const char *name,
+ const char *type)
+{
+ uint8_t i;
+
+ for (i = 0; i < b->num_pointers; ) {
+ struct dcerpc_binding_pointer *p = b->pointers[i];
+ int ret;
+
+ if (name != NULL) {
+ ret = strcmp(p->name, name);
+ if (ret != 0) {
+ i++;
+ continue;
+ }
+ }
+
+ if (type != NULL) {
+ ret = strcmp(p->type, type);
+ if (ret != 0) {
+ i++;
+ continue;
+ }
+ }
+
+ /*
+ * This removes the element at index 'i'
+ */
+ talloc_free(b->pointers[i]);
+ }
}
+#endif
_PUBLIC_ NTSTATUS _dcerpc_binding_set_pointer_option(struct dcerpc_binding *b,
const char *name,
const char *type,
- const void *vp)
+ const void *pointer)
{
- char tsbuf[256];
- char vsbuf[20];
- const char *vs = NULL;
+ struct dcerpc_binding_pointer *p = NULL;
+ uint8_t idx;
if (strlen(name) > 100) {
return NT_STATUS_INVALID_PARAMETER_MIX;
return NT_STATUS_INVALID_PARAMETER_MIX;
}
- snprintf(tsbuf, sizeof(tsbuf), "%s:pointer:%d:%s", name, getpid(), type);
+ if (pointer != NULL) {
+ const void *pv = talloc_check_name(pointer, type);
- if (vp != NULL) {
- snprintf(vsbuf, sizeof(vsbuf), "%p", vp);
- vs = vsbuf;
+ if (pv == NULL) {
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ }
}
- return dcerpc_binding_set_string_option(b, tsbuf, vs);
+ if (b->num_pointers >= INT8_MAX) {
+ return NT_STATUS_TOO_MANY_ADDRESSES;
+ }
+
+ idx = dcerpc_binding_find_pointer_idx(b, name, type);
+ if (idx == UINT8_MAX) {
+ struct dcerpc_binding_pointer **r = NULL;
+
+ if (pointer == NULL) {
+ return NT_STATUS_OK;
+ }
+
+ r = talloc_realloc(b, b->pointers,
+ struct dcerpc_binding_pointer *,
+ b->num_pointers + 1);
+ if (r == NULL) {
+ goto nomem;
+ }
+ b->pointers = r;
+
+ idx = b->num_pointers;
+ b->pointers[idx] = NULL;
+ b->num_pointers += 1;
+ }
+
+ if (pointer == NULL) {
+ talloc_free(b->pointers[idx]);
+ return NT_STATUS_OK;
+ }
+
+ p = talloc_zero(b->pointers, struct dcerpc_binding_pointer);
+ if (p == NULL) {
+ goto nomem;
+ }
+ p->b = b;
+ p->name = talloc_strdup(p, name);
+ if (p->name == NULL) {
+ goto nomem;
+ }
+ p->type = talloc_strdup(p, type);
+ if (p->name == NULL) {
+ goto nomem;
+ }
+ p->pointer = pointer;
+
+ p->r = talloc_zero(pointer, struct dcerpc_binding_pointer_ref);
+ if (p->r == NULL) {
+ goto nomem;
+ }
+ p->r->p = p;
+ talloc_set_destructor(p->r, dcerpc_binding_pointer_ref_destructor);
+
+ TALLOC_FREE(b->pointers[idx]);
+ b->pointers[idx] = p;
+ talloc_set_destructor(p, dcerpc_binding_pointer_destructor);
+
+ return NT_STATUS_OK;
+
+ nomem:
+ TALLOC_FREE(p);
+ b->pointers = talloc_realloc(b, b->pointers,
+ struct dcerpc_binding_pointer *,
+ b->num_pointers);
+ return NT_STATUS_NO_MEMORY;
}
_PUBLIC_ uint32_t dcerpc_binding_get_flags(const struct dcerpc_binding *b)
const struct dcerpc_binding *b)
{
struct dcerpc_binding *n;
- uint32_t count;
+ size_t i, count;
n = talloc_zero(mem_ctx, struct dcerpc_binding);
if (n == NULL) {
for (count = 0; b->options && b->options[count]; count++);
if (count > 0) {
- uint32_t i;
-
n->options = talloc_array(n, const char *, count + 1);
if (n->options == NULL) {
talloc_free(n);
n->options[count] = NULL;
}
+ for (i=0; i < b->num_pointers; i++) {
+ struct dcerpc_binding_pointer *p = b->pointers[i];
+ NTSTATUS status;
+
+ status = _dcerpc_binding_set_pointer_option(n,
+ p->name,
+ p->type,
+ p->pointer);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(n);
+ return NULL;
+ }
+ }
+
return n;
}