diff options
25 files changed, 280 insertions, 187 deletions
diff --git a/source4/build/pidl/header.pm b/source4/build/pidl/header.pm index c993108f98..418ae97aed 100644 --- a/source4/build/pidl/header.pm +++ b/source4/build/pidl/header.pm @@ -269,6 +269,9 @@ sub HeaderInterface($) my $count = 0; + $res .= "#ifndef _HEADER_NDR_$interface->{NAME}\n"; + $res .= "#define _HEADER_NDR_$interface->{NAME}\n\n"; + if (defined $if_uuid) { my $name = uc $interface->{NAME}; $res .= "#define DCERPC_$name\_UUID \"$if_uuid\"\n"; @@ -297,6 +300,7 @@ sub HeaderInterface($) HeaderFunction($d); } + $res .= "#endif /* _HEADER_NDR_$interface->{NAME} */\n"; } ##################################################################### diff --git a/source4/include/includes.h b/source4/include/includes.h index b3f98d2f2c..6d796da6b3 100644 --- a/source4/include/includes.h +++ b/source4/include/includes.h @@ -768,7 +768,6 @@ extern int errno; #include "mutex.h" -#include "librpc/ndr/libndr.h" #include "librpc/rpc/dcerpc.h" #include "rpc_server/dcerpc_server.h" diff --git a/source4/include/rpc_secdes.h b/source4/include/rpc_secdes.h index 70191901c7..80cc71fccf 100644 --- a/source4/include/rpc_secdes.h +++ b/source4/include/rpc_secdes.h @@ -116,8 +116,8 @@ typedef struct security_ace_info /* this stuff may be present when type is XXXX_TYPE_XXXX_OBJECT */ uint32 obj_flags; /* xxxx_ACE_OBJECT_xxxx e.g present/inherited present etc */ - GUID obj_guid; /* object GUID */ - GUID inh_guid; /* inherited object GUID */ + struct GUID obj_guid; /* object GUID */ + struct GUID inh_guid; /* inherited object GUID */ /* eof object stuff */ DOM_SID trustee; diff --git a/source4/include/smb.h b/source4/include/smb.h index 9b8bc28614..89623895ed 100644 --- a/source4/include/smb.h +++ b/source4/include/smb.h @@ -421,7 +421,9 @@ struct vuid_cache { #include "smb_acls.h" #include "enums.h" #include "events.h" +#include "librpc/gen_ndr/ndr_misc.h" #include "smb_interfaces.h" +#include "librpc/ndr/libndr.h" typedef struct smb_vfs_handle_struct { diff --git a/source4/include/smb_interfaces.h b/source4/include/smb_interfaces.h index 4bf557359e..6f820be536 100644 --- a/source4/include/smb_interfaces.h +++ b/source4/include/smb_interfaces.h @@ -24,10 +24,6 @@ typedef SMB_BIG_UINT large_t; /* Globally Unique ID */ #define GUID_SIZE 16 -typedef struct GUID -{ - uint8 info[GUID_SIZE]; -} GUID; /* 64 bit time (100 nanosec) 1601 - cifs6.txt, section 3.5, page 30 */ typedef struct nttime_info @@ -946,7 +942,7 @@ union smb_fsinfo { large_t quota_soft; large_t quota_hard; large_t quota_flags; - GUID guid; + struct GUID guid; char *volume_name; char *fs_type; } out; @@ -1074,7 +1070,7 @@ union smb_fsinfo { enum fsinfo_level level; struct { - GUID guid; + struct GUID guid; large_t unknown[6]; } out; } objectid_information; diff --git a/source4/lib/util_sid.c b/source4/lib/util_sid.c index 6436035f8e..44bb4cebb1 100644 --- a/source4/lib/util_sid.c +++ b/source4/lib/util_sid.c @@ -613,24 +613,6 @@ char *sid_binstring(const DOM_SID *sid) return s; } - -/***************************************************************** - Print a GUID structure for debugging. -*****************************************************************/ - -void print_guid(GUID *guid) -{ - int i; - - d_printf("%08x-%04x-%04x", - IVAL(guid->info, 0), SVAL(guid->info, 4), SVAL(guid->info, 6)); - d_printf("-%02x%02x-", guid->info[8], guid->info[9]); - for (i=10;i<GUID_SIZE;i++) - d_printf("%02x", guid->info[i]); - d_printf("\n"); -} - - /******************************************************************* Check if ACE has OBJECT type. ********************************************************************/ diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c index 1b8c7572c7..0c607fb823 100644 --- a/source4/lib/util_uuid.c +++ b/source4/lib/util_uuid.c @@ -3,6 +3,7 @@ * UUID server routines * Copyright (C) Theodore Ts'o 1996, 1997, * Copyright (C) Jim McDonough 2002. + * Copyright (C) Andrew Tridgell 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,52 +22,9 @@ #include "includes.h" -/* - * Offset between 15-Oct-1582 and 1-Jan-70 - */ -#define TIME_OFFSET_HIGH 0x01B21DD2 -#define TIME_OFFSET_LOW 0x13814000 - -struct uuid { - uint32 time_low; - uint16 time_mid; - uint16 time_hi_and_version; - uint8 clock_seq[2]; - uint8 node[6]; -}; - - -static void uuid_pack(const struct uuid *uu, GUID *ptr) -{ - uint8 *out = ptr->info; - - SIVAL(out, 0, uu->time_low); - SSVAL(out, 4, uu->time_mid); - SSVAL(out, 6, uu->time_hi_and_version); - memcpy(out+8, uu->clock_seq, 2); - memcpy(out+10, uu->node, 6); -} - -static void uuid_unpack(const GUID in, struct uuid *uu) +void uuid_generate_random(struct GUID *out) { - const uint8 *ptr = in.info; - - uu->time_low = IVAL(ptr, 0); - uu->time_mid = SVAL(ptr, 4); - uu->time_hi_and_version = SVAL(ptr, 6); - memcpy(uu->clock_seq, ptr+8, 2); - memcpy(uu->node, ptr+10, 6); -} - -void uuid_generate_random(GUID *out) -{ - GUID tmp; - struct uuid uu; - - generate_random_buffer(tmp.info, sizeof(tmp.info), True); - uuid_unpack(tmp, &uu); - - uu.clock_seq[0] = (uu.clock_seq[0] & 0x3F) | 0x80; - uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; - uuid_pack(&uu, out); + generate_random_buffer(out, sizeof(struct GUID), False); + out->clock_seq[0] = (out->clock_seq[0] & 0x3F) | 0x80; + out->time_hi_and_version = (out->time_hi_and_version & 0x0FFF) | 0x4000; } diff --git a/source4/libcli/raw/rawfsinfo.c b/source4/libcli/raw/rawfsinfo.c index 362063bfc5..85daf654d3 100644 --- a/source4/libcli/raw/rawfsinfo.c +++ b/source4/libcli/raw/rawfsinfo.c @@ -259,7 +259,8 @@ NTSTATUS smb_raw_fsinfo_recv(struct cli_request *req, case RAW_QFS_OBJECTID_INFORMATION: QFS_CHECK_SIZE(64); - memcpy(fsinfo->objectid_information.out.guid.info, blob.data, GUID_SIZE); + status = ndr_pull_struct_blob(&blob, mem_ctx, &fsinfo->objectid_information.out.guid, + (ndr_pull_flags_fn_t)ndr_pull_GUID); for (i=0;i<6;i++) { fsinfo->objectid_information.out.unknown[i] = BVAL(blob.data, 16 + i*8); } diff --git a/source4/librpc/idl/dcerpc.idl b/source4/librpc/idl/dcerpc.idl index cf195b6aea..ad82679576 100644 --- a/source4/librpc/idl/dcerpc.idl +++ b/source4/librpc/idl/dcerpc.idl @@ -13,8 +13,7 @@ interface dcerpc { typedef [public] struct { GUID uuid; - uint16 major_version; - uint16 minor_version; + uint32 if_version; } dcerpc_syntax_id; typedef struct { @@ -28,7 +27,7 @@ interface dcerpc uint16 max_xmit_frag; uint16 max_recv_frag; uint32 assoc_group_id; - uint8 num_contexts; + uint8 num_contexts; dcerpc_ctx_list ctx_list[num_contexts]; [flag(NDR_ALIGN8)] DATA_BLOB _pad; [flag(NDR_REMAINING)] DATA_BLOB auth_info; @@ -167,6 +166,7 @@ interface dcerpc const uint8 DCERPC_PFC_FLAG_NOCALL = 0x20; /* these offsets are needed by the signing code */ + const uint8 DCERPC_DREP_OFFSET = 4; const uint8 DCERPC_FRAG_LEN_OFFSET = 8; const uint8 DCERPC_AUTH_LEN_OFFSET = 10; diff --git a/source4/librpc/idl/misc.idl b/source4/librpc/idl/misc.idl index eb2288bc35..a1f8549eaa 100644 --- a/source4/librpc/idl/misc.idl +++ b/source4/librpc/idl/misc.idl @@ -8,6 +8,14 @@ interface misc { + typedef [public,noprint] struct { + uint32 time_low; + uint16 time_mid; + uint16 time_hi_and_version; + uint8 clock_seq[2]; + uint8 node[6]; + } GUID; + /* a domain SID. Note that unlike Samba3 this contains a pointer, so you can't copy them using assignment */ typedef [public,noprint] struct { diff --git a/source4/librpc/ndr/ndr_basic.c b/source4/librpc/ndr/ndr_basic.c index 3b5aea60ca..ed75b8c27c 100644 --- a/source4/librpc/ndr/ndr_basic.c +++ b/source4/librpc/ndr/ndr_basic.c @@ -22,6 +22,12 @@ #include "includes.h" +#define NDR_BE(ndr) ((ndr)->flags & LIBNDR_FLAG_BIGENDIAN) +#define NDR_SVAL(ndr, ofs) (NDR_BE(ndr)?RSVAL(ndr->data,ofs):SVAL(ndr->data,ofs)) +#define NDR_IVAL(ndr, ofs) (NDR_BE(ndr)?RIVAL(ndr->data,ofs):IVAL(ndr->data,ofs)) +#define NDR_SSVAL(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSSVAL(ndr->data,ofs,v); } else SSVAL(ndr->data,ofs,v); } while (0) +#define NDR_SIVAL(ndr, ofs, v) do { if (NDR_BE(ndr)) { RSIVAL(ndr->data,ofs,v); } else SIVAL(ndr->data,ofs,v); } while (0) + /* parse a uint8 */ @@ -41,7 +47,7 @@ NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, uint16 *v) { NDR_PULL_ALIGN(ndr, 2); NDR_PULL_NEED_BYTES(ndr, 2); - *v = SVAL(ndr->data, ndr->offset); + *v = NDR_SVAL(ndr, ndr->offset); ndr->offset += 2; return NT_STATUS_OK; } @@ -54,7 +60,7 @@ NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, uint32 *v) { NDR_PULL_ALIGN(ndr, 4); NDR_PULL_NEED_BYTES(ndr, 4); - *v = IVAL(ndr->data, ndr->offset); + *v = NDR_IVAL(ndr, ndr->offset); ndr->offset += 4; return NT_STATUS_OK; } @@ -66,8 +72,8 @@ NTSTATUS ndr_pull_HYPER_T(struct ndr_pull *ndr, HYPER_T *v) { NDR_PULL_ALIGN(ndr, 8); NDR_PULL_NEED_BYTES(ndr, 8); - v->low = IVAL(ndr->data, ndr->offset); - v->high = IVAL(ndr->data, ndr->offset+4); + v->low = NDR_IVAL(ndr, ndr->offset); + v->high = NDR_IVAL(ndr, ndr->offset+4); ndr->offset += 8; return NT_STATUS_OK; } @@ -174,18 +180,6 @@ NTSTATUS ndr_pull_array_uint32(struct ndr_pull *ndr, int ndr_flags, uint32 *data } /* - parse a GUID -*/ -NTSTATUS ndr_pull_GUID(struct ndr_pull *ndr, int ndr_flags, GUID *guid) -{ - if (ndr_flags & NDR_SCALARS) { - return ndr_pull_bytes(ndr, guid->info, GUID_SIZE); - } - return NT_STATUS_OK; -} - - -/* push a uint8 */ NTSTATUS ndr_push_uint8(struct ndr_push *ndr, uint8 v) @@ -203,7 +197,7 @@ NTSTATUS ndr_push_uint16(struct ndr_push *ndr, uint16 v) { NDR_PUSH_ALIGN(ndr, 2); NDR_PUSH_NEED_BYTES(ndr, 2); - SSVAL(ndr->data, ndr->offset, v); + NDR_SSVAL(ndr, ndr->offset, v); ndr->offset += 2; return NT_STATUS_OK; } @@ -215,7 +209,7 @@ NTSTATUS ndr_push_uint32(struct ndr_push *ndr, uint32 v) { NDR_PUSH_ALIGN(ndr, 4); NDR_PUSH_NEED_BYTES(ndr, 4); - SIVAL(ndr->data, ndr->offset, v); + NDR_SIVAL(ndr, ndr->offset, v); ndr->offset += 4; return NT_STATUS_OK; } @@ -227,8 +221,8 @@ NTSTATUS ndr_push_HYPER_T(struct ndr_push *ndr, HYPER_T v) { NDR_PUSH_ALIGN(ndr, 8); NDR_PUSH_NEED_BYTES(ndr, 8); - SIVAL(ndr->data, ndr->offset, v.low); - SIVAL(ndr->data, ndr->offset+4, v.high); + NDR_SIVAL(ndr, ndr->offset, v.low); + NDR_SIVAL(ndr, ndr->offset+4, v.high); ndr->offset += 8; return NT_STATUS_OK; } @@ -582,17 +576,6 @@ NTSTATUS ndr_push_string(struct ndr_push *ndr, int ndr_flags, const char *s) } /* - push a GUID -*/ -NTSTATUS ndr_push_GUID(struct ndr_push *ndr, int ndr_flags, GUID *guid) -{ - if (ndr_flags & NDR_SCALARS) { - return ndr_push_bytes(ndr, guid->info, GUID_SIZE); - } - return NT_STATUS_OK; -} - -/* push a NTTIME */ NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t) @@ -770,26 +753,25 @@ NTSTATUS GUID_from_string(const char *s, struct GUID *guid) { uint32 time_low; uint32 time_mid, time_hi_and_version; - uint32 clock_seq_hi_and_reserved; - uint32 clock_seq_low; + uint32 clock_seq[2]; uint32 node[6]; int i; if (11 != sscanf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", &time_low, &time_mid, &time_hi_and_version, - &clock_seq_hi_and_reserved, &clock_seq_low, + &clock_seq[0], &clock_seq[1], &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { return NT_STATUS_INVALID_PARAMETER; } - SIVAL(guid->info, 0, time_low); - SSVAL(guid->info, 4, time_mid); - SSVAL(guid->info, 6, time_hi_and_version); - SCVAL(guid->info, 8, clock_seq_hi_and_reserved); - SCVAL(guid->info, 9, clock_seq_low); + guid->time_low = time_low; + guid->time_mid = time_mid; + guid->time_hi_and_version = time_hi_and_version; + guid->clock_seq[0] = clock_seq[0]; + guid->clock_seq[1] = clock_seq[1]; for (i=0;i<6;i++) { - SCVAL(guid->info, 10 + i, node[i]); - } + guid->node[i] = node[i]; + } return NT_STATUS_OK; } @@ -801,12 +783,13 @@ const char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid) { return talloc_asprintf(mem_ctx, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - IVAL(guid->info, 0), SVAL(guid->info, 4), - SVAL(guid->info, 6), - guid->info[8], guid->info[9], - guid->info[10], guid->info[11], - guid->info[12], guid->info[13], - guid->info[14], guid->info[15]); + guid->time_low, guid->time_mid, + guid->time_hi_and_version, + guid->clock_seq[0], + guid->clock_seq[1], + guid->node[0], guid->node[1], + guid->node[2], guid->node[3], + guid->node[4], guid->node[5]); } void ndr_print_GUID(struct ndr_print *ndr, const char *name, const struct GUID *guid) diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c index 3dcaca83ec..c82d8d67ab 100644 --- a/source4/librpc/rpc/dcerpc.c +++ b/source4/librpc/rpc/dcerpc.c @@ -64,6 +64,35 @@ void dcerpc_pipe_close(struct dcerpc_pipe *p) } } +/* we need to be able to get/set the fragment length without doing a full + decode */ +void dcerpc_set_frag_length(DATA_BLOB *blob, uint16 v) +{ + if (CVAL(blob->data,DCERPC_DREP_OFFSET) & 0x10) { + SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v); + } else { + RSSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v); + } +} + +uint16 dcerpc_get_frag_length(DATA_BLOB *blob) +{ + if (CVAL(blob->data,DCERPC_DREP_OFFSET) & 0x10) { + return SVAL(blob->data, DCERPC_FRAG_LEN_OFFSET); + } else { + return RSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET); + } +} + +void dcerpc_set_auth_length(DATA_BLOB *blob, uint16 v) +{ + if (CVAL(blob->data,DCERPC_DREP_OFFSET) & 0x10) { + SSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v); + } else { + RSSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, v); + } +} + /* parse a data blob into a dcerpc_packet structure. This handles both @@ -79,6 +108,10 @@ static NTSTATUS dcerpc_pull(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } + if (! (CVAL(blob, DCERPC_DREP_OFFSET) & 0x10)) { + ndr->flags |= DCERPC_PULL_BIGENDIAN; + } + return ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); } @@ -104,6 +137,10 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } + if (! (CVAL(blob, DCERPC_DREP_OFFSET) & 0x10)) { + ndr->flags |= DCERPC_PULL_BIGENDIAN; + } + /* pull the basic packet */ status = ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); if (!NT_STATUS_IS_OK(status)) { @@ -132,6 +169,10 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } + if (! (CVAL(blob, DCERPC_DREP_OFFSET) & 0x10)) { + ndr->flags |= DCERPC_PULL_BIGENDIAN; + } + status = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth); if (!NT_STATUS_IS_OK(status)) { return status; @@ -184,7 +225,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, /* non-signed packets are simpler */ if (!p->auth_info || !p->ntlmssp_state) { - return dcerpc_push_auth(blob, mem_ctx, pkt, p->auth_info); + return dcerpc_push_auth(blob, mem_ctx, pkt, p->auth_info, p->flags); } ndr = ndr_push_init_ctx(mem_ctx); @@ -192,6 +233,10 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } + if (p->flags & DCERPC_PUSH_BIGENDIAN) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + status = ndr_push_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); if (!NT_STATUS_IS_OK(status)) { return status; @@ -242,8 +287,8 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, /* fill in the fragment length and auth_length, we can't fill in these earlier as we don't know the signature length (it could be variable length) */ - SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, blob->length); - SSVAL(blob->data, DCERPC_AUTH_LEN_OFFSET, p->auth_info->credentials.length); + dcerpc_set_frag_length(blob, blob->length); + dcerpc_set_auth_length(blob, p->auth_info->credentials.length); data_blob_free(&p->auth_info->credentials); @@ -254,11 +299,15 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, /* fill in the fixed values in a dcerpc header */ -static void init_dcerpc_hdr(struct dcerpc_packet *pkt) +static void init_dcerpc_hdr(struct dcerpc_pipe *p, struct dcerpc_packet *pkt) { pkt->rpc_vers = 5; pkt->rpc_vers_minor = 0; - pkt->drep[0] = 0x10; /* Little endian */ + if (p->flags & DCERPC_PUSH_BIGENDIAN) { + pkt->drep[0] = 0; + } else { + pkt->drep[0] = 0x10; + } pkt->drep[1] = 0; pkt->drep[2] = 0; pkt->drep[3] = 0; @@ -281,7 +330,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p, DATA_BLOB blob; struct dcerpc_syntax_id tsyntax; - init_dcerpc_hdr(&pkt); + init_dcerpc_hdr(p, &pkt); pkt.ptype = DCERPC_PKT_BIND; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; @@ -304,7 +353,7 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p, pkt.u.bind.auth_info = data_blob(NULL, 0); /* construct the NDR form of the packet */ - status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info); + status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info, p->flags); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -353,7 +402,7 @@ NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, NTSTATUS status; DATA_BLOB blob; - init_dcerpc_hdr(&pkt); + init_dcerpc_hdr(p, &pkt); pkt.ptype = DCERPC_PKT_AUTH3; pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; @@ -363,7 +412,7 @@ NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, pkt.u.auth.auth_info = data_blob(NULL, 0); /* construct the NDR form of the packet */ - status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info); + status = dcerpc_push_auth(&blob, mem_ctx, &pkt, p->auth_info, p->flags); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -392,15 +441,13 @@ NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p, DEBUG(2,("Invalid uuid string in dcerpc_bind_byuuid\n")); return status; } - syntax.major_version = version; - syntax.minor_version = 0; + syntax.if_version = version; status = GUID_from_string(NDR_GUID, &transfer_syntax.uuid); if (!NT_STATUS_IS_OK(status)) { return status; } - transfer_syntax.major_version = NDR_GUID_VERSION; - transfer_syntax.minor_version = 0; + transfer_syntax.if_version = NDR_GUID_VERSION; return dcerpc_bind(p, mem_ctx, &syntax, &transfer_syntax); } @@ -420,7 +467,7 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p, DATA_BLOB blob, payload; uint32 remaining, chunk_size; - init_dcerpc_hdr(&pkt); + init_dcerpc_hdr(p, &pkt); remaining = stub_data_in->length; @@ -552,6 +599,12 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p, *stub_data_out = payload; } + if (!(pkt.drep[0] & 0x10)) { + p->flags |= DCERPC_PULL_BIGENDIAN; + } else { + p->flags &= ~DCERPC_PULL_BIGENDIAN; + } + return status; } @@ -723,6 +776,10 @@ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p, return NT_STATUS_NO_MEMORY; } + if (p->flags & DCERPC_PUSH_BIGENDIAN) { + push->flags |= LIBNDR_FLAG_BIGENDIAN; + } + /* push the structure into a blob */ status = ndr_push(push, NDR_IN, struct_ptr); if (!NT_STATUS_IS_OK(status)) { @@ -755,6 +812,10 @@ NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p, goto failed; } + if (p->flags & DCERPC_PULL_BIGENDIAN) { + pull->flags |= LIBNDR_FLAG_BIGENDIAN; + } + DEBUG(10,("rpc reply data:\n")); dump_data(10, pull->data, pull->data_size); diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h index fa2ced2537..5d25882041 100644 --- a/source4/librpc/rpc/dcerpc.h +++ b/source4/librpc/rpc/dcerpc.h @@ -65,6 +65,9 @@ struct dcerpc_pipe { #define DCERPC_SIGN 16 #define DCERPC_SEAL 32 +#define DCERPC_PUSH_BIGENDIAN 64 +#define DCERPC_PULL_BIGENDIAN 128 + /* this is used to find pointers to calls */ diff --git a/source4/librpc/rpc/dcerpc_smb.c b/source4/librpc/rpc/dcerpc_smb.c index 9acae00249..fc71a47cf4 100644 --- a/source4/librpc/rpc/dcerpc_smb.c +++ b/source4/librpc/rpc/dcerpc_smb.c @@ -91,7 +91,7 @@ static NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p, /* we might have recieved a partial fragment, in which case we need to pull the rest of it */ - frag_length = SVAL(payload.data, 8); + frag_length = dcerpc_get_frag_length(&payload); if (frag_length <= payload.length) { goto done; } @@ -197,7 +197,7 @@ NTSTATUS smb_secondary_request(struct dcerpc_pipe *p, return status; } - frag_length = SVAL(blob->data, 8); + frag_length = dcerpc_get_frag_length(blob); if (frag_length <= blob->length) { return status; } diff --git a/source4/librpc/rpc/dcerpc_tcp.c b/source4/librpc/rpc/dcerpc_tcp.c index 468cd9465b..b577260033 100644 --- a/source4/librpc/rpc/dcerpc_tcp.c +++ b/source4/librpc/rpc/dcerpc_tcp.c @@ -60,7 +60,7 @@ static NTSTATUS tcp_raw_recv(struct dcerpc_pipe *p, /* we might have recieved a partial fragment, in which case we need to pull the rest of it */ - frag_length = SVAL(blob1.data, 8); + frag_length = dcerpc_get_frag_length(&blob1); if (frag_length == blob1.length) { *blob = blob1; return NT_STATUS_OK; diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c index 02e224a26f..fbc97f316d 100644 --- a/source4/librpc/rpc/dcerpc_util.c +++ b/source4/librpc/rpc/dcerpc_util.c @@ -59,7 +59,7 @@ NTSTATUS dcerpc_epm_map_tcp_port(const char *server, NTSTATUS status; struct epm_Map r; struct policy_handle handle; - GUID guid; + struct GUID guid; struct epm_twr_t twr, *twr_r; if (strcasecmp(uuid, DCERPC_EPMAPPER_UUID) == 0 || @@ -223,7 +223,8 @@ const struct dcerpc_interface_table *idl_iface_by_uuid(const char *uuid) */ NTSTATUS dcerpc_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct dcerpc_packet *pkt, - struct dcerpc_auth *auth_info) + struct dcerpc_auth *auth_info, + unsigned flags) { NTSTATUS status; struct ndr_push *ndr; @@ -233,6 +234,10 @@ NTSTATUS dcerpc_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } + if (flags & DCERPC_PUSH_BIGENDIAN) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + if (auth_info) { pkt->auth_length = auth_info->credentials.length; } else { @@ -251,7 +256,7 @@ NTSTATUS dcerpc_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, *blob = ndr_push_blob(ndr); /* fill in the frag length */ - SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, blob->length); + dcerpc_set_frag_length(blob, blob->length); return NT_STATUS_OK; } @@ -278,7 +283,8 @@ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_ } options[] = { {"sign", DCERPC_SIGN}, {"seal", DCERPC_SEAL}, - {"validate", DCERPC_DEBUG_VALIDATE_BOTH} + {"validate", DCERPC_DEBUG_VALIDATE_BOTH}, + {"bigendian", DCERPC_PUSH_BIGENDIAN} }; p = strchr(s, ':'); diff --git a/source4/ntvfs/ipc/vfs_ipc.c b/source4/ntvfs/ipc/vfs_ipc.c index a3b3ab19b7..96f28895c9 100644 --- a/source4/ntvfs/ipc/vfs_ipc.c +++ b/source4/ntvfs/ipc/vfs_ipc.c @@ -181,10 +181,13 @@ static NTSTATUS ipc_setpathinfo(struct request_context *req, union smb_setfilein return NT_STATUS_ACCESS_DENIED; } + + /* - open a file - used for MSRPC pipes + open a file backend - used for MSRPC pipes */ -static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi) +static NTSTATUS ipc_open_generic(struct request_context *req, const char *fname, + struct pipe_state **ps) { struct pipe_state *p; TALLOC_CTX *mem_ctx; @@ -192,12 +195,7 @@ static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi) struct dcesrv_endpoint endpoint; struct ipc_private *private = req->conn->ntvfs_private; - /* for now only handle NTcreateX style opens */ - if (oi->generic.level != RAW_OPEN_NTCREATEX) { - return NT_STATUS_ACCESS_DENIED; - } - - mem_ctx = talloc_init("ipc_open '%s'", oi->ntcreatex.in.fname); + mem_ctx = talloc_init("ipc_open '%s'", fname); if (!mem_ctx) { return NT_STATUS_NO_MEMORY; } @@ -209,7 +207,7 @@ static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi) } p->mem_ctx = mem_ctx; - p->pipe_name = talloc_strdup(mem_ctx, oi->ntcreatex.in.fname); + p->pipe_name = talloc_strdup(mem_ctx, fname); if (!p->pipe_name) { talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; @@ -250,11 +248,79 @@ static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi) DLIST_ADD(private->pipe_list, p); + *ps = p; + + return NT_STATUS_OK; +} + +/* + open a file with ntcreatex - used for MSRPC pipes +*/ +static NTSTATUS ipc_open_ntcreatex(struct request_context *req, union smb_open *oi) +{ + struct pipe_state *p; + NTSTATUS status; + + status = ipc_open_generic(req, oi->ntcreatex.in.fname, &p); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + ZERO_STRUCT(oi->ntcreatex.out); oi->ntcreatex.out.fnum = p->fnum; oi->ntcreatex.out.ipc_state = p->ipc_state; - return NT_STATUS_OK; + return status; +} + +/* + open a file with openx - used for MSRPC pipes +*/ +static NTSTATUS ipc_open_openx(struct request_context *req, union smb_open *oi) +{ + struct pipe_state *p; + NTSTATUS status; + const char *fname = oi->openx.in.fname; + + if (strncasecmp(fname, "PIPE\\", 5) != 0) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + fname += 4; + + status = ipc_open_generic(req, fname, &p); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + ZERO_STRUCT(oi->openx.out); + oi->openx.out.fnum = p->fnum; + oi->openx.out.ftype = 2; + oi->openx.out.devstate = p->ipc_state; + + return status; +} + +/* + open a file - used for MSRPC pipes +*/ +static NTSTATUS ipc_open(struct request_context *req, union smb_open *oi) +{ + NTSTATUS status; + + switch (oi->generic.level) { + case RAW_OPEN_NTCREATEX: + status = ipc_open_ntcreatex(req, oi); + break; + case RAW_OPEN_OPENX: + status = ipc_open_openx(req, oi); + break; + default: + status = NT_STATUS_NOT_SUPPORTED; + break; + } + + return status; } /* diff --git a/source4/passdb/secrets.c b/source4/passdb/secrets.c index 60e211e66f..486ccb8b11 100644 --- a/source4/passdb/secrets.c +++ b/source4/passdb/secrets.c @@ -141,25 +141,44 @@ BOOL secrets_fetch_domain_sid(const char *domain, DOM_SID *sid) return True; } -BOOL secrets_store_domain_guid(const char *domain, GUID *guid) +BOOL secrets_store_domain_guid(const char *domain, struct GUID *guid) { + const char *s; fstring key; + TALLOC_CTX *mem_ctx; + BOOL ret; + + mem_ctx = talloc_init("secrets_store_domain_guid"); + if (!mem_ctx) { + return False; + } + + s = GUID_string(mem_ctx, guid); + if (!s) { + talloc_destroy(mem_ctx); + return False; + } + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper(key); - return secrets_store(key, guid, sizeof(GUID)); + ret = secrets_store(key, s, strlen(s)+1); + + talloc_destroy(mem_ctx); + return ret; } -BOOL secrets_fetch_domain_guid(const char *domain, GUID *guid) +BOOL secrets_fetch_domain_guid(const char *domain, struct GUID *guid) { - GUID *dyn_guid; + char *dyn_guid; fstring key; size_t size; - GUID new_guid; + struct GUID new_guid; + NTSTATUS status; slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); strupper(key); - dyn_guid = (GUID *)secrets_fetch(key, &size); + dyn_guid = secrets_fetch(key, &size); DEBUG(6,("key is %s, size is %d\n", key, (int)size)); @@ -167,19 +186,18 @@ BOOL secrets_fetch_domain_guid(const char *domain, GUID *guid) uuid_generate_random(&new_guid); if (!secrets_store_domain_guid(domain, &new_guid)) return False; - dyn_guid = (GUID *)secrets_fetch(key, &size); + dyn_guid = secrets_fetch(key, &size); if (dyn_guid == NULL) return False; } - if (size != sizeof(GUID)) - { - SAFE_FREE(dyn_guid); + status = GUID_from_string(dyn_guid, guid); + SAFE_FREE(dyn_guid); + + if (!NT_STATUS_IS_OK(status)) { return False; } - *guid = *dyn_guid; - SAFE_FREE(dyn_guid); return True; } diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c index f3c7a63c79..5780de0c30 100644 --- a/source4/rpc_server/dcerpc_server.c +++ b/source4/rpc_server/dcerpc_server.c @@ -209,7 +209,7 @@ static NTSTATUS dcesrv_fault(struct dcesrv_call_state *call, uint32 fault_code) return NT_STATUS_NO_MEMORY; } - status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL); + status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL, 0); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -266,7 +266,7 @@ static NTSTATUS dcesrv_bind_nak(struct dcesrv_call_state *call, uint32 reason) return NT_STATUS_NO_MEMORY; } - status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL); + status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, NULL, 0); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -296,13 +296,13 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) return dcesrv_bind_nak(call, 0); } - if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.major_version; + if_version = call->pkt.u.bind.ctx_list[0].abstract_syntax.if_version; uuid = GUID_string(call->mem_ctx, &call->pkt.u.bind.ctx_list[0].abstract_syntax.uuid); if (!uuid) { return dcesrv_bind_nak(call, 0); } - transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].major_version; + transfer_syntax_version = call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].if_version; transfer_syntax = GUID_string(call->mem_ctx, &call->pkt.u.bind.ctx_list[0].transfer_syntaxes[0].uuid); if (!transfer_syntax || @@ -356,8 +356,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) pkt.u.bind_ack.ctx_list[0].result = result; pkt.u.bind_ack.ctx_list[0].reason = reason; GUID_from_string(NDR_GUID, &pkt.u.bind_ack.ctx_list[0].syntax.uuid); - pkt.u.bind_ack.ctx_list[0].syntax.major_version = NDR_GUID_VERSION; - pkt.u.bind_ack.ctx_list[0].syntax.minor_version = 0; + pkt.u.bind_ack.ctx_list[0].syntax.if_version = NDR_GUID_VERSION; pkt.u.bind_ack.auth_info = data_blob(NULL, 0); if (!dcesrv_auth_bind_ack(call, &pkt)) { @@ -370,7 +369,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) } status = dcerpc_push_auth(&rep->data, call->mem_ctx, &pkt, - call->dce->auth_state.auth_info); + call->dce->auth_state.auth_info, 0); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c index f290c741cb..0f4b22ee3d 100644 --- a/source4/rpc_server/dcesrv_auth.c +++ b/source4/rpc_server/dcesrv_auth.c @@ -232,7 +232,7 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call, /* non-signed packets are simple */ if (!dce->auth_state.auth_info || !dce->auth_state.ntlmssp_state) { - status = dcerpc_push_auth(blob, call->mem_ctx, pkt, NULL); + status = dcerpc_push_auth(blob, call->mem_ctx, pkt, NULL, 0); return NT_STATUS_IS_OK(status); } diff --git a/source4/rpc_server/epmapper/rpc_epmapper.c b/source4/rpc_server/epmapper/rpc_epmapper.c index f2ecc0faa9..5e571ee1ef 100644 --- a/source4/rpc_server/epmapper/rpc_epmapper.c +++ b/source4/rpc_server/epmapper/rpc_epmapper.c @@ -30,7 +30,7 @@ enum handle_types {HTYPE_LOOKUP}; /* simple routine to compare a GUID string to a GUID structure */ -static int guid_cmp(TALLOC_CTX *mem_ctx, const GUID *guid, const char *uuid_str) +static int guid_cmp(TALLOC_CTX *mem_ctx, const struct GUID *guid, const char *uuid_str) { const char *s = GUID_string(mem_ctx, guid); if (!s || strcasecmp(s, uuid_str)) { diff --git a/source4/smbd/trans2.c b/source4/smbd/trans2.c index 19f313a860..6a15aad137 100644 --- a/source4/smbd/trans2.c +++ b/source4/smbd/trans2.c @@ -202,6 +202,7 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t NTSTATUS status; uint16 level; uint_t i; + DATA_BLOB guid_blob; /* make sure we got enough parameters */ if (trans->in.params.length != 2) { @@ -369,7 +370,15 @@ static NTSTATUS trans2_qfsinfo(struct request_context *req, struct smb_trans2 *t trans2_setup_reply(req, trans, 0, 64, 0); - memcpy(trans->out.data.data, fsinfo.objectid_information.out.guid.info, GUID_SIZE); + status = ndr_push_struct_blob(&guid_blob, req->mem_ctx, + &fsinfo.objectid_information.out.guid, + (ndr_push_flags_fn_t)ndr_push_GUID); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + memcpy(trans->out.data.data, guid_blob.data, GUID_SIZE); + for (i=0;i<6;i++) { SBVAL(trans->out.data.data, 16 + 8*i, fsinfo.objectid_information.out.unknown[i]); } diff --git a/source4/torture/rpc/epmapper.c b/source4/torture/rpc/epmapper.c index afc83a512d..2b704659d6 100644 --- a/source4/torture/rpc/epmapper.c +++ b/source4/torture/rpc/epmapper.c @@ -104,7 +104,7 @@ static BOOL test_Map(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, { NTSTATUS status; struct epm_Map r; - GUID uuid; + struct GUID uuid; const char *uuid_str; struct policy_handle handle; int i; diff --git a/source4/torture/rpc/mgmt.c b/source4/torture/rpc/mgmt.c index 24bf080ffb..3a50732c7e 100644 --- a/source4/torture/rpc/mgmt.c +++ b/source4/torture/rpc/mgmt.c @@ -55,10 +55,9 @@ static BOOL test_inq_if_ids(struct dcerpc_pipe *p, uuid = GUID_string(mem_ctx, &id->uuid); - printf("\tuuid %s version 0x%04x:0x%04x '%s'\n", + printf("\tuuid %s version 0x%08x '%s'\n", uuid, - id->major_version, id->minor_version, - idl_pipe_name(uuid, id->major_version)); + id->if_version, idl_pipe_name(uuid, id->if_version)); } return True; diff --git a/source4/torture/rpc/scanner.c b/source4/torture/rpc/scanner.c index 3469294552..99c047bf2e 100644 --- a/source4/torture/rpc/scanner.c +++ b/source4/torture/rpc/scanner.c @@ -39,7 +39,7 @@ static BOOL test_num_calls(const struct dcerpc_interface_table *iface, uuid = GUID_string(mem_ctx, &id->uuid); status = torture_rpc_connection(&p, iface->name, - uuid, id->major_version); + uuid, id->if_version); if (!NT_STATUS_IS_OK(status)) { printf("Failed to connect to '%s' on '%s' - %s\n", uuid, iface->name, nt_errstr(status)); @@ -69,7 +69,7 @@ static BOOL test_num_calls(const struct dcerpc_interface_table *iface, } printf("\t%d calls available\n", i); - idl_calls = idl_num_calls(uuid, id->major_version); + idl_calls = idl_num_calls(uuid, id->if_version); if (idl_calls == -1) { printf("\tinterface not known in local IDL\n"); } else if (i != idl_calls) { @@ -117,10 +117,9 @@ static BOOL test_inq_if_ids(struct dcerpc_pipe *p, uuid = GUID_string(mem_ctx, &id->uuid), - printf("\n\tuuid %s version 0x%04x:0x%04x '%s'\n", + printf("\n\tuuid %s version 0x%08x '%s'\n", uuid, - id->major_version, id->minor_version, - idl_pipe_name(uuid, id->major_version)); + id->if_version, idl_pipe_name(uuid, id->if_version)); test_num_calls(iface, mem_ctx, id); } |