From e3d2dbdff6711b0bc768fb6b08f41240f21d5fba Mon Sep 17 00:00:00 2001 From: CVS Import User Date: Sun, 4 Apr 2004 11:51:10 +0000 Subject: r6: merge in the samba4 HEAD branch from cvs to checkout try: svn co svn+ssh://svn.samba.org/home/svn/samba/branches/SAMBA_4_0 metze --- source/librpc/.cvsignore | 2 + source/librpc/config.m4 | 36 + source/librpc/idl/.cvsignore | 2 + source/librpc/idl/atsvc.idl | 67 ++ source/librpc/idl/browser.idl | 10 + source/librpc/idl/dcerpc.idl | 189 +++++ source/librpc/idl/dcom.idl | 43 ++ source/librpc/idl/dfs.idl | 174 +++++ source/librpc/idl/echo.idl | 90 +++ source/librpc/idl/epmapper.idl | 168 +++++ source/librpc/idl/eventlog.idl | 48 ++ source/librpc/idl/idl_types.h | 72 ++ source/librpc/idl/keysvc.idl | 15 + source/librpc/idl/lsa.idl | 500 +++++++++++++ source/librpc/idl/mgmt.idl | 74 ++ source/librpc/idl/misc.idl | 79 ++ source/librpc/idl/netlogon.idl | 796 ++++++++++++++++++++ source/librpc/idl/ntsvcs.idl | 15 + source/librpc/idl/protected_storage.idl | 15 + source/librpc/idl/samr.idl | 894 ++++++++++++++++++++++ source/librpc/idl/scerpc.idl | 16 + source/librpc/idl/spoolss.idl | 843 +++++++++++++++++++++ source/librpc/idl/srvsvc.idl | 1241 +++++++++++++++++++++++++++++++ source/librpc/idl/trkwks.idl | 15 + source/librpc/idl/w32time.idl | 16 + source/librpc/idl/winreg.idl | 299 ++++++++ source/librpc/idl/wkssvc.idl | 249 +++++++ source/librpc/idl/wzcsvc.idl | 15 + source/librpc/ndr/libndr.h | 246 ++++++ source/librpc/ndr/ndr.c | 766 +++++++++++++++++++ source/librpc/ndr/ndr_basic.c | 868 +++++++++++++++++++++ source/librpc/ndr/ndr_sec.c | 185 +++++ source/librpc/ndr/ndr_sec.h | 56 ++ source/librpc/ndr/ndr_spoolss_buf.c | 93 +++ source/librpc/rpc/dcerpc.c | 860 +++++++++++++++++++++ source/librpc/rpc/dcerpc.h | 117 +++ source/librpc/rpc/dcerpc_auth.c | 43 ++ source/librpc/rpc/dcerpc_lsa.c | 79 ++ source/librpc/rpc/dcerpc_ntlm.c | 197 +++++ source/librpc/rpc/dcerpc_schannel.c | 266 +++++++ source/librpc/rpc/dcerpc_smb.c | 391 ++++++++++ source/librpc/rpc/dcerpc_tcp.c | 206 +++++ source/librpc/rpc/dcerpc_util.c | 668 +++++++++++++++++ 43 files changed, 11024 insertions(+) create mode 100644 source/librpc/.cvsignore create mode 100644 source/librpc/config.m4 create mode 100644 source/librpc/idl/.cvsignore create mode 100644 source/librpc/idl/atsvc.idl create mode 100644 source/librpc/idl/browser.idl create mode 100644 source/librpc/idl/dcerpc.idl create mode 100644 source/librpc/idl/dcom.idl create mode 100644 source/librpc/idl/dfs.idl create mode 100644 source/librpc/idl/echo.idl create mode 100644 source/librpc/idl/epmapper.idl create mode 100644 source/librpc/idl/eventlog.idl create mode 100644 source/librpc/idl/idl_types.h create mode 100644 source/librpc/idl/keysvc.idl create mode 100644 source/librpc/idl/lsa.idl create mode 100644 source/librpc/idl/mgmt.idl create mode 100644 source/librpc/idl/misc.idl create mode 100644 source/librpc/idl/netlogon.idl create mode 100644 source/librpc/idl/ntsvcs.idl create mode 100644 source/librpc/idl/protected_storage.idl create mode 100644 source/librpc/idl/samr.idl create mode 100644 source/librpc/idl/scerpc.idl create mode 100644 source/librpc/idl/spoolss.idl create mode 100644 source/librpc/idl/srvsvc.idl create mode 100644 source/librpc/idl/trkwks.idl create mode 100644 source/librpc/idl/w32time.idl create mode 100644 source/librpc/idl/winreg.idl create mode 100644 source/librpc/idl/wkssvc.idl create mode 100644 source/librpc/idl/wzcsvc.idl create mode 100644 source/librpc/ndr/libndr.h create mode 100644 source/librpc/ndr/ndr.c create mode 100644 source/librpc/ndr/ndr_basic.c create mode 100644 source/librpc/ndr/ndr_sec.c create mode 100644 source/librpc/ndr/ndr_sec.h create mode 100644 source/librpc/ndr/ndr_spoolss_buf.c create mode 100644 source/librpc/rpc/dcerpc.c create mode 100644 source/librpc/rpc/dcerpc.h create mode 100644 source/librpc/rpc/dcerpc_auth.c create mode 100644 source/librpc/rpc/dcerpc_lsa.c create mode 100644 source/librpc/rpc/dcerpc_ntlm.c create mode 100644 source/librpc/rpc/dcerpc_schannel.c create mode 100644 source/librpc/rpc/dcerpc_smb.c create mode 100644 source/librpc/rpc/dcerpc_tcp.c create mode 100644 source/librpc/rpc/dcerpc_util.c (limited to 'source/librpc') diff --git a/source/librpc/.cvsignore b/source/librpc/.cvsignore new file mode 100644 index 00000000000..ca42d5444c1 --- /dev/null +++ b/source/librpc/.cvsignore @@ -0,0 +1,2 @@ +gen_ndr +gen_rpc diff --git a/source/librpc/config.m4 b/source/librpc/config.m4 new file mode 100644 index 00000000000..a4e5fa27fac --- /dev/null +++ b/source/librpc/config.m4 @@ -0,0 +1,36 @@ +dnl # LIBRPC subsystem + +SMB_SUBSYSTEM(LIBNDR_RAW,[], + [librpc/ndr/ndr.o librpc/ndr/ndr_basic.o librpc/ndr/ndr_sec.o \ + librpc/ndr/ndr_spoolss_buf.o \ + librpc/gen_ndr/tables.o librpc/gen_ndr/ndr_dcerpc.o \ + librpc/gen_ndr/ndr_echo.o librpc/gen_ndr/ndr_misc.o \ + librpc/gen_ndr/ndr_lsa.o librpc/gen_ndr/ndr_dfs.o \ + librpc/gen_ndr/ndr_samr.o librpc/gen_ndr/ndr_spoolss.o \ + librpc/gen_ndr/ndr_wkssvc.o librpc/gen_ndr/ndr_srvsvc.o \ + librpc/gen_ndr/ndr_atsvc.o librpc/gen_ndr/ndr_eventlog.o \ + librpc/gen_ndr/ndr_epmapper.o librpc/gen_ndr/ndr_winreg.o \ + librpc/gen_ndr/ndr_mgmt.o librpc/gen_ndr/ndr_protected_storage.o \ + librpc/gen_ndr/ndr_dcom.o librpc/gen_ndr/ndr_wzcsvc.o \ + librpc/gen_ndr/ndr_browser.o librpc/gen_ndr/ndr_w32time.o \ + librpc/gen_ndr/ndr_scerpc.o librpc/gen_ndr/ndr_ntsvcs.o \ + librpc/gen_ndr/ndr_netlogon.o librpc/gen_ndr/ndr_trkwks.o \ + librpc/gen_ndr/ndr_keysvc.o], + librpc/gen_ndr/libndr_raw_public_proto.h) + +SMB_SUBSYSTEM(LIBRPC_RAW,[], + [librpc/rpc/dcerpc.o librpc/rpc/dcerpc_auth.o \ + librpc/rpc/dcerpc_util.o \ + librpc/rpc/dcerpc_schannel.o librpc/rpc/dcerpc_ntlm.o \ + librpc/rpc/dcerpc_smb.o librpc/rpc/dcerpc_tcp.o], + librpc/rpc/librpc_raw_public_proto.h) + +SMB_SUBSYSTEM(LIBRPC_CLIENT,[], + [librpc/rpc/dcerpc_lsa.o], + librpc/rpc/librpc/client/public_proto.h) + +SMB_SUBSYSTEM(LIBRPC,[], + [\$(LIBNDR_RAW_OBJS) \$(LIBRPC_RAW_OBJS) \ + \$(LIBRPC_CLIENT_OBJS)], + librpc/librpc_public_proto.h) + diff --git a/source/librpc/idl/.cvsignore b/source/librpc/idl/.cvsignore new file mode 100644 index 00000000000..b8252381b81 --- /dev/null +++ b/source/librpc/idl/.cvsignore @@ -0,0 +1,2 @@ +*.pidl +*.c diff --git a/source/librpc/idl/atsvc.idl b/source/librpc/idl/atsvc.idl new file mode 100644 index 00000000000..e221875f9fb --- /dev/null +++ b/source/librpc/idl/atsvc.idl @@ -0,0 +1,67 @@ +/* + atsvc interface definition +*/ + +#include "idl_types.h" + +[ uuid(1ff70682-0a51-30e8-076d-740be8cee98b), + version(1.0), + pointer_default(unique) +] interface atsvc +{ + typedef struct { + uint32 job_time; + uint32 days_of_month; + uint8 days_of_week; + uint8 flags; + unistr *command; + } atsvc_JobInfo; + + /******************/ + /* Function: 0x00 */ + NTSTATUS atsvc_JobAdd( + [in] unistr *servername, + [in,ref] atsvc_JobInfo *job_info, + [out] uint32 job_id + ); + + /******************/ + /* Function: 0x01 */ + NTSTATUS atsvc_JobDel( + [in] unistr *servername, + [in] uint32 min_job_id, + [in] uint32 max_job_id + ); + + typedef struct { + uint32 job_id; + uint32 job_time; + uint32 days_of_month; + uint8 days_of_week; + uint8 flags; + unistr *command; + } atsvc_JobEnumInfo; + + typedef struct { + uint32 entries_read; + [size_is(entries_read)] atsvc_JobEnumInfo *first_entry; + } atsvc_enum_ctr; + + /******************/ + /* Function: 0x02 */ + NTSTATUS atsvc_JobEnum( + [in] unistr *servername, + [in,out,ref] atsvc_enum_ctr *ctr, + [in] uint32 preferred_max_len, + [out] uint32 total_entries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x03 */ + [public] NTSTATUS atsvc_JobGetInfo( + [in] unistr *servername, + [in] uint32 job_id, + [out] atsvc_JobInfo *job_info + ); +} diff --git a/source/librpc/idl/browser.idl b/source/librpc/idl/browser.idl new file mode 100644 index 00000000000..e1441c7857c --- /dev/null +++ b/source/librpc/idl/browser.idl @@ -0,0 +1,10 @@ +[ + uuid(6bffd098-a112-3610-9833-012892020162), + version(0.0) +] +interface browser +{ + /******************/ + /* Function 0x00 */ + NTSTATUS browser_Unknown0(); +} diff --git a/source/librpc/idl/dcerpc.idl b/source/librpc/idl/dcerpc.idl new file mode 100644 index 00000000000..334ae8ce5db --- /dev/null +++ b/source/librpc/idl/dcerpc.idl @@ -0,0 +1,189 @@ +#include "idl_types.h" + +/* + the base dcerpc packet definitions - not traditionally coded as IDL, + but given that pidl can handle it nicely it simplifies things a lot + to do it this way + + see http://www.opengroup.org/onlinepubs/9629399/chap12.htm for packet + layouts +*/ +[] +interface dcerpc +{ + typedef [public] struct { + GUID uuid; + uint32 if_version; + } dcerpc_syntax_id; + + typedef struct { + uint16 context_id; + uint8 num_transfer_syntaxes; + dcerpc_syntax_id abstract_syntax; + dcerpc_syntax_id transfer_syntaxes[num_transfer_syntaxes]; + } dcerpc_ctx_list; + + typedef struct { + uint16 max_xmit_frag; + uint16 max_recv_frag; + uint32 assoc_group_id; + uint8 num_contexts; + dcerpc_ctx_list ctx_list[num_contexts]; + [flag(NDR_ALIGN8)] DATA_BLOB _pad; + [flag(NDR_REMAINING)] DATA_BLOB auth_info; + } dcerpc_bind; + + + const uint8 DCERPC_REQUEST_LENGTH = 24; + const uint8 DCERPC_MAX_SIGN_SIZE = 32; + + typedef struct { + uint32 alloc_hint; + uint16 context_id; + uint16 opnum; + [flag(NDR_ALIGN8)] DATA_BLOB _pad; + [flag(NDR_REMAINING)] DATA_BLOB stub_and_verifier; + } dcerpc_request; + + const int DCERPC_BIND_PROVIDER_REJECT = 2; + const int DCERPC_BIND_REASON_ASYNTAX = 1; + + typedef struct { + uint16 result; + uint16 reason; + dcerpc_syntax_id syntax; + } dcerpc_ack_ctx; + + typedef struct { + uint16 max_xmit_frag; + uint16 max_recv_frag; + uint32 assoc_group_id; + ascstr3 secondary_address; + [flag(NDR_ALIGN4)] DATA_BLOB _pad1; + uint8 num_results; + dcerpc_ack_ctx ctx_list[num_results]; + [flag(NDR_REMAINING)] DATA_BLOB auth_info; + } dcerpc_bind_ack; + + typedef struct { + uint16 reject_reason; + uint32 num_versions; + uint32 versions[num_versions]; + } dcerpc_bind_nak; + + const uint8 DCERPC_RESPONSE_LENGTH = 24; + + typedef struct { + uint32 alloc_hint; + uint16 context_id; + uint8 cancel_count; + [flag(NDR_ALIGN8)] DATA_BLOB _pad; + [flag(NDR_REMAINING)] DATA_BLOB stub_and_verifier; + } dcerpc_response; + + + const int DCERPC_FAULT_OP_RNG_ERROR = 0x1c010002; + const int DCERPC_FAULT_NDR = 0x000006f7; + const int DCERPC_FAULT_CONTEXT_MISMATCH = 0x1c00001a; + const int DCERPC_FAULT_OTHER = 0x00000001; + + /* we return this fault when we haven't yet run the test + to see what fault w2k3 returns in this case */ + const int DCERPC_FAULT_TODO = 0x00000042; + + typedef struct { + uint32 alloc_hint; + uint16 context_id; + uint8 cancel_count; + uint32 status; + } dcerpc_fault; + + + const uint8 DCERPC_AUTH_TYPE_NONE = 0; + const uint8 DCERPC_AUTH_TYPE_KRB5 = 1; + const uint8 DCERPC_AUTH_TYPE_NTLMSSP = 10; + const uint8 DCERPC_AUTH_TYPE_SCHANNEL = 68; + + const uint8 DCERPC_AUTH_LEVEL_NONE = 1; + const uint8 DCERPC_AUTH_LEVEL_CONNECT = 2; + const uint8 DCERPC_AUTH_LEVEL_CALL = 3; + const uint8 DCERPC_AUTH_LEVEL_PACKET = 4; + const uint8 DCERPC_AUTH_LEVEL_INTEGRITY = 5; + const uint8 DCERPC_AUTH_LEVEL_PRIVACY = 6; + + typedef [public] struct { + uint8 auth_type; + uint8 auth_level; + uint8 auth_pad_length; + uint8 auth_reserved; + uint32 auth_context_id; + [flag(NDR_REMAINING)] DATA_BLOB credentials; + } dcerpc_auth; + + typedef [public] struct { + uint32 _pad; + [flag(NDR_REMAINING)] DATA_BLOB auth_info; + } dcerpc_auth3; + + typedef enum { + DCERPC_PKT_REQUEST = 0, + DCERPC_PKT_PING = 1, + DCERPC_PKT_RESPONSE = 2, + DCERPC_PKT_FAULT = 3, + DCERPC_PKT_WORKING = 4, + DCERPC_PKT_NOCALL = 5, + DCERPC_PKT_REJECT = 6, + DCERPC_PKT_ACK = 7, + DCERPC_PKT_CL_CANCEL = 8, + DCERPC_PKT_FACK = 9, + DCERPC_PKT_CANCEL_ACK = 10, + DCERPC_PKT_BIND = 11, + DCERPC_PKT_BIND_ACK = 12, + DCERPC_PKT_BIND_NAK = 13, + DCERPC_PKT_ALTER = 14, + DCERPC_PKT_ALTER_ACK = 15, + DCERPC_PKT_AUTH3 = 16, + DCERPC_PKT_SHUTDOWN = 17, + DCERPC_PKT_CO_CANCEL = 18, + DCERPC_PKT_ORPHANED = 19 + } dcerpc_pkt_type; + + typedef [nodiscriminant] union { + [case(DCERPC_PKT_REQUEST)] dcerpc_request request; + [case(DCERPC_PKT_RESPONSE)] dcerpc_response response; + [case(DCERPC_PKT_BIND)] dcerpc_bind bind; + [case(DCERPC_PKT_BIND_ACK)] dcerpc_bind_ack bind_ack; + [case(DCERPC_PKT_ALTER)] dcerpc_bind alter; + [case(DCERPC_PKT_ALTER_ACK)] dcerpc_bind_ack alter_ack; + [case(DCERPC_PKT_FAULT)] dcerpc_fault fault; + [case(DCERPC_PKT_AUTH3)] dcerpc_auth3 auth; + [case(DCERPC_PKT_BIND_NAK)] dcerpc_bind_nak bind_nak; + } dcerpc_payload; + + + /* pfc_flags values */ + const uint8 DCERPC_PFC_FLAG_FIRST = 0x01; + const uint8 DCERPC_PFC_FLAG_LAST = 0x02; + 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; + + /* little-endian flag */ + const uint8 DCERPC_DREP_LE = 0x10; + + typedef [public] struct { + uint8 rpc_vers; /* RPC version */ + uint8 rpc_vers_minor; /* Minor version */ + uint8 ptype; /* Packet type */ + uint8 pfc_flags; /* Fragmentation flags */ + uint8 drep[4]; /* NDR data representation */ + uint16 frag_length; /* Total length of fragment */ + uint16 auth_length; /* authenticator length */ + uint32 call_id; /* Call identifier */ + + [switch_is(ptype)] dcerpc_payload u; + } dcerpc_packet; +} diff --git a/source/librpc/idl/dcom.idl b/source/librpc/idl/dcom.idl new file mode 100644 index 00000000000..fc432c6aa4b --- /dev/null +++ b/source/librpc/idl/dcom.idl @@ -0,0 +1,43 @@ +/* + this is just a placeholder until we start to support DCOM calls +*/ + +[ + uuid(99fcfec4-5260-101b-bbcb-00aa0021347a), + version(0.0) +] +interface IOXIDResolver +{ + + /*****************/ + /* Function 0x00 */ + WERROR ResolveOxid(); +} + + +[ + uuid(4d9f4ab8-7d1c-11cf-861e-0020af6e7c57), + version(0.0) +] +interface IRemoteActivation +{ + + /*****************/ + /* Function 0x00 */ + NTSTATUS RemoteActivation(); +} + + + +[ + uuid(000001a0-0000-0000-c000-000000000046), + version(0.0) +] +interface ISystemActivator +{ + + /*****************/ + /* Function 0x00 */ + NTSTATUS isa_Unknown0(); + +} diff --git a/source/librpc/idl/dfs.idl b/source/librpc/idl/dfs.idl new file mode 100644 index 00000000000..16c19744746 --- /dev/null +++ b/source/librpc/idl/dfs.idl @@ -0,0 +1,174 @@ +/* + dfs interface definition +*/ + +#include "idl_types.h" + +[ uuid(4fc742e0-4a10-11cf-8273-00aa004ae673), + version(3.0), + pointer_default(unique) +] interface netdfs +{ + /******************/ + /* Function: 0x00 */ + void dfs_Exist( + [out,ref] uint32 *exist_flag + ); + + + /******************/ + /* Function: 0x01 */ + WERROR dfs_Add ( + [in,ref] unistr *path, + [in,ref] unistr *server, + [in] unistr *share, + [in] unistr *comment, + [in] uint32 flags + ); + + /******************/ + /* Function: 0x02 */ + WERROR dfs_Remove ( + [in,ref] unistr *path, + [in] unistr *server, + [in] unistr *share + ); + + /******************/ + /* Function: 0x03 */ + WERROR dfs_SetInfo (); + + /******************/ + /* Function: 0x04 */ + + typedef struct { + unistr *path; + } dfs_Info1; + + typedef struct { + unistr *path; + unistr *comment; + uint32 state; + uint32 num_stores; + } dfs_Info2; + + typedef struct { + uint32 state; + unistr *server; + unistr *share; + } dfs_StorageInfo; + + typedef struct { + unistr *path; + unistr *comment; + uint32 state; + uint32 num_stores; + [size_is(num_stores)] dfs_StorageInfo *stores; + } dfs_Info3; + + typedef struct { + unistr *path; + unistr *comment; + uint32 state; + uint32 timeout; + GUID guid; + uint32 num_stores; + [size_is(num_stores)] dfs_StorageInfo *stores; + } dfs_Info4; + + typedef struct { + unistr *comment; + } dfs_Info100; + + typedef struct { + uint32 state; + } dfs_Info101; + + typedef struct { + uint32 timeout; + } dfs_Info102; + + typedef struct { + unistr *dom_root; + } dfs_Info200; + + typedef struct { + uint32 flags; + unistr *dom_root; + } dfs_Info300; + + typedef union { + [case(1)] dfs_Info1 *info1; + [case(2)] dfs_Info2 *info2; + [case(3)] dfs_Info3 *info3; + [case(4)] dfs_Info4 *info4; + [case(100)] dfs_Info100 *info100; + [case(101)] dfs_Info101 *info101; + [case(102)] dfs_Info102 *info102; + [default] ; + } dfs_Info; + + WERROR dfs_GetInfo ( + [in,ref] unistr *path, + [in] unistr *server, + [in] unistr *share, + [in] uint32 level, + [out,switch_is(level)] dfs_Info info + ); + + /******************/ + /* Function: 0x05 */ + + typedef struct { + uint32 count; + [size_is(count)] dfs_Info1 *s; + } dfs_EnumArray1; + + typedef struct { + uint32 count; + [size_is(count)] dfs_Info2 *s; + } dfs_EnumArray2; + + typedef struct { + uint32 count; + [size_is(count)] dfs_Info3 *s; + } dfs_EnumArray3; + + typedef struct { + uint32 count; + [size_is(count)] dfs_Info4 *s; + } dfs_EnumArray4; + + typedef struct { + uint32 count; + [size_is(count)] dfs_Info200 *s; + } dfs_EnumArray200; + + typedef struct { + uint32 count; + [size_is(count)] dfs_Info300 *s; + } dfs_EnumArray300; + + + typedef union { + [case(1)] dfs_EnumArray1 *info1; + [case(2)] dfs_EnumArray2 *info2; + [case(3)] dfs_EnumArray3 *info3; + [case(4)] dfs_EnumArray4 *info4; + [case(200)] dfs_EnumArray200 *info200; + [case(300)] dfs_EnumArray300 *info300; + } dfs_EnumInfo; + + typedef struct { + uint32 level; + [switch_is(level)] dfs_EnumInfo e; + } dfs_EnumStruct; + + WERROR dfs_Enum ( + [in] uint32 level, + [in] uint32 bufsize, + [in,out] dfs_EnumStruct *info, + [in] uint32 *unknown, + [in,out] uint32 *total + ); +} diff --git a/source/librpc/idl/echo.idl b/source/librpc/idl/echo.idl new file mode 100644 index 00000000000..e62208ac98a --- /dev/null +++ b/source/librpc/idl/echo.idl @@ -0,0 +1,90 @@ +#include "idl_types.h" + + +[ + uuid(60a15ec5-4de8-11d7-a637-005056a20182), + endpoints(rpcecho, TCP-0), + version(1.0) +] +interface rpcecho +{ + /* Add one to an integer */ + void echo_AddOne( + [in,out,ref] uint32 *v + ); + /* Echo an array of bytes back at the caller */ + void echo_EchoData( + [in] uint32 len, + [in] [size_is(len)] uint8 in_data[], + [out] [size_is(len)] uint8 out_data[] + ); + /* Sink data to the server */ + void echo_SinkData( + [in] uint32 len, + [in,ref,size_is(len)] uint8 *data + ); + /* Source data from server */ + void echo_SourceData( + [in] uint32 len, + [out,ref,size_is(len)] uint8 *data + ); + + + /* test strings */ + void echo_TestCall ( + [in] unistr *s1, + [out] unistr *s2 + ); + + + /* test some alignment issues */ + typedef struct { + uint8 v; + } echo_info1; + + typedef struct { + uint16 v; + } echo_info2; + + typedef struct { + uint32 v; + } echo_info3; + + typedef struct { + HYPER_T v; + } echo_info4; + + typedef struct { + uint8 v1; + HYPER_T v2; + } echo_info5; + + typedef struct { + uint8 v1; + echo_info1 info1; + } echo_info6; + + typedef union { + [case(1)] echo_info1 info1; + } echo_XXX; + + typedef struct { + uint8 v1; + echo_info4 info4; + } echo_info7; + + typedef union { + [case(1)] echo_info1 info1; + [case(2)] echo_info2 info2; + [case(3)] echo_info3 info3; + [case(4)] echo_info4 info4; + [case(5)] echo_info5 info5; + [case(6)] echo_info6 info6; + [case(7)] echo_info7 info7; + } echo_Info; + + NTSTATUS echo_TestCall2 ( + [in] uint16 level, + [out,switch_is(level)] echo_Info *info + ); +} diff --git a/source/librpc/idl/epmapper.idl b/source/librpc/idl/epmapper.idl new file mode 100644 index 00000000000..5db65cd7cf0 --- /dev/null +++ b/source/librpc/idl/epmapper.idl @@ -0,0 +1,168 @@ +#include "idl_types.h" + +/* + endpoint mapper interface +*/ + +[ + uuid(e1af8308-5d1f-11c9-91a4-08002b14a0fa), + version(3.0), + endpoints(epmapper, TCP-135), + pointer_default(unique) +] +interface epmapper +{ + + /* + note that the following IDL won't work in MIDL, and in fact + that the full towers/floors representation of epm cannot be + represented in MIDL at all. I decided to represent it using + the extended IDL syntax in pidl to make it easier to work + with. + */ + + const int EPMAPPER_STATUS_NO_MORE_ENTRIES = 0x16c9a0d6; + + + /* this guid indicates NDR encoding in a protocol tower */ + const string NDR_GUID = "8a885d04-1ceb-11c9-9fe8-08002b104860"; + const string NDR_GUID_VERSION = 2; + + const uint32 EPMAPPER_PORT = 135; + + typedef struct { + GUID uuid; + uint16 version; + } epm_prot_uuid; + + typedef enum { + EPM_PROTOCOL_TCP = 0x07, + EPM_PROTOCOL_IP = 0x09, + EPM_PROTOCOL_PIPE = 0x10, + EPM_PROTOCOL_NETBIOS = 0x11, + EPM_PROTOCOL_RPC_C = 0x0b, + EPM_PROTOCOL_UUID = 0x0d, + EPM_PROTOCOL_SMB = 0x0f, + EPM_PROTOCOL_HTTP = 0x1f + } epm_protocols; + + typedef [nodiscriminant] union { + [case(13)] epm_prot_uuid uuid; + [default] [flag(NDR_REMAINING)] DATA_BLOB lhs_data; + } epm_protocol_info; + + typedef struct { + uint8 protocol; + [switch_is(protocol)] epm_protocol_info info; + } epm_lhs; + + typedef struct { + [flag(NDR_REMAINING)] DATA_BLOB rhs_data; + } epm_rhs; + + typedef struct { + [subcontext(2)] epm_lhs lhs; + [subcontext(2)] epm_rhs rhs; + } epm_floor; + + /* note that the NDR_NOALIGN flag is inherited by all nested + structures. All of the towers/floors stuff is + non-aligned. I wonder what sort of wicked substance these + guys were smoking? + */ + typedef [flag(NDR_NOALIGN|NDR_LITTLE_ENDIAN)] struct { + uint16 num_floors; + epm_floor floors[num_floors]; + } epm_towers; + + typedef struct { + [value(ndr_size_epm_towers(&r->towers))] uint32 tower_length; + [subcontext(4)] epm_towers towers; + } epm_twr_t; + + typedef struct { + GUID object; + epm_twr_t *tower; + ascstr2 annotation; + } epm_entry_t; + + typedef struct { + GUID uuid; + uint16 vers_major; + uint16 vers_minor; + } rpc_if_id_t; + + /**********************/ + /* Function 0x0 */ + void epm_Insert( + [in] uint32 num_ents, + [in,size_is(num_ents)] epm_entry_t entries[], + [in] uint32 replace, + [out] error_status_t status + ); + + /**********************/ + /* Function 0x1 */ + void epm_Delete( + [in] uint32 num_ents, + [in, size_is(num_ents)] epm_entry_t entries[], + [out] error_status_t status + ); + + /**********************/ + /* Function 0x02 */ + void epm_Lookup( + [in] uint32 inquiry_type, + [in] GUID *object, + [in] rpc_if_id_t *interface_id, + [in] uint32 vers_option, + [in,out,ref] policy_handle *entry_handle, + [in] uint32 max_ents, + [out] uint32 num_ents, + [out, length_is(num_ents), size_is(max_ents)] epm_entry_t entries[], + [out] error_status_t status + ); + + + /**********************/ + /* Function 0x03 */ + + typedef struct { + epm_twr_t *twr; + } epm_twr_p_t; + + void epm_Map( + [in] GUID *object, + [in] epm_twr_t *map_tower, + [in,out,ref] policy_handle *entry_handle, + [in] uint32 max_towers, + [out] uint32 num_towers, + [out, length_is(num_towers), size_is(max_towers)] epm_twr_p_t towers[], + [out] error_status_t status + ); + + + /**********************/ + /* Function 0x04 */ + void epm_LookupHandleFree( + [in,out,ref] policy_handle *entry_handle, + [out] error_status_t status + ); + + /**********************/ + /* Function 0x05 */ + void epm_InqObject( + [out] GUID *epm_object, + [out] error_status_t status + ); + + + /**********************/ + /* Function 0x05 */ + void epm_MgmtDelete( + [in] uint32 object_speced, + [in] GUID *object, + [in] epm_twr_t *tower, + [out] error_status_t status + ); +} diff --git a/source/librpc/idl/eventlog.idl b/source/librpc/idl/eventlog.idl new file mode 100644 index 00000000000..ee5bd8bba81 --- /dev/null +++ b/source/librpc/idl/eventlog.idl @@ -0,0 +1,48 @@ +#include "idl_types.h" + +/* + eventlog interface definition +*/ +[ uuid(82273fdc-e32a-18c3-3f78-827929dc23ea), + version(0.0), + pointer_default(unique) +] interface eventlog +{ + typedef struct { + uint16 unknown0; + uint16 unknown1; + } eventlog_OpenUnknown0; + + typedef struct { + [value(2*strlen_m(r->name))] uint16 name_len; + [value(r->name_len)] uint16 name_size; + unistr_noterm *name; + } eventlog_String; + + /******************/ + /* Function: 0x00 */ + NTSTATUS eventlog_OpenEventLog( + [in] eventlog_OpenUnknown0 *unknown0, + [in] eventlog_String source, + [in] eventlog_String unknown1, + [in] uint32 unknown2, + [in] uint32 unknown3, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x01 */ + NTSTATUS eventlog_GetNumRecords( + ); + + /******************/ + /* Function: 0x02 */ + NTSTATUS eventlog_ReadEventLog( + ); + + /******************/ + /* Function: 0x03 */ + NTSTATUS eventlog_CloseEventLog( + [in,out,ref] policy_handle *handle + ); +} diff --git a/source/librpc/idl/idl_types.h b/source/librpc/idl/idl_types.h new file mode 100644 index 00000000000..434dfb8c649 --- /dev/null +++ b/source/librpc/idl/idl_types.h @@ -0,0 +1,72 @@ +#define STR_ASCII LIBNDR_FLAG_STR_ASCII +#define STR_LEN4 LIBNDR_FLAG_STR_LEN4 +#define STR_SIZE4 LIBNDR_FLAG_STR_SIZE4 +#define STR_SIZE2 LIBNDR_FLAG_STR_SIZE2 +#define STR_NOTERM LIBNDR_FLAG_STR_NOTERM +#define STR_NULLTERM LIBNDR_FLAG_STR_NULLTERM + +/* + a UCS2 string prefixed with [size] [offset] [length], all 32 bits + not null terminated +*/ +#define unistr_noterm [flag(STR_NOTERM|STR_SIZE4|STR_LEN4)] string + +/* + a UCS2 string prefixed with [size] [offset] [length], all 32 bits +*/ +#define unistr [flag(STR_SIZE4|STR_LEN4)] string + +/* + a UCS2 string prefixed with [size], 32 bits +*/ +#define lstring [flag(STR_SIZE4)] string + +/* + a null terminated UCS2 string +*/ +#define nstring [flag(STR_NULLTERM)] string + +/* + an ascii string prefixed with [size] [offset] [length], all 32 bits + null terminated +*/ +#define ascstr [flag(STR_ASCII|STR_SIZE4|STR_LEN4)] string + +/* + an ascii string prefixed with [offset] [length], both 32 bits + null terminated +*/ +#define ascstr2 [flag(STR_ASCII|STR_LEN4)] string + +/* + an ascii string prefixed with [size], 16 bits + null terminated +*/ +#define ascstr3 [flag(STR_ASCII|STR_SIZE2)] string + + +#define NDR_NOALIGN LIBNDR_FLAG_NOALIGN +#define NDR_REMAINING LIBNDR_FLAG_REMAINING +#define NDR_ALIGN2 LIBNDR_FLAG_ALIGN2 +#define NDR_ALIGN4 LIBNDR_FLAG_ALIGN4 +#define NDR_ALIGN8 LIBNDR_FLAG_ALIGN8 + +/* this flag is used to force a section of IDL as little endian. It is + needed for the epmapper IDL, which is defined as always being LE */ +#define NDR_LITTLE_ENDIAN LIBNDR_FLAG_LITTLE_ENDIAN + + +/* + these are used by the epmapper and mgmt interfaces +*/ +#define error_status_t uint32 +#define boolean32 uint32 +#define unsigned32 uint32 + +/* + this is used to control formatting of uint8 arrays +*/ +#define NDR_PAHEX LIBNDR_PRINT_ARRAY_HEX + + +#define bool8 uint8 diff --git a/source/librpc/idl/keysvc.idl b/source/librpc/idl/keysvc.idl new file mode 100644 index 00000000000..396e0fedaf9 --- /dev/null +++ b/source/librpc/idl/keysvc.idl @@ -0,0 +1,15 @@ +/* + cryptographic key services interface +*/ + +[ + uuid(8d0ffe72-d252-11d0-bf8f-00c04fd9126b), + version(1.0) +] +interface keysvc +{ + + /*****************/ + /* Function 0x00 */ + WERROR keysvc_Unknown0(); +} diff --git a/source/librpc/idl/lsa.idl b/source/librpc/idl/lsa.idl new file mode 100644 index 00000000000..d8c6389bb3e --- /dev/null +++ b/source/librpc/idl/lsa.idl @@ -0,0 +1,500 @@ +#include "idl_types.h" + +/* + lsa interface definition +*/ + +[ uuid(12345778-1234-abcd-ef00-0123456789ab), + version(0.0), + endpoints(lsarpc,lsass), + pointer_default(unique) +] interface lsarpc +{ + /******************/ + /* Function: 0x00 */ + NTSTATUS lsa_Close ( + [in,out,ref] policy_handle *handle + ); + + + /******************/ + /* Function: 0x01 */ + NTSTATUS lsa_Delete ( + [in,ref] policy_handle *handle + ); + + + /******************/ + /* Function: 0x02 */ + + typedef struct { + [value(2*strlen_m(r->name))] uint16 name_len; + [value(r->name_len)] uint16 name_size; + unistr_noterm *name; + } lsa_Name; + + typedef struct { + lsa_Name name; + uint32 luid_low; + uint32 luid_high; + } lsa_PrivEntry; + + typedef struct { + uint32 count; + [size_is(count)] lsa_PrivEntry *privs; + } lsa_PrivArray; + + NTSTATUS lsa_EnumPrivs ( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 max_count, + [out,ref] lsa_PrivArray *privs + ); + + /******************/ + /* Function: 0x03 */ + + typedef [public] struct { + uint32 size; + [subcontext(4)] security_descriptor *sd; + } sec_desc_buf; + + NTSTATUS lsa_QuerySecObj ( + [in,ref] policy_handle *handle, + [in] uint32 sec_info, + [out] sec_desc_buf *sd + ); + + + /******************/ + /* Function: 0x04 */ + NTSTATUS lsa_SetSecObj (); + + + /******************/ + /* Function: 0x05 */ + NTSTATUS lsa_ChangePassword (); + + + /******************/ + /* Function: 0x06 */ + typedef struct { + uint32 len; /* ignored */ + uint16 impersonation_level; + uint8 context_mode; + uint8 effective_only; + } lsa_QosInfo; + + typedef struct { + uint32 len; /* ignored */ + uint8 *root_dir; + unistr *object_name; + uint32 attributes; + security_descriptor *sec_desc; + lsa_QosInfo *sec_qos; + } lsa_ObjectAttribute; + + /* notice the screwup with the system_name - thats why MS created + OpenPolicy2 */ + NTSTATUS lsa_OpenPolicy ( + [in] uint16 *system_name, + [in,ref] lsa_ObjectAttribute *attr, + [in] uint32 desired_access, + [out,ref] policy_handle *handle + ); + + + + /******************/ + /* Function: 0x07 */ + + typedef struct { + uint32 percent_full; + uint32 log_size; + NTTIME retention_time; + uint8 shutdown_in_progress; + NTTIME time_to_shutdown; + uint32 next_audit_record; + uint32 unknown; + } lsa_AuditLogInfo; + + typedef struct { + uint32 auditing_mode; + [size_is(count)] uint32 *settings; + uint32 count; + } lsa_AuditEventsInfo; + + typedef struct { + lsa_Name name; + dom_sid2 *sid; + } lsa_DomainInfo; + + typedef struct { + lsa_Name name; + } lsa_PDAccountInfo; + + typedef struct { + uint16 unknown; /* an midl padding bug? */ + uint16 role; + } lsa_ServerRole; + + typedef struct { + lsa_Name source; + lsa_Name account; + } lsa_ReplicaSourceInfo; + + typedef struct { + uint32 paged_pool; + uint32 non_paged_pool; + uint32 min_wss; + uint32 max_wss; + uint32 pagefile; + HYPER_T unknown; + } lsa_DefaultQuotaInfo; + + typedef struct { + HYPER_T modified_id; + NTTIME db_create_time; + } lsa_ModificationInfo; + + typedef struct { + uint8 shutdown_on_full; + } lsa_AuditFullSetInfo; + + typedef struct { + uint16 unknown; /* an midl padding bug? */ + uint8 shutdown_on_full; + uint8 log_is_full; + } lsa_AuditFullQueryInfo; + + typedef struct { + lsa_Name name; + lsa_Name dns_domain; + lsa_Name dns_forest; + GUID domain_guid; + dom_sid2 *sid; + } lsa_DnsDomainInfo; + + typedef enum { + LSA_POLICY_INFO_AUDIT_LOG=1, + LSA_POLICY_INFO_AUDIT_EVENTS=2, + LSA_POLICY_INFO_DOMAIN=3, + LSA_POLICY_INFO_PD=4, + LSA_POLICY_INFO_ACCOUNT_DOMAIN=5, + LSA_POLICY_INFO_ROLE=6, + LSA_POLICY_INFO_REPLICA=7, + LSA_POLICY_INFO_QUOTA=8, + LSA_POLICY_INFO_DB=9, + LSA_POLICY_INFO_AUDIT_FULL_SET=10, + LSA_POLICY_INFO_AUDIT_FULL_QUERY=11, + LSA_POLICY_INFO_DNS=12 + } lsaPolicyInfo; + + typedef union { + [case(1)] lsa_AuditLogInfo audit_log; + [case(2)] lsa_AuditEventsInfo audit_events; + [case(3)] lsa_DomainInfo domain; + [case(4)] lsa_PDAccountInfo pd; + [case(5)] lsa_DomainInfo account_domain; + [case(6)] lsa_ServerRole role; + [case(7)] lsa_ReplicaSourceInfo replica; + [case(8)] lsa_DefaultQuotaInfo quota; + [case(9)] lsa_ModificationInfo db; + [case(10)] lsa_AuditFullSetInfo auditfullset; + [case(11)] lsa_AuditFullQueryInfo auditfullquery; + [case(12)] lsa_DnsDomainInfo dns; + } lsa_PolicyInformation; + + NTSTATUS lsa_QueryInfoPolicy ( + [in,ref] policy_handle *handle, + [in] uint16 level, + [out,switch_is(level)] lsa_PolicyInformation *info + ); + + /******************/ + /* Function: 0x08 */ + NTSTATUS lsa_SetInfoPolicy (); + + /******************/ + /* Function: 0x09 */ + NTSTATUS lsa_ClearAuditLog (); + + /******************/ + /* Function: 0x0a */ + NTSTATUS lsa_CreateAccount ( + [in,ref] policy_handle *handle, + [in,ref] dom_sid2 *sid, + [in] uint32 desired_access, + [out,ref] policy_handle *acct_handle + ); + + /******************/ + /* Function: 0x0b */ + typedef struct { + dom_sid2 *sid; + } lsa_SidPtr; + + typedef [public] struct { + uint32 num_sids; + [size_is(num_sids)] lsa_SidPtr *sids; + } lsa_SidArray; + + NTSTATUS lsa_EnumAccounts ( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 num_entries, + [out,ref] lsa_SidArray *sids + ); + + + /*************************************************/ + /* Function: 0x0c */ + + typedef struct { + lsa_Name name; + dom_sid2 *sid; + } lsa_TrustInformation; + + NTSTATUS lsa_CreateTrustedDomain( + [in,ref] policy_handle *handle, + [in,ref] lsa_TrustInformation *info, + [in] uint32 desired_access, + [out,ref] policy_handle *dom_handle + ); + + + /******************/ + /* Function: 0x0d */ + + typedef struct { + lsa_Name name; + dom_sid2 *sid; + } lsa_DomainInformation; + + typedef struct { + uint32 count; + [size_is(count)] lsa_DomainInformation *domains; + } lsa_DomainList; + + NTSTATUS lsa_EnumTrustDom ( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 num_entries, + [out,ref] lsa_DomainList *domains + ); + + + /******************/ + /* Function: 0x0e */ + + typedef struct { + uint16 sid_type; + uint32 rid; + uint32 sid_index; + } lsa_TranslatedSid; + + typedef struct { + uint32 count; + [size_is(count)] lsa_TranslatedSid *sids; + } lsa_TransSidArray; + + typedef struct { + uint32 count; + [size_is(count)] lsa_TrustInformation *domains; + uint32 max_count; + } lsa_RefDomainList; + + NTSTATUS lsa_LookupNames ( + [in,ref] policy_handle *handle, + [in] uint32 num_names, + [in,ref,size_is(num_names)] lsa_Name *names, + [out] lsa_RefDomainList *domains, + [in,out,ref] lsa_TransSidArray *sids, + [in] uint16 level, + [in,out,ref] uint32 *count + ); + + + /******************/ + /* Function: 0x0f */ + + typedef struct { + uint16 sid_type; + lsa_Name name; + uint32 sid_index; + } lsa_TranslatedName; + + typedef struct { + uint32 count; + [size_is(count)] lsa_TranslatedName *names; + } lsa_TransNameArray; + + NTSTATUS lsa_LookupSids ( + [in,ref] policy_handle *handle, + [in,ref] lsa_SidArray *sids, + [out] lsa_RefDomainList *domains, + [in,out,ref] lsa_TransNameArray *names, + [in] uint16 level, + [in,out,ref] uint32 *count + ); + + + /* Function: 0x10 */ + NTSTATUS lsa_CreateSecret( + [in,ref] policy_handle *handle, + [in] lsa_Name name, + [in] uint32 desired_access, + [out,ref] policy_handle *sec_handle + ); + + + /*****************************************/ + /* Function: 0x11 */ + NTSTATUS lsa_OpenAccount ( + [in,ref] policy_handle *handle, + [in,ref] dom_sid2 *sid, + [in] uint32 desired_access, + [out,ref] policy_handle *acct_handle + ); + + + /****************************************/ + /* Function: 0x12 */ + + typedef struct { + uint32 low; + uint32 high; + } lsa_LUID; + + typedef struct { + lsa_LUID luid; + uint32 attribute; + } lsa_LUIDAttribute; + + typedef struct { + uint32 count; + uint32 unknown; + [size_is(count)] lsa_LUIDAttribute set[*]; + } lsa_PrivilegeSet; + + NTSTATUS lsa_EnumPrivsAccount ( + [in,ref] policy_handle *handle, + [out] lsa_PrivilegeSet *privs + ); + + + /* Function: 0x13 */ + NTSTATUS ADDPRIVS (); + /* Function: 0x14 */ + NTSTATUS REMOVEPRIVS (); + /* Function: 0x15 */ + NTSTATUS GETQUOTAS (); + /* Function: 0x16 */ + NTSTATUS SETQUOTAS (); + /* Function: 0x17 */ + NTSTATUS GETSYSTEMACCOUNT (); + /* Function: 0x18 */ + NTSTATUS SETSYSTEMACCOUNT (); + /* Function: 0x19 */ + NTSTATUS OPENTRUSTDOM (); + /* Function: 0x1a */ + NTSTATUS QUERYTRUSTDOM (); + /* Function: 0x1b */ + NTSTATUS SETINFOTRUSTDOM (); + + /* Function: 0x1c */ + NTSTATUS lsa_OpenSecret( + [in,ref] policy_handle *handle, + [in] lsa_Name name, + [in] uint32 desired_access, + [out,ref] policy_handle *sec_handle + ); + + /* Function: 0x1d */ + NTSTATUS SETSECRET (); + /* Function: 0x1e */ + NTSTATUS QUERYSECRET (); + + /* Function: 0x1f */ + NTSTATUS LOOKUPPRIVVALUE (); + + + /* Function: 0x20 */ + NTSTATUS lsa_LookupPrivName ( + [in,ref] policy_handle *handle, + [in,ref] lsa_LUID *luid, + [out] lsa_Name *name + ); + + + /* Function: 0x21 */ + NTSTATUS PRIV_GET_DISPNAME (); + /* Function: 0x22 */ + NTSTATUS DELETEOBJECT (); + /* Function: 0x23 */ + NTSTATUS ENUMACCTWITHRIGHT (); + + /* Function: 0x24 */ + typedef struct { + unistr *name; + } lsa_RightAttribute; + + typedef struct { + uint32 count; + [size_is(count)] lsa_Name *names; + } lsa_RightSet; + + NTSTATUS lsa_EnumAccountRights ( + [in,ref] policy_handle *handle, + [in,ref] dom_sid2 *sid, + [out,ref] lsa_RightSet *rights + ); + + + /* Function: 0x25 */ + NTSTATUS ADDACCTRIGHTS (); + /* Function: 0x26 */ + NTSTATUS REMOVEACCTRIGHTS (); + /* Function: 0x27 */ + NTSTATUS QUERYTRUSTDOMINFO (); + /* Function: 0x28 */ + NTSTATUS SETTRUSTDOMINFO (); + /* Function: 0x29 */ + NTSTATUS DELETETRUSTDOM (); + /* Function: 0x2a */ + NTSTATUS STOREPRIVDATA (); + /* Function: 0x2b */ + NTSTATUS RETRPRIVDATA (); + + + /**********************/ + /* Function: 0x2c */ + NTSTATUS lsa_OpenPolicy2 ( + [in] unistr *system_name, + [in,ref] lsa_ObjectAttribute *attr, + [in] uint32 desired_access, + [out,ref] policy_handle *handle + ); + + + /* Function: 0x2d */ + NTSTATUS UNK_GET_CONNUSER (); + /* Function: 0x2e */ + NTSTATUS QUERYINFO2 (); +} + + +[ + uuid(3919286a-b10c-11d0-9ba8-00c04fd92ef5), + version(0.0), + endpoints(lsarpc,lsass), + pointer_default(unique) +] +interface lsads +{ + + /*****************/ + /* Function 0x00 */ + void lsads_Unknown0(); + +} diff --git a/source/librpc/idl/mgmt.idl b/source/librpc/idl/mgmt.idl new file mode 100644 index 00000000000..7e691d3c31b --- /dev/null +++ b/source/librpc/idl/mgmt.idl @@ -0,0 +1,74 @@ +#include "idl_types.h" + +/* + dcerpc remote management interface +*/ + + +[ + uuid(afa8bd80-7d8a-11c9-bef4-08002b102989), + version(1) +] +interface mgmt +{ + typedef struct { + dcerpc_syntax_id *id; + } dcerpc_syntax_id_p; + + typedef struct { + unsigned32 count; + [size_is(count)] dcerpc_syntax_id_p if_id[*]; + } rpc_if_id_vector_t; + + + /***********************/ + /* Function 0x00 */ + WERROR mgmt_inq_if_ids ( + [out] rpc_if_id_vector_t *if_id_vector + ); + + + + /***********************/ + /* Function 0x01 */ + + + /* these are the array indexes in the statistics array */ + const int MGMT_STATS_CALLS_IN = 0; + const int MGMT_STATS_CALLS_OUT = 1; + const int MGMT_STATS_PKTS_IN = 2; + const int MGMT_STATS_PKTS_OUT = 3; + const int MGMT_STATS_ARRAY_MAX_SIZE = 4; + + typedef struct { + uint32 count; + [size_is(count)] uint32 statistics[*]; + } mgmt_statistics; + + WERROR mgmt_inq_stats ( + [in] uint32 max_count, + [in] uint32 unknown, + [out] mgmt_statistics statistics + ); + + + /***********************/ + /* Function 0x02 */ + boolean32 mgmt_is_server_listening ( + [out] error_status_t status + ); + + + /***********************/ + /* Function 0x03 */ + WERROR mgmt_stop_server_listening (); + + + /***********************/ + /* Function 0x04 */ + WERROR mgmt_inq_princ_name ( + [in] uint32 authn_proto, + [in] uint32 princ_name_size, + [out] ascstr princ_name + ); +} diff --git a/source/librpc/idl/misc.idl b/source/librpc/idl/misc.idl new file mode 100644 index 00000000000..fca8fe876e2 --- /dev/null +++ b/source/librpc/idl/misc.idl @@ -0,0 +1,79 @@ +#include "idl_types.h" + +/* + miscellaneous IDL structures +*/ + +[] +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 { + uint8 sid_rev_num; /**< SID revision number */ + uint8 num_auths; /**< Number of sub-authorities */ + uint8 id_auth[6]; /**< Identifier Authority */ + uint32 sub_auths[num_auths]; + } dom_sid; + + typedef [public] struct { + uint8 type; /* xxxx_xxxx_ACE_TYPE - e.g allowed / denied etc */ + uint8 flags; /* xxxx_INHERIT_xxxx - e.g OBJECT_INHERIT_ACE */ + [value(ndr_size_security_ace(r))] uint16 size; + uint32 access_mask; + +#if 0 + /* the 'obj' part is present when type is XXXX_TYPE_XXXX_OBJECT */ + struct { + uint32 flags; + GUID object_guid; + GUID inherit_guid; + } *obj; +#endif + + dom_sid trustee; + } security_ace; + + typedef [public] struct { + uint16 revision; + [value(ndr_size_security_acl(r))] uint16 size; + uint32 num_aces; + security_ace aces[num_aces]; + } security_acl; + + + typedef [public] struct { + uint8 revision; + uint16 type; /* SEC_DESC_xxxx flags */ + [relative] dom_sid *owner_sid; + [relative] dom_sid *group_sid; + [relative] security_acl *sacl; /* system ACL */ + [relative] security_acl *dacl; /* user (discretionary) ACL */ + } security_descriptor; + + typedef [public] struct { + uint32 handle_type; + GUID uuid; + } policy_handle; + + /* a 4 byte aligned 64-bit integer */ + typedef [public] struct { + uint32 low; + uint32 high; + } ULONG8; + + /* this is also used in samr and netlogon */ + typedef [public, flag(NDR_PAHEX)] struct { + uint16 units_per_week; + [size_is(1260), length_is(units_per_week/8)] uint8 *bitmap; + } samr_LogonHours; +} diff --git a/source/librpc/idl/netlogon.idl b/source/librpc/idl/netlogon.idl new file mode 100644 index 00000000000..5b2d2aa1d34 --- /dev/null +++ b/source/librpc/idl/netlogon.idl @@ -0,0 +1,796 @@ +/* + netlogon interface + much of this was derived from the ethereal sources - thanks to everyone + who contributed! +*/ + +#include "idl_types.h" + +[ + uuid(12345678-1234-abcd-ef00-01234567cffb), + version(1.0), + pointer_default(unique) +] + +interface netlogon +{ + + /*****************/ + /* Function 0x00 */ + + typedef struct { + unistr *account_name; + uint32 priv; + uint32 auth_flags; + uint32 logon_count; + uint32 bad_pw_count; + time_t last_logon; + time_t last_logoff; + time_t logoff_time; + time_t kickoff_time; + uint32 password_age; + time_t pw_can_change; + time_t pw_must_change; + unistr *computer; + unistr *domain; + unistr *script_path; + uint32 unknown; + } netr_UasInfo; + + WERROR netr_LogonUasLogon( + [in] unistr *server_name, + [in] unistr username, + [in] unistr workstation, + [out] netr_UasInfo *info + ); + + + /*****************/ + /* Function 0x01 */ + + typedef struct { + uint32 duration; + uint16 logon_count; + } netr_UasLogoffInfo; + + WERROR netr_LogonUasLogoff( + [in] unistr *server_name, + [in] unistr username, + [in] unistr workstation, + [out] netr_UasLogoffInfo info + ); + + + /*****************/ + /* Function 0x02 */ + + typedef [flag(NDR_PAHEX)] struct { + uint8 data[8]; + } netr_Credential; + + typedef [flag(NDR_PAHEX)] struct { + uint8 session_key[8]; + uint32 sequence; + netr_Credential seed; + netr_Credential client; + netr_Credential server; + } netr_CredentialState; + + typedef struct { + [value(strlen_m(r->string)*2)] uint16 size; + [value(r->size)] uint16 length; + unistr_noterm *string; + } netr_String; + + typedef struct { + netr_String domain_name; + uint32 parameter_control; + uint32 logon_id_low; + uint32 logon_id_high; + netr_String username; + netr_String workstation; + } netr_IdentityInfo; + + typedef [flag(NDR_PAHEX)] struct { + uint8 data[16]; + } netr_Password; + + typedef struct { + netr_IdentityInfo identity_info; + netr_Password lmpassword; + netr_Password ntpassword; + } netr_PasswordInfo; + + typedef [flag(NDR_PAHEX)] struct { + uint16 length; + [value(r->length)] uint16 size; + [size_is(size),length_is(length)] uint8 *data; + } netr_ChallengeResponse; + + typedef [flag(NDR_PAHEX)] struct { + netr_IdentityInfo logon_info; + uint8 challenge[8]; + netr_ChallengeResponse nt; + netr_ChallengeResponse lm; + } netr_NetworkInfo; + + typedef union { + [case(1)] netr_PasswordInfo *interactive; + [case(2)] netr_NetworkInfo *network; + [case(3)] netr_PasswordInfo *service; + } netr_LogonLevel; + + typedef struct { + netr_Credential cred; + time_t timestamp; + } netr_Authenticator; + + typedef struct { + uint32 user_id; + uint32 attributes; + } netr_GroupMembership; + + typedef [flag(NDR_PAHEX)] struct { + uint8 user_session_key[16]; + } netr_UserSessionKey; + + typedef struct { + NTTIME logon_time; + NTTIME logoff_time; + NTTIME kickoff_time; + NTTIME passwd_last_set; + NTTIME passwd_can_change; + NTTIME passwd_must_change; + netr_String account_name; + netr_String full_name; + netr_String logon_script; + netr_String profile_path; + netr_String home_dir; + netr_String home_drive; + uint16 logon_count; + uint16 bad_passwd_count; + uint32 userid; + uint32 primary_group; + uint32 group_count; + [size_is(group_count)] netr_GroupMembership *groupids; + uint32 user_flags; + netr_UserSessionKey key; + netr_String logon_server; + netr_String domain; + dom_sid2 *domain_sid; + uint32 expansionroom[10]; + } netr_SamInfo; + + typedef struct { + dom_sid2 *sid; + uint32 attribute; + } netr_SidAttr; + + typedef struct { + NTTIME logon_time; + NTTIME logoff_time; + NTTIME kickoff_time; + NTTIME passwd_last_set; + NTTIME passwd_can_change; + NTTIME passwd_must_change; + netr_String account_name; + netr_String full_name; + netr_String logon_script; + netr_String profile_path; + netr_String home_dir; + netr_String home_drive; + uint16 logon_count; + uint16 bad_passwd_count; + uint32 userid; + uint32 primary_group; + uint32 group_count; + [size_is(group_count)] netr_GroupMembership *groupids; + uint32 user_flags; + netr_UserSessionKey key; + netr_String logon_server; + netr_String domain; + dom_sid2 *domain_sid; + uint32 expansionroom[10]; + uint32 sidcount; + [size_is(sidcount)] netr_SidAttr *sids; + } netr_SamInfo2; + + typedef struct { + uint32 pac_size; + [size_is(pac_size)] uint8 *pac; + netr_String logon_domain; + netr_String logon_server; + netr_String principal_name; + uint32 auth_size; + [size_is(auth_size)] uint8 *auth; + netr_UserSessionKey user_session_key; + uint32 expansionroom[10]; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + } netr_PacInfo; + + typedef union { + [case(2)] netr_SamInfo *sam; + [case(3)] netr_SamInfo2 *sam2; + [case(4)] netr_PacInfo *pac; + [case(5)] netr_PacInfo *pac2; + } netr_Validation; + + NTSTATUS netr_LogonSamLogon( + [in] unistr *server_name, + [in] unistr *workstation, + [in] netr_Authenticator *credential, + [in][out] netr_Authenticator *authenticator, + [in] uint16 logon_level, + [in] [switch_is(logon_level)] netr_LogonLevel logon, + [in] uint16 validation_level, + [out] [switch_is(validation_level)] netr_Validation validation, + [out] uint32 authoritative + ); + + + /*****************/ + /* Function 0x03 */ + + NTSTATUS netr_LogonSamLogoff( + [in] unistr *server_name, + [in] unistr *computer_name, + [in] netr_Authenticator *credential, + [in][out] netr_Authenticator *return_authenticator, + [in] uint16 logon_level, + [in] [switch_is(logon_level)] netr_LogonLevel logon + ); + + + + /*****************/ + /* Function 0x04 */ + + NTSTATUS netr_ServerReqChallenge( + [in] unistr *server_name, + [in] unistr computer_name, + [in][out] netr_Credential credentials + ); + + + /*****************/ + /* Function 0x05 */ + + /* secure channel types */ + const int SEC_CHAN_WKSTA = 2; + const int SEC_CHAN_DOMAIN = 4; + const int SEC_CHAN_BDC = 6; + + NTSTATUS netr_ServerAuthenticate( + [in] unistr *server_name, + [in] unistr username, + [in] uint16 secure_channel_type, + [in] unistr computer_name, + [in,out] netr_Credential credentials + ); + + + /*****************/ + /* Function 0x06 */ + + NTSTATUS netr_ServerPasswordSet( + [in] unistr *server_name, + [in] unistr username, + [in] uint16 secure_channel_type, + [in] unistr computer_name, + [in] netr_Authenticator credential, + [in] netr_Password new_password, + [out] netr_Authenticator return_authenticator + ); + + + /*****************/ + /* Function 0x07 */ + + typedef struct { + unistr *username; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_DELETE_USER; + + typedef struct { + bool8 SensitiveDataFlag; + uint32 DataLength; + [size_is(DataLength)] uint8 *SensitiveData; + } netr_USER_PRIVATE_INFO; + + typedef struct { + netr_String account_name; + netr_String full_name; + uint32 rid; + uint32 primary_group; + netr_String home_dir; + netr_String home_drive; + netr_String logon_script; + netr_String description; + netr_String workstations; + NTTIME LastLogon; + NTTIME LastLogoff; + samr_LogonHours logon_hours; + uint16 bad_pw_count; + uint16 logon_count; + NTTIME PwLastSet; + NTTIME AccountExpires; + uint32 AccountControl; + netr_Password lmpw; + netr_Password ntpw; + bool8 NTPwPresent; + bool8 LMPwPresent; + bool8 PwExpired; + netr_String UserComment; + netr_String Parameters; + uint16 CountryCode; + uint16 CodePage; + netr_USER_PRIVATE_INFO user_private_info; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String profile_path; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_USER; + + typedef struct { + netr_String DomainName; + netr_String OEMInfo; + NTTIME forcedlogoff; + uint16 minpasswdlen; + uint16 passwdhistorylen; + ULONG8 pwd_must_change_time; + ULONG8 pwd_can_change_time; + ULONG8 sequence_num; + NTTIME domain_create_time; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_DOMAIN; + + typedef struct { + netr_String groupname; + netr_GroupMembership group_membership; + netr_String comment; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_GROUP; + + typedef struct { + netr_String OldName; + netr_String NewName; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_RENAME; + + typedef struct { + [size_is(num_rids)] uint32 *rids; + [size_is(num_rids)] uint32 *attribs; + uint32 num_rids; + uint32 unknown1; + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + } netr_DELTA_GROUP_MEMBER; + + typedef struct { + netr_String alias_name; + uint32 rid; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_ALIAS; + + typedef struct { + lsa_SidArray sids; + uint32 unknown1; + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + } netr_DELTA_ALIAS_MEMBER; + + typedef struct { + uint32 pagedpoollimit; + uint32 nonpagedpoollimit; + uint32 minimumworkingsetsize; + uint32 maximumworkingsetsize; + uint32 pagefilelimit; + NTTIME timelimit; + } netr_QUOTA_LIMITS; + + typedef struct { + uint32 maxlogsize; + NTTIME auditretentionperiod; + bool8 auditingmode; + uint32 maxauditeventcount; + [size_is(maxauditeventcount+1)] uint32 *eventauditoptions; + netr_String primarydomainname; + dom_sid2 *sid; + netr_QUOTA_LIMITS quota_limits; + NTTIME db_modify_time; + NTTIME db_create_time; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_POLICY; + + typedef struct { + netr_String DomainName; + uint32 num_controllers; + [size_is(num_controllers)] netr_String *controller_names; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_TRUSTED_DOMAINS; + + typedef struct { + uint32 privilege_entries; + uint32 privilege_control; + [size_is(privilege_entries)] uint32 *privilege_attrib; + [size_is(privilege_entries)] netr_String *privilege_name; + netr_QUOTA_LIMITS quotalimits; + uint32 system_flags; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_ACCOUNTS; + + typedef struct { + uint32 len; + uint32 maxlen; + [size_is(maxlen)][length_is(len)] uint8 *cipher_data; + } netr_CIPHER_VALUE; + + typedef struct { + netr_CIPHER_VALUE current_cipher; + NTTIME current_cipher_set_time; + netr_CIPHER_VALUE old_cipher; + NTTIME old_cipher_set_time; + uint32 SecurityInformation; + sec_desc_buf sdbuf; + netr_String unknown1; + netr_String unknown2; + netr_String unknown3; + netr_String unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; + uint32 unknown8; + } netr_DELTA_SECRET; + + typedef union { + [case(1)] netr_DELTA_DOMAIN *domain; + [case(2)] netr_DELTA_GROUP *group; + [case(4)] netr_DELTA_RENAME *rename_group; + [case(5)] netr_DELTA_USER *user; + [case(7)] netr_DELTA_RENAME *rename_user; + [case(8)] netr_DELTA_GROUP_MEMBER *group_member; + [case(9)] netr_DELTA_ALIAS *alias; + [case(11)] netr_DELTA_RENAME *rename_alias; + [case(12)] netr_DELTA_ALIAS_MEMBER *alias_member; + [case(13)] netr_DELTA_POLICY *policy; + [case(14)] netr_DELTA_TRUSTED_DOMAINS *trusted_domains; + [case(16)] netr_DELTA_ACCOUNTS *accounts; + [case(18)] netr_DELTA_SECRET *secret; + [case(20)] netr_DELTA_DELETE_USER *delete_group; + [case(21)] netr_DELTA_DELETE_USER *delete_user; + [case(22)] ULONG8 *modified_count; + } netr_DELTA_UNION; + + typedef union { + [case(1)] uint32 rid; + [case(2)] uint32 rid; + [case(3)] uint32 rid; + [case(4)] uint32 rid; + [case(5)] uint32 rid; + [case(6)] uint32 rid; + [case(7)] uint32 rid; + [case(8)] uint32 rid; + [case(9)] uint32 rid; + [case(10)] uint32 rid; + [case(11)] uint32 rid; + [case(12)] uint32 rid; + [case(13)] dom_sid2 *sid; + [case(14)] dom_sid2 *sid; + [case(15)] dom_sid2 *sid; + [case(16)] dom_sid2 *sid; + [case(17)] dom_sid2 *sid; + [case(18)] unistr *Name; + [case(19)] unistr *Name; + [case(20)] uint32 rid; + [case(21)] uint32 rid; + } netr_DELTA_ID_UNION; + + typedef struct { + uint16 delta_type; + [switch_is(delta_type)] netr_DELTA_ID_UNION delta_id_union; + [switch_is(delta_type)] netr_DELTA_UNION delta_union; + } netr_DELTA_ENUM; + + typedef struct { + uint32 num_deltas; + [size_is(num_deltas)] netr_DELTA_ENUM *delta_enum; + } netr_DELTA_ENUM_ARRAY; + + + NTSTATUS netr_DatabaseDeltas( + [in] unistr logon_server, + [in] unistr computername, + [in] netr_Authenticator credential, + [in,out] netr_Authenticator return_authenticator, + [in] uint32 database_id, + [in,out] ULONG8 sequence_num, + [in] uint32 preferredmaximumlength, + [out] netr_DELTA_ENUM_ARRAY *delta_enum_array + ); + + + /*****************/ + /* Function 0x08 */ + + NTSTATUS netr_DatabaseSync( + [in] unistr logon_server, + [in] unistr computername, + [in] netr_Authenticator credential, + [in,out] netr_Authenticator return_authenticator, + [in] uint32 database_id, + [in,out] uint32 sync_context, + [in] uint32 preferredmaximumlength, + [out] netr_DELTA_ENUM_ARRAY *delta_enum_array + ); + + + /*****************/ + /* Function 0x09 */ + + /* w2k3 returns NT_STATUS_NOT_IMPLEMENTED for this call */ + + typedef [flag(NDR_PAHEX)] struct { + uint8 computer_name[16]; + uint32 timecreated; + uint32 serial_number; + } netr_UAS_INFO_0; + + typedef struct { + [flag(NDR_REMAINING)] DATA_BLOB blob; + } netr_AccountBuffer; + + NTSTATUS netr_AccountDeltas( + [in] unistr *logon_server, + [in] unistr computername, + [in] netr_Authenticator credential, + [in,out] netr_Authenticator return_authenticator, + [in] netr_UAS_INFO_0 uas, + [in] uint32 count, + [in] uint32 level, + [in] uint32 buffersize, + [out,subcontext(4)] netr_AccountBuffer buffer, + [out] uint32 count_returned, + [out] uint32 total_entries, + [out] netr_UAS_INFO_0 recordid + ); + + + /*****************/ + /* Function 0x0A */ + + NTSTATUS netr_AccountSync( + [in] unistr *logon_server, + [in] unistr computername, + [in] netr_Authenticator credential, + [in,out] netr_Authenticator return_authenticator, + [in] uint32 reference, + [in] uint32 level, + [in] uint32 buffersize, + [out,subcontext(4)] netr_AccountBuffer buffer, + [out] uint32 count_returned, + [out] uint32 total_entries, + [out] uint32 next_reference, + [in,out] netr_UAS_INFO_0 recordid + ); + + + /*****************/ + /* Function 0x0B */ + + NTSTATUS netr_GetDcName( + [in] unistr logon_server, + [in] unistr *domainname, + [out] unistr *dcname + ); + + + + /*****************/ + /* Function 0x0C */ + + typedef struct { + uint32 flags; + uint32 pdc_connection_status; + } netr_NETLOGON_INFO_1; + + typedef struct { + uint32 flags; + uint32 pdc_connection_status; + unistr trusted_dc_name; + uint32 tc_connection_status; + } netr_NETLOGON_INFO_2; + + typedef struct { + uint32 flags; + uint32 logon_attempts; + uint32 unknown1; + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + uint32 unknown5; + } netr_NETLOGON_INFO_3; + + typedef union { + [case(1)] netr_NETLOGON_INFO_1 *info1; + [case(2)] netr_NETLOGON_INFO_2 *info2; + [case(3)] netr_NETLOGON_INFO_3 *info3; + } netr_CONTROL_QUERY_INFORMATION; + + /* function_code values */ + const int NETLOGON_CONTROL_REDISCOVER = 5; + const int NETLOGON_CONTROL_TC_QUERY = 6; + const int NETLOGON_CONTROL_TRANSPORT_NOTIFY = 7; + const int NETLOGON_CONTROL_SET_DBFLAG = 65534; + + WERROR netr_LogonControl( + [in] unistr *logon_server, + [in] uint32 function_code, + [in] uint32 level, + [out,switch_is(level)] netr_CONTROL_QUERY_INFORMATION info + ); + + + /*****************/ + /* Function 0x0D */ + + WERROR netr_GetAnyDCName( + [in] unistr *logon_server, + [in] unistr *domainname, + [out] unistr *dcname + ); + + + /*****************/ + /* Function 0x0E */ + + typedef union { + [case(NETLOGON_CONTROL_REDISCOVER)] unistr *domain; + [case(NETLOGON_CONTROL_TC_QUERY)] unistr *domain; + [case(NETLOGON_CONTROL_TRANSPORT_NOTIFY)] unistr *domain; + [case(NETLOGON_CONTROL_SET_DBFLAG)] uint32 debug_level; + } netr_CONTROL_DATA_INFORMATION; + + WERROR netr_LogonControl2( + [in] unistr *logon_server, + [in] uint32 function_code, + [in] uint32 level, + [in][switch_is(function_code)] netr_CONTROL_DATA_INFORMATION data, + [out][switch_is(level)] netr_CONTROL_QUERY_INFORMATION query + ); + + + /*****************/ + /* Function 0x0F */ + + NTSTATUS netr_ServerAuthenticate2( + [in] unistr *server_name, + [in] unistr username, + [in] uint16 secure_channel_type, + [in] unistr computer_name, + [in,out] netr_Credential credentials, + [in,out,ref] uint32 *negotiate_flags + ); + + + /*****************/ + /* Function 0x10 */ + + NTSTATUS netr_DatabaseSync2( + [in] unistr logon_server, + [in] unistr computername, + [in] netr_Authenticator credential, + [in,out] netr_Authenticator return_authenticator, + [in] uint32 database_id, + [in] uint16 restart_state, + [in,out] uint32 sync_context, + [in] uint32 preferredmaximumlength, + [out] netr_DELTA_ENUM_ARRAY *delta_enum_array + ); + + + /*****************/ + /* Function 0x11 */ + + /* i'm not at all sure how this call works */ + + NTSTATUS netr_DatabaseRedo( + [in] unistr logon_server, + [in] unistr computername, + [in] netr_Authenticator credential, + [in,out] netr_Authenticator return_authenticator, + [in][size_is(change_log_entry_size)] uint8 *change_log_entry, + [in] uint32 change_log_entry_size, + [out] netr_DELTA_ENUM_ARRAY *delta_enum_array + ); + + + /*****************/ + /* Function 0x12 */ + + WERROR netr_LogonControl2Ex( + [in] unistr *logon_server, + [in] uint32 function_code, + [in] uint32 level, + [in][switch_is(function_code)] netr_CONTROL_DATA_INFORMATION data, + [out][switch_is(level)] netr_CONTROL_QUERY_INFORMATION query + ); +} diff --git a/source/librpc/idl/ntsvcs.idl b/source/librpc/idl/ntsvcs.idl new file mode 100644 index 00000000000..88d51a05bae --- /dev/null +++ b/source/librpc/idl/ntsvcs.idl @@ -0,0 +1,15 @@ +/* + plug and play services? +*/ + +[ + uuid(8d9f4e40-a03d-11ce-8f69-08003e30051b), + version(1.0) +] +interface ntsvcs +{ + + /*****************/ + /* Function 0x00 */ + WERROR ntsvcs_Unknown0(); +} diff --git a/source/librpc/idl/protected_storage.idl b/source/librpc/idl/protected_storage.idl new file mode 100644 index 00000000000..aaf223bbb21 --- /dev/null +++ b/source/librpc/idl/protected_storage.idl @@ -0,0 +1,15 @@ +#include "idl_types.h" + +/* + protected_storage interface definitions +*/ + +[ uuid(e3514235-4b06-11d1-ab04-00c04fc2dcd2), + version(4.0), + pointer_default(unique) +] interface protected_storage +{ + /*****************************/ + /* Function 0x00 */ + WERROR ps_XXX (); +} diff --git a/source/librpc/idl/samr.idl b/source/librpc/idl/samr.idl new file mode 100644 index 00000000000..1226d1f7707 --- /dev/null +++ b/source/librpc/idl/samr.idl @@ -0,0 +1,894 @@ +#include "idl_types.h" + +/* + samr interface definition +*/ + +/* + Thanks to Todd Sabin for some information from his samr.idl in acltools +*/ + +[ uuid(12345778-1234-abcd-ef00-0123456789ac), + version(1.0), + pointer_default(unique) +] interface samr +{ + /******************/ + /* Function: 0x00 */ + NTSTATUS samr_Connect ( + /* notice the lack of [string] */ + [in] uint16 *system_name, + [in] uint32 access_mask, + [out,ref] policy_handle *handle + ); + + + /******************/ + /* Function: 0x01 */ + NTSTATUS samr_Close ( + [in,out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x02 */ + + typedef struct { + [value(ndr_size_security_descriptor(r->sd))] uint32 sd_size; + [subcontext(4)] security_descriptor *sd; + } samr_SdBuf; + + NTSTATUS samr_SetSecurity ( + [in,ref] policy_handle *handle, + [in] uint32 sec_info, + [in,ref] samr_SdBuf *sdbuf + ); + + /******************/ + /* Function: 0x03 */ + + NTSTATUS samr_QuerySecurity ( + [in,ref] policy_handle *handle, + [in] uint32 sec_info, + [out] samr_SdBuf *sdbuf + ); + + /******************/ + /* Function: 0x04 */ + NTSTATUS samr_Shutdown (); + + /******************/ + /* Function: 0x05 */ + typedef struct { + [value(2*strlen_m(r->name))] uint16 name_len; + [value(r->name_len)] uint16 name_size; + unistr_noterm *name; + } samr_Name; + + NTSTATUS samr_LookupDomain ( + [in,ref] policy_handle *handle, + [in,ref] samr_Name *domain, + [out] dom_sid2 *sid + ); + + + /******************/ + /* Function: 0x06 */ + + typedef struct { + uint32 idx; + samr_Name name; + } samr_SamEntry; + + typedef struct { + uint32 count; + [size_is(count)] samr_SamEntry *entries; + } samr_SamArray; + + NTSTATUS samr_EnumDomains ( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 buf_size, + [out] samr_SamArray *sam, + [out] uint32 num_entries + ); + + + /************************/ + /* Function 0x07 */ + NTSTATUS samr_OpenDomain( + [in,ref] policy_handle *handle, + [in] uint32 access_mask, + [in,ref] dom_sid2 *sid, + [out,ref] policy_handle *domain_handle + ); + + /************************/ + /* Function 0x08 */ + + typedef struct { + uint16 min_length_password; + uint16 password_history; + uint32 flag; + NTTIME expire; + NTTIME min_passwordage; + } samr_DomInfo1; + + typedef struct { + ULONG8 force_logoff_time; + samr_Name unknown1; + samr_Name domain; /* domain name */ + samr_Name primary; /* PDC name if this is a BDC */ + HYPER_T sequence_num; + uint32 unknown2; + uint32 role; + uint32 unknown3; + uint32 num_users; + uint32 num_groups; + uint32 num_aliases; + } samr_DomInfo2; + + typedef struct { + ULONG8 force_logoff_time; + } samr_DomInfo3; + + typedef struct { + samr_Name unknown; + } samr_DomInfo4; + + typedef struct { + samr_Name domain; + } samr_DomInfo5; + + typedef struct { + samr_Name primary; + } samr_DomInfo6; + + typedef struct { + uint32 role; + } samr_DomInfo7; + + typedef struct { + HYPER_T sequence_num; + NTTIME last_xxx_time; + } samr_DomInfo8; + + typedef struct { + uint32 unknown; + } samr_DomInfo9; + + typedef struct { + ULONG8 force_logoff_time; + samr_Name unknown1; + samr_Name domain; + samr_Name primary; + HYPER_T sequence_num; + uint32 unknown2; + uint32 role; + uint32 unknown3; + uint32 num_users; + uint32 num_groups; + uint32 num_aliases; + HYPER_T lockout_duration; + HYPER_T lockout_window; + uint16 lockout_threshold; + } samr_DomInfo11; + + typedef struct { + HYPER_T lockout_duration; + HYPER_T lockout_window; + uint16 lockout_threshold; + } samr_DomInfo12; + + typedef struct { + HYPER_T sequence_num; + NTTIME last_xxx_time; + uint32 unknown1; + uint32 unknown2; + } samr_DomInfo13; + + typedef union { + [case(1)] samr_DomInfo1 info1; + [case(2)] samr_DomInfo2 info2; + [case(3)] samr_DomInfo3 info3; + [case(4)] samr_DomInfo4 info4; + [case(5)] samr_DomInfo5 info5; + [case(6)] samr_DomInfo6 info6; + [case(7)] samr_DomInfo7 info7; + [case(8)] samr_DomInfo8 info8; + [case(9)] samr_DomInfo9 info9; + [case(11)] samr_DomInfo11 info11; + [case(12)] samr_DomInfo12 info12; + [case(13)] samr_DomInfo13 info13; + } samr_DomainInfo; + + NTSTATUS samr_QueryDomainInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [out,switch_is(level)] samr_DomainInfo *info + ); + + /************************/ + /* Function 0x09 */ + NTSTATUS samr_SET_DOMAIN_INFO(); + + /************************/ + /* Function 0x0a */ + NTSTATUS samr_CREATE_DOM_GROUP(); + + /************************/ + /* Function 0x0b */ + NTSTATUS samr_EnumDomainGroups( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 max_size, + [out] samr_SamArray *sam, + [out] uint32 num_entries + ); + + /************************/ + /* Function 0x0c */ + NTSTATUS samr_CreateUser( + [in,ref] policy_handle *handle, + [in,ref] samr_Name *username, + [in] uint32 access_mask, + [out,ref] policy_handle *acct_handle, + [out,ref] uint32 *rid + ); + + /************************/ + /* Function 0x0d */ + NTSTATUS samr_EnumDomainUsers( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 acct_flags, + [in] uint32 max_size, + [out] samr_SamArray *sam, + [out] uint32 num_entries + ); + + /************************/ + /* Function 0x0e */ + NTSTATUS samr_CreateDomAlias( + [in,ref] policy_handle *handle, + [in,ref] samr_Name *aliasname, + [in] uint32 access_mask, + [out,ref] policy_handle *acct_handle, + [out,ref] uint32 *rid + ); + + /************************/ + /* Function 0x0f */ + NTSTATUS samr_EnumDomainAliases( + [in,ref] policy_handle *handle, + [in,out,ref] uint32 *resume_handle, + [in] uint32 max_size, + [out] samr_SamArray *sam, + [out] uint32 num_entries + ); + + /************************/ + /* Function 0x10 */ + + typedef struct { + uint32 count; + [size_is(count)] uint32 *ids; + } samr_Ids; + + NTSTATUS samr_GetAliasMembership( + [in,ref] policy_handle *handle, + [in,ref] lsa_SidArray *sids, + [out] samr_Ids *rids + ); + + /************************/ + /* Function 0x11 */ + + NTSTATUS samr_LookupNames( + [in,ref] policy_handle *handle, + [in] uint32 num_names, + [in,ref,size_is(1000),length_is(num_names)] samr_Name *names, + [out] samr_Ids rids, + [out] samr_Ids types + ); + + + /************************/ + /* Function 0x12 */ + + typedef struct { + uint32 count; + [size_is(count)] samr_Name *names; + } samr_Names; + + NTSTATUS samr_LookupRids( + [in,ref] policy_handle *handle, + [in] uint32 num_rids, + [in,ref,size_is(1000),length_is(num_rids)] uint32 *rids, + [out] samr_Names names, + [out] samr_Ids types + ); + + /************************/ + /* Function 0x13 */ + NTSTATUS samr_OpenGroup( + [in,ref] policy_handle *handle, + [in] uint32 access_mask, + [in] uint32 rid, + [out,ref] policy_handle *acct_handle + ); + + + /************************/ + /* Function 0x14 */ + + typedef struct { + samr_Name name; + uint32 unknown; + uint32 num_members; + samr_Name description; + } samr_GroupInfoAll; + + typedef struct { + uint32 unknown; + } samr_GroupInfoX; + + typedef struct { + samr_Name description; + } samr_GroupInfoDesciption; + + typedef enum { + GroupInfoAll = 1, + GroupInfoName, + GroupInfoX, + GroupInfoDescription + } GroupInfo; + + typedef union { + [case(GroupInfoAll)] samr_GroupInfoAll all; + [case(GroupInfoName)] samr_Name name; + [case(GroupInfoX)] samr_GroupInfoX unknown; + [case(GroupInfoDescription)] samr_Name description; + } samr_GroupInfo; + + NTSTATUS samr_QueryGroupInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [out,switch_is(level)] samr_GroupInfo *info + ); + + /************************/ + /* Function 0x15 */ + NTSTATUS samr_SET_GROUPINFO(); + + /************************/ + /* Function 0x16 */ + NTSTATUS samr_ADD_GROUPMEM(); + + /************************/ + /* Function 0x17 */ + NTSTATUS samr_DELETE_DOM_GROUP(); + + /************************/ + /* Function 0x18 */ + NTSTATUS samr_DEL_GROUPMEM(); + + /************************/ + /* Function 0x19 */ + NTSTATUS samr_QUERY_GROUPMEM(); + + /************************/ + /* Function 0x1a */ + NTSTATUS samr_SET_MEMBER_ATTRIBUTES_OF_GROUP(); + + + /************************/ + /* Function 0x1b */ + NTSTATUS samr_OpenAlias ( + [in,ref] policy_handle *handle, + [in] uint32 access_mask, + [in] uint32 rid, + [out,ref] policy_handle *acct_handle + ); + + + /************************/ + /* Function 0x1c */ + + typedef struct { + samr_Name name; + uint32 num_members; + samr_Name description; + } samr_AliasInfoAll; + + typedef union { + [case(1)] samr_AliasInfoAll all; + [case(2)] samr_Name name; + [case(3)] samr_Name description; + } samr_AliasInfo; + + NTSTATUS samr_QueryAliasInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [out,switch_is(level)] samr_AliasInfo *info + ); + + /************************/ + /* Function 0x1d */ + NTSTATUS samr_SetAliasInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [in,switch_is(level)] samr_AliasInfo info + ); + + /************************/ + /* Function 0x1e */ + NTSTATUS samr_DeleteDomAlias( + [in,out,ref] policy_handle *handle + ); + + /************************/ + /* Function 0x1f */ + NTSTATUS samr_AddAliasMem( + [in,ref] policy_handle *handle, + [in,ref] dom_sid2 *sid + ); + + /************************/ + /* Function 0x20 */ + NTSTATUS samr_DelAliasMem( + [in,ref] policy_handle *handle, + [in,ref] dom_sid2 *sid + ); + + /************************/ + /* Function 0x21 */ + NTSTATUS samr_GetMembersInAlias( + [in,ref] policy_handle *handle, + [out,ref] lsa_SidArray *sids + ); + + /************************/ + /* Function 0x22 */ + NTSTATUS samr_OpenUser( + [in,ref] policy_handle *handle, + [in] uint32 access_mask, + [in] uint32 rid, + [out,ref] policy_handle *acct_handle + ); + + /************************/ + /* Function 0x23 */ + NTSTATUS samr_DeleteUser( + [in,out,ref] policy_handle *handle + ); + + /************************/ + /* Function 0x24 */ + typedef struct { + samr_Name username; + samr_Name full_name; + uint32 primary_gid; + samr_Name description; + samr_Name comment; + } samr_UserInfo1; + + typedef struct { + samr_Name comment; + samr_Name unknown; /* settable, but doesn't stick. probably obsolete */ + uint16 country_code; + uint16 code_page; + } samr_UserInfo2; + + typedef struct { + samr_Name username; + samr_Name full_name; + uint32 Rid; + uint32 primary_gid; + samr_Name home_directory; + samr_Name home_drive; + samr_Name logon_script; + samr_Name profile; + samr_Name workstations; + NTTIME last_logon; + NTTIME last_logoff; + NTTIME last_pwd_change; + NTTIME allow_pwd_change; + NTTIME force_pwd_change; + samr_LogonHours logon_hours; + uint16 bad_pwd_count; + uint16 num_logons; + uint32 acct_flags; + } samr_UserInfo3; + + typedef struct { + samr_LogonHours logon_hours; + } samr_UserInfo4; + + typedef struct { + samr_Name username; + samr_Name full_name; + uint32 rid; + uint32 primary_gid; + samr_Name home_directory; + samr_Name home_drive; + samr_Name logon_script; + samr_Name profile; + samr_Name description; + samr_Name workstations; + NTTIME last_logon; + NTTIME last_logoff; + samr_LogonHours logon_hours; + uint16 bad_pwd_count; + uint16 num_logons; + NTTIME last_pwd_change; + NTTIME acct_expiry; + uint32 acct_flags; + } samr_UserInfo5; + + typedef struct { + samr_Name username; + samr_Name full_name; + } samr_UserInfo6; + + typedef struct { + samr_Name username; + } samr_UserInfo7; + + typedef struct { + samr_Name full_name; + } samr_UserInfo8; + + typedef struct { + uint32 primary_gid; + } samr_UserInfo9; + + typedef struct { + samr_Name home_dir; + samr_Name home_drive; + } samr_UserInfo10; + + typedef struct { + samr_Name logon_script; + } samr_UserInfo11; + + typedef struct { + samr_Name profile; + } samr_UserInfo12; + + typedef struct { + samr_Name description; + } samr_UserInfo13; + + typedef struct { + samr_Name workstations; + } samr_UserInfo14; + + typedef struct { + uint32 acct_flags; + } samr_UserInfo16; + + typedef struct { + NTTIME acct_expiry; + } samr_UserInfo17; + + typedef struct { + samr_Name callback; + } samr_UserInfo20; + + typedef struct { + NTTIME last_logon; + NTTIME last_logoff; + NTTIME last_pwd_change; + NTTIME acct_expiry; + NTTIME allow_pwd_change; + NTTIME force_pwd_change; + samr_Name username; + samr_Name full_name; + samr_Name home_dir; + samr_Name home_drive; + samr_Name logon_script; + samr_Name profile; + samr_Name description; + samr_Name workstations; + samr_Name comment; + samr_Name callback; + samr_Name unknown1; + samr_Name unknown2; + samr_Name unknown3; + uint32 buf_count; + [size_is(buf_count)] uint8 *buffer; + uint32 rid; + uint32 primary_gid; + uint32 acct_flags; + uint32 fields_present; + samr_LogonHours logon_hours; + uint16 bad_pwd_count; + uint16 num_logons; + uint16 country_code; + uint16 code_page; + uint8 nt_pwd_set; + uint8 lm_pwd_set; + uint8 expired_flag; + uint8 unknown4; + } samr_UserInfo21; + + typedef union { + [case(1)] samr_UserInfo1 info1; + [case(2)] samr_UserInfo2 info2; + [case(3)] samr_UserInfo3 info3; + [case(4)] samr_UserInfo4 info4; + [case(5)] samr_UserInfo5 info5; + [case(6)] samr_UserInfo6 info6; + [case(7)] samr_UserInfo7 info7; + [case(8)] samr_UserInfo8 info8; + [case(9)] samr_UserInfo9 info9; + [case(10)] samr_UserInfo10 info10; + [case(11)] samr_UserInfo11 info11; + [case(12)] samr_UserInfo12 info12; + [case(13)] samr_UserInfo13 info13; + [case(14)] samr_UserInfo14 info14; + [case(16)] samr_UserInfo16 info16; + [case(17)] samr_UserInfo17 info17; + [case(20)] samr_UserInfo20 info20; + [case(21)] samr_UserInfo21 info21; + } samr_UserInfo; + + NTSTATUS samr_QueryUserInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [out,switch_is(level)] samr_UserInfo *info + ); + + + /************************/ + /* Function 0x25 */ + NTSTATUS samr_SetUserInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [in,ref,switch_is(level)] samr_UserInfo *info + ); + + /************************/ + /* Function 0x26 */ + NTSTATUS samr_CHANGE_PASSWORD_USER(); + + /************************/ + /* Function 0x27 */ + + typedef struct { + uint32 rid; + uint32 type; + } samr_RidType; + + typedef struct { + uint32 count; + [size_is(count)] samr_RidType *rid; + } samr_RidArray; + + NTSTATUS samr_GetGroupsForUser( + [in,ref] policy_handle *handle, + [out] samr_RidArray *rids + ); + + /************************/ + /* Function 0x28 */ + + typedef struct { + uint32 idx; + uint32 rid; + uint32 acct_flags; + samr_Name account_name; + samr_Name full_name; + samr_Name description; + } samr_DispEntryGeneral; + + typedef struct { + uint32 count; + [size_is(count)] samr_DispEntryGeneral *entries; + } samr_DispInfoGeneral; + + typedef struct { + uint32 idx; + uint32 rid; + uint32 acct_flags; + samr_Name account_name; + samr_Name description; + } samr_DispEntryFull; + + typedef struct { + uint32 count; + [size_is(count)] samr_DispEntryFull *entries; + } samr_DispInfoFull; + + typedef struct { + [value(strlen_m(r->name))] uint16 name_len; + [value(strlen_m(r->name))] uint16 name_size; + ascstr *name; + } samr_AsciiName; + + typedef struct { + uint32 idx; + samr_AsciiName account_name; + } samr_DispEntryAscii; + + typedef struct { + uint32 count; + [size_is(count)] samr_DispEntryAscii *entries; + } samr_DispInfoAscii; + + typedef union { + [case(1)] samr_DispInfoGeneral info1;/* users */ + [case(2)] samr_DispInfoFull info2; /* trust accounts? */ + [case(3)] samr_DispInfoFull info3; /* groups */ + [case(4)] samr_DispInfoAscii info4; /* users */ + [case(5)] samr_DispInfoAscii info5; /* groups */ + } samr_DispInfo; + + NTSTATUS samr_QueryDisplayInfo( + [in,ref] policy_handle *handle, + [in] uint16 level, + [in] uint32 start_idx, + [in] uint32 max_entries, + [in] uint32 buf_size, + [out] uint32 total_size, + [out] uint32 returned_size, + [out,switch_is(level)] samr_DispInfo info + ); + + /************************/ + /* Function 0x29 */ + NTSTATUS samr_GET_DISPLAY_ENUMERATION_INDEX(); + + /************************/ + /* Function 0x2a */ + NTSTATUS samr_TEST_PRIVATE_FUNCTIONS_DOMAIN(); + + /************************/ + /* Function 0x2b */ + NTSTATUS samr_TEST_PRIVATE_FUNCTIONS_USER(); + + + /************************/ + /* Function 0x2c */ + + /* password properties flags */ + const uint32 DOMAIN_PASSWORD_COMPLEX = 0x00000001; + const uint32 DOMAIN_PASSWORD_NO_ANON_CHANGE = 0x00000002; + const uint32 DOMAIN_PASSWORD_NO_CLEAR_CHANGE = 0x00000004; + const uint32 DOMAIN_PASSWORD_STORE_CLEARTEXT = 0x00000010; + const uint32 DOMAIN_REFUSE_PASSWORD_CHANGE = 0x00000020; + + typedef struct { + uint16 min_pwd_len; + uint32 password_properties; + } samr_PwInfo; + + NTSTATUS samr_GetUserPwInfo( + [in,ref] policy_handle *handle, + [out] samr_PwInfo info + ); + + /************************/ + /* Function 0x2d */ + NTSTATUS samr_REMOVE_MEMBER_FROM_FOREIGN_DOMAIN(); + + /************************/ + /* Function 0x2e */ + NTSTATUS samr_QUERY_INFORMATION_DOMAIN2(); + + /************************/ + /* Function 0x2f */ + NTSTATUS samr_QUERY_INFORMATION_USER2(); + + /************************/ + /* Function 0x30 */ + NTSTATUS samr_QUERY_DISPINFO2(); + + /************************/ + /* Function 0x31 */ + NTSTATUS samr_GET_DISPLAY_ENUMERATION_INDEX2(); + + /************************/ + /* Function 0x32 */ + NTSTATUS samr_CreateUser2( + /************************/ + [in,ref] policy_handle *handle, + [in,ref] samr_Name *username, + [in] uint32 acct_flags, + [in] uint32 access_mask, + [out,ref] policy_handle *acct_handle, + [out,ref] uint32 *access_granted, + [out,ref] uint32 *rid + ); + + + /************************/ + /* Function 0x33 */ + NTSTATUS samr_QUERY_DISPINFO3(); + + /************************/ + /* Function 0x34 */ + NTSTATUS samr_ADD_MULTIPLE_MEMBERS_TO_ALIAS(); + + /************************/ + /* Function 0x35 */ + NTSTATUS samr_REMOVE_MULTIPLE_MEMBERS_FROM_ALIAS(); + + /************************/ + /* Function 0x36 */ + NTSTATUS samr_OEM_CHANGE_PASSWORD_USER2(); + + /************************/ + /* Function 0x37 */ + NTSTATUS samr_UNICODE_CHANGE_PASSWORD_USER2(); + + /************************/ + /* Function 0x38 */ + NTSTATUS samr_GET_DOM_PWINFO(); + + /************************/ + /* Function 0x39 */ + NTSTATUS samr_Connect2( + [in] unistr *system_name, + [in] uint32 access_mask, + [out,ref] policy_handle *handle + ); + + /************************/ + /* Function 0x3a */ + NTSTATUS samr_SET_USERINFO2(); + + /************************/ + /* Function 0x3b */ + NTSTATUS samr_SET_BOOT_KEY_INFORMATION(); + + /************************/ + /* Function 0x3c */ + NTSTATUS samr_GET_BOOT_KEY_INFORMATION(); + + /************************/ + /* Function 0x3d */ + NTSTATUS samr_CONNECT3(); + + /************************/ + /* Function 0x3e */ + NTSTATUS samr_Connect4( + [in] unistr *system_name, + [in] uint32 unknown, + [in] uint32 access_mask, + [out,ref] policy_handle *handle + ); + + /************************/ + /* Function 0x3f */ + NTSTATUS samr_UNICODE_CHANGE_PASSWORD_USER3(); + + /************************/ + /* Function 0x40 */ + NTSTATUS samr_Connect5( + [in] unistr *system_name, + [in] uint32 access_mask, + [in] uint32 unknown0, + [in] uint32 unknown1, + [in] uint32 unknown2, + [in] uint32 unknown3, + [out] uint32 unknown4, + [out] uint32 unknown5, + [out] uint32 unknown6, + [out] uint32 unknown7, + [out,ref] policy_handle *handle + ); + + /************************/ + /* Function 0x41 */ + NTSTATUS samr_RID_TO_SID(); + + /************************/ + /* Function 0x42 */ + NTSTATUS samr_SET_DSRM_PASSWORD(); + + /************************/ + /* Function 0x43 */ + NTSTATUS samr_VALIDATE_PASSWORD(); + +} diff --git a/source/librpc/idl/scerpc.idl b/source/librpc/idl/scerpc.idl new file mode 100644 index 00000000000..049de3b19b9 --- /dev/null +++ b/source/librpc/idl/scerpc.idl @@ -0,0 +1,16 @@ +/* + security configuration editor interface definitions +*/ + +[ + uuid(93149ca2-973b-11d1-8c39-00c04fb984f9), + version(0.0) +] +interface scerpc +{ + + /*****************/ + /* Function 0x00 */ + WERROR scerpc_Unknown0(); +} + diff --git a/source/librpc/idl/spoolss.idl b/source/librpc/idl/spoolss.idl new file mode 100644 index 00000000000..f9cd7705834 --- /dev/null +++ b/source/librpc/idl/spoolss.idl @@ -0,0 +1,843 @@ +#include "idl_types.h" + +/* + spoolss interface definitions +*/ + +[ uuid(12345678-1234-abcd-ef00-0123456789ab), + version(1.0), + pointer_default(unique) +] interface spoolss +{ + typedef struct { + nstring devicename; + uint16 specversion; + uint16 driverversion; + uint16 size; + uint16 driverextra; + uint32 fields; + uint16 orientation; + uint16 papersize; + uint16 paperlength; + uint16 paperwidth; + uint16 scale; + uint16 copies; + uint16 defaultsource; + uint16 printquality; + uint16 color; + uint16 duplex; + uint16 yresolution; + uint16 ttoption; + uint16 collate; + nstring formname; + uint16 logpixels; + uint32 bitsperpel; + uint32 pelswidth; + uint32 pelsheight; + uint32 displayflags; + uint32 displayfrequency; + uint32 icmmethod; + uint32 icmintent; + uint32 mediatype; + uint32 dithertype; + uint32 reserved1; + uint32 reserved2; + uint32 panningwidth; + uint32 panningheight; + uint8 private[driverextra]; + } spoolss_DeviceMode; + + typedef struct { + uint32 flags; + [relative] nstring *name; + [relative] nstring *description; + [relative] nstring *comment; + } spoolss_PrinterInfo1; + + typedef struct { + uint32 flags; + [relative] nstring *name; + uint32 width; + uint32 length; + uint32 left; + uint32 top; + uint32 right; + uint32 bottom; + } spoolss_FormInfo1; + + typedef struct { + [relative] nstring *servername; + [relative] nstring *printername; + [relative] nstring *sharename; + [relative] nstring *portname; + [relative] nstring *drivername; + [relative] nstring *comment; + [relative] nstring *location; + [relative] spoolss_DeviceMode *devmode; + [relative] nstring *sepfile; + [relative] nstring *printprocessor; + [relative] nstring *datatype; + [relative] nstring *parameters; + [relative] security_descriptor *secdesc; + uint32 attributes; + uint32 priority; + uint32 defaultpriority; + uint32 starttime; + uint32 untiltime; + uint32 status; + uint32 cjobs; + uint32 averageppm; + } spoolss_PrinterInfo2; + + typedef struct { + uint32 flags; + security_descriptor secdesc; + } spoolss_PrinterInfo3; + + typedef struct { + [relative] nstring *printername; + [relative] nstring *servername; + uint32 attributes; + } spoolss_PrinterInfo4; + + typedef struct { + [relative] nstring *printername; + [relative] nstring *portname; + uint32 attributes; + uint32 device_not_selected_timeout; + uint32 transmission_retry_timeout; + } spoolss_PrinterInfo5; + + typedef struct { + uint32 unknown; + } spoolss_PrinterInfo6; + + typedef struct { + [relative] nstring *guid; /* text form of printer guid */ + uint32 action; + } spoolss_PrinterInfo7; + + typedef [nodiscriminant,public] union { + [case(1)] spoolss_PrinterInfo1 info1; + [case(2)] spoolss_PrinterInfo2 info2; + [case(3)] spoolss_PrinterInfo3 info3; + [case(4)] spoolss_PrinterInfo4 info4; + [case(5)] spoolss_PrinterInfo5 info5; + [case(6)] spoolss_PrinterInfo6 info6; + [case(7)] spoolss_PrinterInfo7 info7; + } spoolss_PrinterInfo; + + /******************/ + /* Function: 0x00 */ + WERROR spoolss_EnumPrinters( + [in] uint32 flags, + [in] unistr *server, + [in] uint32 level, + [in,out] DATA_BLOB *buffer, + [in,out,ref] uint32 *buf_size, + [out] uint32 count + ); + + /******************/ + /* Function: 0x01 */ + WERROR spoolss_OpenPrinter( + [in] unistr *server, + [in] unistr *printer, + [in] DATA_BLOB *buffer, + [in] uint32 access_mask, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x02 */ + WERROR spoolss_SetJob( + [in,ref] policy_handle *handle, + [in] uint32 job_id, + [in] uint32 level, + [in] uint32 command + ); + + /******************/ + /* Function: 0x03 */ + WERROR spoolss_GetJob( + [in,ref] policy_handle *handle, + [in] uint32 job_id, + [in] uint32 level, + [in] DATA_BLOB *buffer, + [out,subcontext(4),switch_is(level)] spoolss_JobInfo *info, + [in,out,ref] uint32 *buf_size + ); + + typedef struct { + uint16 year; + uint16 month; + uint16 day_of_week; + uint16 day; + uint16 hour; + uint16 minute; + uint16 second; + uint16 millisecond; + } spoolss_Time; + + typedef struct { + uint32 job_id; + [relative] nstring printer_name; + [relative] nstring server_name; + [relative] nstring user_name; + [relative] nstring document_name; + [relative] nstring data_type; + [relative] nstring text_status; + uint32 status; + uint32 priority; + uint32 position; + uint32 total_pages; + uint32 pages_printed; + spoolss_Time time; + } spoolss_JobInfo1; + + typedef [nodiscriminant,public] union { + [case(1)] spoolss_JobInfo1 info1; + } spoolss_JobInfo; + + /******************/ + /* Function: 0x04 */ + WERROR spoolss_EnumJobs( + [in,ref] policy_handle *handle, + [in] uint32 firstjob, + [in] uint32 numjobs, + [in] uint32 level, + [in,out] DATA_BLOB *buffer, + [in,out,ref] uint32 *buf_size, + [out] uint32 count + ); + + /******************/ + /* Function: 0x05 */ + WERROR spoolss_AddPrinter( + /* This function is not implemented in Samba 3 as no + clients have been observed using it. */ + ); + + /******************/ + /* Function: 0x06 */ + WERROR spoolss_DeletePrinter( + ); + + /******************/ + /* Function: 0x07 */ + WERROR spoolss_SetPrinter( + ); + + /******************/ + /* Function: 0x08 */ + WERROR spoolss_GetPrinter( + [in,ref] policy_handle *handle, + [in] uint32 level, + [in] DATA_BLOB *buffer, + [out,subcontext(4),switch_is(level)] spoolss_PrinterInfo *info, + [in,out,ref] uint32 *buf_size + ); + + /******************/ + /* Function: 0x09 */ + WERROR spoolss_AddPrinterDriver( + ); + + typedef struct { + [relative] nstring *driver_name; + } spoolss_DriverInfo1; + + typedef struct { + uint32 version; + [relative] nstring *driver_name; + [relative] nstring *architecture; + [relative] nstring *driver_path; + [relative] nstring *data_file; + [relative] nstring *config_file; + } spoolss_DriverInfo2; + + typedef struct { + uint32 version; + [relative] nstring *driver_name; + [relative] nstring *architecture; + [relative] nstring *driver_path; + [relative] nstring *data_file; + [relative] nstring *config_file; + [relative] nstring *help_file; + [relative] nstring *dependent_files; /* array */ + [relative] nstring *monitor_name; + [relative] nstring *default_datatype; + } spoolss_DriverInfo3; + + typedef [nodiscriminant,public] union { + [case(1)] spoolss_DriverInfo1 info1; + [case(2)] spoolss_DriverInfo2 info2; + [case(3)] spoolss_DriverInfo3 info3; + } spoolss_DriverInfo; + + /******************/ + /* Function: 0x0a */ + WERROR spoolss_EnumPrinterDrivers( + [in] unistr *server, + [in] unistr *environment, + [in] uint32 level, + [in,out] DATA_BLOB *buffer, + [in,out,ref] uint32 *buf_size, + [out] uint32 count + ); + + /******************/ + /* Function: 0x0b */ + WERROR spoolss_GetPrinterDriver( + ); + + /******************/ + /* Function: 0x0c */ + WERROR spoolss_GetPrinterDriverDirectory( + ); + + /******************/ + /* Function: 0x0d */ + WERROR spoolss_DeletePrinterDriver( + [in,ref] policy_handle *handle, + [in] unistr *server, + [in] unistr architecture, + [in] unistr driver + ); + + /******************/ + /* Function: 0x0e */ + WERROR spoolss_AddPrintProcessor( + ); + + /******************/ + /* Function: 0x0f */ + WERROR spoolss_EnumPrintProcessors( + ); + + /******************/ + /* Function: 0x10 */ + WERROR spoolss_GetPrintProcessorDirectory( + ); + + /******************/ + /* Function: 0x11 */ + WERROR spoolss_StartDocPrinter( + ); + + /******************/ + /* Function: 0x12 */ + WERROR spoolss_StartPagePrinter( + [in,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x13 */ + WERROR spoolss_WritePrinter( + ); + + /******************/ + /* Function: 0x14 */ + WERROR spoolss_EndPagePrinter( + [in,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x15 */ + WERROR spoolss_AbortPrinter( + ); + + /******************/ + /* Function: 0x16 */ + WERROR spoolss_ReadPrinter( + ); + + /******************/ + /* Function: 0x17 */ + WERROR spoolss_EndDocPrinter( + ); + + /******************/ + /* Function: 0x18 */ + WERROR spoolss_AddJob( + ); + + /******************/ + /* Function: 0x19 */ + WERROR spoolss_ScheduleJob( + ); + + /******************/ + /* Function: 0x1a */ + WERROR spoolss_GetPrinterData( + [in,ref] policy_handle *handle, + [in] unistr value_name, + [out] uint32 type, + [out] DATA_BLOB buffer, + [in,out,ref] uint32 *buf_size + ); + + /******************/ + /* Function: 0x1b */ + WERROR spoolss_SetPrinterData( + [in,ref] policy_handle *handle, + [in] unistr value_name, + [in] uint32 type, + [in] DATA_BLOB buffer, + [in] uint32 real_len + ); + + /******************/ + /* Function: 0x1c */ + WERROR spoolss_WaitForPrinterChange( + ); + + /******************/ + /* Function: 0x1d */ + WERROR spoolss_ClosePrinter( + [in,out,ref] policy_handle *handle + ); + + typedef struct { + uint32 flags; + [relative] unistr *name; + uint32 width; + uint32 length; + uint32 left; + uint32 top; + uint32 right; + uint32 bottom; + } spoolss_AddFormInfo1; + + typedef union { + [case(1)] spoolss_AddFormInfo1 *info1; + } spoolss_AddFormInfo; + + /******************/ + /* Function: 0x1e */ + WERROR spoolss_AddForm( + [in,ref] policy_handle *handle, + [in] uint32 level, + [in,switch_is(level)] spoolss_AddFormInfo info + ); + + /******************/ + /* Function: 0x1f */ + WERROR spoolss_DeleteForm( + [in,ref] policy_handle *handle, + [in] unistr formname + ); + + /******************/ + /* Function: 0x20 */ + WERROR spoolss_GetForm( + [in,ref] policy_handle *handle, + [in] unistr formname, + [in] uint32 level, + [in] DATA_BLOB *buffer, + [out,subcontext(4),switch_is(level)] spoolss_FormInfo *info, + [in,out,ref] uint32 *buf_size + ); + + /******************/ + /* Function: 0x21 */ + WERROR spoolss_SetForm( + [in,ref] policy_handle *handle, + [in] unistr form_name, + [in] uint32 level, + [in,switch_is(level)] spoolss_AddFormInfo info + ); + + typedef [nodiscriminant,public] union { + [case(1)] spoolss_FormInfo1 info1; + } spoolss_FormInfo; + + /******************/ + /* Function: 0x22 */ + WERROR spoolss_EnumForms( + [in,ref] policy_handle *handle, + [in] uint32 level, + [in,out] DATA_BLOB *buffer, + [in,out,ref] uint32 *buf_size, + [out] uint32 count + ); + + /******************/ + /* Function: 0x23 */ + WERROR spoolss_EnumPorts( + ); + + /******************/ + /* Function: 0x24 */ + WERROR spoolss_EnumMonitors( + ); + + /******************/ + /* Function: 0x25 */ + WERROR spoolss_AddPort( + ); + + /******************/ + /* Function: 0x26 */ + WERROR spoolss_ConfigurePort( + ); + + /******************/ + /* Function: 0x27 */ + WERROR spoolss_DeletePort( + ); + + /******************/ + /* Function: 0x28 */ + WERROR spoolss_CreatePrinterIC( + ); + + /******************/ + /* Function: 0x29 */ + WERROR spoolss_PlayGDIScriptOnPrinterIC( + ); + + /******************/ + /* Function: 0x2a */ + WERROR spoolss_DeletePrinterIC( + ); + + /******************/ + /* Function: 0x2b */ + WERROR spoolss_AddPrinterConnection( + ); + + /******************/ + /* Function: 0x2c */ + WERROR spoolss_DeletePrinterConnection( + ); + + /******************/ + /* Function: 0x2d */ + WERROR spoolss_PrinterMessageBox( + /* Marked as obsolete in MSDN. "Not necessary and has + no effect". */ + ); + + /******************/ + /* Function: 0x2e */ + WERROR spoolss_AddMonitor( + ); + + /******************/ + /* Function: 0x2f */ + WERROR spoolss_DeleteMonitor( + ); + + /******************/ + /* Function: 0x30 */ + WERROR spoolss_DeletePrintProcessor( + ); + + /******************/ + /* Function: 0x31 */ + WERROR spoolss_AddPrintProvidor( + ); + + /******************/ + /* Function: 0x32 */ + WERROR spoolss_DeletePrintProvidor( + ); + + /******************/ + /* Function: 0x33 */ + WERROR spoolss_EnumPrintProcDataTypes( + ); + + /******************/ + /* Function: 0x34 */ + WERROR spoolss_ResetPrinter( + ); + + /******************/ + /* Function: 0x35 */ + WERROR spoolss_GetPrinterDriver2( + [in,ref] policy_handle *handle, + [in] unistr *architecture, + [in] uint32 level, + [in,out] DATA_BLOB *buffer, + [in,out,ref] uint32 *buf_size, + [in] uint32 client_major_version, + [in] uint32 client_minor_version, + [out] uint32 server_major_version, + [out] uint32 server_minor_version + ); + + /******************/ + /* Function: 0x36 */ + WERROR spoolss_FindFirstPrinterChangeNotification( + ); + + /******************/ + /* Function: 0x37 */ + WERROR spoolss_FindNextPrinterChangeNotification( + ); + + /******************/ + /* Function: 0x38 */ + WERROR spoolss_FindClosePrinterNotify( + ); + + /******************/ + /* Function: 0x39 */ + WERROR spoolss_RouterFindFirstPrinterChangeNotificationOld( + ); + + /******************/ + /* Function: 0x3a */ + WERROR spoolss_ReplyOpenPrinter( + ); + + /******************/ + /* Function: 0x3b */ + WERROR spoolss_RouterReplyPrinter( + ); + + /******************/ + /* Function: 0x3c */ + WERROR spoolss_ReplyClosePrinter( + ); + + /******************/ + /* Function: 0x3d */ + WERROR spoolss_AddPortEx( + ); + + /******************/ + /* Function: 0x3e */ + WERROR spoolss_RouterFindFirstPrinterChangeNotification( + ); + + /******************/ + /* Function: 0x3f */ + WERROR spoolss_SpoolerInit( + ); + + /******************/ + /* Function: 0x40 */ + WERROR spoolss_ResetPrinterEx( + ); + + /******************/ + /* Function: 0x41 */ + WERROR spoolss_RemoteFindFirstPrinterChangeNotifyEx( + ); + + /******************/ + /* Function: 0x42 */ + WERROR spoolss_RouterRefreshPrinterChangeNotification( + ); + + /******************/ + /* Function: 0x43 */ + WERROR spoolss_RemoteFindNextPrinterChangeNotifyEx( + ); + + /******************/ + /* Function: 0x44 */ + WERROR spoolss_44( + ); + + typedef struct { + uint32 foo; + } spoolss_Devmode; + + typedef struct { + uint32 size; + spoolss_Devmode *devmode; + } spoolss_DevmodeContainer; + + typedef struct { + uint32 size; + unistr *client; + unistr *user; + uint32 build; + uint32 major; + uint32 minor; + uint32 processor; + } spoolss_UserLevel1; + + typedef union { + [case(1)] spoolss_UserLevel1 *level1; + } spoolss_UserLevel; + + /******************/ + /* Function: 0x45 */ + WERROR spoolss_OpenPrinterEx( + [in] unistr *printername, + [in] unistr *datatype, + [in] spoolss_DevmodeContainer devmode_ctr, + [in] uint32 access_required, + [in] uint32 level, + [in,switch_is(level)] spoolss_UserLevel userlevel, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x46 */ + WERROR spoolss_AddPrinterEx( + [in] unistr *server, + [in] uint32 level, + [in,switch_is(level)] spoolss_PrinterInfo *info, + [in] spoolss_DevmodeContainer devmode_ctr, + [in] security_descriptor *secdesc, + [in] uint32 ulevel, + [in,switch_is(ulevel)] spoolss_UserLevel userlevel + ); + + /******************/ + /* Function: 0x47 */ + WERROR spoolss_47( + ); + + /******************/ + /* Function: 0x48 */ + WERROR spoolss_EnumPrinterData( + [in,ref] policy_handle *handle, + [in] uint32 enum_index, + [in] uint32 value_offered, + [out] lstring value_name, + [out] uint32 value_needed, + [out] uint32 printerdata_type, + [out] DATA_BLOB data, + [in,out,ref] uint32 *data_size + ); + + /******************/ + /* Function: 0x49 */ + WERROR spoolss_DeletePrinterData( + [in,ref] policy_handle *handle, + [in] unistr value_name + ); + + /******************/ + /* Function: 0x4a */ + WERROR spoolss_4a( + ); + + /******************/ + /* Function: 0x4b */ + WERROR spoolss_4b( + ); + + /******************/ + /* Function: 0x4c */ + WERROR spoolss_4c( + ); + + /******************/ + /* Function: 0x4d */ + WERROR spoolss_SetPrinterDataEx( + [in,ref] policy_handle *handle, + [in] unistr key_name, + [in] unistr value_name, + [in] uint32 type, + [in] DATA_BLOB buffer, + [in,out,ref] uint32 *buf_size + ); + + /******************/ + /* Function: 0x4e */ + WERROR spoolss_GetPrinterDataEx( + [in,ref] policy_handle *handle, + [in] unistr key_name, + [in] unistr value_name, + [out] uint32 type, + [out] DATA_BLOB buffer, + [in,out,ref] uint32 *buf_size + ); + + /******************/ + /* Function: 0x4f */ + WERROR spoolss_EnumPrinterDataEx( + [in,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x50 */ + WERROR spoolss_EnumPrinterKey( + ); + + /******************/ + /* Function: 0x51 */ + WERROR spoolss_DeletePrinterDataEx( + [in,ref] policy_handle *handle, + [in] unistr key_name, + [in] unistr value_name + ); + + /******************/ + /* Function: 0x52 */ + WERROR spoolss_DeletePrinterKey( + ); + + /******************/ + /* Function: 0x53 */ + WERROR spoolss_53( + ); + + /******************/ + /* Function: 0x54 */ + WERROR spoolss_DeletePrinterDriverEx( + ); + + /******************/ + /* Function: 0x55 */ + WERROR spoolss_55( + ); + + /******************/ + /* Function: 0x56 */ + WERROR spoolss_56( + ); + + /******************/ + /* Function: 0x57 */ + WERROR spoolss_57( + ); + + /******************/ + /* Function: 0x58 */ + WERROR spoolss_58( + ); + + /******************/ + /* Function: 0x59 */ + WERROR spoolss_AddPrinterDriverEx( + ); + + /******************/ + /* Function: 0x5a */ + WERROR spoolss_5a( + ); + + /******************/ + /* Function: 0x5b */ + WERROR spoolss_5b( + ); + + /******************/ + /* Function: 0x5c */ + WERROR spoolss_5c( + ); + + /******************/ + /* Function: 0x5d */ + WERROR spoolss_5d( + ); + + /******************/ + /* Function: 0x5e */ + WERROR spoolss_5e( + ); + + /******************/ + /* Function: 0x5f */ + WERROR spoolss_5f( + ); +} diff --git a/source/librpc/idl/srvsvc.idl b/source/librpc/idl/srvsvc.idl new file mode 100644 index 00000000000..4d737a6c0d7 --- /dev/null +++ b/source/librpc/idl/srvsvc.idl @@ -0,0 +1,1241 @@ +#include "idl_types.h" + +/* + srvsvc interface definitions +*/ + +[ uuid(4b324fc8-1670-01d3-1278-5a47bf6ee188), + version(3.0), + pointer_default(unique) +] interface srvsvc +{ +/**************************/ +/* srvsvc_NetCharDev */ +/**************************/ + typedef struct { + unistr *device; + } srvsvc_NetCharDevInfo0; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetCharDevInfo0 *array; + } srvsvc_NetCharDevCtr0; + + typedef struct { + unistr *device; + uint32 status; + unistr *user; + uint32 time; + } srvsvc_NetCharDevInfo1; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetCharDevInfo1 *array; + } srvsvc_NetCharDevCtr1; + + typedef union { + [case(0)] srvsvc_NetCharDevInfo0 *info0; + [case(1)] srvsvc_NetCharDevInfo1 *info1; + [default] ; + } srvsvc_NetCharDevInfo; + + typedef union { + [case(0)] srvsvc_NetCharDevCtr0 *ctr0; + [case(1)] srvsvc_NetCharDevCtr1 *ctr1; + [default] ; + } srvsvc_NetCharDevCtr; + + /******************/ + /* Function: 0x00 */ + WERROR srvsvc_NetCharDevEnum( + [in] unistr *server_unc, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetCharDevCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x01 */ + WERROR srvsvc_NetCharDevGetInfo( + [in] unistr *server_unc, + [in] unistr device_name, + [in] uint32 level, + [out,switch_is(level)] srvsvc_NetCharDevInfo info + ); + + /******************/ + /* Function: 0x02 */ + WERROR srvsvc_NetCharDevControl( + [in] unistr *server_unc, + [in] unistr device_name, + [in] uint32 opcode + ); + +/**************************/ +/* srvsvc_NetCharDevQ */ +/**************************/ + typedef struct { + unistr *device; + } srvsvc_NetCharDevQInfo0; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetCharDevQInfo0 *array; + } srvsvc_NetCharDevQCtr0; + + typedef struct { + unistr *device; + uint32 priority; + unistr *devices; + uint32 users; + uint32 num_ahead; + } srvsvc_NetCharDevQInfo1; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetCharDevQInfo1 *array; + } srvsvc_NetCharDevQCtr1; + + typedef union { + [case(0)] srvsvc_NetCharDevQInfo0 *info0; + [case(1)] srvsvc_NetCharDevQInfo1 *info1; + [default] ; + } srvsvc_NetCharDevQInfo; + + typedef union { + [case(0)] srvsvc_NetCharDevQCtr0 *ctr0; + [case(1)] srvsvc_NetCharDevQCtr1 *ctr1; + [default] ; + } srvsvc_NetCharDevQCtr; + + /******************/ + /* Function: 0x03 */ + WERROR srvsvc_NetCharDevQEnum( + [in] unistr *server_unc, + [in] unistr *user, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetCharDevQCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x04 */ + WERROR srvsvc_NetCharDevQGetInfo( + [in] unistr *server_unc, + [in] unistr queue_name, + [in] unistr user, + [in] uint32 level, + [out,switch_is(level)] srvsvc_NetCharDevQInfo info + ); + + /******************/ + /* Function: 0x05 */ + WERROR srvsvc_NetCharDevQSetInfo( + [in] unistr *server_unc, + [in] unistr queue_name, + [in] uint32 level, + [in,switch_is(level)] srvsvc_NetCharDevQInfo info, + [in,out] uint32 *parm_error + ); + + /******************/ + /* Function: 0x06 */ + WERROR srvsvc_NetCharDevQPurge( + [in] unistr *server_unc, + [in] unistr queue_name + ); + + /******************/ + /* Function: 0x07 */ + WERROR srvsvc_NetCharDevQPurgeSelf( + [in] unistr *server_unc, + [in] unistr queue_name, + [in] unistr computer_name + ); + +/**************************/ +/* srvsvc_NetConn */ +/**************************/ + typedef struct { + uint32 conn_id; + } srvsvc_NetConnInfo0; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetConnInfo0 *array; + } srvsvc_NetConnCtr0; + + typedef struct { + uint32 conn_id; + uint32 conn_type; + uint32 num_open; + uint32 num_users; + uint32 conn_time; + unistr *user; + unistr *client; + } srvsvc_NetConnInfo1; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetConnInfo1 *array; + } srvsvc_NetConnCtr1; + + typedef union { + [case(0)] srvsvc_NetConnCtr0 *ctr0; + [case(1)] srvsvc_NetConnCtr1 *ctr1; + [default] ; + } srvsvc_NetConnCtr; + + /******************/ + /* Function: 0x08 */ + WERROR srvsvc_NetConnEnum( + [in] unistr *server_unc, + [in] unistr *path, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetConnCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + +/**************************/ +/* srvsvc_NetFile */ +/**************************/ + typedef struct { + uint32 fid; + } srvsvc_NetFileInfo2; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetFileInfo2 *array; + } srvsvc_NetFileCtr2; + + typedef struct { + uint32 fid; + uint32 permissions; + uint32 num_locks; + unistr *path; + unistr *user; + } srvsvc_NetFileInfo3; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetFileInfo3 *array; + } srvsvc_NetFileCtr3; + + typedef union { + [case(2)] srvsvc_NetFileInfo2 *info2; + [case(3)] srvsvc_NetFileInfo3 *info3; + [default] ; + } srvsvc_NetFileInfo; + + typedef union { + [case(2)] srvsvc_NetFileCtr2 *ctr2; + [case(3)] srvsvc_NetFileCtr3 *ctr3; + [default] ; + } srvsvc_NetFileCtr; + + /******************/ + /* Function: 0x09 */ + WERROR srvsvc_NetFileEnum( + [in] unistr *server_unc, + [in] unistr *path, + [in] unistr *user, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetFileCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x0a */ + WERROR srvsvc_NetFileGetInfo( + [in] unistr *server_unc, + [in] uint32 fid, + [in] uint32 level, + [out,switch_is(level)] srvsvc_NetFileInfo info + ); + + /******************/ + /* Function: 0x0b */ + WERROR srvsvc_NetFileClose( + [in] unistr *server_unc, + [in] uint32 fid + ); + +/**************************/ +/* srvsvc_NetSess */ +/**************************/ + typedef struct { + unistr *client; + } srvsvc_NetSessInfo0; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetSessInfo0 *array; + } srvsvc_NetSessCtr0; + + typedef struct { + unistr *client; + unistr *user; + uint32 num_open; + uint32 time; + uint32 idle_time; + uint32 user_flags; + } srvsvc_NetSessInfo1; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetSessInfo1 *array; + } srvsvc_NetSessCtr1; + + typedef struct { + unistr *client; + unistr *user; + uint32 num_open; + uint32 time; + uint32 idle_time; + uint32 user_flags; + unistr *client_type; + } srvsvc_NetSessInfo2; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetSessInfo2 *array; + } srvsvc_NetSessCtr2; + + typedef struct { + unistr *client; + unistr *user; + uint32 time; + uint32 idle_time; + } srvsvc_NetSessInfo10; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetSessInfo10 *array; + } srvsvc_NetSessCtr10; + + typedef struct { + unistr *client; + unistr *user; + uint32 num_open; + uint32 time; + uint32 idle_time; + uint32 user_flags; + unistr *client_type; + unistr *transport; + } srvsvc_NetSessInfo502; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetSessInfo502 *array; + } srvsvc_NetSessCtr502; + + typedef union { + [case(0)] srvsvc_NetSessCtr0 *ctr0; + [case(1)] srvsvc_NetSessCtr1 *ctr1; + [case(2)] srvsvc_NetSessCtr2 *ctr2; + [case(10)] srvsvc_NetSessCtr10 *ctr10; + [case(502)] srvsvc_NetSessCtr502 *ctr502; + [default] ; + } srvsvc_NetSessCtr; + + /******************/ + /* Function: 0x0c */ + WERROR srvsvc_NetSessEnum( + [in] unistr *server_unc, + [in] unistr *client, + [in] unistr *user, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetSessCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x0d */ + WERROR srvsvc_NetSessDel( + [in] unistr *server_unc, + [in] unistr *client, + [in] unistr *user + ); + +/**************************/ +/* srvsvc_NetShare */ +/**************************/ + typedef struct { + unistr *name; + } srvsvc_NetShareInfo0; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetShareInfo0 *array; + } srvsvc_NetShareCtr0; + + typedef struct { + unistr *name; + uint32 type; + unistr *comment; + } srvsvc_NetShareInfo1; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetShareInfo1 *array; + } srvsvc_NetShareCtr1; + + typedef struct { + unistr *name; + uint32 type; + unistr *comment; + uint32 permissions; + uint32 max_users; + uint32 current_users; + unistr *path; + unistr *password; + } srvsvc_NetShareInfo2; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetShareInfo2 *array; + } srvsvc_NetShareCtr2; + + typedef struct { + unistr *name; + uint32 type; + unistr *comment; + uint32 csc_policy; + } srvsvc_NetShareInfo501; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetShareInfo501 *array; + } srvsvc_NetShareCtr501; + + typedef struct { + unistr *name; + uint32 type; + unistr *comment; + uint32 permissions; + uint32 max_users; + uint32 current_users; + unistr *path; + unistr *password; + uint32 unknown; + [subcontext(4)] security_descriptor *sd; + } srvsvc_NetShareInfo502; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetShareInfo502 *array; + } srvsvc_NetShareCtr502; + + typedef union { + [case(0)] srvsvc_NetShareInfo0 *info0; + [case(1)] srvsvc_NetShareInfo1 *info1; + [case(2)] srvsvc_NetShareInfo2 *info2; + [case(501)] srvsvc_NetShareInfo501 *info501; + [case(502)] srvsvc_NetShareInfo502 *info502; + [default] ; + } srvsvc_NetShareInfo; + + typedef union { + [case(0)] srvsvc_NetShareCtr0 *ctr0; + [case(1)] srvsvc_NetShareCtr1 *ctr1; + [case(2)] srvsvc_NetShareCtr2 *ctr2; + [case(501)] srvsvc_NetShareCtr501 *ctr501; + [case(502)] srvsvc_NetShareCtr502 *ctr502; + [default] ; + } srvsvc_NetShareCtr; + + /******************/ + /* Function: 0x0e */ + WERROR srvsvc_NetShareAdd( + [in] unistr *server_unc, + [in] uint32 level, + [in,switch_is(level)] srvsvc_NetShareInfo info, + [in,out] uint32 *parm_error + ); + + /******************/ + /* Function: 0x0f */ + WERROR srvsvc_NetShareEnumAll ( + [in] unistr *server_unc, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetShareCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x10 */ + WERROR srvsvc_NetShareGetInfo( + [in] unistr *server_unc, + [in] unistr *share_name, + [in] uint32 level, + [out,switch_is(level)] srvsvc_NetShareInfo info + ); + + /******************/ + /* Function: 0x11 */ + WERROR srvsvc_NetShareSetInfo( + [in] unistr *server_unc, + [in] unistr *share_name, + [in] uint32 level, + [in,switch_is(level)] srvsvc_NetShareInfo info, + [in,out] uint32 *parm_error + ); + + /******************/ + /* Function: 0x12 */ + WERROR srvsvc_NetShareDel( + [in] unistr *server_unc, + [in] unistr *share_name, + [in] uint32 reserved + ); + + /******************/ + /* Function: 0x13 */ + WERROR srvsvc_NetShareDelSticky( + [in] unistr *server_unc, + [in] unistr *share_name, + [in] uint32 reserved + ); + + /******************/ + /* Function: 0x14 */ + WERROR srvsvc_NetShareCheck( + [in] unistr *server_unc, + [in] unistr *share_name, + [out] uint32 type + ); + +/**************************/ +/* srvsvc_NetSrv */ +/**************************/ + typedef struct { + uint32 platform_id; + unistr *server_unc; + } srvsvc_NetSrvInfo100; + + typedef struct { + uint32 platform_id; + unistr *server_unc; + uint32 ver_major; + uint32 ver_minor; + uint32 type; + unistr *comment; + } srvsvc_NetSrvInfo101; + + typedef struct { + uint32 platform_id; + unistr *server_unc; + uint32 ver_major; + uint32 ver_minor; + uint32 type; + unistr *comment; + uint32 users; + uint32 disc; + uint32 hidden; + uint32 announce; + uint32 anndelta; + uint32 licences; + unistr *userpath; + } srvsvc_NetSrvInfo102; + + typedef struct { + uint32 ulist_mtime; + uint32 glist_mtime; + uint32 alist_mtime; + unistr *alerts; + uint32 security; + uint32 numadmin; + uint32 lanmask; + unistr *guestaccount; + uint32 chdevs; + uint32 chdevqs; + uint32 chdevjobs; + uint32 connections; + uint32 shares; + uint32 openfiles; + uint32 sessopen; + uint32 sesssvc; + uint32 sessreqs; + uint32 opensearch; + uint32 activelocks; + uint32 sizereqbufs; + uint32 numbigbufs; + uint32 numfiletasks; + uint32 alertsched; + uint32 eroralert; + uint32 logonalert; + uint32 accessalert; + uint32 diskalert; + uint32 netioalert; + uint32 maxaudits; + unistr *srvheuristics; + } srvsvc_NetSrvInfo402; + + typedef struct { + uint32 ulist_mtime; + uint32 glist_mtime; + uint32 alist_mtime; + unistr *alerts; + uint32 security; + uint32 numadmin; + uint32 lanmask; + unistr *guestaccount; + uint32 chdevs; + uint32 chdevqs; + uint32 chdevjobs; + uint32 connections; + uint32 shares; + uint32 openfiles; + uint32 sessopen; + uint32 sesssvc; + uint32 sessreqs; + uint32 opensearch; + uint32 activelocks; + uint32 sizereqbufs; + uint32 numbigbufs; + uint32 numfiletasks; + uint32 alertsched; + uint32 eroralert; + uint32 logonalert; + uint32 accessalert; + uint32 diskalert; + uint32 netioalert; + uint32 maxaudits; + unistr *srvheuristics; + uint32 auditedevents; + uint32 auditprofile; + unistr *autopath; + } srvsvc_NetSrvInfo403; + + typedef struct { + uint32 sessopen; + uint32 sesssvc; + uint32 opensearch; + uint32 sizereqbufs; + uint32 initworkitems; + uint32 maxworkitems; + uint32 rawworkitems; + uint32 irpstacksize; + uint32 maxrawbuflen; + uint32 sessusers; + uint32 sessconns; + uint32 maxpagedmemoryusage; + uint32 maxnonpagedmemoryusage; + uint32 enablesoftcompat; + uint32 enableforcedlogoff; + uint32 timesource; + uint32 acceptdownlevelapis; + uint32 lmannounce; + } srvsvc_NetSrvInfo502; + + typedef struct{ + uint32 sessopen; + uint32 sesssvc; + uint32 opensearch; + uint32 sizereqbufs; + uint32 initworkitems; + uint32 maxworkitems; + uint32 rawworkitems; + uint32 irpstacksize; + uint32 maxrawbuflen; + uint32 sessusers; + uint32 sessconns; + uint32 maxpagedmemoryusage; + uint32 maxnonpagedmemoryusage; + uint32 enablesoftcompat; + uint32 enableforcedlogoff; + uint32 timesource; + uint32 acceptdownlevelapis; + uint32 lmannounce; + unistr *domain; + uint32 maxcopyreadlen; + uint32 maxcopywritelen; + uint32 minkeepsearch; + uint32 maxkeepsearch; + uint32 minkeepcomplsearch; + uint32 maxkeepcomplsearch; + uint32 threadcountadd; + uint32 numlockthreads; + uint32 scavtimeout; + uint32 minrcvqueue; + uint32 minfreeworkitems; + uint32 xactmemsize; + uint32 threadpriority; + uint32 maxmpxct; + uint32 oplockbreakwait; + uint32 oplockbreakresponsewait; + uint32 enableoplocks; + uint32 enableoplockforceclose; + uint32 enablefcbopens; + uint32 enableraw; + uint32 enablesharednetdrives; + uint32 minfreeconnections; + uint32 maxfreeconnections; + } srvsvc_NetSrvInfo503; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo599; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1005; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1010; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1016; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1017; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1018; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1107; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1501; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1502; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1503; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1506; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1509; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1510; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1511; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1512; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1513; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1514; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1515; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1516; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1518; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1520; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1521; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1522; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1523; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1524; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1525; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1528; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1529; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1530; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1533; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1534; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1535; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1536; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1537; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1538; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1539; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1540; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1541; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1542; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1543; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1544; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1545; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1546; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1547; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1548; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1549; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1550; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1552; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1553; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1554; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1555; + + typedef struct{ + uint32 dummy; + } srvsvc_NetSrvInfo1556; + + + typedef union{ + [case(100)] srvsvc_NetSrvInfo100 *info100; + [case(101)] srvsvc_NetSrvInfo101 *info101; + [case(102)] srvsvc_NetSrvInfo102 *info102; + [case(402)] srvsvc_NetSrvInfo402 *info402; + [case(403)] srvsvc_NetSrvInfo403 *info403; + [case(502)] srvsvc_NetSrvInfo502 *info502; + [case(503)] srvsvc_NetSrvInfo503 *info503; + [case(599)] srvsvc_NetSrvInfo599 *info599; + [case(1005)] srvsvc_NetSrvInfo1005 *info1005; + [case(1010)] srvsvc_NetSrvInfo1010 *info1010; + [case(1016)] srvsvc_NetSrvInfo1016 *info1016; + [case(1017)] srvsvc_NetSrvInfo1017 *info1017; + [case(1018)] srvsvc_NetSrvInfo1018 *info1018; + [case(1107)] srvsvc_NetSrvInfo1107 *info1107; + [case(1501)] srvsvc_NetSrvInfo1501 *info1501; + [case(1502)] srvsvc_NetSrvInfo1502 *info1502; + [case(1503)] srvsvc_NetSrvInfo1503 *info1503; + [case(1506)] srvsvc_NetSrvInfo1506 *info1506; + [case(1509)] srvsvc_NetSrvInfo1509 *info1509; + [case(1510)] srvsvc_NetSrvInfo1510 *info1510; + [case(1511)] srvsvc_NetSrvInfo1511 *info1511; + [case(1512)] srvsvc_NetSrvInfo1512 *info1512; + [case(1513)] srvsvc_NetSrvInfo1513 *info1513; + [case(1514)] srvsvc_NetSrvInfo1514 *info1514; + [case(1515)] srvsvc_NetSrvInfo1515 *info1515; + [case(1516)] srvsvc_NetSrvInfo1516 *info1516; + [case(1518)] srvsvc_NetSrvInfo1518 *info1518; + [case(1520)] srvsvc_NetSrvInfo1520 *info1520; + [case(1521)] srvsvc_NetSrvInfo1521 *info1521; + [case(1522)] srvsvc_NetSrvInfo1522 *info1522; + [case(1523)] srvsvc_NetSrvInfo1523 *info1523; + [case(1524)] srvsvc_NetSrvInfo1524 *info1524; + [case(1525)] srvsvc_NetSrvInfo1525 *info1525; + [case(1528)] srvsvc_NetSrvInfo1528 *info1528; + [case(1529)] srvsvc_NetSrvInfo1529 *info1529; + [case(1530)] srvsvc_NetSrvInfo1530 *info1530; + [case(1533)] srvsvc_NetSrvInfo1533 *info1533; + [case(1534)] srvsvc_NetSrvInfo1534 *info1534; + [case(1535)] srvsvc_NetSrvInfo1535 *info1535; + [case(1536)] srvsvc_NetSrvInfo1536 *info1536; + [case(1537)] srvsvc_NetSrvInfo1537 *info1537; + [case(1538)] srvsvc_NetSrvInfo1538 *info1538; + [case(1539)] srvsvc_NetSrvInfo1539 *info1539; + [case(1540)] srvsvc_NetSrvInfo1540 *info1540; + [case(1541)] srvsvc_NetSrvInfo1541 *info1541; + [case(1542)] srvsvc_NetSrvInfo1542 *info1542; + [case(1543)] srvsvc_NetSrvInfo1543 *info1543; + [case(1544)] srvsvc_NetSrvInfo1544 *info1544; + [case(1545)] srvsvc_NetSrvInfo1545 *info1545; + [case(1546)] srvsvc_NetSrvInfo1546 *info1546; + [case(1547)] srvsvc_NetSrvInfo1547 *info1547; + [case(1548)] srvsvc_NetSrvInfo1548 *info1548; + [case(1549)] srvsvc_NetSrvInfo1549 *info1549; + [case(1550)] srvsvc_NetSrvInfo1550 *info1550; + [case(1552)] srvsvc_NetSrvInfo1552 *info1552; + [case(1553)] srvsvc_NetSrvInfo1553 *info1553; + [case(1554)] srvsvc_NetSrvInfo1554 *info1554; + [case(1555)] srvsvc_NetSrvInfo1555 *info1555; + [case(1556)] srvsvc_NetSrvInfo1556 *info1556; + [default]; + } srvsvc_NetSrvInfo; + + /******************/ + /* Function: 0x15 */ + WERROR srvsvc_NetSrvGetInfo( + [in] unistr *server_unc, + [in] uint32 level, + [out,switch_is(level)] srvsvc_NetSrvInfo info + ); + + /******************/ + /* Function: 0x16 */ + WERROR srvsvc_NetSrvSetInfo( + [in] unistr *server_unc, + [in] uint32 level, + [in,switch_is(level)] srvsvc_NetSrvInfo info, + [in,out] uint32 *parm_error + ); + +/**************************/ +/* srvsvc_NetDisk */ +/**************************/ + typedef struct { + uint32 unknown; + lstring disk; + uint16 unknown2; + } srvsvc_NetDiskInfo0; + + typedef struct { + uint32 unknown; + uint32 count; + [size_is(count)] srvsvc_NetDiskInfo0 array[]; + } srvsvc_NetDiskCtr0; + + typedef union { + [case(0)] srvsvc_NetDiskCtr0 *ctr0; + } srvsvc_NetDiskCtr; + + /******************/ + /* Function: 0x17 */ + WERROR srvsvc_NetDiskEnum( + [in] unistr *server_unc, + [in] uint32 level, + [out] uint32 count, + [in,switch_is(level)] srvsvc_NetDiskCtr ctr, + [out] srvsvc_NetDiskCtr0 *ctr0, + [in] uint32 unknown, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x18 */ + NTSTATUS srvsvc_NETRSERVERSTATISTICSGET( + ); + + /******************/ + /* Function: 0x19 */ + NTSTATUS srvsvc_NETRSERVERTRANSPORTADD( + ); + +/**************************/ +/* srvsvc_NetTransport */ +/**************************/ + typedef struct { + uint32 count; + uint8 addr[count]; + } srvsvc_NetTransportAddress; + + typedef struct { + uint32 vcs; + unistr *name; + srvsvc_NetTransportAddress *addr; + uint32 addr_len; + unistr *net_addr; + } srvsvc_NetTransportInfo0; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetTransportInfo0 *array; + } srvsvc_NetTransportCtr0; + + typedef struct { + uint32 vcs; + unistr *name; + srvsvc_NetTransportAddress *addr; + uint32 addr_len; + unistr *net_addr; + unistr *domain; + } srvsvc_NetTransportInfo1; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetTransportInfo1 *array; + } srvsvc_NetTransportCtr1; + + typedef struct { + uint32 dummy; + } srvsvc_NetTransportInfo2; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetTransportInfo2 *array; + } srvsvc_NetTransportCtr2; + + typedef struct { + uint32 dummy; + } srvsvc_NetTransportInfo3; + + typedef struct { + uint32 count; + [size_is(count)] srvsvc_NetTransportInfo3 *array; + } srvsvc_NetTransportCtr3; + + typedef union { + [case(0)] srvsvc_NetTransportInfo0 *info0; + [case(1)] srvsvc_NetTransportInfo1 *info1; + [case(2)] srvsvc_NetTransportInfo2 *info2; + [case(3)] srvsvc_NetTransportInfo3 *info3; + [default]; + } srvsvc_NetTransportInfo; + + typedef union { + [case(0)] srvsvc_NetTransportCtr0 *ctr0; + [case(1)] srvsvc_NetTransportCtr1 *ctr1; + [case(2)] srvsvc_NetTransportCtr2 *ctr2; + [case(3)] srvsvc_NetTransportCtr3 *ctr3; + [default]; + } srvsvc_NetTransportCtr; + + /******************/ + /* Function: 0x1a */ + WERROR srvsvc_NetTransportEnum( + [in] unistr *server_unc, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetTransportCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x1b */ + NTSTATUS srvsvc_NETRSERVERTRANSPORTDEL( + ); + + /******************/ + /* Function: 0x1c */ + NTSTATUS srvsvc_NET_REMOTE_TOD( + ); + + /******************/ + /* Function: 0x1d */ + NTSTATUS srvsvc_NETRSERVERSETSERVICEBITS( + ); + + /******************/ + /* Function: 0x1e */ + NTSTATUS srvsvc_NETRPRPATHTYPE( + ); + + /******************/ + /* Function: 0x1f */ + NTSTATUS srvsvc_NETRPRPATHCANONICALIZE( + ); + + /******************/ + /* Function: 0x20 */ + NTSTATUS srvsvc_NETRPRPATHCOMPARE( + ); + + /******************/ + /* Function: 0x21 */ + NTSTATUS srvsvc_NET_NAME_VALIDATE( + ); + + /******************/ + /* Function: 0x22 */ + NTSTATUS srvsvc_NETRPRNAMECANONICALIZE( + ); + + /******************/ + /* Function: 0x23 */ + NTSTATUS srvsvc_NETRPRNAMECOMPARE( + ); + + /******************/ + /* Function: 0x24 */ + /* Note, there must be some way to return entries read vs + total entries ... */ + WERROR srvsvc_NetShareEnum( + [in] unistr *server_unc, + [in,out] uint32 level, + [in,out,switch_is(level)] srvsvc_NetShareCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + /******************/ + /* Function: 0x25 */ + NTSTATUS srvsvc_NETRSHAREDELSTART( + ); + + /******************/ + /* Function: 0x26 */ + NTSTATUS srvsvc_NETRSHAREDELCOMMIT( + ); + + /******************/ + /* Function: 0x27 */ + NTSTATUS srvsvc_NET_FILE_QUERY_SECDESC( + ); + + /******************/ + /* Function: 0x28 */ + NTSTATUS srvsvc_NET_FILE_SET_SECDESC( + ); + + /******************/ + /* Function: 0x29 */ + NTSTATUS srvsvc_NETRSERVERTRANSPORTADDEX( + ); + + /******************/ + /* Function: 0x2a */ + NTSTATUS srvsvc_NETRSERVERSETSERVICEBITSEX( + ); + + /******************/ + /* Function: 0x2b */ + NTSTATUS srvsvc_NETRDFSGETVERSION( + ); + + /******************/ + /* Function: 0x2c */ + NTSTATUS srvsvc_NETRDFSCREATELOCALPARTITION( + ); + + /******************/ + /* Function: 0x2d */ + NTSTATUS srvsvc_NETRDFSDELETELOCALPARTITION( + ); + + /******************/ + /* Function: 0x2e */ + NTSTATUS srvsvc_NETRDFSSETLOCALVOLUMESTATE( + ); + + /******************/ + /* Function: 0x2f */ + NTSTATUS srvsvc_NETRDFSSETSERVERINFO( + ); + + /******************/ + /* Function: 0x30 */ + NTSTATUS srvsvc_NETRDFSCREATEEXITPOINT( + ); + + /******************/ + /* Function: 0x31 */ + NTSTATUS srvsvc_NETRDFSDELETEEXITPOINT( + ); + + /******************/ + /* Function: 0x32 */ + NTSTATUS srvsvc_NETRDFSMODIFYPREFIX( + ); + + /******************/ + /* Function: 0x33 */ + NTSTATUS srvsvc_NETRDFSFIXLOCALVOLUME( + ); + + /******************/ + /* Function: 0x34 */ + NTSTATUS srvsvc_NETRDFSMANAGERREPORTSITEINFO( + ); + + /******************/ + /* Function: 0x35 */ + NTSTATUS srvsvc_NETRSERVERTRANSPORTDELEX( + ); +} diff --git a/source/librpc/idl/trkwks.idl b/source/librpc/idl/trkwks.idl new file mode 100644 index 00000000000..c91e1ea7884 --- /dev/null +++ b/source/librpc/idl/trkwks.idl @@ -0,0 +1,15 @@ +/* + distributed key tracking services +*/ + +[ + uuid(300f3532-38cc-11d0-a3f0-0020af6b0add), + version(1.2) +] +interface trkwks +{ + + /*****************/ + /* Function 0x00 */ + WERROR trkwks_Unknown0(); +} diff --git a/source/librpc/idl/w32time.idl b/source/librpc/idl/w32time.idl new file mode 100644 index 00000000000..ef411b126a6 --- /dev/null +++ b/source/librpc/idl/w32time.idl @@ -0,0 +1,16 @@ +/* + w32time interface definitions +*/ + +[ + uuid(8fb6d884-2388-11d0-8c35-00c04fda2795), + endpoints(srvsvc,atsvc,browser,keysvc,wkssvc), + version(4.1) +] +interface w32time +{ + + /*****************/ + /* Function 0x00 */ + WERROR w32time_Unknown0(); +} diff --git a/source/librpc/idl/winreg.idl b/source/librpc/idl/winreg.idl new file mode 100644 index 00000000000..54cba24760b --- /dev/null +++ b/source/librpc/idl/winreg.idl @@ -0,0 +1,299 @@ +#include "idl_types.h" + +/* + winreg interface definition +*/ + +[ uuid(338cd001-2244-31f1-aaaa-900038001003), + version(1.0), + pointer_default(unique) +] interface winreg +{ + typedef struct { + [value(strlen_m_term(r->name)*2)] uint16 name_len; + [value(r->name_len)] uint16 name_size; + unistr *name; + } winreg_String; + + typedef struct { + uint16 unknown0; + uint16 unknown1; + } winreg_OpenUnknown; + + /******************/ + /* Function: 0x00 */ + WERROR winreg_OpenHKCR( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x01 */ + WERROR winreg_OpenHKCU( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x02 */ + WERROR winreg_OpenHKLM( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x03 */ + WERROR winreg_OpenHKPD( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x04 */ + WERROR winreg_OpenHKU( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x05 */ + WERROR winreg_CloseKey( + [in,out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x06 */ + WERROR winreg_CreateKey( + ); + + /******************/ + /* Function: 0x07 */ + WERROR winreg_DeleteKey( + [in,ref] policy_handle *handle, + [in] winreg_String key + ); + + /******************/ + /* Function: 0x08 */ + WERROR winreg_DeleteValue( + [in,ref] policy_handle *handle, + [in] winreg_String value + ); + + typedef struct { + uint32 low; + uint32 high; + } winreg_Time; + + typedef struct { + uint32 unknown; + winreg_String key_name; + } winreg_EnumKeyNameRequest; + + typedef struct { + uint32 unknown1; + uint32 unknown2; + lstring name; + } winreg_EnumKeyNameResponse; + + /******************/ + /* Function: 0x09 */ + WERROR winreg_EnumKey( + [in,ref] policy_handle *handle, + [in] uint32 enum_index, + [in,out] uint16 key_name_len, + [in,out] uint16 unknown, + [in] winreg_EnumKeyNameRequest *in_name, + [out] winreg_EnumKeyNameResponse *out_name, + [in,out] winreg_String *class, + [in,out] winreg_Time *last_changed_time + ); + + typedef struct { + uint32 max_len; + uint32 offset; + uint32 len; + uint16 buffer[len]; + } winreg_Uint16buf; + + typedef struct { + uint16 len; + uint16 max_len; + winreg_Uint16buf *buf; + } winreg_EnumValueName; + + typedef struct { + uint32 max_len; + uint32 offset; + uint32 len; + uint8 buffer[len]; + } winreg_Uint8buf; + + /******************/ + /* Function: 0x0a */ + WERROR winreg_EnumValue( + [in,ref] policy_handle *handle, + [in] uint32 enum_index, + [in,out,ref] winreg_EnumValueName *name, + [in,out] uint32 *type, + [in,out] winreg_Uint8buf *value, + [in,out] uint32 *requested_len, + [in,out] uint32 *returned_len + ); + + /******************/ + /* Function: 0x0b */ + WERROR winreg_FlushKey( + [in,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x0c */ + WERROR winreg_GetKeySecurity( + ); + + /******************/ + /* Function: 0x0d */ + WERROR winreg_LoadKey( + ); + + /******************/ + /* Function: 0x0e */ + WERROR winreg_NotifyChangeKeyValue( + ); + + /******************/ + /* Function: 0x0f */ + WERROR winreg_OpenKey( + [in,ref] policy_handle *handle, + [in] winreg_String keyname, + [in] uint32 unknown, + [in] uint32 access_mask, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x10 */ + WERROR winreg_QueryInfoKey( + [in,ref] policy_handle *handle, + [in] winreg_String class, + [out] winreg_String class, + [out] uint32 num_subkeys, + [out] uint32 max_subkeylen, + [out] uint32 max_subkeysize, + [out] uint32 num_values, + [out] uint32 max_valnamelen, + [out] uint32 max_valbufsize, + [out] uint32 secdescsize, + [out] winreg_Time last_changed_time + ); + + /******************/ + /* Function: 0x11 */ + WERROR winreg_QueryValue( + ); + + /******************/ + /* Function: 0x12 */ + WERROR winreg_ReplaceKey( + ); + + /******************/ + /* Function: 0x13 */ + WERROR winreg_RestoreKey( + ); + + /******************/ + /* Function: 0x14 */ + WERROR winreg_SaveKey( + ); + + /******************/ + /* Function: 0x15 */ + WERROR winreg_SetKeySecurity( + ); + + /******************/ + /* Function: 0x16 */ + WERROR winreg_SetValue( + ); + + /******************/ + /* Function: 0x17 */ + WERROR winreg_UnLoadKey( + ); + + /******************/ + /* Function: 0x18 */ + WERROR winreg_InitiateSystemShutdown( + ); + + /******************/ + /* Function: 0x19 */ + WERROR winreg_AbortSystemShutdown( + ); + + /******************/ + /* Function: 0x1a */ + WERROR winreg_GetVersion( + [in,ref] policy_handle *handle, + [out] uint32 version + ); + + /******************/ + /* Function: 0x1b */ + WERROR winreg_OpenHKCC( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x1c */ + WERROR winreg_OpenHKDD( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x1d */ + WERROR winreg_QueryMultipleValues( + ); + + /******************/ + /* Function: 0x1e */ + WERROR winreg_InitiateSystemShutdownEx( + ); + + /******************/ + /* Function: 0x1f */ + WERROR winreg_SaveKeyEx( + ); + + /******************/ + /* Function: 0x20 */ + WERROR winreg_OpenHKPT( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x21 */ + WERROR winreg_OpenHKPN( + [in] winreg_OpenUnknown *unknown, + [in] uint32 access_required, + [out,ref] policy_handle *handle + ); + + /******************/ + /* Function: 0x21 */ + WERROR winreg_QueryMultipleValues2( + ); +} diff --git a/source/librpc/idl/wkssvc.idl b/source/librpc/idl/wkssvc.idl new file mode 100644 index 00000000000..9a92d4e3e00 --- /dev/null +++ b/source/librpc/idl/wkssvc.idl @@ -0,0 +1,249 @@ +#include "idl_types.h" + +/* + wkssvc interface definitions +*/ + +[ uuid(6bffd098-a112-3610-9833-46c3f87e345a), + version(1.0), + pointer_default(unique) +] interface wkssvc +{ + +#define BOOL uint32 + + /******************/ + /* Function: 0x00 */ + + typedef struct { + uint32 platform_id; + unistr *server; + unistr *domain; + uint32 ver_major; + uint32 ver_minor; + } wkssvc_NetWkstaInfo100; + + typedef struct { + uint32 platform_id; + unistr *server; + unistr *domain; + uint32 ver_major; + uint32 ver_minor; + unistr *lan_root; + } wkssvc_NetWkstaInfo101; + + typedef struct { + uint32 platform_id; + unistr *server; + unistr *domain; + uint32 ver_major; + uint32 ver_minor; + unistr *lan_root; + uint32 logged_on_users; + } wkssvc_NetWkstaInfo102; + + typedef struct { + uint32 char_wait; + uint32 collection_time; + uint32 maximum_collection_count; + uint32 keep_connection; + uint32 max_commands; + uint32 session_timeout; + uint32 size_char_buf; + uint32 max_threads; + uint32 lock_quota; + uint32 lock_increment; + uint32 lock_maximum; + uint32 pipe_increment; + uint32 pipe_maximum; + uint32 cache_file_timeout; + uint32 dormant_file_limit; + uint32 read_ahead_throughput; + uint32 num_mailslot_buffers; + uint32 num_srv_announce_buffers; + uint32 max_illegal_dgram_events; + uint32 dgram_event_reset_freq; + BOOL log_election_packets; + BOOL use_opportunistic_locking; + BOOL use_unlock_behind; + BOOL use_close_behind; + BOOL buf_named_pipes; + BOOL use_lock_read_unlock; + BOOL utilize_nt_caching; + BOOL use_raw_read; + BOOL use_raw_write; + BOOL use_write_raw_data; + BOOL use_encryption; + BOOL buf_files_deny_write; + BOOL buf_read_only_files; + BOOL force_core_create_mode; + BOOL use_512_byte_max_transfer; + } wkssvc_NetWkstaInfo502; + + typedef union { + [case(100)] wkssvc_NetWkstaInfo100 *info100; + [case(101)] wkssvc_NetWkstaInfo101 *info101; + [case(102)] wkssvc_NetWkstaInfo102 *info102; + [case(502)] wkssvc_NetWkstaInfo502 *info502; + } wkssvc_NetWkstaInfo; + + WERROR wkssvc_NetWkstaGetInfo( + [in] unistr *server_name, + [in] uint32 level, + [out,switch_is(level)] wkssvc_NetWkstaInfo info + ); + + + /******************/ + /* Function: 0x01 */ + WERROR wkssvc_NetWkstaSetInfo( + [in] unistr *server_name, + [in] uint32 level, + [in,switch_is(level)] wkssvc_NetWkstaInfo info, + [in,out] uint32 *parm_error + ); + + /*****************************/ + /* Function 0x02 */ + WERROR WKSSVC_NETRWKSTAUSERENUM (); + + /*****************************/ + /* Function 0x03 */ + WERROR WKSSVC_NETRWKSTAUSERGETINFO (); + + /*****************************/ + /* Function 0x04 */ + WERROR WKSSVC_NETRWKSTAUSERSETINFO (); + + + /*****************************/ + /* Function 0x05 */ + + typedef struct { + uint32 quality_of_service; + uint32 vc_count; + unistr *name; + unistr *address; + uint32 wan_link; + } wkssvc_NetWkstaTransportInfo0; + + typedef struct { + uint32 count; + [size_is(count)] wkssvc_NetWkstaTransportInfo0 *array; + } wkssvc_NetWkstaTransportCtr0; + + typedef union { + [case(0)] wkssvc_NetWkstaTransportCtr0 *ctr0; + [default] ; + } wkssvc_NetWkstaTransportCtr; + + WERROR wkssvc_NetWkstaTransportEnum ( + [in] unistr *server_name, + [in,out] uint32 level, + [in,out,switch_is(level)] wkssvc_NetWkstaTransportCtr ctr, + [in] uint32 max_buffer, + [out] uint32 totalentries, + [in,out] uint32 *resume_handle + ); + + + /*****************************/ + /* Function 0x06 */ + WERROR WKSSVC_NETRWKSTATRANSPORTADD (); + + /*****************************/ + /* Function 0x07 */ + WERROR WKSSVC_NETRWKSTATRANSPORTDEL (); + + /*****************************/ + /* Function 0x08 */ + WERROR WKSSVC_NETRUSEADD (); + + /*****************************/ + /* Function 0x09 */ + WERROR WKSSVC_NETRUSEGETINFO (); + + /*****************************/ + /* Function 0x0a */ + WERROR WKSSVC_NETRUSEDEL (); + + /*****************************/ + /* Function 0x0b */ + WERROR WKSSVC_NETRUSEENUM (); + + /*****************************/ + /* Function 0x0c */ + WERROR WKSSVC_NETRMESSAGEBUFFERSEND (); + + /*****************************/ + /* Function 0x0d */ + WERROR WKSSVC_NETRWORKSTATIONSTATISTICSGET (); + + /*****************************/ + /* Function 0x0e */ + WERROR WKSSVC_NETRLOGONDOMAINNAMEADD (); + + /*****************************/ + /* Function 0x0f */ + WERROR WKSSVC_NETRLOGONDOMAINNAMEDEL (); + + /*****************************/ + /* Function 0x10 */ + WERROR WKSSVC_NETRJOINDOMAIN (); + + /*****************************/ + /* Function 0x11 */ + WERROR WKSSVC_NETRUNJOINDOMAIN (); + + /*****************************/ + /* Function 0x12 */ + WERROR WKSSVC_NETRRENAMEMACHINEINDOMAIN (); + + /*****************************/ + /* Function 0x13 */ + WERROR WKSSVC_NETRVALIDATENAME (); + + /*****************************/ + /* Function 0x14 */ + WERROR WKSSVC_NETRGETJOININFORMATION (); + + /*****************************/ + /* Function 0x15 */ + WERROR WKSSVC_NETRGETJOINABLEOUS (); + + /*****************************/ + /* Function 0x16 */ + WERROR WKSSVC_NETRJOINDOMAIN2 (); + + /*****************************/ + /* Function 0x17 */ + WERROR WKSSVC_NETRUNJOINDOMAIN2 (); + + /*****************************/ + /* Function 0x18 */ + WERROR WKSSVC_NETRRENAMEMACHINEINDOMAIN2 (); + + /*****************************/ + /* Function 0x19 */ + WERROR WKSSVC_NETRVALIDATENAME2 (); + + /*****************************/ + /* Function 0x1a */ + WERROR WKSSVC_NETRGETJOINABLEOUS2 (); + + /*****************************/ + /* Function 0x1b */ + WERROR WKSSVC_NETRADDALTERNATECOMPUTERNAME (); + + /*****************************/ + /* Function 0x1c */ + WERROR WKSSVC_NETRREMOVEALTERNATECOMPUTERNAME (); + + /*****************************/ + /* Function 0x1d */ + WERROR WKSSVC_NETRSETPRIMARYCOMPUTERNAME (); + + /*****************************/ + /* Function 0x1e */ + WERROR WKSSVC_NETRENUMERATECOMPUTERNAMES (); +} diff --git a/source/librpc/idl/wzcsvc.idl b/source/librpc/idl/wzcsvc.idl new file mode 100644 index 00000000000..167496e3cc7 --- /dev/null +++ b/source/librpc/idl/wzcsvc.idl @@ -0,0 +1,15 @@ +/* + windows zero-configuration service +*/ + +[ + uuid(378e52b0-c0a9-11cf-822d-00aa0051e40f), + version(1.0) +] +interface wzcsvc +{ + + /*****************/ + /* Function 0x00 */ + WERROR wzcsvc_Unknown0(); +} diff --git a/source/librpc/ndr/libndr.h b/source/librpc/ndr/libndr.h new file mode 100644 index 00000000000..97f36b78d0c --- /dev/null +++ b/source/librpc/ndr/libndr.h @@ -0,0 +1,246 @@ +/* + Unix SMB/CIFS implementation. + rpc interface definitions + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + this provides definitions for the libcli/rpc/ MSRPC library +*/ + + +/* offset lists are used to allow a push/pull function to find the + start of an encapsulating structure */ +struct ndr_ofs_list { + uint32 offset; + struct ndr_ofs_list *next; +}; + + +/* this is the base structure passed to routines that + parse MSRPC formatted data + + note that in Samba4 we use separate routines and structures for + MSRPC marshalling and unmarshalling. Also note that these routines + are being kept deliberately very simple, and are not tied to a + particular transport +*/ +struct ndr_pull { + uint32 flags; /* LIBNDR_FLAG_* */ + char *data; + uint32 data_size; + uint32 offset; + TALLOC_CTX *mem_ctx; + + /* this points at a list of offsets to the structures being processed. + The first element in the list is the current structure */ + struct ndr_ofs_list *ofs_list; +}; + +struct ndr_pull_save { + uint32 data_size; + uint32 offset; + struct ndr_pull_save *next; +}; + +/* structure passed to functions that generate NDR formatted data */ +struct ndr_push { + uint32 flags; /* LIBNDR_FLAG_* */ + char *data; + uint32 alloc_size; + uint32 offset; + TALLOC_CTX *mem_ctx; + + /* this is used to ensure we generate unique reference IDs */ + uint32 ptr_count; + + /* this points at a list of offsets to the structures being processed. + The first element in the list is the current structure */ + struct ndr_ofs_list *ofs_list; + + /* this list is used by the [relative] code to find the offsets */ + struct ndr_ofs_list *relative_list, *relative_list_end; +}; + +struct ndr_push_save { + uint32 offset; + struct ndr_push_save *next; +}; + + +/* structure passed to functions that print IDL structures */ +struct ndr_print { + uint32 flags; /* LIBNDR_FLAG_* */ + TALLOC_CTX *mem_ctx; + uint32 depth; + void (*print)(struct ndr_print *, const char *, ...); + void *private; +}; + +#define LIBNDR_FLAG_BIGENDIAN (1<<0) +#define LIBNDR_FLAG_NOALIGN (1<<1) + +#define LIBNDR_FLAG_STR_ASCII (1<<2) +#define LIBNDR_FLAG_STR_LEN4 (1<<3) +#define LIBNDR_FLAG_STR_SIZE4 (1<<4) +#define LIBNDR_FLAG_STR_NOTERM (1<<5) +#define LIBNDR_FLAG_STR_NULLTERM (1<<6) +#define LIBNDR_FLAG_STR_SIZE2 (1<<7) +#define LIBNDR_STRING_FLAGS (0xFC) + +#define LIBNDR_FLAG_REF_ALLOC (1<<10) +#define LIBNDR_FLAG_REMAINING (1<<11) +#define LIBNDR_FLAG_ALIGN2 (1<<12) +#define LIBNDR_FLAG_ALIGN4 (1<<13) +#define LIBNDR_FLAG_ALIGN8 (1<<14) + +#define LIBNDR_ALIGN_FLAGS (LIBNDR_FLAG_ALIGN2|LIBNDR_FLAG_ALIGN4|LIBNDR_FLAG_ALIGN8) + +#define LIBNDR_PRINT_ARRAY_HEX (1<<15) +#define LIBNDR_PRINT_SET_VALUES (1<<16) + +/* used to force a section of IDL to be little-endian */ +#define LIBNDR_FLAG_LITTLE_ENDIAN (1<<17) + + +/* useful macro for debugging */ +#define NDR_PRINT_DEBUG(type, p) ndr_print_debug((ndr_print_fn_t)ndr_print_ ##type, #p, p) +#define NDR_PRINT_UNION_DEBUG(type, level, p) ndr_print_union_debug((ndr_print_union_fn_t)ndr_print_ ##type, #p, level, p) +#define NDR_PRINT_FUNCTION_DEBUG(type, flags, p) ndr_print_function_debug((ndr_print_function_t)ndr_print_ ##type, #type, flags, p) +#define NDR_PRINT_BOTH_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_BOTH, p) +#define NDR_PRINT_OUT_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_OUT, p) +#define NDR_PRINT_IN_DEBUG(type, p) NDR_PRINT_FUNCTION_DEBUG(type, NDR_IN | NDR_SET_VALUES, p) + + +enum ndr_err_code { + NDR_ERR_CONFORMANT_SIZE, + NDR_ERR_ARRAY_SIZE, + NDR_ERR_BAD_SWITCH, + NDR_ERR_OFFSET, + NDR_ERR_RELATIVE, + NDR_ERR_CHARCNV, + NDR_ERR_LENGTH, + NDR_ERR_SUBCONTEXT, + NDR_ERR_STRING, + NDR_ERR_VALIDATE, + NDR_ERR_BUFSIZE, + NDR_ERR_ALLOC +}; + +/* + flags passed to control parse flow +*/ +#define NDR_SCALARS 1 +#define NDR_BUFFERS 2 + +/* + flags passed to ndr_print_*() +*/ +#define NDR_IN 1 +#define NDR_OUT 2 +#define NDR_BOTH 3 +#define NDR_SET_VALUES 4 + +#define NDR_PULL_NEED_BYTES(ndr, n) do { \ + if ((n) > ndr->data_size || ndr->offset + (n) > ndr->data_size) { \ + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull bytes %u", n); \ + } \ +} while(0) + +#define NDR_ALIGN(ndr, n) ndr_align_size(ndr->offset, n) + +#define NDR_PULL_ALIGN(ndr, n) do { \ + if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \ + ndr->offset = (ndr->offset + (n-1)) & ~(n-1); \ + } \ + if (ndr->offset >= ndr->data_size) { \ + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, "Pull align %u", n); \ + } \ +} while(0) + +#define NDR_PUSH_NEED_BYTES(ndr, n) NDR_CHECK(ndr_push_expand(ndr, ndr->offset+(n))) + +#define NDR_PUSH_ALIGN(ndr, n) do { \ + if (!(ndr->flags & LIBNDR_FLAG_NOALIGN)) { \ + uint32 _pad = ((ndr->offset + (n-1)) & ~(n-1)) - ndr->offset; \ + while (_pad--) NDR_CHECK(ndr_push_uint8(ndr, 0)); \ + } \ +} while(0) + + +/* these are used to make the error checking on each element in libndr + less tedious, hopefully making the code more readable */ +#define NDR_CHECK(call) do { NTSTATUS _status; \ + _status = call; \ + if (!NT_STATUS_IS_OK(_status)) \ + return _status; \ + } while (0) + + +#define NDR_ALLOC_SIZE(ndr, s, size) do { \ + (s) = talloc(ndr->mem_ctx, size); \ + if ((size) && !(s)) return ndr_pull_error(ndr, NDR_ERR_ALLOC, \ + "Alloc %u failed\n", \ + size); \ + } while (0) + +#define NDR_ALLOC(ndr, s) NDR_ALLOC_SIZE(ndr, s, sizeof(*(s))) + + +#define NDR_ALLOC_N_SIZE(ndr, s, n, elsize) do { \ + if ((n) == 0) { \ + (s) = NULL; \ + } else { \ + (s) = talloc(ndr->mem_ctx, (n) * elsize); \ + if (!(s)) return ndr_pull_error(ndr, \ + NDR_ERR_ALLOC, \ + "Alloc %u * %u failed\n", \ + n, elsize); \ + } \ + } while (0) + +#define NDR_ALLOC_N(ndr, s, n) NDR_ALLOC_N_SIZE(ndr, s, n, sizeof(*(s))) + + +#define NDR_PUSH_ALLOC_SIZE(ndr, s, size) do { \ + (s) = talloc(ndr->mem_ctx, size); \ + if ((size) && !(s)) return ndr_push_error(ndr, NDR_ERR_ALLOC, \ + "push alloc %u failed\n",\ + size); \ + } while (0) + +#define NDR_PUSH_ALLOC(ndr, s) NDR_PUSH_ALLOC_SIZE(ndr, s, sizeof(*(s))) + + +/* these are used when generic fn pointers are needed for ndr push/pull fns */ +typedef NTSTATUS (*ndr_push_fn_t)(struct ndr_push *, void *); +typedef NTSTATUS (*ndr_pull_fn_t)(struct ndr_pull *, void *); + +typedef NTSTATUS (*ndr_push_flags_fn_t)(struct ndr_push *, int ndr_flags, void *); +typedef NTSTATUS (*ndr_push_const_fn_t)(struct ndr_push *, int ndr_flags, const void *); +typedef NTSTATUS (*ndr_pull_flags_fn_t)(struct ndr_pull *, int ndr_flags, void *); +typedef NTSTATUS (*ndr_push_union_fn_t)(struct ndr_push *, int ndr_flags, uint32, void *); +typedef NTSTATUS (*ndr_pull_union_fn_t)(struct ndr_pull *, int ndr_flags, uint32, void *); +typedef void (*ndr_print_fn_t)(struct ndr_print *, const char *, void *); +typedef void (*ndr_print_function_t)(struct ndr_print *, const char *, int, void *); +typedef void (*ndr_print_union_fn_t)(struct ndr_print *, const char *, uint32, void *); + +#include "librpc/ndr/ndr_basic.h" +#include "librpc/ndr/ndr_sec.h" + +/* now pull in the individual parsers */ +#include "librpc/gen_ndr/tables.h" diff --git a/source/librpc/ndr/ndr.c b/source/librpc/ndr/ndr.c new file mode 100644 index 00000000000..b44bf11c153 --- /dev/null +++ b/source/librpc/ndr/ndr.c @@ -0,0 +1,766 @@ +/* + Unix SMB/CIFS implementation. + + libndr interface + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + this provides the core routines for NDR parsing functions + + see http://www.opengroup.org/onlinepubs/9629399/chap14.htm for details + of NDR encoding rules +*/ + +#include "includes.h" + +#define NDR_BASE_MARSHALL_SIZE 1024 + +/* + work out the number of bytes needed to align on a n byte boundary +*/ +size_t ndr_align_size(uint32 offset, size_t n) +{ + if ((offset & (n-1)) == 0) return 0; + return n - (offset & (n-1)); +} + +/* + initialise a ndr parse structure from a data blob +*/ +struct ndr_pull *ndr_pull_init_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx) +{ + struct ndr_pull *ndr; + + ndr = talloc(mem_ctx, sizeof(*ndr)); + if (!ndr) return NULL; + + ndr->flags = 0; + ndr->data = blob->data; + ndr->data_size = blob->length; + ndr->offset = 0; + ndr->mem_ctx = mem_ctx; + + return ndr; +} + +/* + create an ndr sub-context based on an existing context. The new context starts + at the current offset, with the given size limit +*/ +NTSTATUS ndr_pull_subcontext(struct ndr_pull *ndr, struct ndr_pull *ndr2, uint32 size) +{ + NDR_PULL_NEED_BYTES(ndr, size); + *ndr2 = *ndr; + ndr2->data += ndr2->offset; + ndr2->offset = 0; + ndr2->data_size = size; + ndr2->flags = ndr->flags; + return NT_STATUS_OK; +} + + +/* + advance by 'size' bytes +*/ +NTSTATUS ndr_pull_advance(struct ndr_pull *ndr, uint32 size) +{ + ndr->offset += size; + if (ndr->offset > ndr->data_size) { + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, + "ndr_pull_advance by %u failed", + size); + } + return NT_STATUS_OK; +} + +/* + set the parse offset to 'ofs' +*/ +NTSTATUS ndr_pull_set_offset(struct ndr_pull *ndr, uint32 ofs) +{ + ndr->offset = ofs; + if (ndr->offset > ndr->data_size) { + return ndr_pull_error(ndr, NDR_ERR_BUFSIZE, + "ndr_pull_set_offset %u failed", + ofs); + } + return NT_STATUS_OK; +} + +/* save the offset/size of the current ndr state */ +void ndr_pull_save(struct ndr_pull *ndr, struct ndr_pull_save *save) +{ + save->offset = ndr->offset; + save->data_size = ndr->data_size; +} + +/* restore the size/offset of a ndr structure */ +void ndr_pull_restore(struct ndr_pull *ndr, struct ndr_pull_save *save) +{ + ndr->offset = save->offset; + ndr->data_size = save->data_size; +} + + +/* create a ndr_push structure, ready for some marshalling */ +struct ndr_push *ndr_push_init_ctx(TALLOC_CTX *mem_ctx) +{ + struct ndr_push *ndr; + + ndr = talloc(mem_ctx, sizeof(*ndr)); + if (!ndr) { + return NULL; + } + + ndr->mem_ctx = mem_ctx; + ndr->flags = 0; + ndr->alloc_size = NDR_BASE_MARSHALL_SIZE; + ndr->data = talloc(ndr->mem_ctx, ndr->alloc_size); + if (!ndr->data) { + return NULL; + } + ndr->offset = 0; + ndr->ptr_count = 0; + ndr->relative_list = NULL; + ndr->relative_list_end = NULL; + + return ndr; +} + + +/* create a ndr_push structure, ready for some marshalling */ +struct ndr_push *ndr_push_init(void) +{ + struct ndr_push *ndr; + TALLOC_CTX *mem_ctx = talloc_init("ndr_push_init"); + if (!mem_ctx) return NULL; + ndr = ndr_push_init_ctx(mem_ctx); + if (!ndr) { + talloc_destroy(mem_ctx); + } + return ndr; +} + +/* free a ndr_push structure */ +void ndr_push_free(struct ndr_push *ndr) +{ + talloc_destroy(ndr->mem_ctx); +} + + +/* return a DATA_BLOB structure for the current ndr_push marshalled data */ +DATA_BLOB ndr_push_blob(struct ndr_push *ndr) +{ + DATA_BLOB blob; + blob.data = ndr->data; + blob.length = ndr->offset; + return blob; +} + + +/* + expand the available space in the buffer to 'size' +*/ +NTSTATUS ndr_push_expand(struct ndr_push *ndr, uint32 size) +{ + if (ndr->alloc_size >= size) { + return NT_STATUS_OK; + } + + ndr->alloc_size += NDR_BASE_MARSHALL_SIZE; + if (size > ndr->alloc_size) { + ndr->alloc_size = size; + } + ndr->data = talloc_realloc(ndr->mem_ctx, ndr->data, ndr->alloc_size); + if (!ndr->data) { + return ndr_push_error(ndr, NDR_ERR_ALLOC, "Failed to push_expand to %u", + ndr->alloc_size); + } + + return NT_STATUS_OK; +} + +/* + set the push offset to 'ofs' +*/ +NTSTATUS ndr_push_set_offset(struct ndr_push *ndr, uint32 ofs) +{ + NDR_CHECK(ndr_push_expand(ndr, ofs)); + ndr->offset = ofs; + return NT_STATUS_OK; +} + +/* + push a generic array +*/ +NTSTATUS ndr_push_array(struct ndr_push *ndr, int ndr_flags, void *base, + size_t elsize, uint32 count, + NTSTATUS (*push_fn)(struct ndr_push *, int, void *)) +{ + int i; + char *p = base; + if (!(ndr_flags & NDR_SCALARS)) goto buffers; + for (i=0;iprint(ndr, "%s: ARRAY(%d)", name, count); + ndr->depth++; + for (i=0;idepth--; +} + + + +void ndr_print_debug_helper(struct ndr_print *ndr, const char *format, ...) +{ + va_list ap; + char *s = NULL; + int i; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + for (i=0;idepth;i++) { + DEBUG(0,(" ")); + } + + DEBUG(0,("%s\n", s)); + free(s); +} + +/* + a useful helper function for printing idl structures via DEBUG() +*/ +void ndr_print_debug(void (*fn)(struct ndr_print *, const char *, void *), + const char *name, + void *ptr) +{ + struct ndr_print ndr; + + ndr.mem_ctx = talloc_init("ndr_print_debug"); + if (!ndr.mem_ctx) return; + ndr.print = ndr_print_debug_helper; + ndr.depth = 1; + fn(&ndr, name, ptr); + talloc_destroy(ndr.mem_ctx); +} + + +/* + a useful helper function for printing idl unions via DEBUG() +*/ +void ndr_print_union_debug(void (*fn)(struct ndr_print *, const char *, uint32, void *), + const char *name, + uint32 level, + void *ptr) +{ + struct ndr_print ndr; + + ndr.mem_ctx = talloc_init("ndr_print_union"); + if (!ndr.mem_ctx) return; + ndr.print = ndr_print_debug_helper; + ndr.depth = 1; + fn(&ndr, name, level, ptr); + talloc_destroy(ndr.mem_ctx); +} + +/* + a useful helper function for printing idl function calls via DEBUG() +*/ +void ndr_print_function_debug(void (*fn)(struct ndr_print *, const char *, int , void *), + const char *name, + int flags, + void *ptr) +{ + struct ndr_print ndr; + + ndr.mem_ctx = talloc_init("ndr_print_function"); + if (!ndr.mem_ctx) return; + ndr.print = ndr_print_debug_helper; + ndr.depth = 1; + fn(&ndr, name, flags, ptr); + talloc_destroy(ndr.mem_ctx); +} + + +static NTSTATUS ndr_map_error(enum ndr_err_code err) +{ + switch (err) { + case NDR_ERR_BUFSIZE: + return NT_STATUS_BUFFER_TOO_SMALL; + case NDR_ERR_ALLOC: + return NT_STATUS_NO_MEMORY; + } + + /* we should all error codes to different status codes */ + return NT_STATUS_INVALID_PARAMETER; +} + +/* + return and possibly log an NDR error +*/ +NTSTATUS ndr_pull_error(struct ndr_pull *ndr, enum ndr_err_code err, const char *format, ...) +{ + char *s=NULL; + va_list ap; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + DEBUG(3,("ndr_pull_error(%u): %s\n", err, s)); + + free(s); + + return ndr_map_error(err); +} + +/* + return and possibly log an NDR error +*/ +NTSTATUS ndr_push_error(struct ndr_push *ndr, enum ndr_err_code err, const char *format, ...) +{ + char *s=NULL; + va_list ap; + + va_start(ap, format); + vasprintf(&s, format, ap); + va_end(ap); + + DEBUG(3,("ndr_push_error(%u): %s\n", err, s)); + + free(s); + + return ndr_map_error(err); +} + + +/* + handle subcontext buffers, which in midl land are user-marshalled, but + we use magic in pidl to make them easier to cope with +*/ +static NTSTATUS ndr_pull_subcontext_header(struct ndr_pull *ndr, + size_t sub_size, + struct ndr_pull *ndr2) +{ + switch (sub_size) { + case 0: { + uint32 size = ndr->data_size - ndr->offset; + if (size == 0) return NT_STATUS_OK; + NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, size)); + break; + } + + case 2: { + uint16 size; + NDR_CHECK(ndr_pull_uint16(ndr, &size)); + if (size == 0) return NT_STATUS_OK; + NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, size)); + break; + } + + case 4: { + uint32 size; + NDR_CHECK(ndr_pull_uint32(ndr, &size)); + if (size == 0) return NT_STATUS_OK; + NDR_CHECK(ndr_pull_subcontext(ndr, ndr2, size)); + break; + } + default: + return ndr_pull_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext size %d", + sub_size); + } + return NT_STATUS_OK; +} + +/* + handle subcontext buffers, which in midl land are user-marshalled, but + we use magic in pidl to make them easier to cope with +*/ +NTSTATUS ndr_pull_subcontext_fn(struct ndr_pull *ndr, + size_t sub_size, + void *base, + NTSTATUS (*fn)(struct ndr_pull *, void *)) +{ + struct ndr_pull ndr2; + + NDR_CHECK(ndr_pull_subcontext_header(ndr, sub_size, &ndr2)); + NDR_CHECK(fn(&ndr2, base)); + if (sub_size) { + NDR_CHECK(ndr_pull_advance(ndr, ndr2.data_size)); + } else { + NDR_CHECK(ndr_pull_advance(ndr, ndr2.offset)); + } + return NT_STATUS_OK; +} + + +NTSTATUS ndr_pull_subcontext_flags_fn(struct ndr_pull *ndr, + size_t sub_size, + void *base, + NTSTATUS (*fn)(struct ndr_pull *, int , void *)) +{ + struct ndr_pull ndr2; + + NDR_CHECK(ndr_pull_subcontext_header(ndr, sub_size, &ndr2)); + NDR_CHECK(fn(&ndr2, NDR_SCALARS|NDR_BUFFERS, base)); + if (sub_size) { + NDR_CHECK(ndr_pull_advance(ndr, ndr2.data_size)); + } else { + NDR_CHECK(ndr_pull_advance(ndr, ndr2.offset)); + } + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_subcontext_union_fn(struct ndr_pull *ndr, + size_t sub_size, + uint32 level, + void *base, + NTSTATUS (*fn)(struct ndr_pull *, int , uint32 , void *)) +{ + struct ndr_pull ndr2; + + NDR_CHECK(ndr_pull_subcontext_header(ndr, sub_size, &ndr2)); + NDR_CHECK(fn(&ndr2, NDR_SCALARS|NDR_BUFFERS, level, base)); + if (sub_size) { + NDR_CHECK(ndr_pull_advance(ndr, ndr2.data_size)); + } else { + NDR_CHECK(ndr_pull_advance(ndr, ndr2.offset)); + } + return NT_STATUS_OK; +} + + +/* + push a subcontext header +*/ +static NTSTATUS ndr_push_subcontext_header(struct ndr_push *ndr, + size_t sub_size, + struct ndr_push *ndr2) +{ + switch (sub_size) { + case 0: + break; + + case 2: + NDR_CHECK(ndr_push_uint16(ndr, ndr2->offset)); + break; + + case 4: + NDR_CHECK(ndr_push_uint32(ndr, ndr2->offset)); + break; + + default: + return ndr_push_error(ndr, NDR_ERR_SUBCONTEXT, "Bad subcontext size %d", + sub_size); + } + return NT_STATUS_OK; +} + +/* + handle subcontext buffers, which in midl land are user-marshalled, but + we use magic in pidl to make them easier to cope with +*/ +NTSTATUS ndr_push_subcontext_fn(struct ndr_push *ndr, + size_t sub_size, + void *base, + NTSTATUS (*fn)(struct ndr_push *, void *)) +{ + struct ndr_push *ndr2; + + ndr2 = ndr_push_init_ctx(ndr->mem_ctx); + if (!ndr2) return NT_STATUS_NO_MEMORY; + + ndr2->flags = ndr->flags; + NDR_CHECK(fn(ndr2, base)); + NDR_CHECK(ndr_push_subcontext_header(ndr, sub_size, ndr2)); + NDR_CHECK(ndr_push_bytes(ndr, ndr2->data, ndr2->offset)); + return NT_STATUS_OK; +} + +/* + handle subcontext buffers for function that take a flags arg +*/ +NTSTATUS ndr_push_subcontext_flags_fn(struct ndr_push *ndr, + size_t sub_size, + void *base, + NTSTATUS (*fn)(struct ndr_push *, int, void *)) +{ + struct ndr_push *ndr2; + + ndr2 = ndr_push_init_ctx(ndr->mem_ctx); + if (!ndr2) return NT_STATUS_NO_MEMORY; + + ndr2->flags = ndr->flags; + NDR_CHECK(fn(ndr2, NDR_SCALARS|NDR_BUFFERS, base)); + NDR_CHECK(ndr_push_subcontext_header(ndr, sub_size, ndr2)); + NDR_CHECK(ndr_push_bytes(ndr, ndr2->data, ndr2->offset)); + return NT_STATUS_OK; +} + +/* + handle subcontext buffers for function that take a union +*/ +NTSTATUS ndr_push_subcontext_union_fn(struct ndr_push *ndr, + size_t sub_size, + uint32 level, + void *base, + NTSTATUS (*fn)(struct ndr_push *, int, uint32, void *)) +{ + struct ndr_push *ndr2; + + ndr2 = ndr_push_init_ctx(ndr->mem_ctx); + if (!ndr2) return NT_STATUS_NO_MEMORY; + + ndr2->flags = ndr->flags; + NDR_CHECK(fn(ndr2, NDR_SCALARS|NDR_BUFFERS, level, base)); + NDR_CHECK(ndr_push_subcontext_header(ndr, sub_size, ndr2)); + NDR_CHECK(ndr_push_bytes(ndr, ndr2->data, ndr2->offset)); + return NT_STATUS_OK; +} + + +/* + mark the start of a structure +*/ +NTSTATUS ndr_pull_struct_start(struct ndr_pull *ndr) +{ + struct ndr_ofs_list *ofs; + NDR_ALLOC(ndr, ofs); + ofs->offset = ndr->offset; + ofs->next = ndr->ofs_list; + ndr->ofs_list = ofs; + return NT_STATUS_OK; +} + +/* + mark the end of a structure +*/ +void ndr_pull_struct_end(struct ndr_pull *ndr) +{ + ndr->ofs_list = ndr->ofs_list->next; +} + +/* + mark the start of a structure +*/ +NTSTATUS ndr_push_struct_start(struct ndr_push *ndr) +{ + struct ndr_ofs_list *ofs; + NDR_PUSH_ALLOC(ndr, ofs); + ofs->offset = ndr->offset; + ofs->next = ndr->ofs_list; + ndr->ofs_list = ofs; + return NT_STATUS_OK; +} + +/* + mark the end of a structure +*/ +void ndr_push_struct_end(struct ndr_push *ndr) +{ + ndr->ofs_list = ndr->ofs_list->next; +} + + +/* + pull a relative structure +*/ +NTSTATUS ndr_pull_relative(struct ndr_pull *ndr, const void **buf, size_t size, + NTSTATUS (*fn)(struct ndr_pull *, int ndr_flags, void *)) +{ + struct ndr_pull ndr2; + uint32 ofs; + struct ndr_pull_save save; + void *p; + + NDR_CHECK(ndr_pull_uint32(ndr, &ofs)); + if (ofs == 0) { + (*buf) = NULL; + return NT_STATUS_OK; + } + ndr_pull_save(ndr, &save); + NDR_CHECK(ndr_pull_set_offset(ndr, ofs + ndr->ofs_list->offset)); + NDR_CHECK(ndr_pull_subcontext(ndr, &ndr2, ndr->data_size - ndr->offset)); + /* strings must be allocated by the backend functions */ + if (ndr->flags & LIBNDR_STRING_FLAGS) { + NDR_CHECK(fn(&ndr2, NDR_SCALARS|NDR_BUFFERS, &p)); + } else { + NDR_ALLOC_SIZE(ndr, p, size); + NDR_CHECK(fn(&ndr2, NDR_SCALARS|NDR_BUFFERS, p)); + } + (*buf) = p; + ndr_pull_restore(ndr, &save); + return NT_STATUS_OK; +} + +/* + push a relative structure +*/ +NTSTATUS ndr_push_relative(struct ndr_push *ndr, int ndr_flags, const void *p, + NTSTATUS (*fn)(struct ndr_push *, int , const void *)) +{ + struct ndr_ofs_list *ofs; + if (ndr_flags & NDR_SCALARS) { + if (!p) { + NDR_CHECK(ndr_push_uint32(ndr, 0)); + return NT_STATUS_OK; + } + NDR_PUSH_ALLOC(ndr, ofs); + NDR_CHECK(ndr_push_align(ndr, 4)); + ofs->offset = ndr->offset; + NDR_CHECK(ndr_push_uint32(ndr, 0xFFFFFFFF)); + ofs->next = NULL; + if (ndr->relative_list_end) { + ndr->relative_list_end->next = ofs; + } else { + ndr->relative_list = ofs; + } + ndr->relative_list_end = ofs; + } + if (ndr_flags & NDR_BUFFERS) { + struct ndr_push_save save; + if (!p) { + return NT_STATUS_OK; + } + ofs = ndr->relative_list; + if (!ofs) { + return ndr_push_error(ndr, NDR_ERR_RELATIVE, "Empty relative stack"); + } + ndr->relative_list = ndr->relative_list->next; + if (ndr->relative_list == NULL) { + ndr->relative_list_end = NULL; + } + NDR_CHECK(ndr_push_align(ndr, 4)); + ndr_push_save(ndr, &save); + ndr->offset = ofs->offset; + NDR_CHECK(ndr_push_uint32(ndr, save.offset - ndr->ofs_list->offset)); + ndr_push_restore(ndr, &save); + NDR_CHECK(fn(ndr, NDR_SCALARS|NDR_BUFFERS, p)); + } + return NT_STATUS_OK; +} + + +/* + pull a union from a blob using NDR +*/ +NTSTATUS ndr_pull_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, uint32 level, void *p, + NTSTATUS (*fn)(struct ndr_pull *, int ndr_flags, uint32, void *)) +{ + struct ndr_pull *ndr; + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + return fn(ndr, NDR_SCALARS|NDR_BUFFERS, level, p); +} + +/* + pull a struct from a blob using NDR +*/ +NTSTATUS ndr_pull_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, + NTSTATUS (*fn)(struct ndr_pull *, int , void *)) +{ + struct ndr_pull *ndr; + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + return fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); +} + +/* + push a struct to a blob using NDR +*/ +NTSTATUS ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, + NTSTATUS (*fn)(struct ndr_push *, int , void *)) +{ + NTSTATUS status; + struct ndr_push *ndr; + ndr = ndr_push_init_ctx(mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + status = fn(ndr, NDR_SCALARS|NDR_BUFFERS, p); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + *blob = ndr_push_blob(ndr); + + return NT_STATUS_OK; +} diff --git a/source/librpc/ndr/ndr_basic.c b/source/librpc/ndr/ndr_basic.c new file mode 100644 index 00000000000..0c63faf347d --- /dev/null +++ b/source/librpc/ndr/ndr_basic.c @@ -0,0 +1,868 @@ +/* + Unix SMB/CIFS implementation. + + routines for marshalling/unmarshalling basic types + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#define NDR_BE(ndr) (((ndr)->flags & (LIBNDR_FLAG_BIGENDIAN|LIBNDR_FLAG_LITTLE_ENDIAN)) == 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 +*/ +NTSTATUS ndr_pull_uint8(struct ndr_pull *ndr, uint8 *v) +{ + NDR_PULL_NEED_BYTES(ndr, 1); + *v = CVAL(ndr->data, ndr->offset); + ndr->offset += 1; + return NT_STATUS_OK; +} + + +/* + parse a uint16 +*/ +NTSTATUS ndr_pull_uint16(struct ndr_pull *ndr, uint16 *v) +{ + NDR_PULL_ALIGN(ndr, 2); + NDR_PULL_NEED_BYTES(ndr, 2); + *v = NDR_SVAL(ndr, ndr->offset); + ndr->offset += 2; + return NT_STATUS_OK; +} + + +/* + parse a uint32 +*/ +NTSTATUS ndr_pull_uint32(struct ndr_pull *ndr, uint32 *v) +{ + NDR_PULL_ALIGN(ndr, 4); + NDR_PULL_NEED_BYTES(ndr, 4); + *v = NDR_IVAL(ndr, ndr->offset); + ndr->offset += 4; + return NT_STATUS_OK; +} + +/* + parse a HYPER_T +*/ +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 = NDR_IVAL(ndr, ndr->offset); + v->high = NDR_IVAL(ndr, ndr->offset+4); + ndr->offset += 8; + return NT_STATUS_OK; +} + +/* + pull a NTSTATUS +*/ +NTSTATUS ndr_pull_NTSTATUS(struct ndr_pull *ndr, NTSTATUS *status) +{ + uint32 v; + NDR_CHECK(ndr_pull_uint32(ndr, &v)); + *status = NT_STATUS(v); + return NT_STATUS_OK; +} + +/* + push a NTSTATUS +*/ +NTSTATUS ndr_push_NTSTATUS(struct ndr_push *ndr, NTSTATUS status) +{ + return ndr_push_uint32(ndr, NT_STATUS_V(status)); +} + +void ndr_print_NTSTATUS(struct ndr_print *ndr, const char *name, NTSTATUS *r) +{ + ndr->print(ndr, "%-25s: %s", name, nt_errstr(*r)); +} + +/* + pull a WERROR +*/ +NTSTATUS ndr_pull_WERROR(struct ndr_pull *ndr, WERROR *status) +{ + uint32 v; + NDR_CHECK(ndr_pull_uint32(ndr, &v)); + *status = W_ERROR(v); + return NT_STATUS_OK; +} + +/* + push a WERROR +*/ +NTSTATUS ndr_push_WERROR(struct ndr_push *ndr, WERROR status) +{ + return ndr_push_uint32(ndr, W_ERROR_V(status)); +} + +void ndr_print_WERROR(struct ndr_print *ndr, const char *name, WERROR *r) +{ + ndr->print(ndr, "%-25s: %s", name, win_errstr(*r)); +} + +/* + parse a set of bytes +*/ +NTSTATUS ndr_pull_bytes(struct ndr_pull *ndr, char *data, uint32 n) +{ + NDR_PULL_NEED_BYTES(ndr, n); + memcpy(data, ndr->data + ndr->offset, n); + ndr->offset += n; + return NT_STATUS_OK; +} + +/* + pull an array of uint8 +*/ +NTSTATUS ndr_pull_array_uint8(struct ndr_pull *ndr, int ndr_flags, char *data, uint32 n) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + return ndr_pull_bytes(ndr, data, n); +} + + +/* + pull an array of uint16 +*/ +NTSTATUS ndr_pull_array_uint16(struct ndr_pull *ndr, int ndr_flags, uint16 *data, uint32 n) +{ + uint32 i; + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + for (i=0;idata, ndr->offset, v); + ndr->offset += 1; + return NT_STATUS_OK; +} + +/* + push a uint16 +*/ +NTSTATUS ndr_push_uint16(struct ndr_push *ndr, uint16 v) +{ + NDR_PUSH_ALIGN(ndr, 2); + NDR_PUSH_NEED_BYTES(ndr, 2); + NDR_SSVAL(ndr, ndr->offset, v); + ndr->offset += 2; + return NT_STATUS_OK; +} + +/* + push a uint32 +*/ +NTSTATUS ndr_push_uint32(struct ndr_push *ndr, uint32 v) +{ + NDR_PUSH_ALIGN(ndr, 4); + NDR_PUSH_NEED_BYTES(ndr, 4); + NDR_SIVAL(ndr, ndr->offset, v); + ndr->offset += 4; + return NT_STATUS_OK; +} + +/* + push a HYPER_T +*/ +NTSTATUS ndr_push_HYPER_T(struct ndr_push *ndr, HYPER_T v) +{ + NDR_PUSH_ALIGN(ndr, 8); + NDR_PUSH_NEED_BYTES(ndr, 8); + NDR_SIVAL(ndr, ndr->offset, v.low); + NDR_SIVAL(ndr, ndr->offset+4, v.high); + ndr->offset += 8; + return NT_STATUS_OK; +} + +NTSTATUS ndr_push_align(struct ndr_push *ndr, size_t size) +{ + NDR_PUSH_ALIGN(ndr, size); + return NT_STATUS_OK; +} + +NTSTATUS ndr_pull_align(struct ndr_pull *ndr, size_t size) +{ + NDR_PULL_ALIGN(ndr, size); + return NT_STATUS_OK; +} + +/* + push some bytes +*/ +NTSTATUS ndr_push_bytes(struct ndr_push *ndr, const char *data, uint32 n) +{ + NDR_PUSH_NEED_BYTES(ndr, n); + memcpy(ndr->data + ndr->offset, data, n); + ndr->offset += n; + return NT_STATUS_OK; +} + +/* + push some zero bytes +*/ +NTSTATUS ndr_push_zero(struct ndr_push *ndr, uint32 n) +{ + NDR_PUSH_NEED_BYTES(ndr, n); + memset(ndr->data + ndr->offset, 0, n); + ndr->offset += n; + return NT_STATUS_OK; +} + +/* + push an array of uint8 +*/ +NTSTATUS ndr_push_array_uint8(struct ndr_push *ndr, int ndr_flags, const char *data, uint32 n) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + return ndr_push_bytes(ndr, data, n); +} + +/* + push an array of uint16 +*/ +NTSTATUS ndr_push_array_uint16(struct ndr_push *ndr, int ndr_flags, const uint16 *data, uint32 n) +{ + int i; + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + for (i=0;ioffset = ndr->offset; +} + +/* + restore the position + */ +void ndr_push_restore(struct ndr_push *ndr, struct ndr_push_save *save) +{ + ndr->offset = save->offset; +} + +/* + push a 1 if a pointer is non-NULL, otherwise 0 +*/ +NTSTATUS ndr_push_ptr(struct ndr_push *ndr, const void *p) +{ + uint32 ptr = 0; + if (p) { + /* we do this to ensure that we generate unique ref ids, + which means we can handle the case where a MS programmer + forgot to mark a pointer as unique */ + ndr->ptr_count++; + ptr = ndr->ptr_count; + } + return ndr_push_uint32(ndr, ptr); +} + + +/* + pull a general string from the wire +*/ +NTSTATUS ndr_pull_string(struct ndr_pull *ndr, int ndr_flags, const char **s) +{ + char *as=NULL; + uint32 len1, ofs, len2; + uint16 len3; + int ret; + int chset = CH_UCS2; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + if (NDR_BE(ndr)) { + chset = CH_UCS2BE; + } + + switch (ndr->flags & LIBNDR_STRING_FLAGS) { + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM: + NDR_CHECK(ndr_pull_uint32(ndr, &len1)); + NDR_CHECK(ndr_pull_uint32(ndr, &ofs)); + NDR_CHECK(ndr_pull_uint32(ndr, &len2)); + if (len2 > len1) { + return ndr_pull_error(ndr, NDR_ERR_STRING, + "Bad string lengths len1=%u ofs=%u len2=%u\n", + len1, ofs, len2); + } + if (len2 == 0) { + *s = talloc_strdup(ndr->mem_ctx, ""); + break; + } + NDR_PULL_NEED_BYTES(ndr, len2*2); + ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, + ndr->data+ndr->offset, + len2*2, + (const void **)&as); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_pull_advance(ndr, len2*2)); + *s = as; + break; + + case LIBNDR_FLAG_STR_SIZE4: + NDR_CHECK(ndr_pull_uint32(ndr, &len1)); + NDR_PULL_NEED_BYTES(ndr, len1*2); + if (len1 == 0) { + *s = talloc_strdup(ndr->mem_ctx, ""); + break; + } + ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, + ndr->data+ndr->offset, + len1*2, + (const void **)&as); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_pull_advance(ndr, len1*2)); + *s = as; + break; + + case LIBNDR_FLAG_STR_NULLTERM: + len1 = strnlen_w(ndr->data+ndr->offset, + (ndr->data_size - ndr->offset)/2); + if (len1*2+2 <= ndr->data_size - ndr->offset) { + len1++; + } + ret = convert_string_talloc(ndr->mem_ctx, chset, CH_UNIX, + ndr->data+ndr->offset, + len1*2, + (const void **)s); + if (ret == -1) { + return ndr_pull_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + NDR_CHECK(ndr_pull_advance(ndr, len1*2)); + break; + + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: + NDR_CHECK(ndr_pull_uint32(ndr, &len1)); + NDR_CHECK(ndr_pull_uint32(ndr, &ofs)); + NDR_CHECK(ndr_pull_uint32(ndr, &len2)); + if (len2 > len1) { + return ndr_pull_error(ndr, NDR_ERR_STRING, + "Bad ascii string lengths len1=%u ofs=%u len2=%u\n", + len1, ofs, len2); + } + NDR_ALLOC_N(ndr, as, (len2+1)); + NDR_CHECK(ndr_pull_bytes(ndr, as, len2)); + as[len2] = 0; + (*s) = as; + break; + + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4: + NDR_CHECK(ndr_pull_uint32(ndr, &ofs)); + NDR_CHECK(ndr_pull_uint32(ndr, &len2)); + NDR_ALLOC_N(ndr, as, (len2+1)); + NDR_CHECK(ndr_pull_bytes(ndr, as, len2)); + as[len2] = 0; + (*s) = as; + break; + + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2: + NDR_CHECK(ndr_pull_uint16(ndr, &len3)); + NDR_ALLOC_N(ndr, as, (len3+1)); + NDR_CHECK(ndr_pull_bytes(ndr, as, len3)); + as[len3] = 0; + (*s) = as; + break; + + default: + return ndr_pull_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", + ndr->flags & LIBNDR_STRING_FLAGS); + } + + return NT_STATUS_OK; +} + + +/* + 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; + int ret; + int chset = CH_UCS2; + + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + + if (NDR_BE(ndr)) { + chset = CH_UCS2BE; + } + + s_len = s?strlen(s):0; + c_len = s?strlen_m(s):0; + + switch (ndr->flags & LIBNDR_STRING_FLAGS) { + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: + NDR_CHECK(ndr_push_uint32(ndr, c_len+1)); + NDR_CHECK(ndr_push_uint32(ndr, 0)); + NDR_CHECK(ndr_push_uint32(ndr, c_len+1)); + NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2); + ret = convert_string(CH_UNIX, chset, + s, s_len+1, + ndr->data+ndr->offset, c_len*2 + 2); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len*2 + 2; + break; + + case LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4|LIBNDR_FLAG_STR_NOTERM: + NDR_CHECK(ndr_push_uint32(ndr, c_len)); + NDR_CHECK(ndr_push_uint32(ndr, 0)); + NDR_CHECK(ndr_push_uint32(ndr, c_len)); + NDR_PUSH_NEED_BYTES(ndr, c_len*2); + ret = convert_string(CH_UNIX, chset, + s, s_len, + ndr->data+ndr->offset, c_len*2); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len*2; + break; + + case LIBNDR_FLAG_STR_SIZE4: + NDR_CHECK(ndr_push_uint32(ndr, c_len + 1)); + NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2); + ret = convert_string(CH_UNIX, chset, + s, s_len + 1, + ndr->data+ndr->offset, c_len*2 + 2); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len*2 + 2; + break; + + case LIBNDR_FLAG_STR_NULLTERM: + NDR_PUSH_NEED_BYTES(ndr, c_len*2 + 2); + ret = convert_string(CH_UNIX, chset, + s, s_len+1, + ndr->data+ndr->offset, c_len*2 + 2); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len*2 + 2; + break; + + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4|LIBNDR_FLAG_STR_SIZE4: + NDR_CHECK(ndr_push_uint32(ndr, c_len+1)); + NDR_CHECK(ndr_push_uint32(ndr, 0)); + NDR_CHECK(ndr_push_uint32(ndr, c_len+1)); + NDR_PUSH_NEED_BYTES(ndr, c_len + 1); + ret = convert_string(CH_UNIX, CH_DOS, + s, s_len + 1, + ndr->data+ndr->offset, c_len + 1); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len + 1; + break; + + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_LEN4: + NDR_CHECK(ndr_push_uint32(ndr, 0)); + NDR_CHECK(ndr_push_uint32(ndr, c_len+1)); + NDR_PUSH_NEED_BYTES(ndr, c_len + 1); + ret = convert_string(CH_UNIX, CH_DOS, + s, s_len + 1, + ndr->data+ndr->offset, c_len + 1); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len + 1; + break; + + case LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_SIZE2: + NDR_CHECK(ndr_push_uint16(ndr, c_len+1)); + NDR_PUSH_NEED_BYTES(ndr, c_len + 1); + ret = convert_string(CH_UNIX, CH_DOS, + s, s_len + 1, + ndr->data+ndr->offset, c_len + 1); + if (ret == -1) { + return ndr_push_error(ndr, NDR_ERR_CHARCNV, + "Bad character conversion"); + } + ndr->offset += c_len + 1; + break; + + default: + return ndr_push_error(ndr, NDR_ERR_STRING, "Bad string flags 0x%x\n", + ndr->flags & LIBNDR_STRING_FLAGS); + } + + return NT_STATUS_OK; +} + +/* + push a NTTIME +*/ +NTSTATUS ndr_push_NTTIME(struct ndr_push *ndr, NTTIME t) +{ + NDR_CHECK(ndr_push_uint32(ndr, t.low)); + NDR_CHECK(ndr_push_uint32(ndr, t.high)); + return NT_STATUS_OK; +} + +/* + pull a NTTIME +*/ +NTSTATUS ndr_pull_NTTIME(struct ndr_pull *ndr, NTTIME *t) +{ + NDR_CHECK(ndr_pull_uint32(ndr, &t->low)); + NDR_CHECK(ndr_pull_uint32(ndr, &t->high)); + return NT_STATUS_OK; +} + +/* + push a time_t +*/ +NTSTATUS ndr_push_time_t(struct ndr_push *ndr, time_t t) +{ + return ndr_push_uint32(ndr, t); +} + +/* + pull a time_t +*/ +NTSTATUS ndr_pull_time_t(struct ndr_pull *ndr, time_t *t) +{ + uint32 tt; + NDR_CHECK(ndr_pull_uint32(ndr, &tt)); + *t = tt; + return NT_STATUS_OK; +} + + +void ndr_print_struct(struct ndr_print *ndr, const char *name, const char *type) +{ + ndr->print(ndr, "%s: struct %s", name, type); +} + +void ndr_print_uint8(struct ndr_print *ndr, const char *name, uint8 v) +{ + ndr->print(ndr, "%-25s: 0x%02x (%u)", name, v, v); +} + +void ndr_print_uint16(struct ndr_print *ndr, const char *name, uint16 v) +{ + ndr->print(ndr, "%-25s: 0x%04x (%u)", name, v, v); +} + +void ndr_print_uint32(struct ndr_print *ndr, const char *name, uint32 v) +{ + ndr->print(ndr, "%-25s: 0x%08x (%u)", name, v, v); +} + +void ndr_print_HYPER_T(struct ndr_print *ndr, const char *name, HYPER_T v) +{ + ndr->print(ndr, "%-25s: 0x%08x%08x", name, v.high, v.low); +} + +void ndr_print_ptr(struct ndr_print *ndr, const char *name, const void *p) +{ + if (p) { + ndr->print(ndr, "%-25s: *", name); + } else { + ndr->print(ndr, "%-25s: NULL", name); + } +} + +void ndr_print_string(struct ndr_print *ndr, const char *name, const char *s) +{ + if (s) { + ndr->print(ndr, "%-25s: '%s'", name, s); + } else { + ndr->print(ndr, "%-25s: NULL", name); + } +} + +void ndr_print_NTTIME(struct ndr_print *ndr, const char *name, NTTIME t) +{ + ndr->print(ndr, "%-25s: %s", name, nt_time_string(ndr->mem_ctx, &t)); +} + +void ndr_print_time_t(struct ndr_print *ndr, const char *name, time_t t) +{ + if (t == (time_t)-1 || t == 0) { + ndr->print(ndr, "%-25s: (time_t)%d", name, (int)t); + } else { + ndr->print(ndr, "%-25s: %s", name, http_timestring(ndr->mem_ctx, t)); + } +} + +void ndr_print_union(struct ndr_print *ndr, const char *name, uint16 level, const char *type) +{ + ndr->print(ndr, "%-25s: union %s(case %u)", name, type, level); +} + +void ndr_print_bad_level(struct ndr_print *ndr, const char *name, uint16 level) +{ + ndr->print(ndr, "UNKNOWN LEVEL %u", level); +} + +void ndr_print_array_uint32(struct ndr_print *ndr, const char *name, + const uint32 *data, uint32 count) +{ + int i; + + ndr->print(ndr, "%s: ARRAY(%d)", name, count); + ndr->depth++; + for (i=0;idepth--; +} + +void ndr_print_array_uint16(struct ndr_print *ndr, const char *name, + const uint16 *data, uint32 count) +{ + int i; + + ndr->print(ndr, "%s: ARRAY(%d)", name, count); + ndr->depth++; + for (i=0;idepth--; +} + +void ndr_print_array_uint8(struct ndr_print *ndr, const char *name, + const uint8 *data, uint32 count) +{ + int i; + + if (count <= 32 && (ndr->flags & LIBNDR_PRINT_ARRAY_HEX)) { + char s[65]; + for (i=0;iprint(ndr, "%-25s: %s", name, s); + return; + } + + ndr->print(ndr, "%s: ARRAY(%d)", name, count); + ndr->depth++; + for (i=0;idepth--; +} + +/* + build a GUID from a string +*/ +NTSTATUS GUID_from_string(const char *s, struct GUID *guid) +{ + uint32 time_low; + uint32 time_mid, time_hi_and_version; + 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[0], &clock_seq[1], + &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { + return NT_STATUS_INVALID_PARAMETER; + } + + 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++) { + guid->node[i] = node[i]; + } + + return NT_STATUS_OK; +} + +/* + its useful to be able to display these in debugging messages +*/ +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", + 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) +{ + ndr->print(ndr, "%-25s: %s", name, GUID_string(ndr->mem_ctx, guid)); +} + +void ndr_print_DATA_BLOB(struct ndr_print *ndr, const char *name, DATA_BLOB r) +{ + ndr->print(ndr, "%-25s: DATA_BLOB length=%u", name, r.length); + if (r.length) { + dump_data(10, r.data, r.length); + } +} + + +/* + push a DATA_BLOB onto the wire. +*/ +NTSTATUS ndr_push_DATA_BLOB(struct ndr_push *ndr, 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, blob.length)); + } + NDR_CHECK(ndr_push_bytes(ndr, blob.data, blob.length)); + return NT_STATUS_OK; +} + +/* + pull a DATA_BLOB from the wire. +*/ +NTSTATUS ndr_pull_DATA_BLOB(struct ndr_pull *ndr, DATA_BLOB *blob) +{ + uint32 length; + + if (ndr->flags & LIBNDR_ALIGN_FLAGS) { + if (ndr->flags & LIBNDR_FLAG_ALIGN2) { + length = NDR_ALIGN(ndr, 2); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { + length = NDR_ALIGN(ndr, 4); + } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { + length = NDR_ALIGN(ndr, 8); + } + if (ndr->data_size - ndr->offset < length) { + length = ndr->data_size - ndr->offset; + } + } else if (ndr->flags & LIBNDR_FLAG_REMAINING) { + length = ndr->data_size - ndr->offset; + } else { + NDR_CHECK(ndr_pull_uint32(ndr, &length)); + } + NDR_PULL_NEED_BYTES(ndr, length); + *blob = data_blob_talloc(ndr->mem_ctx, ndr->data+ndr->offset, length); + ndr->offset += length; + return NT_STATUS_OK; +} diff --git a/source/librpc/ndr/ndr_sec.c b/source/librpc/ndr/ndr_sec.c new file mode 100644 index 00000000000..3ea0f4e3037 --- /dev/null +++ b/source/librpc/ndr/ndr_sec.c @@ -0,0 +1,185 @@ +/* + Unix SMB/CIFS implementation. + + routines for marshalling/unmarshalling security descriptors + and related structures + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + +/* + parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field +*/ +NTSTATUS ndr_pull_dom_sid2(struct ndr_pull *ndr, int ndr_flags, struct dom_sid *sid) +{ + uint32 num_auths; + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + NDR_CHECK(ndr_pull_uint32(ndr, &num_auths)); + return ndr_pull_dom_sid(ndr, ndr_flags, sid); +} + +/* + parse a dom_sid2 - this is a dom_sid but with an extra copy of the num_auths field +*/ +NTSTATUS ndr_push_dom_sid2(struct ndr_push *ndr, int ndr_flags, struct dom_sid *sid) +{ + if (!(ndr_flags & NDR_SCALARS)) { + return NT_STATUS_OK; + } + NDR_CHECK(ndr_push_uint32(ndr, sid->num_auths)); + return ndr_push_dom_sid(ndr, ndr_flags, sid); +} + + +/* + convert a dom_sid to a string +*/ +const char *dom_sid_string(TALLOC_CTX *mem_ctx, const struct dom_sid *sid) +{ + int i, ofs, maxlen; + uint32 ia; + char *ret; + + if (!sid) { + return "(NULL SID)"; + } + + maxlen = sid->num_auths * 11 + 25; + ret = talloc(mem_ctx, maxlen); + if (!ret) return "(SID ERR)"; + + ia = (sid->id_auth[5]) + + (sid->id_auth[4] << 8 ) + + (sid->id_auth[3] << 16) + + (sid->id_auth[2] << 24); + + ofs = snprintf(ret, maxlen, "S-%u-%lu", + (unsigned int)sid->sid_rev_num, (unsigned long)ia); + + for (i = 0; i < sid->num_auths; i++) { + ofs += snprintf(ret + ofs, maxlen - ofs, "-%lu", (unsigned long)sid->sub_auths[i]); + } + + return ret; +} + + +/* + print a dom_sid +*/ +void ndr_print_dom_sid(struct ndr_print *ndr, const char *name, struct dom_sid *sid) +{ + ndr->print(ndr, "%-25s: %s", name, dom_sid_string(ndr->mem_ctx, sid)); +} + +void ndr_print_dom_sid2(struct ndr_print *ndr, const char *name, struct dom_sid2 *sid) +{ + ndr_print_dom_sid(ndr, name, sid); +} + +/* + return the wire size of a dom_sid +*/ +size_t ndr_size_dom_sid(struct dom_sid *sid) +{ + if (!sid) return 0; + return 8 + 4*sid->num_auths; +} + +/* + add a rid to a domain dom_sid to make a full dom_sid +*/ +struct dom_sid *dom_sid_add_rid(TALLOC_CTX *mem_ctx, + const struct dom_sid *domain_sid, + uint32 rid) +{ + struct dom_sid *sid; + + sid = talloc_p(mem_ctx, struct dom_sid); + if (!sid) return NULL; + + *sid = *domain_sid; + sid->sub_auths = talloc_array_p(mem_ctx, uint32, sid->num_auths+1); + if (!sid->sub_auths) { + return NULL; + } + memcpy(sid->sub_auths, domain_sid->sub_auths, sid->num_auths*sizeof(uint32)); + sid->sub_auths[sid->num_auths] = rid; + sid->num_auths++; + return sid; +} + +/* + return the wire size of a security_ace +*/ +size_t ndr_size_security_ace(struct security_ace *ace) +{ + if (!ace) return 0; + return 8 + ndr_size_dom_sid(&ace->trustee); +} + + +/* + return the wire size of a security_acl +*/ +size_t ndr_size_security_acl(struct security_acl *acl) +{ + size_t ret; + int i; + if (!acl) return 0; + ret = 8; + for (i=0;inum_aces;i++) { + ret += ndr_size_security_ace(&acl->aces[i]); + } + return ret; +} + +/* + return the wire size of a security descriptor +*/ +size_t ndr_size_security_descriptor(struct security_descriptor *sd) +{ + size_t ret; + if (!sd) return 0; + + ret = 20; + ret += ndr_size_dom_sid(sd->owner_sid); + ret += ndr_size_dom_sid(sd->group_sid); + ret += ndr_size_security_acl(sd->dacl); + ret += ndr_size_security_acl(sd->sacl); + return ret; +} + +/* + talloc and copy a security descriptor + */ +struct security_descriptor *copy_security_descriptor(TALLOC_CTX *mem_ctx, + const struct security_descriptor *osd) +{ + struct security_descriptor *nsd; + + /* FIXME */ + DEBUG(1, ("copy_security_descriptor: sorry unimplemented yet\n")); + nsd = NULL; + + return nsd; +} diff --git a/source/librpc/ndr/ndr_sec.h b/source/librpc/ndr/ndr_sec.h new file mode 100644 index 00000000000..728d46535d8 --- /dev/null +++ b/source/librpc/ndr/ndr_sec.h @@ -0,0 +1,56 @@ +/* + Unix SMB/CIFS implementation. + + definitions for marshalling/unmarshalling security descriptors + and related structures + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +/* + use the same structure for dom_sid2 as dom_sid. A dom_sid2 is really + just a dom sid, but with the sub_auths represented as a conformant + array. As with all in-structure conformant arrays, the array length + is placed before the start of the structure. That's what gives rise + to the extra num_auths elemenent. We don't want the Samba code to + have to bother with such esoteric NDR details, so its easier to just + define it as a dom_sid and use pidl magic to make it all work. It + just means you need to mark a sid as a "dom_sid2" in the IDL when you + know it is of the conformant array variety +*/ +#define dom_sid2 dom_sid + +/* query security descriptor */ +struct smb_query_secdesc { + struct { + uint16 fnum; + uint32 secinfo_flags; + } in; + struct { + struct security_descriptor *sd; + } out; +}; + +/* set security descriptor */ +struct smb_set_secdesc { + struct { + uint16 fnum; + uint32 secinfo_flags; + struct security_descriptor *sd; + } in; +}; diff --git a/source/librpc/ndr/ndr_spoolss_buf.c b/source/librpc/ndr/ndr_spoolss_buf.c new file mode 100644 index 00000000000..d8a3f6a07e3 --- /dev/null +++ b/source/librpc/ndr/ndr_spoolss_buf.c @@ -0,0 +1,93 @@ +/* + Unix SMB/CIFS implementation. + + routines for marshalling/unmarshalling spoolss subcontext buffer structures + + Copyright (C) Andrew Tridgell 2003 + Copyright (C) Tim Potter 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + +NTSTATUS pull_spoolss_PrinterInfoArray(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + uint32 level, uint32 count, + union spoolss_PrinterInfo **info) +{ + int i; + struct ndr_pull *ndr; + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + NDR_ALLOC_N(ndr, *info, count); + for (i=0;ireference_count = 0; + p->mem_ctx = mem_ctx; + p->call_id = 1; + p->auth_info = NULL; + p->security_state = NULL; + p->flags = 0; + p->srv_max_xmit_frag = 0; + p->srv_max_recv_frag = 0; + + return p; +} + +/* close down a dcerpc over SMB pipe */ +void dcerpc_pipe_close(struct dcerpc_pipe *p) +{ + if (!p) return; + p->reference_count--; + if (p->reference_count <= 0) { + if (p->security_state) { + p->security_state->security_end(p->security_state); + } + p->transport.shutdown_pipe(p); + talloc_destroy(p->mem_ctx); + } +} + +/* 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) & DCERPC_DREP_LE) { + SSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v); + } else { + RSSVAL(blob->data, DCERPC_FRAG_LEN_OFFSET, v); + } +} + +uint16 dcerpc_get_frag_length(const DATA_BLOB *blob) +{ + if (CVAL(blob->data,DCERPC_DREP_OFFSET) & DCERPC_DREP_LE) { + 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) & DCERPC_DREP_LE) { + 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 + input and output packets +*/ +static NTSTATUS dcerpc_pull(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + struct dcerpc_packet *pkt) +{ + struct ndr_pull *ndr; + + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + + if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + + return ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); +} + +/* + parse a possibly signed blob into a dcerpc request packet structure +*/ +static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p, + DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + struct dcerpc_packet *pkt) +{ + struct ndr_pull *ndr; + NTSTATUS status; + struct dcerpc_auth auth; + DATA_BLOB auth_blob; + + /* non-signed packets are simpler */ + if (!p->auth_info || !p->security_state) { + return dcerpc_pull(blob, mem_ctx, pkt); + } + + ndr = ndr_pull_init_blob(blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + + if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + + /* pull the basic packet */ + status = ndr_pull_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (pkt->ptype != DCERPC_PKT_RESPONSE) { + return status; + } + + auth_blob.length = 8 + pkt->auth_length; + + /* check for a valid length */ + if (pkt->u.response.stub_and_verifier.length < auth_blob.length) { + return NT_STATUS_INFO_LENGTH_MISMATCH; + } + + auth_blob.data = + pkt->u.response.stub_and_verifier.data + + pkt->u.response.stub_and_verifier.length - auth_blob.length; + pkt->u.response.stub_and_verifier.length -= auth_blob.length; + + /* pull the auth structure */ + ndr = ndr_pull_init_blob(&auth_blob, mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + + if (! (CVAL(blob->data, DCERPC_DREP_OFFSET) & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + + status = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + + /* check signature or unseal the packet */ + switch (p->auth_info->auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = p->security_state->unseal_packet(p->security_state, + pkt->u.response.stub_and_verifier.data, + pkt->u.response.stub_and_verifier.length, + &auth.credentials); + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = p->security_state->check_packet(p->security_state, + pkt->u.response.stub_and_verifier.data, + pkt->u.response.stub_and_verifier.length, + &auth.credentials); + break; + + case DCERPC_AUTH_LEVEL_NONE: + break; + + default: + status = NT_STATUS_INVALID_LEVEL; + break; + } + + /* remove the indicated amount of paddiing */ + if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) { + return NT_STATUS_INFO_LENGTH_MISMATCH; + } + pkt->u.response.stub_and_verifier.length -= auth.auth_pad_length; + + return status; +} + + +/* + push a dcerpc request packet into a blob, possibly signing it. +*/ +static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p, + DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + struct dcerpc_packet *pkt) +{ + NTSTATUS status; + struct ndr_push *ndr; + + /* non-signed packets are simpler */ + if (!p->auth_info || !p->security_state) { + return dcerpc_push_auth(blob, mem_ctx, pkt, p->auth_info); + } + + ndr = ndr_push_init_ctx(mem_ctx); + if (!ndr) { + 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; + } + + /* pad to 8 byte multiple */ + p->auth_info->auth_pad_length = NDR_ALIGN(ndr, 8); + ndr_push_zero(ndr, p->auth_info->auth_pad_length); + + /* sign or seal the packet */ + switch (p->auth_info->auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + status = p->security_state->seal_packet(p->security_state, + ndr->data + DCERPC_REQUEST_LENGTH, + ndr->offset - DCERPC_REQUEST_LENGTH, + &p->auth_info->credentials); + break; + + case DCERPC_AUTH_LEVEL_INTEGRITY: + status = p->security_state->sign_packet(p->security_state, + ndr->data + DCERPC_REQUEST_LENGTH, + ndr->offset - DCERPC_REQUEST_LENGTH, + &p->auth_info->credentials); + break; + + case DCERPC_AUTH_LEVEL_NONE: + p->auth_info->credentials = data_blob(NULL, 0); + break; + + default: + status = NT_STATUS_INVALID_LEVEL; + break; + } + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* add the auth verifier */ + status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, p->auth_info); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* extract the whole packet as a blob */ + *blob = ndr_push_blob(ndr); + + /* 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) */ + dcerpc_set_frag_length(blob, blob->length); + dcerpc_set_auth_length(blob, p->auth_info->credentials.length); + + data_blob_free(&p->auth_info->credentials); + + return NT_STATUS_OK; +} + + +/* + fill in the fixed values in a dcerpc header +*/ +static void init_dcerpc_hdr(struct dcerpc_pipe *p, struct dcerpc_packet *pkt) +{ + pkt->rpc_vers = 5; + pkt->rpc_vers_minor = 0; + if (p->flags & DCERPC_PUSH_BIGENDIAN) { + pkt->drep[0] = 0; + } else { + pkt->drep[0] = DCERPC_DREP_LE; + } + pkt->drep[1] = 0; + pkt->drep[2] = 0; + pkt->drep[3] = 0; +} + + +/* + perform a bind using the given syntax + + the auth_info structure is updated with the reply authentication info + on success +*/ +NTSTATUS dcerpc_bind(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + const struct dcerpc_syntax_id *syntax, + const struct dcerpc_syntax_id *transfer_syntax) +{ + struct dcerpc_packet pkt; + NTSTATUS status; + DATA_BLOB blob; + struct dcerpc_syntax_id tsyntax; + + init_dcerpc_hdr(p, &pkt); + + pkt.ptype = DCERPC_PKT_BIND; + pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; + pkt.call_id = p->call_id; + pkt.auth_length = 0; + + pkt.u.bind.max_xmit_frag = 0x2000; + pkt.u.bind.max_recv_frag = 0x2000; + pkt.u.bind.assoc_group_id = 0; + pkt.u.bind.num_contexts = 1; + pkt.u.bind.ctx_list = talloc(mem_ctx, sizeof(pkt.u.bind.ctx_list[0])); + if (!pkt.u.bind.ctx_list) { + return NT_STATUS_NO_MEMORY; + } + pkt.u.bind.ctx_list[0].context_id = 0; + pkt.u.bind.ctx_list[0].num_transfer_syntaxes = 1; + pkt.u.bind.ctx_list[0].abstract_syntax = *syntax; + tsyntax = *transfer_syntax; + pkt.u.bind.ctx_list[0].transfer_syntaxes = &tsyntax; + 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); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* send it on its way */ + status = p->transport.full_request(p, mem_ctx, &blob, &blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* unmarshall the NDR */ + status = dcerpc_pull(&blob, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if ((pkt.ptype != DCERPC_PKT_BIND_ACK && pkt.ptype != DCERPC_PKT_ALTER_ACK) || + pkt.u.bind_ack.num_results == 0 || + pkt.u.bind_ack.ctx_list[0].result != 0) { + status = NT_STATUS_UNSUCCESSFUL; + } + + if (pkt.ptype != DCERPC_PKT_ALTER_ACK) { + p->srv_max_xmit_frag = pkt.u.bind_ack.max_xmit_frag; + p->srv_max_recv_frag = pkt.u.bind_ack.max_recv_frag; + } + + /* the bind_ack might contain a reply set of credentials */ + if (p->auth_info && pkt.u.bind_ack.auth_info.length) { + status = ndr_pull_struct_blob(&pkt.u.bind_ack.auth_info, + mem_ctx, + p->auth_info, + (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth); + } + + return status; +} + +/* + perform a continued bind (and auth3) +*/ +NTSTATUS dcerpc_auth3(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx) +{ + struct dcerpc_packet pkt; + NTSTATUS status; + DATA_BLOB blob; + + init_dcerpc_hdr(p, &pkt); + + pkt.ptype = DCERPC_PKT_AUTH3; + pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; + pkt.call_id = p->call_id++; + pkt.auth_length = 0; + pkt.u.auth._pad = 0; + 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); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* send it on its way */ + status = p->transport.initial_request(p, mem_ctx, &blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return status; +} + + +/* perform a dcerpc bind, using the uuid as the key */ +NTSTATUS dcerpc_bind_byuuid(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + const char *uuid, unsigned version) +{ + struct dcerpc_syntax_id syntax; + struct dcerpc_syntax_id transfer_syntax; + NTSTATUS status; + + status = GUID_from_string(uuid, &syntax.uuid); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("Invalid uuid string in dcerpc_bind_byuuid\n")); + return status; + } + syntax.if_version = version; + + status = GUID_from_string(NDR_GUID, &transfer_syntax.uuid); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + transfer_syntax.if_version = NDR_GUID_VERSION; + + return dcerpc_bind(p, mem_ctx, &syntax, &transfer_syntax); +} + +/* + perform a full request/response pair on a dcerpc pipe +*/ +NTSTATUS dcerpc_request(struct dcerpc_pipe *p, + uint16 opnum, + TALLOC_CTX *mem_ctx, + DATA_BLOB *stub_data_in, + DATA_BLOB *stub_data_out) +{ + + struct dcerpc_packet pkt; + NTSTATUS status; + DATA_BLOB blob, payload; + uint32 remaining, chunk_size; + + init_dcerpc_hdr(p, &pkt); + + remaining = stub_data_in->length; + + /* we can write a full max_recv_frag size, minus the dcerpc + request header size */ + chunk_size = p->srv_max_recv_frag - (DCERPC_MAX_SIGN_SIZE+DCERPC_REQUEST_LENGTH); + + pkt.ptype = DCERPC_PKT_REQUEST; + pkt.call_id = p->call_id++; + pkt.auth_length = 0; + pkt.u.request.alloc_hint = remaining; + pkt.u.request.context_id = 0; + pkt.u.request.opnum = opnum; + + /* we send a series of pdus without waiting for a reply until + the last pdu */ + while (remaining > chunk_size) { + if (remaining == stub_data_in->length) { + pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST; + } else { + pkt.pfc_flags = 0; + } + + pkt.u.request.stub_and_verifier.data = stub_data_in->data + + (stub_data_in->length - remaining); + pkt.u.request.stub_and_verifier.length = chunk_size; + + status = dcerpc_push_request_sign(p, &blob, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = p->transport.initial_request(p, mem_ctx, &blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + remaining -= chunk_size; + } + + /* now we send a pdu with LAST_FRAG sent and get the first + part of the reply */ + if (remaining == stub_data_in->length) { + pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST; + } else { + pkt.pfc_flags = DCERPC_PFC_FLAG_LAST; + } + pkt.u.request.stub_and_verifier.data = stub_data_in->data + + (stub_data_in->length - remaining); + pkt.u.request.stub_and_verifier.length = remaining; + + status = dcerpc_push_request_sign(p, &blob, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* send the pdu and get the initial response pdu */ + status = p->transport.full_request(p, mem_ctx, &blob, &blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = dcerpc_pull_request_sign(p, &blob, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (pkt.ptype == DCERPC_PKT_FAULT) { + p->last_fault_code = pkt.u.fault.status; + return NT_STATUS_NET_WRITE_FAULT; + } + + if (pkt.ptype != DCERPC_PKT_RESPONSE) { + return NT_STATUS_UNSUCCESSFUL; + } + + if (!(pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST)) { + /* something is badly wrong! */ + return NT_STATUS_UNSUCCESSFUL; + } + + payload = pkt.u.response.stub_and_verifier; + + /* continue receiving fragments */ + while (!(pkt.pfc_flags & DCERPC_PFC_FLAG_LAST)) { + uint32 length; + + status = p->transport.secondary_request(p, mem_ctx, &blob); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = dcerpc_pull_request_sign(p, &blob, mem_ctx, &pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (pkt.pfc_flags & DCERPC_PFC_FLAG_FIRST) { + /* start of another packet!? */ + return NT_STATUS_UNSUCCESSFUL; + } + + if (pkt.ptype == DCERPC_PKT_FAULT) { + p->last_fault_code = pkt.u.fault.status; + return NT_STATUS_NET_WRITE_FAULT; + } + + if (pkt.ptype != DCERPC_PKT_RESPONSE) { + return NT_STATUS_UNSUCCESSFUL; + } + + length = pkt.u.response.stub_and_verifier.length; + + payload.data = talloc_realloc(mem_ctx, + payload.data, + payload.length + length); + if (!payload.data) { + return NT_STATUS_NO_MEMORY; + } + + memcpy(payload.data + payload.length, + pkt.u.response.stub_and_verifier.data, + length); + + payload.length += length; + } + + if (stub_data_out) { + *stub_data_out = payload; + } + + if (!(pkt.drep[0] & DCERPC_DREP_LE)) { + p->flags |= DCERPC_PULL_BIGENDIAN; + } else { + p->flags &= ~DCERPC_PULL_BIGENDIAN; + } + + return status; +} + + +/* + this is a paranoid NDR validator. For every packet we push onto the wire + we pull it back again, then push it again. Then we compare the raw NDR data + for that to the NDR we initially generated. If they don't match then we know + we must have a bug in either the pull or push side of our code +*/ +static NTSTATUS dcerpc_ndr_validate_in(TALLOC_CTX *mem_ctx, + DATA_BLOB blob, + size_t struct_size, + NTSTATUS (*ndr_push)(struct ndr_push *, int, void *), + NTSTATUS (*ndr_pull)(struct ndr_pull *, int, void *)) +{ + void *st; + struct ndr_pull *pull; + struct ndr_push *push; + NTSTATUS status; + DATA_BLOB blob2; + + st = talloc(mem_ctx, struct_size); + if (!st) { + return NT_STATUS_NO_MEMORY; + } + + pull = ndr_pull_init_blob(&blob, mem_ctx); + if (!pull) { + return NT_STATUS_NO_MEMORY; + } + + status = ndr_pull(pull, NDR_IN, st); + if (!NT_STATUS_IS_OK(status)) { + return ndr_pull_error(pull, NDR_ERR_VALIDATE, + "failed input validation pull - %s", + nt_errstr(status)); + } + + push = ndr_push_init_ctx(mem_ctx); + if (!push) { + return NT_STATUS_NO_MEMORY; + } + + status = ndr_push(push, NDR_IN, st); + if (!NT_STATUS_IS_OK(status)) { + return ndr_push_error(push, NDR_ERR_VALIDATE, + "failed input validation push - %s", + nt_errstr(status)); + } + + blob2 = ndr_push_blob(push); + + if (!data_blob_equal(&blob, &blob2)) { + DEBUG(3,("original:\n")); + dump_data(3, blob.data, blob.length); + DEBUG(3,("secondary:\n")); + dump_data(3, blob2.data, blob2.length); + return ndr_push_error(push, NDR_ERR_VALIDATE, + "failed input validation data - %s", + nt_errstr(status)); + } + + return NT_STATUS_OK; +} + +/* + this is a paranoid NDR input validator. For every packet we pull + from the wire we push it back again then pull and push it + again. Then we compare the raw NDR data for that to the NDR we + initially generated. If they don't match then we know we must have a + bug in either the pull or push side of our code +*/ +static NTSTATUS dcerpc_ndr_validate_out(TALLOC_CTX *mem_ctx, + void *struct_ptr, + size_t struct_size, + NTSTATUS (*ndr_push)(struct ndr_push *, int, void *), + NTSTATUS (*ndr_pull)(struct ndr_pull *, int, void *)) +{ + void *st; + struct ndr_pull *pull; + struct ndr_push *push; + NTSTATUS status; + DATA_BLOB blob, blob2; + + st = talloc(mem_ctx, struct_size); + if (!st) { + return NT_STATUS_NO_MEMORY; + } + memcpy(st, struct_ptr, struct_size); + + push = ndr_push_init_ctx(mem_ctx); + if (!push) { + return NT_STATUS_NO_MEMORY; + } + + status = ndr_push(push, NDR_OUT, struct_ptr); + if (!NT_STATUS_IS_OK(status)) { + return ndr_push_error(push, NDR_ERR_VALIDATE, + "failed output validation push - %s", + nt_errstr(status)); + } + + blob = ndr_push_blob(push); + + pull = ndr_pull_init_blob(&blob, mem_ctx); + if (!pull) { + return NT_STATUS_NO_MEMORY; + } + + pull->flags |= LIBNDR_FLAG_REF_ALLOC; + status = ndr_pull(pull, NDR_OUT, st); + if (!NT_STATUS_IS_OK(status)) { + return ndr_pull_error(pull, NDR_ERR_VALIDATE, + "failed output validation pull - %s", + nt_errstr(status)); + } + + push = ndr_push_init_ctx(mem_ctx); + if (!push) { + return NT_STATUS_NO_MEMORY; + } + + status = ndr_push(push, NDR_OUT, st); + if (!NT_STATUS_IS_OK(status)) { + return ndr_push_error(push, NDR_ERR_VALIDATE, + "failed output validation push2 - %s", + nt_errstr(status)); + } + + blob2 = ndr_push_blob(push); + + if (!data_blob_equal(&blob, &blob2)) { + DEBUG(3,("original:\n")); + dump_data(3, blob.data, blob.length); + DEBUG(3,("secondary:\n")); + dump_data(3, blob2.data, blob2.length); + return ndr_push_error(push, NDR_ERR_VALIDATE, + "failed output validation data - %s", + nt_errstr(status)); + } + + return NT_STATUS_OK; +} + +/* + a useful helper function for synchronous rpc requests + + this can be used when you have ndr push/pull functions in the + standard format +*/ +NTSTATUS dcerpc_ndr_request(struct dcerpc_pipe *p, + uint32 opnum, + TALLOC_CTX *mem_ctx, + NTSTATUS (*ndr_push)(struct ndr_push *, int, void *), + NTSTATUS (*ndr_pull)(struct ndr_pull *, int, void *), + void *struct_ptr, + size_t struct_size) +{ + struct ndr_push *push; + struct ndr_pull *pull; + NTSTATUS status; + DATA_BLOB request, response; + + /* setup for a ndr_push_* call */ + push = ndr_push_init(); + if (!push) { + talloc_destroy(mem_ctx); + 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)) { + goto failed; + } + + /* retrieve the blob */ + request = ndr_push_blob(push); + + if (p->flags & DCERPC_DEBUG_VALIDATE_IN) { + status = dcerpc_ndr_validate_in(mem_ctx, request, struct_size, + ndr_push, ndr_pull); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } + } + + DEBUG(10,("rpc request data:\n")); + dump_data(10, request.data, request.length); + + /* make the actual dcerpc request */ + status = dcerpc_request(p, opnum, mem_ctx, &request, &response); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } + + /* prepare for ndr_pull_* */ + pull = ndr_pull_init_blob(&response, mem_ctx); + if (!pull) { + 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); + + /* pull the structure from the blob */ + status = ndr_pull(pull, NDR_OUT, struct_ptr); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } + + /* possibly check the packet signature */ + + + if (p->flags & DCERPC_DEBUG_VALIDATE_OUT) { + status = dcerpc_ndr_validate_out(mem_ctx, struct_ptr, struct_size, + ndr_push, ndr_pull); + if (!NT_STATUS_IS_OK(status)) { + goto failed; + } + } + + if (pull->offset != pull->data_size) { + DEBUG(0,("Warning! %d unread bytes\n", pull->data_size - pull->offset)); + status = NT_STATUS_INFO_LENGTH_MISMATCH; + goto failed; + } + +failed: + ndr_push_free(push); + return status; +} + + +/* + a useful function for retrieving the server name we connected to +*/ +const char *dcerpc_server_name(struct dcerpc_pipe *p) +{ + if (!p->transport.peer_name) { + return ""; + } + return p->transport.peer_name(p); +} diff --git a/source/librpc/rpc/dcerpc.h b/source/librpc/rpc/dcerpc.h new file mode 100644 index 00000000000..55c81c374e5 --- /dev/null +++ b/source/librpc/rpc/dcerpc.h @@ -0,0 +1,117 @@ +/* + Unix SMB/CIFS implementation. + DCERPC interface structures + + Copyright (C) Tim Potter 2003 + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +enum dcerpc_transport_t {NCACN_NP, NCACN_IP_TCP}; + +/* + this defines a generic security context for signed/sealed dcerpc pipes. +*/ +struct dcerpc_security { + void *private; + NTSTATUS (*unseal_packet)(struct dcerpc_security *, + uchar *data, size_t length, DATA_BLOB *sig); + NTSTATUS (*check_packet)(struct dcerpc_security *, + const uchar *data, size_t length, const DATA_BLOB *sig); + NTSTATUS (*seal_packet)(struct dcerpc_security *, + uchar *data, size_t length, DATA_BLOB *sig); + NTSTATUS (*sign_packet)(struct dcerpc_security *, + const uchar *data, size_t length, DATA_BLOB *sig); + void (*security_end)(struct dcerpc_security *); +}; + + +struct dcerpc_pipe { + TALLOC_CTX *mem_ctx; + int reference_count; + uint32 call_id; + uint32 srv_max_xmit_frag; + uint32 srv_max_recv_frag; + unsigned flags; + struct dcerpc_security *security_state; + struct dcerpc_auth *auth_info; + const char *binding_string; + + struct dcerpc_transport { + enum dcerpc_transport_t transport; + void *private; + NTSTATUS (*full_request)(struct dcerpc_pipe *, + TALLOC_CTX *, DATA_BLOB *, DATA_BLOB *); + NTSTATUS (*secondary_request)(struct dcerpc_pipe *, TALLOC_CTX *, DATA_BLOB *); + NTSTATUS (*initial_request)(struct dcerpc_pipe *, TALLOC_CTX *, DATA_BLOB *); + NTSTATUS (*shutdown_pipe)(struct dcerpc_pipe *); + const char *(*peer_name)(struct dcerpc_pipe *); + } transport; + + /* the last fault code from a DCERPC fault */ + uint32 last_fault_code; +}; + +/* dcerpc pipe flags */ +#define DCERPC_DEBUG_PRINT_IN (1<<0) +#define DCERPC_DEBUG_PRINT_OUT (1<<1) +#define DCERPC_DEBUG_PRINT_BOTH (DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT) + +#define DCERPC_DEBUG_VALIDATE_IN 4 +#define DCERPC_DEBUG_VALIDATE_OUT 8 +#define DCERPC_DEBUG_VALIDATE_BOTH (DCERPC_DEBUG_VALIDATE_IN | DCERPC_DEBUG_VALIDATE_OUT) + +#define DCERPC_SIGN 16 +#define DCERPC_SEAL 32 + +#define DCERPC_PUSH_BIGENDIAN 64 +#define DCERPC_PULL_BIGENDIAN 128 + +#define DCERPC_SCHANNEL 256 + +/* + this is used to find pointers to calls +*/ +struct dcerpc_interface_call { + const char *name; + size_t struct_size; + NTSTATUS (*ndr_push)(struct ndr_push *, int , void *); + NTSTATUS (*ndr_pull)(struct ndr_pull *, int , void *); + void (*ndr_print)(struct ndr_print *, const char *, int, void *); +}; + +struct dcerpc_endpoint_list { + uint32 count; + const char * const *names; +}; + +struct dcerpc_interface_table { + const char *name; + const char *uuid; + uint32 if_version; + uint32 num_calls; + const struct dcerpc_interface_call *calls; + const struct dcerpc_endpoint_list *endpoints; +}; + + +/* this describes a binding to a particular transport/pipe */ +struct dcerpc_binding { + enum dcerpc_transport_t transport; + const char *host; + const char **options; + uint32 flags; +}; diff --git a/source/librpc/rpc/dcerpc_auth.c b/source/librpc/rpc/dcerpc_auth.c new file mode 100644 index 00000000000..2b01ad2d4e9 --- /dev/null +++ b/source/librpc/rpc/dcerpc_auth.c @@ -0,0 +1,43 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc authentication operations + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + do a non-athenticated dcerpc bind +*/ +NTSTATUS dcerpc_bind_auth_none(struct dcerpc_pipe *p, + const char *uuid, unsigned version) +{ + TALLOC_CTX *mem_ctx; + NTSTATUS status; + + mem_ctx = talloc_init("dcerpc_bind_auth_ntlm"); + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version); + talloc_destroy(mem_ctx); + + return status; +} diff --git a/source/librpc/rpc/dcerpc_lsa.c b/source/librpc/rpc/dcerpc_lsa.c new file mode 100644 index 00000000000..482853c0abd --- /dev/null +++ b/source/librpc/rpc/dcerpc_lsa.c @@ -0,0 +1,79 @@ +/* + Unix SMB/CIFS implementation. + raw dcerpc operations + + Copyright (C) Tim Potter 2004 + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +NTSTATUS lsa_OpenPolicy(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + struct lsa_ObjectAttribute attr; + struct lsa_QosInfo qos; + struct lsa_OpenPolicy r; + NTSTATUS status; + uint16 system_name = '\\'; + + qos.len = 0; + qos.impersonation_level = 2; + qos.context_mode = 1; + qos.effective_only = 0; + + attr.len = 0; + attr.root_dir = NULL; + attr.object_name = NULL; + attr.attributes = 0; + attr.sec_desc = NULL; + attr.sec_qos = &qos; + + r.in.system_name = &system_name; + r.in.attr = &attr; + r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + r.out.handle = handle; + + return dcerpc_lsa_OpenPolicy(p, mem_ctx, &r); +} + +NTSTATUS lsa_OpenPolicy2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, + struct policy_handle *handle) +{ + struct lsa_ObjectAttribute attr; + struct lsa_QosInfo qos; + struct lsa_OpenPolicy2 r; + + qos.len = 0; + qos.impersonation_level = 2; + qos.context_mode = 1; + qos.effective_only = 0; + + attr.len = 0; + attr.root_dir = NULL; + attr.object_name = NULL; + attr.attributes = 0; + attr.sec_desc = NULL; + attr.sec_qos = &qos; + + r.in.system_name = "\\"; + r.in.attr = &attr; + r.in.desired_access = SEC_RIGHTS_MAXIMUM_ALLOWED; + r.out.handle = handle; + + return dcerpc_lsa_OpenPolicy2(p, mem_ctx, &r); +} + diff --git a/source/librpc/rpc/dcerpc_ntlm.c b/source/librpc/rpc/dcerpc_ntlm.c new file mode 100644 index 00000000000..81f434cccfd --- /dev/null +++ b/source/librpc/rpc/dcerpc_ntlm.c @@ -0,0 +1,197 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc authentication operations + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + wrappers for the ntlmssp_*() functions +*/ +static NTSTATUS ntlm_unseal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_unseal_packet(ntlmssp_state, data, length, sig); +} + +static NTSTATUS ntlm_check_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + const DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_check_packet(ntlmssp_state, data, length, sig); +} + +static NTSTATUS ntlm_seal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_seal_packet(ntlmssp_state, data, length, sig); +} + +static NTSTATUS ntlm_sign_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + return ntlmssp_sign_packet(ntlmssp_state, data, length, sig); +} + +static void ntlm_security_end(struct dcerpc_security *dcerpc_security) +{ + struct ntlmssp_state *ntlmssp_state = dcerpc_security->private; + ntlmssp_end(&ntlmssp_state); +} + + + +/* + do ntlm style authentication on a dcerpc pipe +*/ +NTSTATUS dcerpc_bind_auth_ntlm(struct dcerpc_pipe *p, + const char *uuid, unsigned version, + const char *domain, + const char *username, + const char *password) +{ + NTSTATUS status; + struct ntlmssp_state *state; + TALLOC_CTX *mem_ctx; + DATA_BLOB credentials; + + mem_ctx = talloc_init("dcerpc_bind_auth_ntlm"); + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + status = ntlmssp_client_start(&state); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = ntlmssp_set_domain(state, domain); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = ntlmssp_set_username(state, username); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + status = ntlmssp_set_password(state, password); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + p->auth_info = talloc(p->mem_ctx, sizeof(*p->auth_info)); + if (!p->auth_info) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + p->auth_info->auth_type = DCERPC_AUTH_TYPE_NTLMSSP; + + if (p->flags & DCERPC_SEAL) { + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_SEAL; + } else { + /* ntlmssp does not work on dcerpc with + AUTH_LEVEL_NONE */ + state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; + } + p->auth_info->auth_pad_length = 0; + p->auth_info->auth_reserved = 0; + p->auth_info->auth_context_id = random(); + p->auth_info->credentials = data_blob(NULL, 0); + p->security_state = NULL; + + status = ntlmssp_update(state, + p->auth_info->credentials, + &credentials); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + goto done; + } + + p->auth_info->credentials = data_blob_talloc(mem_ctx, + credentials.data, + credentials.length); + data_blob_free(&credentials); + + status = dcerpc_bind_byuuid(p, mem_ctx, uuid, version); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + + status = ntlmssp_update(state, + p->auth_info->credentials, + &credentials); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + goto done; + } + + p->auth_info->credentials = data_blob_talloc(mem_ctx, + credentials.data, + credentials.length); + data_blob_free(&credentials); + + status = dcerpc_auth3(p, mem_ctx); + + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + p->security_state = talloc_p(p->mem_ctx, struct dcerpc_security); + if (!p->security_state) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + p->security_state->private = state; + p->security_state->unseal_packet = ntlm_unseal_packet; + p->security_state->check_packet = ntlm_check_packet; + p->security_state->seal_packet = ntlm_seal_packet; + p->security_state->sign_packet = ntlm_sign_packet; + p->security_state->security_end = ntlm_security_end; + + switch (p->auth_info->auth_level) { + case DCERPC_AUTH_LEVEL_PRIVACY: + case DCERPC_AUTH_LEVEL_INTEGRITY: + /* setup for signing */ + status = ntlmssp_sign_init(state); + break; + } + +done: + talloc_destroy(mem_ctx); + + if (!NT_STATUS_IS_OK(status)) { + p->security_state = NULL; + p->auth_info = NULL; + } + + return status; +} + + diff --git a/source/librpc/rpc/dcerpc_schannel.c b/source/librpc/rpc/dcerpc_schannel.c new file mode 100644 index 00000000000..2a4c0a6bb1b --- /dev/null +++ b/source/librpc/rpc/dcerpc_schannel.c @@ -0,0 +1,266 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc schannel operations + + Copyright (C) Andrew Tridgell 2004 + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + wrappers for the schannel_*() functions +*/ +static NTSTATUS schan_unseal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_unseal_packet(schannel_state, data, length, sig); +} + +static NTSTATUS schan_check_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + const DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_check_packet(schannel_state, data, length, sig); +} + +static NTSTATUS schan_seal_packet(struct dcerpc_security *dcerpc_security, + uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_seal_packet(schannel_state, data, length, sig); +} + +static NTSTATUS schan_sign_packet(struct dcerpc_security *dcerpc_security, + const uchar *data, size_t length, + DATA_BLOB *sig) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + return schannel_sign_packet(schannel_state, data, length, sig); +} + +static void schan_security_end(struct dcerpc_security *dcerpc_security) +{ + struct schannel_state *schannel_state = dcerpc_security->private; + schannel_end(&schannel_state); +} + + +/* + get a schannel key using a netlogon challenge on a secondary pipe +*/ +NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p, + const char *domain, + const char *username, + const char *password, + int chan_type, + uint8 new_session_key[8]) +{ + NTSTATUS status; + struct dcerpc_pipe *p2; + struct netr_ServerReqChallenge r; + struct netr_ServerAuthenticate2 a; + uint8 mach_pwd[16]; + struct netr_CredentialState creds; + const char *workgroup, *workstation; + uint32 negotiate_flags = 0; + + workstation = username; + workgroup = domain; + + /* + step 1 - establish a netlogon connection, with no authentication + */ + status = dcerpc_secondary_smb(p, &p2, + DCERPC_NETLOGON_NAME, + DCERPC_NETLOGON_UUID, + DCERPC_NETLOGON_VERSION); + + + /* + step 2 - request a netlogon challenge + */ + r.in.server_name = talloc_asprintf(p->mem_ctx, "\\\\%s", dcerpc_server_name(p)); + r.in.computer_name = workstation; + generate_random_buffer(r.in.credentials.data, sizeof(r.in.credentials.data), False); + + status = dcerpc_netr_ServerReqChallenge(p2, p->mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* + step 3 - authenticate on the netlogon pipe + */ + E_md4hash(password, mach_pwd); + creds_client_init(&creds, &r.in.credentials, &r.out.credentials, mach_pwd, + &a.in.credentials); + + a.in.server_name = r.in.server_name; + a.in.username = talloc_asprintf(p->mem_ctx, "%s$", workstation); + a.in.secure_channel_type = chan_type; + a.in.computer_name = workstation; + a.in.negotiate_flags = &negotiate_flags; + a.out.negotiate_flags = &negotiate_flags; + + status = dcerpc_netr_ServerAuthenticate2(p2, p->mem_ctx, &a); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (!creds_client_check(&creds, &a.out.credentials)) { + return NT_STATUS_UNSUCCESSFUL; + } + + /* + the schannel session key is now in creds.session_key + + we no longer need the netlogon pipe open + */ + dcerpc_pipe_close(p2); + + memcpy(new_session_key, creds.session_key, 8); + + return NT_STATUS_OK; +} + + +/* + do a schannel style bind on a dcerpc pipe with the given schannel + key. The username is usually of the form HOSTNAME$ and the password + is the domain trust password +*/ +NTSTATUS dcerpc_bind_auth_schannel_key(struct dcerpc_pipe *p, + const char *uuid, unsigned version, + const char *domain, + const char *username, + const uint8 session_key[8]) +{ + NTSTATUS status; + uint8 full_session_key[16]; + struct schannel_state *schannel_state; + const char *workgroup, *workstation; + + memcpy(full_session_key, session_key, 8); + memset(full_session_key+8, 0, 8); + + workstation = username; + workgroup = domain; + + /* + perform a bind with security type schannel + */ + p->auth_info = talloc(p->mem_ctx, sizeof(*p->auth_info)); + if (!p->auth_info) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + p->auth_info->auth_type = DCERPC_AUTH_TYPE_SCHANNEL; + + if (p->flags & DCERPC_SEAL) { + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_PRIVACY; + } else { + /* note that DCERPC_AUTH_LEVEL_NONE does not make any + sense, and would be rejected by the server */ + p->auth_info->auth_level = DCERPC_AUTH_LEVEL_INTEGRITY; + } + p->auth_info->auth_pad_length = 0; + p->auth_info->auth_reserved = 0; + p->auth_info->auth_context_id = random(); + p->security_state = NULL; + + p->auth_info->credentials = data_blob_talloc(p->mem_ctx, + NULL, + 8 + + strlen(workgroup)+1 + + strlen(workstation)+1); + if (!p->auth_info->credentials.data) { + return NT_STATUS_NO_MEMORY; + } + + /* oh, this is ugly! */ + SIVAL(p->auth_info->credentials.data, 0, 0); + SIVAL(p->auth_info->credentials.data, 4, 3); + memcpy(p->auth_info->credentials.data+8, workgroup, strlen(workgroup)+1); + memcpy(p->auth_info->credentials.data+8+strlen(workgroup)+1, + workstation, strlen(workstation)+1); + + /* send the authenticated bind request */ + status = dcerpc_bind_byuuid(p, p->mem_ctx, uuid, version); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + p->security_state = talloc_p(p->mem_ctx, struct dcerpc_security); + if (!p->security_state) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + schannel_state = talloc_p(p->mem_ctx, struct schannel_state); + if (!schannel_state) { + status = NT_STATUS_NO_MEMORY; + goto done; + } + + status = schannel_start(&schannel_state, full_session_key, True); + if (!NT_STATUS_IS_OK(status)) { + goto done; + } + + dump_data_pw("session key:\n", schannel_state->session_key, 16); + + p->security_state->private = schannel_state; + p->security_state->unseal_packet = schan_unseal_packet; + p->security_state->check_packet = schan_check_packet; + p->security_state->seal_packet = schan_seal_packet; + p->security_state->sign_packet = schan_sign_packet; + p->security_state->security_end = schan_security_end; + +done: + return status; +} + + +/* + do a schannel style bind on a dcerpc pipe. The username is usually + of the form HOSTNAME$ and the password is the domain trust password +*/ +NTSTATUS dcerpc_bind_auth_schannel(struct dcerpc_pipe *p, + const char *uuid, unsigned version, + const char *domain, + const char *username, + const char *password) +{ + NTSTATUS status; + uint8 session_key[8]; + + status = dcerpc_schannel_key(p, domain, username, password, + lp_server_role() == ROLE_DOMAIN_BDC? SEC_CHAN_BDC:SEC_CHAN_WKSTA, + session_key); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + status = dcerpc_bind_auth_schannel_key(p, uuid, version, domain, username, session_key); + + return status; +} + diff --git a/source/librpc/rpc/dcerpc_smb.c b/source/librpc/rpc/dcerpc_smb.c new file mode 100644 index 00000000000..7822231b826 --- /dev/null +++ b/source/librpc/rpc/dcerpc_smb.c @@ -0,0 +1,391 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc over SMB transport + + Copyright (C) Tim Potter 2003 + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* transport private information used by SMB pipe transport */ +struct smb_private { + uint16 fnum; + struct cli_tree *tree; +}; + +static struct cli_request *dcerpc_raw_send(struct dcerpc_pipe *p, DATA_BLOB *blob) +{ + struct smb_private *smb = p->transport.private; + struct smb_trans2 trans; + uint16 setup[2]; + struct cli_request *req; + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init("dcerpc_raw_send"); + if (!mem_ctx) return NULL; + + trans.in.data = *blob; + trans.in.params = data_blob(NULL, 0); + + setup[0] = TRANSACT_DCERPCCMD; + setup[1] = smb->fnum; + + trans.in.max_param = 0; + trans.in.max_data = 0x8000; + trans.in.max_setup = 0; + trans.in.setup_count = 2; + trans.in.flags = 0; + trans.in.timeout = 0; + trans.in.setup = setup; + trans.in.trans_name = "\\PIPE\\"; + + req = smb_raw_trans_send(smb->tree, &trans); + + talloc_destroy(mem_ctx); + + return req; +} + + +static NTSTATUS dcerpc_raw_recv(struct dcerpc_pipe *p, + struct cli_request *req, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) +{ + struct smb_private *smb = p->transport.private; + struct smb_trans2 trans; + NTSTATUS status; + uint16 frag_length; + DATA_BLOB payload; + + status = smb_raw_trans_recv(req, mem_ctx, &trans); + /* STATUS_BUFFER_OVERFLOW means that there is more data + available via SMBreadX */ + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { + return status; + } + + payload = trans.out.data; + + if (trans.out.data.length < 16 || + !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { + goto done; + } + + /* we might have recieved a partial fragment, in which case we + need to pull the rest of it */ + frag_length = dcerpc_get_frag_length(&payload); + if (frag_length <= payload.length) { + goto done; + } + + /* make sure the payload can hold the whole fragment */ + payload.data = talloc_realloc(mem_ctx, payload.data, frag_length); + if (!payload.data) { + return NT_STATUS_NO_MEMORY; + } + + /* the rest of the data is available via SMBreadX */ + while (frag_length > payload.length) { + uint32 n; + union smb_read io; + + n = frag_length - payload.length; + if (n > 0xFF00) { + n = 0xFF00; + } + + io.generic.level = RAW_READ_READX; + io.readx.in.fnum = smb->fnum; + io.readx.in.mincnt = n; + io.readx.in.maxcnt = n; + io.readx.in.offset = 0; + io.readx.in.remaining = 0; + io.readx.out.data = payload.data + payload.length; + status = smb_raw_read(smb->tree, &io); + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { + break; + } + + n = io.readx.out.nread; + if (n == 0) { + status = NT_STATUS_UNSUCCESSFUL; + break; + } + + payload.length += n; + + /* if the SMBreadX returns NT_STATUS_OK then there + isn't any more data to be read */ + if (NT_STATUS_IS_OK(status)) { + break; + } + } + +done: + if (blob) { + *blob = payload; + } + + return status; +} + +static NTSTATUS smb_full_request(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *request_blob, + DATA_BLOB *reply_blob) +{ + struct cli_request *req; + req = dcerpc_raw_send(p, request_blob); + return dcerpc_raw_recv(p, req, mem_ctx, reply_blob); +} + + +/* + retrieve a secondary pdu from a pipe +*/ +static NTSTATUS smb_secondary_request(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) +{ + struct smb_private *smb = p->transport.private; + union smb_read io; + uint32 n = 0x2000; + uint32 frag_length; + NTSTATUS status; + + *blob = data_blob_talloc(mem_ctx, NULL, n); + if (!blob->data) { + return NT_STATUS_NO_MEMORY; + } + + io.generic.level = RAW_READ_READX; + io.readx.in.fnum = smb->fnum; + io.readx.in.mincnt = n; + io.readx.in.maxcnt = n; + io.readx.in.offset = 0; + io.readx.in.remaining = 0; + io.readx.out.data = blob->data; + + status = smb_raw_read(smb->tree, &io); + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { + return status; + } + + blob->length = io.readx.out.nread; + + if (blob->length < 16) { + return status; + } + + frag_length = dcerpc_get_frag_length(blob); + if (frag_length <= blob->length) { + return status; + } + + blob->data = talloc_realloc(mem_ctx, blob->data, frag_length); + if (!blob->data) { + return NT_STATUS_NO_MEMORY; + } + + while (frag_length > blob->length && + NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { + + n = frag_length - blob->length; + if (n > 0xFF00) { + n = 0xFF00; + } + + io.readx.in.mincnt = n; + io.readx.in.maxcnt = n; + io.readx.out.data = blob->data + blob->length; + status = smb_raw_read(smb->tree, &io); + + if (!NT_STATUS_IS_OK(status) && + !NT_STATUS_EQUAL(status, STATUS_BUFFER_OVERFLOW)) { + return status; + } + + n = io.readx.out.nread; + blob->length += n; + } + + return status; +} + + +/* + send an initial pdu in a multi-pdu sequence +*/ +static NTSTATUS smb_initial_request(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) +{ + struct smb_private *smb = p->transport.private; + union smb_write io; + NTSTATUS status; + + io.generic.level = RAW_WRITE_WRITEX; + io.writex.in.fnum = smb->fnum; + io.writex.in.offset = 0; + io.writex.in.wmode = PIPE_START_MESSAGE; + io.writex.in.remaining = blob->length; + io.writex.in.count = blob->length; + io.writex.in.data = blob->data; + + status = smb_raw_write(smb->tree, &io); + if (NT_STATUS_IS_OK(status)) { + return status; + } + + /* make sure it accepted it all */ + if (io.writex.out.nwritten != blob->length) { + return NT_STATUS_UNSUCCESSFUL; + } + + return status; +} + + +/* + shutdown SMB pipe connection +*/ +static NTSTATUS smb_shutdown_pipe(struct dcerpc_pipe *p) +{ + struct smb_private *smb = p->transport.private; + union smb_close c; + + /* maybe we're still starting up */ + if (!smb) return NT_STATUS_OK; + + c.close.level = RAW_CLOSE_CLOSE; + c.close.in.fnum = smb->fnum; + c.close.in.write_time = 0; + smb_raw_close(smb->tree, &c); + cli_tree_close(smb->tree); + + return NT_STATUS_OK; +} + +/* + return SMB server name +*/ +static const char *smb_peer_name(struct dcerpc_pipe *p) +{ + struct smb_private *smb = p->transport.private; + return smb->tree->session->transport->called.name; +} + +/* + open a rpc connection to a named pipe +*/ +NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p, + struct cli_tree *tree, + const char *pipe_name) +{ + struct smb_private *smb; + NTSTATUS status; + char *name = NULL; + union smb_open io; + TALLOC_CTX *mem_ctx; + + asprintf(&name, "\\%s", pipe_name); + if (!name) { + return NT_STATUS_NO_MEMORY; + } + + io.ntcreatex.level = RAW_OPEN_NTCREATEX; + io.ntcreatex.in.flags = 0; + io.ntcreatex.in.root_fid = 0; + io.ntcreatex.in.access_mask = + STD_RIGHT_READ_CONTROL_ACCESS | + SA_RIGHT_FILE_WRITE_ATTRIBUTES | + SA_RIGHT_FILE_WRITE_EA | + GENERIC_RIGHTS_FILE_READ | + GENERIC_RIGHTS_FILE_WRITE; + io.ntcreatex.in.file_attr = 0; + io.ntcreatex.in.alloc_size = 0; + io.ntcreatex.in.share_access = + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN; + io.ntcreatex.in.create_options = 0; + io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_IMPERSONATION; + io.ntcreatex.in.security_flags = 0; + io.ntcreatex.in.fname = name; + + mem_ctx = talloc_init("torture_rpc_connection"); + if (!mem_ctx) { + free(name); + return NT_STATUS_NO_MEMORY; + } + status = smb_raw_open(tree, mem_ctx, &io); + free(name); + talloc_destroy(mem_ctx); + + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (!(*p = dcerpc_pipe_init())) { + return NT_STATUS_NO_MEMORY; + } + + /* + fill in the transport methods + */ + (*p)->transport.transport = NCACN_NP; + (*p)->transport.private = NULL; + (*p)->transport.full_request = smb_full_request; + (*p)->transport.secondary_request = smb_secondary_request; + (*p)->transport.initial_request = smb_initial_request; + (*p)->transport.shutdown_pipe = smb_shutdown_pipe; + (*p)->transport.peer_name = smb_peer_name; + + smb = talloc((*p)->mem_ctx, sizeof(*smb)); + if (!smb) { + dcerpc_pipe_close(*p); + return NT_STATUS_NO_MEMORY; + } + + smb->fnum = io.ntcreatex.out.fnum; + smb->tree = tree; + + (*p)->transport.private = smb; + tree->reference_count++; + + return NT_STATUS_OK; +} + +/* + return the SMB tree used for a dcerpc over SMB pipe +*/ +struct cli_tree *dcerpc_smb_tree(struct dcerpc_pipe *p) +{ + struct smb_private *smb = p->transport.private; + + if (p->transport.transport != NCACN_NP) { + return NULL; + } + + return smb->tree; +} diff --git a/source/librpc/rpc/dcerpc_tcp.c b/source/librpc/rpc/dcerpc_tcp.c new file mode 100644 index 00000000000..77b536b10cb --- /dev/null +++ b/source/librpc/rpc/dcerpc_tcp.c @@ -0,0 +1,206 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc over TCP transport + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* transport private information used by TCP pipe transport */ +struct tcp_private { + int fd; + char *server_name; + uint32 port; +}; + +static NTSTATUS tcp_raw_recv(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) +{ + struct tcp_private *tcp = p->transport.private; + ssize_t ret; + uint32 frag_length; + DATA_BLOB blob1; + + blob1 = data_blob_talloc(mem_ctx, NULL, 16); + if (!blob1.data) { + return NT_STATUS_NO_MEMORY; + } + + ret = read_data(tcp->fd, blob1.data, blob1.length); + if (ret != blob1.length) { + return NT_STATUS_NET_WRITE_FAULT; + } + + /* this could be a ncacn_http endpoint - this doesn't work + yet, but it goes close */ + if (strncmp(blob1.data, "ncacn_http/1.0", 14) == 0) { + memmove(blob1.data, blob1.data+14, 2); + ret = read_data(tcp->fd, blob1.data+2, 14); + if (ret != 14) { + return NT_STATUS_NET_WRITE_FAULT; + } + } + + /* we might have recieved a partial fragment, in which case we + need to pull the rest of it */ + frag_length = dcerpc_get_frag_length(&blob1); + if (frag_length == blob1.length) { + *blob = blob1; + return NT_STATUS_OK; + } + + *blob = data_blob_talloc(mem_ctx, NULL, frag_length); + if (!blob->data) { + return NT_STATUS_NO_MEMORY; + } + memcpy(blob->data, blob1.data, blob1.length); + + ret = read_data(tcp->fd, blob->data + blob1.length, frag_length - blob1.length); + if (ret != frag_length - blob1.length) { + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + +static NTSTATUS tcp_full_request(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *request_blob, + DATA_BLOB *reply_blob) +{ + struct tcp_private *tcp = p->transport.private; + ssize_t ret; + + ret = write_data(tcp->fd, request_blob->data, request_blob->length); + if (ret != request_blob->length) { + return NT_STATUS_NET_WRITE_FAULT; + } + + return tcp_raw_recv(p, mem_ctx, reply_blob); +} + + +/* + retrieve a secondary pdu from a pipe +*/ +static NTSTATUS tcp_secondary_request(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) +{ + return tcp_raw_recv(p, mem_ctx, blob); +} + + +/* + send an initial pdu in a multi-pdu sequence +*/ +static NTSTATUS tcp_initial_request(struct dcerpc_pipe *p, + TALLOC_CTX *mem_ctx, + DATA_BLOB *blob) +{ + struct tcp_private *tcp = p->transport.private; + ssize_t ret; + + ret = write_data(tcp->fd, blob->data, blob->length); + if (ret != blob->length) { + return NT_STATUS_NET_WRITE_FAULT; + } + + return NT_STATUS_OK; +} + + +/* + shutdown TCP pipe connection +*/ +static NTSTATUS tcp_shutdown_pipe(struct dcerpc_pipe *p) +{ + struct tcp_private *tcp = p->transport.private; + + if (tcp) { + close(tcp->fd); + } + + return NT_STATUS_OK; +} + +/* + return TCP server name +*/ +static const char *tcp_peer_name(struct dcerpc_pipe *p) +{ + struct tcp_private *tcp = p->transport.private; + return tcp->server_name; +} + + +/* + open a rpc connection to a named pipe +*/ +NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p, + const char *server, + uint32 port) +{ + struct tcp_private *tcp; + int fd; + struct in_addr addr; + + if (port == 0) { + port = EPMAPPER_PORT; + } + + addr.s_addr = interpret_addr(server); + if (addr.s_addr == 0) { + return NT_STATUS_BAD_NETWORK_NAME; + } + + fd = open_socket_out(SOCK_STREAM, &addr, port, 30000); + if (fd == -1) { + return NT_STATUS_PORT_CONNECTION_REFUSED; + } + + if (!(*p = dcerpc_pipe_init())) { + return NT_STATUS_NO_MEMORY; + } + + /* + fill in the transport methods + */ + (*p)->transport.transport = NCACN_IP_TCP; + (*p)->transport.private = NULL; + (*p)->transport.full_request = tcp_full_request; + (*p)->transport.secondary_request = tcp_secondary_request; + (*p)->transport.initial_request = tcp_initial_request; + (*p)->transport.shutdown_pipe = tcp_shutdown_pipe; + (*p)->transport.peer_name = tcp_peer_name; + + tcp = talloc((*p)->mem_ctx, sizeof(*tcp)); + if (!tcp) { + dcerpc_pipe_close(*p); + return NT_STATUS_NO_MEMORY; + } + + tcp->fd = fd; + tcp->server_name = talloc_strdup((*p)->mem_ctx, server); + + (*p)->transport.private = tcp; + + return NT_STATUS_OK; +} diff --git a/source/librpc/rpc/dcerpc_util.c b/source/librpc/rpc/dcerpc_util.c new file mode 100644 index 00000000000..ba61f28c95d --- /dev/null +++ b/source/librpc/rpc/dcerpc_util.c @@ -0,0 +1,668 @@ +/* + Unix SMB/CIFS implementation. + + dcerpc utility functions + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* + this ndr_size_* stuff should really be auto-generated .... +*/ + +static size_t ndr_size_epm_floor(struct epm_floor *fl) +{ + size_t ret = 5; + if (fl->lhs.protocol == EPM_PROTOCOL_UUID) { + ret += 18; + } else { + ret += fl->lhs.info.lhs_data.length; + } + ret += fl->rhs.rhs_data.length; + return ret; +} + +size_t ndr_size_epm_towers(struct epm_towers *towers) +{ + size_t ret = 2; + int i; + for (i=0;inum_floors;i++) { + ret += ndr_size_epm_floor(&towers->floors[i]); + } + return ret; +} + +/* + work out what TCP port to use for a given interface on a given host +*/ +NTSTATUS dcerpc_epm_map_tcp_port(const char *server, + const char *uuid, unsigned version, + uint32 *port) +{ + struct dcerpc_pipe *p; + NTSTATUS status; + struct epm_Map r; + struct policy_handle handle; + struct GUID guid; + struct epm_twr_t twr, *twr_r; + + if (strcasecmp(uuid, DCERPC_EPMAPPER_UUID) == 0 || + strcasecmp(uuid, DCERPC_MGMT_UUID) == 0) { + /* don't lookup epmapper via epmapper! */ + *port = EPMAPPER_PORT; + return NT_STATUS_OK; + } + + status = dcerpc_pipe_open_tcp(&p, server, EPMAPPER_PORT); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* we can use the pipes memory context here as we will have a short + lived connection */ + status = dcerpc_bind_byuuid(p, p->mem_ctx, + DCERPC_EPMAPPER_UUID, + DCERPC_EPMAPPER_VERSION); + if (!NT_STATUS_IS_OK(status)) { + dcerpc_pipe_close(p); + return status; + } + + ZERO_STRUCT(handle); + ZERO_STRUCT(guid); + + twr.towers.num_floors = 5; + twr.towers.floors = talloc(p->mem_ctx, sizeof(twr.towers.floors[0]) * 5); + + /* what I'd like for christmas ... */ + + /* an RPC interface ... */ + twr.towers.floors[0].lhs.protocol = EPM_PROTOCOL_UUID; + GUID_from_string(uuid, &twr.towers.floors[0].lhs.info.uuid.uuid); + twr.towers.floors[0].lhs.info.uuid.version = version; + twr.towers.floors[0].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2); + + /* encoded with NDR ... */ + twr.towers.floors[1].lhs.protocol = EPM_PROTOCOL_UUID; + GUID_from_string(NDR_GUID, &twr.towers.floors[1].lhs.info.uuid.uuid); + twr.towers.floors[1].lhs.info.uuid.version = NDR_GUID_VERSION; + twr.towers.floors[1].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2); + + /* on an RPC connection ... */ + twr.towers.floors[2].lhs.protocol = EPM_PROTOCOL_RPC_C; + twr.towers.floors[2].lhs.info.lhs_data = data_blob(NULL, 0); + twr.towers.floors[2].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2); + + /* on a TCP port ... */ + twr.towers.floors[3].lhs.protocol = EPM_PROTOCOL_TCP; + twr.towers.floors[3].lhs.info.lhs_data = data_blob(NULL, 0); + twr.towers.floors[3].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 2); + + /* on an IP link ... */ + twr.towers.floors[4].lhs.protocol = EPM_PROTOCOL_IP; + twr.towers.floors[4].lhs.info.lhs_data = data_blob(NULL, 0); + twr.towers.floors[4].rhs.rhs_data = data_blob_talloc_zero(p->mem_ctx, 4); + + /* with some nice pretty paper around it of course */ + r.in.object = &guid; + r.in.map_tower = &twr; + r.in.entry_handle = &handle; + r.in.max_towers = 1; + r.out.entry_handle = &handle; + + status = dcerpc_epm_Map(p, p->mem_ctx, &r); + if (!NT_STATUS_IS_OK(status)) { + dcerpc_pipe_close(p); + return status; + } + if (r.out.status != 0 || r.out.num_towers != 1) { + dcerpc_pipe_close(p); + return NT_STATUS_PORT_UNREACHABLE; + } + + twr_r = r.out.towers[0].twr; + if (!twr_r) { + dcerpc_pipe_close(p); + return NT_STATUS_PORT_UNREACHABLE; + } + + if (twr_r->towers.num_floors != 5 || + twr_r->towers.floors[3].lhs.protocol != twr.towers.floors[3].lhs.protocol || + twr_r->towers.floors[3].rhs.rhs_data.length != 2) { + dcerpc_pipe_close(p); + return NT_STATUS_PORT_UNREACHABLE; + } + + *port = RSVAL(twr_r->towers.floors[3].rhs.rhs_data.data, 0); + + dcerpc_pipe_close(p); + + return NT_STATUS_OK; +} + + +/* + find the pipe name for a local IDL interface +*/ +const char *idl_pipe_name(const char *uuid, uint32 if_version) +{ + int i; + for (i=0;dcerpc_pipes[i];i++) { + if (strcasecmp(dcerpc_pipes[i]->uuid, uuid) == 0 && + dcerpc_pipes[i]->if_version == if_version) { + return dcerpc_pipes[i]->name; + } + } + return "UNKNOWN"; +} + +/* + find the number of calls defined by local IDL +*/ +int idl_num_calls(const char *uuid, uint32 if_version) +{ + int i; + for (i=0;dcerpc_pipes[i];i++) { + if (strcasecmp(dcerpc_pipes[i]->uuid, uuid) == 0 && + dcerpc_pipes[i]->if_version == if_version) { + return dcerpc_pipes[i]->num_calls; + } + } + return -1; +} + + +/* + find a dcerpc interface by name +*/ +const struct dcerpc_interface_table *idl_iface_by_name(const char *name) +{ + int i; + for (i=0;dcerpc_pipes[i];i++) { + if (strcasecmp(dcerpc_pipes[i]->name, name) == 0) { + return dcerpc_pipes[i]; + } + } + return NULL; +} + +/* + find a dcerpc interface by uuid +*/ +const struct dcerpc_interface_table *idl_iface_by_uuid(const char *uuid) +{ + int i; + for (i=0;dcerpc_pipes[i];i++) { + if (strcasecmp(dcerpc_pipes[i]->uuid, uuid) == 0) { + return dcerpc_pipes[i]; + } + } + return NULL; +} + + + +/* + push a dcerpc_packet into a blob, potentially with auth info +*/ +NTSTATUS dcerpc_push_auth(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, + struct dcerpc_packet *pkt, + struct dcerpc_auth *auth_info) +{ + NTSTATUS status; + struct ndr_push *ndr; + + ndr = ndr_push_init_ctx(mem_ctx); + if (!ndr) { + return NT_STATUS_NO_MEMORY; + } + + if (!(pkt->drep[0] & DCERPC_DREP_LE)) { + ndr->flags |= LIBNDR_FLAG_BIGENDIAN; + } + + if (auth_info) { + pkt->auth_length = auth_info->credentials.length; + } else { + pkt->auth_length = 0; + } + + status = ndr_push_dcerpc_packet(ndr, NDR_SCALARS|NDR_BUFFERS, pkt); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (auth_info) { + status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info); + } + + *blob = ndr_push_blob(ndr); + + /* fill in the frag length */ + dcerpc_set_frag_length(blob, blob->length); + + return NT_STATUS_OK; +} + + +static const struct { + const char *name; + enum dcerpc_transport_t transport; +} ncacn_transports[] = { + {"ncacn_np", NCACN_NP}, + {"ncacn_ip_tcp", NCACN_IP_TCP} +}; + +static const struct { + const char *name; + uint32 flag; +} ncacn_options[] = { + {"sign", DCERPC_SIGN}, + {"seal", DCERPC_SEAL}, + {"schannel", DCERPC_SCHANNEL}, + {"validate", DCERPC_DEBUG_VALIDATE_BOTH}, + {"print", DCERPC_DEBUG_PRINT_BOTH}, + {"bigendian", DCERPC_PUSH_BIGENDIAN} +}; + +/* + form a binding string from a binding structure +*/ +const char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b) +{ + char *s = NULL; + int i; + const char *t_name=NULL; + + for (i=0;itransport) { + t_name = ncacn_transports[i].name; + } + } + if (!t_name) { + return NULL; + } + + s = talloc_asprintf(mem_ctx, "%s:%s:[", t_name, b->host); + if (!s) return NULL; + + /* this is a *really* inefficent way of dealing with strings, + but this is rarely called and the strings are always short, + so I don't care */ + for (i=0;b->options && b->options[i];i++) { + s = talloc_asprintf(mem_ctx, "%s%s,", s, b->options[i]); + if (!s) return NULL; + } + for (i=0;iflags & ncacn_options[i].flag) { + s = talloc_asprintf(mem_ctx, "%s%s,", s, ncacn_options[i].name); + if (!s) return NULL; + } + } + if (s[strlen(s)-1] == ',') { + s[strlen(s)-1] = 0; + } + s = talloc_asprintf(mem_ctx, "%s]", s); + + return s; +} + +/* + parse a binding string into a dcerpc_binding structure +*/ +NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *s, struct dcerpc_binding *b) +{ + char *part1, *part2, *part3; + char *p; + int i, j, comma_count; + + p = strchr(s, ':'); + if (!p) { + return NT_STATUS_INVALID_PARAMETER; + } + part1 = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s)); + if (!part1) { + return NT_STATUS_NO_MEMORY; + } + s = p+1; + + p = strchr(s, ':'); + if (!p) { + p = strchr(s, '['); + if (p) { + part2 = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s)); + part3 = talloc_strdup(mem_ctx, p+1); + if (part3[strlen(part3)-1] != ']') { + return NT_STATUS_INVALID_PARAMETER; + } + part3[strlen(part3)-1] = 0; + } else { + part2 = talloc_strdup(mem_ctx, s); + part3 = NULL; + } + } else { + part2 = talloc_strndup(mem_ctx, s, PTR_DIFF(p, s)); + part3 = talloc_strdup(mem_ctx, p+1); + } + if (!part2) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0;itransport = ncacn_transports[i].transport; + break; + } + } + if (i==ARRAY_SIZE(ncacn_transports)) { + DEBUG(0,("Unknown dcerpc transport '%s'\n", part1)); + return NT_STATUS_INVALID_PARAMETER; + } + + b->host = part2; + b->options = NULL; + b->flags = 0; + + if (!part3) { + return NT_STATUS_OK; + } + + /* the [] brackets are optional */ + if (*part3 == '[' && part3[strlen(part3)-1] == ']') { + part3++; + part3[strlen(part3)-1] = 0; + } + + comma_count = count_chars(part3, ','); + b->options = talloc_array_p(mem_ctx, const char *, comma_count+2); + if (!b->options) { + return NT_STATUS_NO_MEMORY; + } + + for (i=0; (p = strchr(part3, ',')); i++) { + b->options[i] = talloc_strndup(mem_ctx, part3, PTR_DIFF(p, part3)); + if (!b->options[i]) { + return NT_STATUS_NO_MEMORY; + } + part3 = p+1; + } + b->options[i] = part3; + b->options[i+1] = NULL; + + /* some options are pre-parsed for convenience */ + for (i=0;b->options[i];i++) { + for (j=0;joptions[i]) == 0) { + int k; + b->flags |= ncacn_options[j].flag; + for (k=i;b->options[k];k++) { + b->options[k] = b->options[k+1]; + } + i--; + break; + } + } + } + + return NT_STATUS_OK; +} + + +/* open a rpc connection to a rpc pipe on SMB using the binding + structure to determine the endpoint and options */ +static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p, + struct dcerpc_binding *binding, + const char *pipe_uuid, + uint32 pipe_version, + const char *domain, + const char *username, + const char *password) +{ + NTSTATUS status; + BOOL retry; + struct cli_state *cli; + const char *pipe_name; + + if (!binding->options || !binding->options[0]) { + const struct dcerpc_interface_table *table = idl_iface_by_uuid(pipe_uuid); + if (!table) { + DEBUG(0,("Unknown interface endpoint '%s'\n", pipe_uuid)); + return NT_STATUS_INVALID_PARAMETER; + } + /* only try the first endpoint for now */ + pipe_name = table->endpoints->names[0]; + } else { + pipe_name = binding->options[0]; + } + + if (strncasecmp(pipe_name, "\\pipe\\", 6) == 0) { + pipe_name += 6; + } + if (strncasecmp(pipe_name, "/pipe/", 6) == 0) { + pipe_name += 6; + } + + status = cli_full_connection(&cli, lp_netbios_name(), + binding->host, NULL, + "ipc$", "?????", + username, username[0]?domain:"", + password, 0, &retry); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to connect to %s - %s\n", binding->host, nt_errstr(status))); + return status; + } + + status = dcerpc_pipe_open_smb(p, cli->tree, pipe_name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to open pipe %s - %s\n", pipe_name, nt_errstr(status))); + cli_tdis(cli); + cli_shutdown(cli); + return status; + } + + /* this ensures that the reference count is decremented so + a pipe close will really close the link */ + cli_tree_close(cli->tree); + + (*p)->flags = binding->flags; + + if (binding->flags & DCERPC_SCHANNEL) { + const char *trust_password = secrets_fetch_machine_password(); + if (!trust_password) { + DEBUG(0,("Unable to fetch machine password\n")); + goto done; + } + status = dcerpc_bind_auth_schannel(*p, pipe_uuid, pipe_version, + lp_workgroup(), + lp_netbios_name(), + trust_password); + } else if (binding->flags & (DCERPC_SIGN | DCERPC_SEAL)) { + status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password); + } else { + status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); + } + +done: + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status))); + dcerpc_pipe_close(*p); + return status; + } + + return NT_STATUS_OK; +} + + +/* open a rpc connection to a rpc pipe on SMP using the binding + structure to determine the endpoint and options */ +static NTSTATUS dcerpc_pipe_connect_ncacn_ip_tcp(struct dcerpc_pipe **p, + struct dcerpc_binding *binding, + const char *pipe_uuid, + uint32 pipe_version, + const char *domain, + const char *username, + const char *password) +{ + NTSTATUS status; + uint32 port = 0; + + if (binding->options && binding->options[0]) { + port = atoi(binding->options[0]); + } + + if (port == 0) { + status = dcerpc_epm_map_tcp_port(binding->host, + pipe_uuid, pipe_version, + &port); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to map DCERPC/TCP port for '%s' - %s\n", + pipe_uuid, nt_errstr(status))); + return status; + } + DEBUG(1,("Mapped to DCERPC/TCP port %u\n", port)); + } + + status = dcerpc_pipe_open_tcp(p, binding->host, port); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to connect to %s:%d\n", binding->host, port)); + return status; + } + + /* it doesn't seem to work to do a null NTLMSSP session without either sign + or seal, so force signing if we are doing ntlmssp */ + if (username[0] && !(binding->flags & (DCERPC_SIGN|DCERPC_SEAL))) { + binding->flags |= DCERPC_SIGN; + } + + (*p)->flags = binding->flags; + + if (!(binding->flags & (DCERPC_SIGN|DCERPC_SEAL)) && !username[0]) { + status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version); + } else { + status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, + domain, username, password); + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to bind to uuid %s - %s\n", pipe_uuid, nt_errstr(status))); + dcerpc_pipe_close(*p); + return status; + } + + return status; +} + + +/* open a rpc connection to a rpc pipe, using the specified + binding structure to determine the endpoint and options */ +NTSTATUS dcerpc_pipe_connect_b(struct dcerpc_pipe **p, + struct dcerpc_binding *binding, + const char *pipe_uuid, + uint32 pipe_version, + const char *domain, + const char *username, + const char *password) +{ + NTSTATUS status = NT_STATUS_INVALID_PARAMETER; + + switch (binding->transport) { + case NCACN_NP: + status = dcerpc_pipe_connect_ncacn_np(p, binding, pipe_uuid, pipe_version, + domain, username, password); + break; + case NCACN_IP_TCP: + status = dcerpc_pipe_connect_ncacn_ip_tcp(p, binding, pipe_uuid, pipe_version, + domain, username, password); + break; + } + + /* remember the binding string for possible secondary connections */ + if (NT_STATUS_IS_OK(status)) { + (*p)->binding_string = dcerpc_binding_string((*p)->mem_ctx, binding); + } + + return status; +} + + +/* open a rpc connection to a rpc pipe, using the specified string + binding to determine the endpoint and options */ +NTSTATUS dcerpc_pipe_connect(struct dcerpc_pipe **p, + const char *binding, + const char *pipe_uuid, + uint32 pipe_version, + const char *domain, + const char *username, + const char *password) +{ + struct dcerpc_binding b; + NTSTATUS status; + TALLOC_CTX *mem_ctx; + + mem_ctx = talloc_init("dcerpc_pipe_connect"); + if (!mem_ctx) return NT_STATUS_NO_MEMORY; + + status = dcerpc_parse_binding(mem_ctx, binding, &b); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to parse dcerpc binding '%s'\n", binding)); + talloc_destroy(mem_ctx); + return status; + } + + DEBUG(3,("Using binding %s\n", dcerpc_binding_string(mem_ctx, &b))); + + status = dcerpc_pipe_connect_b(p, &b, pipe_uuid, pipe_version, domain, username, password); + + talloc_destroy(mem_ctx); + return status; +} + + +/* + create a secondary dcerpc connection on SMB + the secondary connection will be on the same SMB connection, but + use a new fnum +*/ +NTSTATUS dcerpc_secondary_smb(struct dcerpc_pipe *p, struct dcerpc_pipe **p2, + const char *pipe_name, + const char *pipe_uuid, + uint32 pipe_version) +{ + NTSTATUS status; + struct cli_tree *tree; + + tree = dcerpc_smb_tree(p); + if (!tree) { + return NT_STATUS_INVALID_PARAMETER; + } + + status = dcerpc_pipe_open_smb(p2, tree, pipe_name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + (*p2)->flags = p->flags; + + status = dcerpc_bind_auth_none(*p2, pipe_uuid, pipe_version); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} -- cgit