+ if (ofs == 0) {
+ *blob = data_blob(NULL, 0);
+ return NT_STATUS_OK;
+ }
+ if (smb2_oob(buf, buf->hdr + ofs, size)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ *blob = data_blob_talloc(mem_ctx, buf->hdr + ofs, size);
+ NT_STATUS_HAVE_NO_MEMORY(blob->data);
+ return NT_STATUS_OK;
+}
+
+/*
+ push a uint16_t ofs/ uint16_t length/blob triple into a data blob
+ the ofs points to the start of the offset/length pair, and is relative
+ to the body start
+*/
+NTSTATUS smb2_push_o16s16_blob(struct smb2_request_buffer *buf,
+ uint16_t ofs, DATA_BLOB blob)
+{
+ NTSTATUS status;
+ size_t offset;
+ size_t padding_length;
+ size_t padding_fix;
+ uint8_t *ptr = buf->body+ofs;
+
+ if (buf->dynamic == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* we have only 16 bit for the size */
+ if (blob.length > 0xFFFF) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* check if there're enough room for ofs and size */
+ if (smb2_oob(buf, ptr, 4)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ SSVAL(ptr, 0, 0);
+ SSVAL(ptr, 2, 0);
+ return NT_STATUS_OK;
+ }
+
+ offset = buf->dynamic - buf->hdr;
+ padding_length = smb2_padding_size(offset, 2);
+ offset += padding_length;
+ padding_fix = smb2_padding_fix(buf);
+
+ SSVAL(ptr, 0, offset);
+ SSVAL(ptr, 2, blob.length);
+
+ status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ memset(buf->dynamic, 0, padding_length);
+ buf->dynamic += padding_length;
+
+ memcpy(buf->dynamic, blob.data, blob.length);
+ buf->dynamic += blob.length;
+
+ buf->size += blob.length + padding_length - padding_fix;
+ buf->body_size += blob.length + padding_length;
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ push a uint16_t ofs/ uint32_t length/blob triple into a data blob
+ the ofs points to the start of the offset/length pair, and is relative
+ to the body start
+*/
+NTSTATUS smb2_push_o16s32_blob(struct smb2_request_buffer *buf,
+ uint16_t ofs, DATA_BLOB blob)
+{
+ NTSTATUS status;
+ size_t offset;
+ size_t padding_length;
+ size_t padding_fix;
+ uint8_t *ptr = buf->body+ofs;
+
+ if (buf->dynamic == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* check if there're enough room for ofs and size */
+ if (smb2_oob(buf, ptr, 6)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ SSVAL(ptr, 0, 0);
+ SIVAL(ptr, 2, 0);
+ return NT_STATUS_OK;
+ }
+
+ offset = buf->dynamic - buf->hdr;
+ padding_length = smb2_padding_size(offset, 2);
+ offset += padding_length;
+ padding_fix = smb2_padding_fix(buf);
+
+ SSVAL(ptr, 0, offset);
+ SIVAL(ptr, 2, blob.length);
+
+ status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ memset(buf->dynamic, 0, padding_length);
+ buf->dynamic += padding_length;
+
+ memcpy(buf->dynamic, blob.data, blob.length);
+ buf->dynamic += blob.length;
+
+ buf->size += blob.length + padding_length - padding_fix;
+ buf->body_size += blob.length + padding_length;
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ push a uint32_t ofs/ uint32_t length/blob triple into a data blob
+ the ofs points to the start of the offset/length pair, and is relative
+ to the body start
+*/
+NTSTATUS smb2_push_o32s32_blob(struct smb2_request_buffer *buf,
+ uint32_t ofs, DATA_BLOB blob)
+{
+ NTSTATUS status;
+ size_t offset;
+ size_t padding_length;
+ size_t padding_fix;
+ uint8_t *ptr = buf->body+ofs;
+
+ if (buf->dynamic == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* check if there're enough room for ofs and size */
+ if (smb2_oob(buf, ptr, 8)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ SIVAL(ptr, 0, 0);
+ SIVAL(ptr, 4, 0);
+ return NT_STATUS_OK;
+ }
+
+ offset = buf->dynamic - buf->hdr;
+ padding_length = smb2_padding_size(offset, 8);
+ offset += padding_length;
+ padding_fix = smb2_padding_fix(buf);
+
+ SIVAL(ptr, 0, offset);
+ SIVAL(ptr, 4, blob.length);
+
+ status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ memset(buf->dynamic, 0, padding_length);
+ buf->dynamic += padding_length;
+
+ memcpy(buf->dynamic, blob.data, blob.length);
+ buf->dynamic += blob.length;
+
+ buf->size += blob.length + padding_length - padding_fix;
+ buf->body_size += blob.length + padding_length;
+
+ return NT_STATUS_OK;
+}
+
+
+/*
+ push a uint32_t length/ uint32_t ofs/blob triple into a data blob
+ the ofs points to the start of the length/offset pair, and is relative
+ to the body start
+*/
+NTSTATUS smb2_push_s32o32_blob(struct smb2_request_buffer *buf,
+ uint32_t ofs, DATA_BLOB blob)
+{
+ NTSTATUS status;
+ size_t offset;
+ size_t padding_length;
+ size_t padding_fix;
+ uint8_t *ptr = buf->body+ofs;
+
+ if (buf->dynamic == NULL) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* check if there're enough room for ofs and size */
+ if (smb2_oob(buf, ptr, 8)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (blob.data == NULL) {
+ if (blob.length != 0) {
+ return NT_STATUS_INTERNAL_ERROR;
+ }
+ SIVAL(ptr, 0, 0);
+ SIVAL(ptr, 4, 0);
+ return NT_STATUS_OK;
+ }
+
+ offset = buf->dynamic - buf->hdr;
+ padding_length = smb2_padding_size(offset, 8);
+ offset += padding_length;
+ padding_fix = smb2_padding_fix(buf);
+
+ SIVAL(ptr, 0, blob.length);
+ SIVAL(ptr, 4, offset);
+
+ status = smb2_grow_buffer(buf, blob.length + padding_length - padding_fix);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ memset(buf->dynamic, 0, padding_length);
+ buf->dynamic += padding_length;
+
+ memcpy(buf->dynamic, blob.data, blob.length);
+ buf->dynamic += blob.length;
+
+ buf->size += blob.length + padding_length - padding_fix;
+ buf->body_size += blob.length + padding_length;
+
+ return NT_STATUS_OK;
+}
+
+/*
+ pull a uint16_t ofs/ uint32_t length/blob triple from a data blob
+ the ptr points to the start of the offset/length pair
+*/
+NTSTATUS smb2_pull_o16s32_blob(struct smb2_request_buffer *buf, TALLOC_CTX *mem_ctx, uint8_t *ptr, DATA_BLOB *blob)
+{
+ uint16_t ofs;
+ uint32_t size;
+
+ if (smb2_oob(buf, ptr, 6)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ ofs = SVAL(ptr, 0);
+ size = IVAL(ptr, 2);
+ if (ofs == 0) {
+ *blob = data_blob(NULL, 0);
+ return NT_STATUS_OK;
+ }