/* push an array of uint8 */ _PUBLIC_ enum ndr_err_code ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const uint8_t *data, uint32_t n) { if (!(ndr_flags & NDR_SCALARS)) { return NDR_ERR_SUCCESS; } return ndr_push_bytes(ndr, data, n); }
/* push a DATA_BLOB onto the wire. */ _PUBLIC_ enum ndr_err_code ndr_push_DATA_BLOB(struct ndr_push *ndr, int ndr_flags, DATA_BLOB blob) { if (ndr->flags & LIBNDR_ALIGN_FLAGS) { if (ndr->flags & LIBNDR_FLAG_ALIGN2) { blob.length = NDR_ALIGN(ndr, 2); } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { blob.length = NDR_ALIGN(ndr, 4); } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { blob.length = NDR_ALIGN(ndr, 8); } NDR_PUSH_ALLOC_SIZE(ndr, blob.data, blob.length); data_blob_clear(&blob); } else if (!(ndr->flags & LIBNDR_FLAG_REMAINING)) { NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, blob.length)); } NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length)); return NDR_ERR_SUCCESS; }
/* push a subcontext header */ _PUBLIC_ enum ndr_err_code ndr_push_subcontext_end(struct ndr_push *ndr, struct ndr_push *subndr, size_t header_size, ssize_t size_is) { ssize_t padding_len; if (size_is >= 0) { padding_len = size_is - subndr->offset; if (padding_len < 0) { return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext (PUSH) content_size %d is larger than size_is(%d)", (int)subndr->offset, (int)size_is); } subndr->offset = size_is; } switch (header_size) { case 0: break; case 2: NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, subndr->offset)); break; case 4: NDR_CHECK(ndr_push_uint3264(ndr, NDR_SCALARS, subndr->offset)); break; case 0xFFFFFC01: /* * Common Type Header for the Serialization Stream * See [MS-RPCE] 2.2.6 Type Serialization Version 1 */ padding_len = NDR_ROUND(subndr->offset, 8) - subndr->offset; if (padding_len > 0) { NDR_CHECK(ndr_push_zero(subndr, padding_len)); } /* version */ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, 1)); /* * 0x10 little endian * 0x00 big endian */ NDR_CHECK(ndr_push_uint8(ndr, NDR_SCALARS, NDR_BE(ndr)?0x00:0x10)); /* length of the "Private Header for Constructed Type" */ NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, 8)); /* filler */ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0xCCCCCCCC)); /* * Private Header for Constructed Type */ /* length - will be updated latter */ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, subndr->offset)); /* reserved */ NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); break; default: return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext header size %d", (int)header_size); } NDR_CHECK(ndr_push_bytes(ndr, subndr->data, subndr->offset)); return NDR_ERR_SUCCESS; }
/** push a general string onto the wire */ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) { ssize_t s_len, c_len, d_len; charset_t chset = CH_UTF16LE; unsigned flags = ndr->flags; unsigned byte_mul = 2; uint8_t *dest = NULL; if (!(ndr_flags & NDR_SCALARS)) { return NT_STATUS_OK; } if (NDR_BE(ndr)) { chset = CH_UTF16BE; } s_len = s?strlen(s):0; if (flags & LIBNDR_FLAG_STR_ASCII) { chset = CH_DOS; byte_mul = 1; flags &= ~LIBNDR_FLAG_STR_ASCII; } if (flags & LIBNDR_FLAG_STR_UTF8) { chset = CH_UTF8; byte_mul = 1; flags &= ~LIBNDR_FLAG_STR_UTF8; } flags &= ~LIBNDR_FLAG_STR_CONFORMANT; if (!(flags & (LIBNDR_FLAG_STR_NOTERM | LIBNDR_FLAG_STR_FIXLEN15 | LIBNDR_FLAG_STR_FIXLEN32))) { s_len++; } d_len = convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, &dest, False); if (d_len == -1) { return ndr_push_error(ndr, NDR_ERR_CHARCNV, "Bad character conversion"); } if (flags & LIBNDR_FLAG_STR_BYTESIZE) { c_len = d_len; flags &= ~LIBNDR_FLAG_STR_BYTESIZE; } else if (flags & LIBNDR_FLAG_STR_CHARLEN) { c_len = (d_len / byte_mul)-1; flags &= ~LIBNDR_FLAG_STR_CHARLEN; } else { c_len = d_len / byte_mul; } switch ((flags & LIBNDR_STRING_FLAGS) & ~LIBNDR_FLAG_STR_NOTERM) { case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); break; case LIBNDR_FLAG_STR_LEN4: NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); break; case LIBNDR_FLAG_STR_SIZE4: NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, c_len)); NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); break; case LIBNDR_FLAG_STR_SIZE2: NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, c_len)); NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); break; case LIBNDR_FLAG_STR_NULLTERM: NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); break; case LIBNDR_FLAG_STR_FIXLEN15: case LIBNDR_FLAG_STR_FIXLEN32: { ssize_t fix_len = (flags & LIBNDR_FLAG_STR_FIXLEN32)?32:15; uint32_t pad_len = fix_len - d_len; if (d_len > fix_len) { return ndr_push_error(ndr, NDR_ERR_CHARCNV, "Bad character conversion"); } NDR_CHECK(ndr_push_bytes(ndr, dest, d_len)); if (pad_len != 0) { NDR_CHECK(ndr_push_zero(ndr, pad_len)); } break; } default: return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", ndr->flags & LIBNDR_STRING_FLAGS); } talloc_free(dest); return NT_STATUS_OK; }