X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source4%2Flibcli%2Fnbt%2Fnbtname.c;h=d7f0b1b077296bc1d0838dc45eaea92c1f91c08c;hb=e835621799647ee70630b389fb53d15b15d68355;hp=0d2840e0b5b36d802ae66cabfc04624fe1db13c5;hpb=dd689afdc807b9ff057ee7e917e12b6597fe319c;p=kamenim%2Fsamba.git diff --git a/source4/libcli/nbt/nbtname.c b/source4/libcli/nbt/nbtname.c index 0d2840e0b5..d7f0b1b077 100644 --- a/source4/libcli/nbt/nbtname.c +++ b/source4/libcli/nbt/nbtname.c @@ -25,13 +25,22 @@ */ #include "includes.h" +#include "system/iconv.h" #include "librpc/gen_ndr/ndr_nbt.h" /* don't allow an unlimited number of name components */ #define MAX_COMPONENTS 10 /* - pull one component of a compressed name + print a nbt string +*/ +void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s) +{ + ndr_print_string(ndr, name, s); +} + +/* + pull one component of a nbt_string */ static NTSTATUS ndr_pull_component(struct ndr_pull *ndr, uint8_t **component, uint32_t *offset, uint32_t *max_offset) @@ -54,8 +63,9 @@ static NTSTATUS ndr_pull_component(struct ndr_pull *ndr, uint8_t **component, if (1 + *offset >= ndr->data_size) { return NT_STATUS_BAD_NETWORK_NAME; } + *max_offset = MAX(*max_offset, *offset + 2); *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset]; - *max_offset = MAX(*max_offset, *offset + 1); + *max_offset = MAX(*max_offset, *offset); loops++; continue; } @@ -77,6 +87,119 @@ static NTSTATUS ndr_pull_component(struct ndr_pull *ndr, uint8_t **component, return NT_STATUS_BAD_NETWORK_NAME; } +/* + pull a nbt_string from the wire +*/ +NTSTATUS ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s) +{ + NTSTATUS status; + uint32_t offset = ndr->offset; + uint32_t max_offset = offset; + unsigned num_components; + char *name; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + name = NULL; + + /* break up name into a list of components */ + for (num_components=0;num_componentsoffset = max_offset; + + return NT_STATUS_OK; +} + +/* + push a nbt string to the wire +*/ +NTSTATUS ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + while (s && *s) { + NTSTATUS status; + char *compname; + size_t complen; + uint32_t offset; + + /* see if we have pushed the remaing string allready, + * if so we use a label pointer to this string + */ + status = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, False); + if (NT_STATUS_IS_OK(status)) { + uint8_t b[2]; + + if (offset > 0x3FFF) { + return ndr_push_error(ndr, NDR_ERR_STRING, + "offset for nbt string label pointer %u[%08X] > 0x00003FFF", + offset, offset); + } + + b[0] = 0xC0 | (offset>>8); + b[1] = (offset & 0xFF); + + return ndr_push_bytes(ndr, b, 2); + } + + complen = strcspn(s, "."); + + /* we need to make sure the length fits into 6 bytes */ + if (complen >= 0x3F) { + return ndr_push_error(ndr, NDR_ERR_STRING, + "component length %u[%08X] > 0x00003F", + (unsigned)complen, (unsigned)complen); + } + + compname = talloc_asprintf(ndr, "%c%*.*s", + (unsigned char)complen, + (unsigned char)complen, + (unsigned char)complen, s); + NT_STATUS_HAVE_NO_MEMORY(compname); + + /* remember the current componemt + the rest of the string + * so it can be reused later + */ + NDR_CHECK(ndr_token_store(ndr, &ndr->nbt_string_list, s, ndr->offset)); + + /* push just this component into the blob */ + NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, complen+1)); + talloc_free(compname); + + s += complen; + if (*s == '.') s++; + } + + /* if we reach the end of the string and have pushed the last component + * without using a label pointer, we need to terminate the string + */ + return ndr_push_bytes(ndr, (const uint8_t *)"", 1); +} + + /* decompress a 'compressed' name component */ @@ -131,7 +254,7 @@ static uint8_t *compress_name(TALLOC_CTX *mem_ctx, cname[2*i] = 'A' + (name[i]>>4); cname[1+2*i] = 'A' + (name[i]&0xF); } - if (name[0] == '*') { + if (strcmp(name, "*") == 0) { pad_char = 0; } else { pad_char = ' '; @@ -149,57 +272,49 @@ static uint8_t *compress_name(TALLOC_CTX *mem_ctx, return cname; } + /* pull a nbt name from the wire */ NTSTATUS ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r) { NTSTATUS status; - uint_t num_components; - uint32_t offset = ndr->offset; - uint32_t max_offset = offset; - uint8_t *components[MAX_COMPONENTS]; - int i; uint8_t *scope; + char *cname; + const char *s; if (!(ndr_flags & NDR_SCALARS)) { return NT_STATUS_OK; } - /* break up name into a list of components */ - for (num_components=0;num_componentsscope = talloc_strdup(ndr, scope+1); + NT_STATUS_HAVE_NO_MEMORY(r->scope); + } else { + r->scope = NULL; } - ndr->offset = max_offset; + cname = discard_const_p(char, s); /* the first component is limited to 16 bytes in the DOS charset, which is 32 in the 'compressed' form */ - if (strlen(components[0]) > 32) { + if (strlen(cname) > 32) { return NT_STATUS_BAD_NETWORK_NAME; } /* decompress the first component */ - status = decompress_name(components[0], &r->type); + status = decompress_name(cname, &r->type); NT_STATUS_NOT_OK_RETURN(status); - r->name = components[0]; + r->name = talloc_strdup(ndr, cname); + NT_STATUS_HAVE_NO_MEMORY(r->name); - /* combine the remaining components into the scope */ - scope = components[1]; - for (i=2;iscope = scope; + talloc_free(cname); return NT_STATUS_OK; } @@ -207,53 +322,34 @@ NTSTATUS ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name /* push a nbt name to the wire */ -NTSTATUS ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, struct nbt_name *r) +NTSTATUS ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r) { - uint_t num_components; - uint8_t *components[MAX_COMPONENTS]; - char *dscope=NULL, *p; - uint8_t *cname; - int i; + uint8_t *cname, *fullname; + NTSTATUS status; if (!(ndr_flags & NDR_SCALARS)) { return NT_STATUS_OK; } - if (r->scope) { - dscope = talloc_strdup(ndr, r->scope); - NT_STATUS_HAVE_NO_MEMORY(dscope); - } - cname = compress_name(ndr, r->name, r->type); NT_STATUS_HAVE_NO_MEMORY(cname); - /* form the base components */ - components[0] = cname; - num_components = 1; - - while (dscope && (p=strchr(dscope, '.')) && - num_components < MAX_COMPONENTS) { - *p = 0; - components[num_components] = dscope; - dscope = p+1; - num_components++; - } - if (dscope && num_components < MAX_COMPONENTS) { - components[num_components++] = dscope; - } - if (num_components == MAX_COMPONENTS) { - return NT_STATUS_BAD_NETWORK_NAME; - } - - /* push the components */ - for (i=0;iscope) { + fullname = talloc_asprintf(ndr, "%s.%s", cname, r->scope); + NT_STATUS_HAVE_NO_MEMORY(fullname); + talloc_free(cname); + } else { + fullname = cname; } - NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 0)); - - return NT_STATUS_OK; + + status = ndr_push_nbt_string(ndr, ndr_flags, fullname); +#if 0 + /* this free conflicts with the use of pointers into strings + in the ndr_token_store() calls above. Metze, can you look + at this? */ + talloc_free(fullname); +#endif + return status; } @@ -310,13 +406,72 @@ void nbt_choose_called_name(TALLOC_CTX *mem_ctx, } if (strlen(name) > 15) { const char *p = strchr(name, '.'); + char *s; if (p - name > 15) { n->name = "*SMBSERVER"; return; } - n->name = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name)); + s = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name)); + n->name = strupper_talloc(mem_ctx, s); return; } - n->name = talloc_strdup(mem_ctx, name); + n->name = strupper_talloc(mem_ctx, name); } + + +/* + escape a string into a form containing only a small set of characters, + the rest is hex encoded. This is similar to URL encoding +*/ +static const char *nbt_hex_encode(TALLOC_CTX *mem_ctx, const char *s) +{ + int i, len; + char *ret; + const char *valid_chars = "_-.$@ "; +#define NBT_CHAR_ALLOW(c) (isalnum((unsigned char)c) || strchr(valid_chars, c)) + + for (len=i=0;s[i];i++,len++) { + if (!NBT_CHAR_ALLOW(s[i])) { + len += 2; + } + } + + ret = talloc_array(mem_ctx, char, len+1); + if (ret == NULL) return NULL; + + for (len=i=0;s[i];i++) { + if (NBT_CHAR_ALLOW(s[i])) { + ret[len++] = s[i]; + } else { + snprintf(&ret[len], 4, "%%%02x", (unsigned char)s[i]); + len += 3; + } + } + ret[len] = 0; + + return ret; +} + + +/* + form a string for a NBT name +*/ +char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name) +{ + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + char *ret; + if (name->scope) { + ret = talloc_asprintf(mem_ctx, "%s<%02x>-%s", + nbt_hex_encode(tmp_ctx, name->name), + name->type, + nbt_hex_encode(tmp_ctx, name->scope)); + } else { + ret = talloc_asprintf(mem_ctx, "%s<%02x>", + nbt_hex_encode(tmp_ctx, name->name), + name->type); + } + talloc_free(tmp_ctx); + return ret; +} +