1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-22 22:04:08 +03:00

"For I have laboured mightily on Luke's code, and hath broken

all I saw" - the book of Jeremy, chapter 1 :-).

So here is the mega-merge of the NTDOM branch server code.
It doesn't include the new client side pieces, we'll look
at that later.

This should give the same functionality, server wise, as
the NTDOM branch does, only merged into the main branch.

Any fixes to domain controler functionality should be
added to the main branch, not the NTDOM branch.

This code compiles without warnings on gcc2.8, but will
need further testing before we are sure all the working
functionality of the NTDOM server branch has been
correctly carried over.

I hereby declare the server side of the NTDOM branch
dead (and all who sail in her :-).

Jeremy.
(This used to be commit 118ba4d77a33248e762a2cf843fb7cbc906ee6e7)
This commit is contained in:
Jeremy Allison 1998-03-11 21:11:04 +00:00
parent 4c6230afd2
commit fdeea341ed
56 changed files with 22918 additions and 2575 deletions

View File

@ -33,13 +33,10 @@ extern pstring workgroup;
#define CLIENT_TIMEOUT (30*1000)
#ifdef NTDOMAIN
/****************************************************************************
experimental nt login.
****************************************************************************/
BOOL do_nt_login(char *desthost, char *myhostname,
BOOL client_do_nt_login(char *desthost, char *myhostname,
int Client, int cnum)
{
DOM_CHAL clnt_chal;
@ -351,4 +348,3 @@ BOOL do_nt_login(char *desthost, char *myhostname,
return True;
}
#endif /* NTDOMAIN */

127
source3/include/ntdomain.h Normal file
View File

@ -0,0 +1,127 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _NT_DOMAIN_H /* _NT_DOMAIN_H */
#define _NT_DOMAIN_H
/* dce/rpc support */
#include "lib/rpc/include/rpc_dce.h"
/* miscellaneous structures / defines */
#include "lib/rpc/include/rpc_misc.h"
/* different dce/rpc pipes */
#include "lib/rpc/include/rpc_lsa.h"
#include "lib/rpc/include/rpc_netlogon.h"
#include "lib/rpc/include/rpc_reg.h"
#include "lib/rpc/include/rpc_samr.h"
#include "lib/rpc/include/rpc_srvsvc.h"
#include "lib/rpc/include/rpc_wkssvc.h"
/*
* A bunch of stuff that was put into smb.h
* in the NTDOM branch - it didn't belong there.
*/
typedef struct
{
struct mem_buf *data; /* memory buffer */
uint32 offset; /* offset currently being accessed in memory buffer */
uint8 align; /* data alignment */
BOOL io; /* parsing in or out of data stream */
} prs_struct;
typedef struct
{
int cnum;
int uid;
BOOL open; /* open connection */
uint16 device_state;
fstring name;
fstring pipe_srv_name;
prs_struct rhdr; /* output header */
prs_struct rdata; /* output data */
prs_struct rauth; /* output authentication verifier */
RPC_HDR hdr;
RPC_HDR_BA hdr_ba;
RPC_HDR_RB hdr_rb;
RPC_HDR_RR hdr_rr;
RPC_AUTH_NTLMSSP_REQ ntlmssp_req;
RPC_AUTH_NTLMSSP_RESP ntlmssp_resp;
uint32 max_rdata_len;
uint32 hdr_offsets;
} pipes_struct;
struct acct_info
{
fstring acct_name; /* account name */
uint32 smb_userid; /* domain-relative RID */
};
struct api_struct
{
char *name;
uint8 opnum;
void (*fn) (int uid, prs_struct*, prs_struct*);
};
struct mem_desc
{
/* array memory offsets */
uint32 start;
uint32 end;
};
struct mem_buf
{
BOOL dynamic; /* True iff data has been dynamically allocated
(and therefore can be freed) */
char *data;
uint32 data_size;
uint32 data_used;
uint32 margin; /* safety margin when reallocing. */
/* this can be abused quite nicely */
uint8 align; /* alignment of data structures (smb, dce/rpc, udp etc) */
struct mem_desc offset;
struct mem_buf *next;
};
typedef struct
{
uint32 rid;
char *name;
} rid_name;
#endif /* _NT_DOMAIN_H */

View File

@ -7,6 +7,7 @@
#define NT_STATUS_INVALID_INFO_CLASS (3)
#define NT_STATUS_INFO_LENGTH_MISMATCH (4)
#define NT_STATUS_ACCESS_VIOLATION (5)
#define STATUS_BUFFER_OVERFLOW (5)
#define NT_STATUS_IN_PAGE_ERROR (6)
#define NT_STATUS_PAGEFILE_QUOTA (7)
#define NT_STATUS_INVALID_HANDLE (8)

File diff suppressed because it is too large Load Diff

211
source3/include/rpc_dce.h Normal file
View File

@ -0,0 +1,211 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _DCE_RPC_H /* _DCE_RPC_H */
#define _DCE_RPC_H
#include "rpc_misc.h" /* this only pulls in STRHDR */
/* DCE/RPC packet types */
enum RPC_PKT_TYPE
{
RPC_REQUEST = 0x00,
RPC_RESPONSE = 0x02,
RPC_BIND = 0x0B,
RPC_BINDACK = 0x0C
};
/* DCE/RPC flags */
#define RPC_FLG_FIRST 0x01
#define RPC_FLG_LAST 0x02
/* RPC_IFACE */
typedef struct rpc_iface_info
{
uint8 data[16]; /* 16 bytes of rpc interface identification */
uint32 version; /* the interface version number */
} RPC_IFACE;
struct pipe_id_info
{
/* the names appear not to matter: the syntaxes _do_ matter */
char *client_pipe;
RPC_IFACE abstr_syntax; /* this one is the abstract syntax id */
char *server_pipe; /* this one is the secondary syntax name */
RPC_IFACE trans_syntax; /* this one is the primary syntax id */
};
/* RPC_HDR - dce rpc header */
typedef struct rpc_hdr_info
{
uint8 major; /* 5 - RPC major version */
uint8 minor; /* 0 - RPC minor version */
uint8 pkt_type; /* RPC_PKT_TYPE - RPC response packet */
uint8 flags; /* DCE/RPC flags */
uint32 pack_type; /* 0x1000 0000 - packed data representation */
uint16 frag_len; /* fragment length - data size (bytes) inc header and tail. */
uint16 auth_len; /* 0 - authentication length */
uint32 call_id; /* call identifier. matches 12th uint32 of incoming RPC data. */
} RPC_HDR;
/* RPC_HDR_RR - ms request / response rpc header */
typedef struct rpc_hdr_rr_info
{
uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */
uint8 context_id; /* 0 - presentation context identifier */
uint8 cancel_count; /* 0 - cancel count */
uint8 opnum; /* opnum */
uint8 reserved; /* 0 - reserved. */
} RPC_HDR_RR;
/* this seems to be the same string name depending on the name of the pipe,
* but is more likely to be linked to the interface name
* "srvsvc", "\\PIPE\\ntsvcs"
* "samr", "\\PIPE\\lsass"
* "wkssvc", "\\PIPE\\wksvcs"
* "NETLOGON", "\\PIPE\\NETLOGON"
*/
/* RPC_ADDR_STR */
typedef struct rpc_addr_info
{
uint16 len; /* length of the string including null terminator */
fstring str; /* the string above in single byte, null terminated form */
} RPC_ADDR_STR;
/* RPC_HDR_BBA */
typedef struct rpc_hdr_bba_info
{
uint16 max_tsize; /* maximum transmission fragment size (0x1630) */
uint16 max_rsize; /* max receive fragment size (0x1630) */
uint32 assoc_gid; /* associated group id (0x0) */
} RPC_HDR_BBA;
/* RPC_BIND_REQ - ms req bind */
typedef struct rpc_bind_req_info
{
RPC_HDR_BBA bba;
uint32 num_elements; /* the number of elements (0x1) */
uint16 context_id; /* presentation context identifier (0x0) */
uint8 num_syntaxes; /* the number of syntaxes (has always been 1?)(0x1) */
RPC_IFACE abstract; /* num and vers. of interface client is using */
RPC_IFACE transfer; /* num and vers. of interface to use for replies */
} RPC_HDR_RB;
/* RPC_RESULTS - can only cope with one reason, right now... */
typedef struct rpc_results_info
{
/* uint8[] # 4-byte alignment padding, against SMB header */
uint8 num_results; /* the number of results (0x01) */
/* uint8[] # 4-byte alignment padding, against SMB header */
uint16 result; /* result (0x00 = accept) */
uint16 reason; /* reason (0x00 = no reason specified) */
} RPC_RESULTS;
/* RPC_HDR_BA */
typedef struct rpc_hdr_ba_info
{
RPC_HDR_BBA bba;
RPC_ADDR_STR addr ; /* the secondary address string, as described earlier */
RPC_RESULTS res ; /* results and reasons */
RPC_IFACE transfer; /* the transfer syntax from the request */
} RPC_HDR_BA;
/* this is TEMPORARY */
/* RPC_AUTH_VERIFIER */
typedef struct rpc_auth_verif_info
{
fstring ssp_str;
uint32 ssp_ver;
} RPC_AUTH_VERIFIER;
/* this is TEMPORARILY coded up as a specific structure */
/* this structure comes after the bind request */
/* RPC_AUTH_NTLMSSP_REQ */
typedef struct rpc_auth_ntlmssp_req_info
{
fstring ntlmssp_str; /* "NTLMSSP" */
uint32 ntlmssp_ver; /* 0x0000 0001 */
uint32 unknown_0; /* 0x00b2b3 */
STRHDR hdr_myname; /* offset is against START of this structure */
STRHDR hdr_domain; /* offset is against START of this structure */
fstring myname; /* calling workstation's name */
fstring domain; /* calling workstations's domain */
} RPC_AUTH_NTLMSSP_REQ;
/* this is TEMPORARILY coded up as a specific structure */
/* this structure comes after the bind acknowledgement */
/* RPC_AUTH_NTLMSSP_RESP */
typedef struct rpc_auth_ntlmssp_resp_info
{
uint8 auth_type; /* 0x0a */
uint8 auth_level; /* 0x06 */
uint8 stub_type_len; /* don't know */
uint8 padding; /* padding */
uint32 ptr_0; /* non-zero pointer to something */
fstring ntlmssp_str; /* "NTLMSSP" */
uint32 ntlmssp_ver; /* 0x0000 0002 */
uint32 unknown_1; /* 0x0000 0000 */
uint32 unknown_2; /* 0x00b2b3 */
uint32 unknown_3; /* 0x0082b1 */
uint8 data[16]; /* 0x10 bytes of something */
} RPC_AUTH_NTLMSSP_RESP;
/* attached to the end of encrypted rpc requests and responses */
/* RPC_AUTH_NTLMSSP_CHK */
typedef struct rpc_auth_ntlmssp_chk_info
{
uint32 ver; /* 0x1 */
uint8 data[12];
} RPC_AUTH_NTLMSSP_CHK;
#endif /* _DCE_RPC_H */

288
source3/include/rpc_lsa.h Normal file
View File

@ -0,0 +1,288 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _RPC_LSA_H /* _RPC_LSA_H */
#define _RPC_LSA_H
#include "rpc_misc.h"
enum SID_NAME_USE
{
SID_NAME_USER = 1,
SID_NAME_DOM_GRP = 2, /* domain group */
SID_NAME_WKN_GRP = 5 /* well-known group */
};
/* ntlsa pipe */
#define LSA_OPENPOLICY 0x2c
#define LSA_QUERYINFOPOLICY 0x07
#define LSA_ENUMTRUSTDOM 0x0d
#define LSA_CLOSE 0x00
#define LSA_OPENSECRET 0x1C
#define LSA_LOOKUPSIDS 0x0f
/* XXXX these are here to get a compile! */
#define LSA_LOOKUPRIDS 0xFD
#define LSA_LOOKUPNAMES 0xFC
#define LSA_MAX_GROUPS 32
#define LSA_MAX_SIDS 32
/* DOM_QUERY - info class 3 and 5 LSA Query response */
typedef struct dom_query_info
{
uint16 uni_dom_max_len; /* domain name string length * 2 */
uint16 uni_dom_str_len; /* domain name string length * 2 */
uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */
uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */
UNISTR2 uni_domain_name; /* domain name (unicode string) */
DOM_SID2 dom_sid; /* domain SID */
} DOM_QUERY;
/* level 5 is same as level 3. we hope. */
typedef DOM_QUERY DOM_QUERY_3;
typedef DOM_QUERY DOM_QUERY_5;
typedef struct obj_attr_info
{
uint32 len; /* 0x18 - length (in bytes) inc. the length field. */
uint32 ptr_root_dir; /* 0 - root directory (pointer) */
uint32 ptr_obj_name; /* 0 - object name (pointer) */
uint32 attributes; /* 0 - attributes (undocumented) */
uint32 ptr_sec_desc; /* 0 - security descriptior (pointer) */
uint32 sec_qos; /* 0 - security quality of service */
} LSA_OBJ_ATTR;
/* LSA_Q_OPEN_POL - LSA Query Open Policy */
typedef struct lsa_q_open_pol_info
{
uint32 ptr; /* undocumented buffer pointer */
UNISTR2 uni_server_name; /* server name, starting with two '\'s */
LSA_OBJ_ATTR attr ; /* object attributes */
uint32 des_access; /* desired access attributes */
} LSA_Q_OPEN_POL;
/* LSA_R_OPEN_POL - response to LSA Open Policy */
typedef struct lsa_r_open_pol_info
{
POLICY_HND pol; /* policy handle */
uint32 status; /* return code */
} LSA_R_OPEN_POL;
/* LSA_Q_QUERY_INFO - LSA query info policy */
typedef struct lsa_query_info
{
POLICY_HND pol; /* policy handle */
uint16 info_class; /* info class */
} LSA_Q_QUERY_INFO;
/* LSA_R_QUERY_INFO - response to LSA query info policy */
typedef struct lsa_r_query_info
{
uint32 undoc_buffer; /* undocumented buffer pointer */
uint16 info_class; /* info class (same as info class in request) */
union
{
DOM_QUERY_3 id3;
DOM_QUERY_5 id5;
} dom;
uint32 status; /* return code */
} LSA_R_QUERY_INFO;
/* LSA_Q_ENUM_TRUST_DOM - LSA enumerate trusted domains */
typedef struct lsa_enum_trust_dom_info
{
POLICY_HND pol; /* policy handle */
uint32 enum_context; /* enumeration context handle */
uint32 preferred_len; /* preferred maximum length */
} LSA_Q_ENUM_TRUST_DOM;
/* LSA_R_ENUM_TRUST_DOM - response to LSA enumerate trusted domains */
typedef struct lsa_r_enum_trust_dom_info
{
uint32 enum_context; /* enumeration context handle */
uint32 num_domains; /* number of domains */
uint32 ptr_enum_domains; /* buffer pointer to num domains */
/* this lot is only added if ptr_enum_domains is non-NULL */
uint32 num_domains2; /* number of domains */
UNIHDR2 hdr_domain_name;
UNISTR2 uni_domain_name;
DOM_SID2 other_domain_sid;
uint32 status; /* return code */
} LSA_R_ENUM_TRUST_DOM;
/* LSA_Q_CLOSE */
typedef struct lsa_q_close_info
{
POLICY_HND pol; /* policy handle */
} LSA_Q_CLOSE;
/* LSA_R_CLOSE */
typedef struct lsa_r_close_info
{
POLICY_HND pol; /* policy handle. should be all zeros. */
uint32 status; /* return code */
} LSA_R_CLOSE;
#define MAX_REF_DOMAINS 10
/* DOM_R_REF */
typedef struct dom_ref_info
{
uint32 undoc_buffer; /* undocumented buffer pointer. */
uint32 num_ref_doms_1; /* num referenced domains? */
uint32 buffer_dom_name; /* undocumented domain name buffer pointer. */
uint32 max_entries; /* 32 - max number of entries */
uint32 num_ref_doms_2; /* 4 - num referenced domains? */
UNIHDR2 hdr_dom_name; /* domain name unicode string header */
UNIHDR2 hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domain unicode string headers */
UNISTR uni_dom_name; /* domain name unicode string */
DOM_SID2 ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */
} DOM_R_REF;
/* LSA_TRANS_NAME - translated name */
typedef struct lsa_trans_name_info
{
uint32 sid_name_use; /* value is 5 for a well-known group; 2 for a domain group; 1 for a user... */
UNIHDR hdr_name;
UNISTR2 uni_name;
uint32 domain_idx;
} LSA_TRANS_NAME;
#define MAX_LOOKUP_SIDS 10
/* LSA_TRANS_NAME_ENUM - LSA Translated Name Enumeration container */
typedef struct lsa_trans_name_enum_info
{
uint32 num_entries;
uint32 ptr_trans_names;
uint32 num_entries2;
uint32 ptr_name[MAX_LOOKUP_SIDS]; /* translated name pointers */
LSA_TRANS_NAME name [MAX_LOOKUP_SIDS]; /* translated names */
} LSA_TRANS_NAME_ENUM;
/* LSA_SID_ENUM - LSA SID enumeration container */
typedef struct lsa_sid_enum_info
{
uint32 num_entries;
uint32 ptr_sid_enum;
uint32 num_entries2;
uint32 ptr_sid[MAX_LOOKUP_SIDS]; /* domain SID pointers to be looked up. */
DOM_SID2 sid [MAX_LOOKUP_SIDS]; /* domain SIDs to be looked up. */
} LSA_SID_ENUM;
/* LSA_Q_LOOKUP_SIDS - LSA Lookup SIDs */
typedef struct lsa_q_lookup_sids
{
POLICY_HND pol_hnd; /* policy handle */
LSA_SID_ENUM sids;
LSA_TRANS_NAME_ENUM names;
LOOKUP_LEVEL level;
uint32 mapped_count;
} LSA_Q_LOOKUP_SIDS;
/* LSA_R_LOOKUP_SIDS - response to LSA Lookup SIDs */
typedef struct lsa_r_lookup_sids
{
DOM_R_REF *dom_ref; /* domain reference info */
LSA_TRANS_NAME_ENUM *names;
uint32 mapped_count;
uint32 status; /* return code */
} LSA_R_LOOKUP_SIDS;
/* DOM_NAME - XXXX not sure about this structure */
typedef struct dom_name_info
{
uint32 uni_str_len;
UNISTR str;
} DOM_NAME;
#define UNKNOWN_LEN 1
/* LSA_Q_LOOKUP_RIDS - LSA Lookup RIDs */
typedef struct lsa_q_lookup_rids
{
POLICY_HND pol_hnd; /* policy handle */
uint32 num_entries;
uint32 num_entries2;
uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */
uint32 buffer_dom_name; /* undocumented domain name buffer pointer */
DOM_NAME lookup_name[MAX_LOOKUP_SIDS]; /* names to be looked up */
uint8 undoc[UNKNOWN_LEN]; /* completely undocumented bytes of unknown length */
} LSA_Q_LOOKUP_RIDS;
/* LSA_R_LOOKUP_RIDS - response to LSA Lookup RIDs by name */
typedef struct lsa_r_lookup_rids
{
DOM_R_REF dom_ref; /* domain reference info */
uint32 num_entries;
uint32 undoc_buffer; /* undocumented buffer pointer */
uint32 num_entries2;
DOM_RID2 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */
uint32 num_entries3;
uint32 status; /* return code */
} LSA_R_LOOKUP_RIDS;
#endif /* _RPC_LSA_H */

272
source3/include/rpc_misc.h Normal file
View File

@ -0,0 +1,272 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _RPC_MISC_H /* _RPC_MISC_H */
#define _RPC_MISC_H
#include "rpc_dce.h"
/* pipe string names */
#define PIPE_SRVSVC "\\PIPE\\srvsvc"
#define PIPE_SAMR "\\PIPE\\samr"
#define PIPE_WINREG "\\PIPE\\winreg"
#define PIPE_WKSSVC "\\PIPE\\wkssvc"
#define PIPE_NETLOGON "\\PIPE\\NETLOGON"
#define PIPE_NTLSA "\\PIPE\\ntlsa"
#define PIPE_NTSVCS "\\PIPE\\ntsvcs"
#define PIPE_LSASS "\\PIPE\\lsass"
#define PIPE_LSARPC "\\PIPE\\lsarpc"
/* well-known RIDs - Relative IDs */
/* RIDs - Well-known users ... */
#define DOMAIN_USER_RID_ADMIN (0x000001F4L)
#define DOMAIN_USER_RID_GUEST (0x000001F5L)
/* RIDs - well-known groups ... */
#define DOMAIN_GROUP_RID_ADMINS (0x00000200L)
#define DOMAIN_GROUP_RID_USERS (0x00000201L)
#define DOMAIN_GROUP_RID_GUESTS (0x00000202L)
/* RIDs - well-known aliases ... */
#define DOMAIN_ALIAS_RID_ADMINS (0x00000220L)
#define DOMAIN_ALIAS_RID_USERS (0x00000221L)
#define DOMAIN_ALIAS_RID_GUESTS (0x00000222L)
#define DOMAIN_ALIAS_RID_POWER_USERS (0x00000223L)
#define DOMAIN_ALIAS_RID_ACCOUNT_OPS (0x00000224L)
#define DOMAIN_ALIAS_RID_SYSTEM_OPS (0x00000225L)
#define DOMAIN_ALIAS_RID_PRINT_OPS (0x00000226L)
#define DOMAIN_ALIAS_RID_BACKUP_OPS (0x00000227L)
#define DOMAIN_ALIAS_RID_REPLICATOR (0x00000228L)
/* ENUM_HND */
typedef struct enum_hnd_info
{
uint32 ptr_hnd; /* pointer to enumeration handle */
uint32 handle; /* enumeration handle */
} ENUM_HND;
/* LOOKUP_LEVEL - switch value */
typedef struct lookup_level_info
{
uint16 value;
} LOOKUP_LEVEL;
#define MAXSUBAUTHS 15 /* max sub authorities in a SID */
/* DOM_SID - security id */
typedef struct sid_info
{
uint8 sid_rev_num; /* SID revision number */
uint8 num_auths; /* number of sub-authorities */
uint8 id_auth[6]; /* Identifier Authority */
uint32 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */
} DOM_SID;
/* DOM_SID2 - security id */
typedef struct sid_info_2
{
uint32 num_auths; /* length, bytes, including length of len :-) */
DOM_SID sid;
} DOM_SID2;
/* STRHDR - string header */
typedef struct header_info
{
uint16 str_max_len;
uint16 str_str_len;
uint32 buffer; /* non-zero */
} STRHDR;
/* UNIHDR - unicode string header */
typedef struct unihdr_info
{
uint16 uni_max_len;
uint16 uni_str_len;
uint32 buffer; /* usually has a value of 4 */
} UNIHDR;
/* UNIHDR2 - unicode string header and undocumented buffer */
typedef struct unihdr2_info
{
UNIHDR unihdr;
uint32 buffer; /* 32 bit buffer pointer */
} UNIHDR2;
/* clueless as to what maximum length should be */
#define MAX_UNISTRLEN 256
#define MAX_STRINGLEN 256
/* UNISTR - unicode string size and buffer */
typedef struct unistr_info
{
uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. ***MUST*** be null-terminated */
} UNISTR;
/* UNINOTSTR2 - unicode string, size (in uint8 ascii chars) and buffer */
/* pathetic. some stupid team of \PIPE\winreg writers got the concept */
/* of a unicode string different from the other \PIPE\ writers */
typedef struct uninotstr2_info
{
uint32 uni_max_len;
uint32 undoc;
uint32 uni_buf_len;
uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */
} UNINOTSTR2;
/* UNISTR2 - unicode string size (in uint16 unicode chars) and buffer */
typedef struct unistr2_info
{
uint32 uni_max_len;
uint32 undoc;
uint32 uni_str_len;
uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */
} UNISTR2;
/* STRING2 - string size (in uint8 chars) and buffer */
typedef struct string2_info
{
uint32 str_max_len;
uint32 undoc;
uint32 str_str_len;
uint8 buffer[MAX_STRINGLEN]; /* uint8 characters. **NOT** necessarily null-terminated */
} STRING2;
/* DOM_RID2 - domain RID structure for ntlsa pipe */
typedef struct domrid2_info
{
uint32 type; /* value is 5 */
uint32 undoc; /* value is non-zero */
uint32 rid;
uint32 rid_idx; /* don't know what this is */
} DOM_RID2;
/* DOM_RID3 - domain RID structure for samr pipe */
typedef struct domrid3_info
{
uint32 rid; /* domain-relative (to a SID) id */
uint32 type1; /* value is 0x1 */
uint32 ptr_type; /* undocumented pointer */
uint32 type2; /* value is 0x1 */
} DOM_RID3;
/* DOM_RID4 - rid + user attributes */
typedef struct domrid4_info
{
uint32 unknown;
uint16 attr;
uint32 rid; /* user RID */
} DOM_RID4;
/* DOM_CLNT_SRV - client / server names */
typedef struct clnt_srv_info
{
uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */
UNISTR2 uni_logon_srv; /* logon server name */
uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */
UNISTR2 uni_comp_name; /* client machine name */
} DOM_CLNT_SRV;
/* DOM_LOG_INFO - login info */
typedef struct log_info
{
uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */
UNISTR2 uni_logon_srv; /* logon server name */
UNISTR2 uni_acct_name; /* account name */
uint16 sec_chan; /* secure channel type */
UNISTR2 uni_comp_name; /* client machine name */
} DOM_LOG_INFO;
/* DOM_CLNT_INFO - client info */
typedef struct clnt_info
{
DOM_LOG_INFO login;
DOM_CRED cred;
} DOM_CLNT_INFO;
/* DOM_CLNT_INFO2 - client info */
typedef struct clnt_info2
{
DOM_CLNT_SRV login;
uint32 ptr_cred;
DOM_CRED cred;
} DOM_CLNT_INFO2;
/* DOM_LOGON_ID - logon id */
typedef struct logon_info
{
uint32 low;
uint32 high;
} DOM_LOGON_ID;
/* ARC4_OWF */
typedef struct arc4_owf_info
{
uint8 data[16];
} ARC4_OWF;
/* DOM_GID - group id + user attributes */
typedef struct gid_info
{
uint32 g_rid; /* a group RID */
uint32 attr;
} DOM_GID;
#define POL_HND_SIZE 20
/* POLICY_HND */
typedef struct lsa_policy_info
{
uint8 data[POL_HND_SIZE]; /* policy handle */
} POLICY_HND;
#endif /* _RPC_MISC_H */

View File

@ -0,0 +1,372 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _RPC_NETLOGON_H /* _RPC_NETLOGON_H */
#define _RPC_NETLOGON_H
/* NETLOGON pipe */
#define NET_REQCHAL 0x04
#define NET_SRVPWSET 0x06
#define NET_SAMLOGON 0x02
#define NET_SAMLOGOFF 0x03
#define NET_AUTH2 0x0f
#define NET_LOGON_CTRL2 0x0e
#define NET_TRUST_DOM_LIST 0x13
/* Secure Channel types. used in NetrServerAuthenticate negotiation */
#define SEC_CHAN_WKSTA 2
#define SEC_CHAN_DOMAIN 4
/* NET_USER_INFO_3 */
typedef struct net_user_info_3
{
uint32 ptr_user_info;
NTTIME logon_time; /* logon time */
NTTIME logoff_time; /* logoff time */
NTTIME kickoff_time; /* kickoff time */
NTTIME pass_last_set_time; /* password last set time */
NTTIME pass_can_change_time; /* password can change time */
NTTIME pass_must_change_time; /* password must change time */
UNIHDR hdr_user_name; /* username unicode string header */
UNIHDR hdr_full_name; /* user's full name unicode string header */
UNIHDR hdr_logon_script; /* logon script unicode string header */
UNIHDR hdr_profile_path; /* profile path unicode string header */
UNIHDR hdr_home_dir; /* home directory unicode string header */
UNIHDR hdr_dir_drive; /* home directory drive unicode string header */
uint16 logon_count; /* logon count */
uint16 bad_pw_count; /* bad password count */
uint32 user_id; /* User ID */
uint32 group_id; /* Group ID */
uint32 num_groups; /* num groups */
uint32 buffer_groups; /* undocumented buffer pointer to groups. */
uint32 user_flgs; /* user flags */
uint8 user_sess_key[16]; /* unused user session key */
UNIHDR hdr_logon_srv; /* logon server unicode string header */
UNIHDR hdr_logon_dom; /* logon domain unicode string header */
uint32 buffer_dom_id; /* undocumented logon domain id pointer */
uint8 padding[40]; /* unused padding bytes. expansion room */
uint32 num_other_sids; /* 0 - num_sids */
uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */
UNISTR2 uni_user_name; /* username unicode string */
UNISTR2 uni_full_name; /* user's full name unicode string */
UNISTR2 uni_logon_script; /* logon script unicode string */
UNISTR2 uni_profile_path; /* profile path unicode string */
UNISTR2 uni_home_dir; /* home directory unicode string */
UNISTR2 uni_dir_drive; /* home directory drive unicode string */
uint32 num_groups2; /* num groups */
DOM_GID gids[LSA_MAX_GROUPS]; /* group info */
UNISTR2 uni_logon_srv; /* logon server unicode string */
UNISTR2 uni_logon_dom; /* logon domain unicode string */
DOM_SID2 dom_sid; /* domain SID */
DOM_SID2 other_sids[LSA_MAX_SIDS]; /* undocumented - domain SIDs */
} NET_USER_INFO_3;
/********************************************************
Logon Control Query
query_level 0x1 - pdc status
query_level 0x3 - number of logon attempts.
********************************************************/
/* NET_Q_LOGON_CTRL2 - LSA Netr Logon Control 2*/
typedef struct net_q_logon_ctrl2_info
{
uint32 ptr; /* undocumented buffer pointer */
UNISTR2 uni_server_name; /* server name, starting with two '\'s */
uint32 function_code; /* 0x1 */
uint32 query_level; /* 0x1, 0x3 */
uint32 switch_value; /* 0x1 */
} NET_Q_LOGON_CTRL2;
/* NETLOGON_INFO_1 - pdc status info, i presume */
typedef struct netlogon_1_info
{
uint32 flags; /* 0x0 - undocumented */
uint32 pdc_status; /* 0x0 - undocumented */
} NETLOGON_INFO_1;
/* NETLOGON_INFO_2 - pdc status info, plus trusted domain info */
typedef struct netlogon_2_info
{
uint32 flags; /* 0x0 - undocumented */
uint32 pdc_status; /* 0x0 - undocumented */
uint32 ptr_trusted_dc_name; /* pointer to trusted domain controller name */
uint32 tc_status; /* 0x051f - ERROR_NO_LOGON_SERVERS */
UNISTR2 uni_trusted_dc_name; /* unicode string - trusted dc name */
} NETLOGON_INFO_2;
/* NETLOGON_INFO_3 - logon status info, i presume */
typedef struct netlogon_3_info
{
uint32 flags; /* 0x0 - undocumented */
uint32 logon_attempts; /* number of logon attempts */
uint32 reserved_1; /* 0x0 - undocumented */
uint32 reserved_2; /* 0x0 - undocumented */
uint32 reserved_3; /* 0x0 - undocumented */
uint32 reserved_4; /* 0x0 - undocumented */
uint32 reserved_5; /* 0x0 - undocumented */
} NETLOGON_INFO_3;
/*******************************************************
Logon Control Response
switch_value is same as query_level in request
*******************************************************/
/* NET_R_LOGON_CTRL2 - response to LSA Logon Control2 */
typedef struct net_r_logon_ctrl2_info
{
uint32 switch_value; /* 0x1, 0x3 */
uint32 ptr;
union
{
NETLOGON_INFO_1 info1;
NETLOGON_INFO_2 info2;
NETLOGON_INFO_3 info3;
} logon;
uint32 status; /* return code */
} NET_R_LOGON_CTRL2;
/* NET_Q_TRUST_DOM_LIST - LSA Query Trusted Domains */
typedef struct net_q_trust_dom_info
{
uint32 ptr; /* undocumented buffer pointer */
UNISTR2 uni_server_name; /* server name, starting with two '\'s */
uint32 function_code; /* 0x31 */
} NET_Q_TRUST_DOM_LIST;
#define MAX_TRUST_DOMS 1
/* NET_R_TRUST_DOM_LIST - response to LSA Trusted Domains */
typedef struct net_r_trust_dom_info
{
UNISTR2 uni_trust_dom_name[MAX_TRUST_DOMS];
uint32 status; /* return code */
} NET_R_TRUST_DOM_LIST;
/* NEG_FLAGS */
typedef struct neg_flags_info
{
uint32 neg_flags; /* negotiated flags */
} NEG_FLAGS;
/* NET_Q_REQ_CHAL */
typedef struct net_q_req_chal_info
{
uint32 undoc_buffer; /* undocumented buffer pointer */
UNISTR2 uni_logon_srv; /* logon server unicode string */
UNISTR2 uni_logon_clnt; /* logon client unicode string */
DOM_CHAL clnt_chal; /* client challenge */
} NET_Q_REQ_CHAL;
/* NET_R_REQ_CHAL */
typedef struct net_r_req_chal_info
{
DOM_CHAL srv_chal; /* server challenge */
uint32 status; /* return code */
} NET_R_REQ_CHAL;
/* NET_Q_AUTH_2 */
typedef struct net_q_auth2_info
{
DOM_LOG_INFO clnt_id; /* client identification info */
DOM_CHAL clnt_chal; /* client-calculated credentials */
NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */
} NET_Q_AUTH_2;
/* NET_R_AUTH_2 */
typedef struct net_r_auth2_info
{
DOM_CHAL srv_chal; /* server-calculated credentials */
NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */
uint32 status; /* return code */
} NET_R_AUTH_2;
/* NET_Q_SRV_PWSET */
typedef struct net_q_srv_pwset_info
{
DOM_CLNT_INFO clnt_id; /* client identification/authentication info */
uint8 pwd[16]; /* new password - undocumented. */
} NET_Q_SRV_PWSET;
/* NET_R_SRV_PWSET */
typedef struct net_r_srv_pwset_info
{
DOM_CRED srv_cred; /* server-calculated credentials */
uint32 status; /* return code */
} NET_R_SRV_PWSET;
/* NET_ID_INFO_2 */
typedef struct net_network_info_2
{
uint32 ptr_id_info2; /* pointer to id_info_2 */
UNIHDR hdr_domain_name; /* domain name unicode header */
uint32 param_ctrl; /* param control (0x2) */
DOM_LOGON_ID logon_id; /* logon ID */
UNIHDR hdr_user_name; /* user name unicode header */
UNIHDR hdr_wksta_name; /* workstation name unicode header */
uint8 lm_chal[8]; /* lan manager 8 byte challenge */
STRHDR hdr_nt_chal_resp; /* nt challenge response */
STRHDR hdr_lm_chal_resp; /* lm challenge response */
UNISTR2 uni_domain_name; /* domain name unicode string */
UNISTR2 uni_user_name; /* user name unicode string */
UNISTR2 uni_wksta_name; /* workgroup name unicode string */
STRING2 nt_chal_resp; /* nt challenge response */
STRING2 lm_chal_resp; /* lm challenge response */
} NET_ID_INFO_2;
/* NET_ID_INFO_1 */
typedef struct id_info_1
{
uint32 ptr_id_info1; /* pointer to id_info_1 */
UNIHDR hdr_domain_name; /* domain name unicode header */
uint32 param_ctrl; /* param control */
DOM_LOGON_ID logon_id; /* logon ID */
UNIHDR hdr_user_name; /* user name unicode header */
UNIHDR hdr_wksta_name; /* workstation name unicode header */
ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */
ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */
UNISTR2 uni_domain_name; /* domain name unicode string */
UNISTR2 uni_user_name; /* user name unicode string */
UNISTR2 uni_wksta_name; /* workgroup name unicode string */
} NET_ID_INFO_1;
/* NET_ID_INFO_CTR */
typedef struct net_id_info_ctr_info
{
uint16 switch_value;
union
{
NET_ID_INFO_1 id1; /* auth-level 1 - interactive user login */
NET_ID_INFO_2 id2; /* auth-level 2 - workstation referred login */
} auth;
} NET_ID_INFO_CTR;
/* SAM_INFO - sam logon/off id structure */
typedef struct sam_info
{
DOM_CLNT_INFO2 client;
uint32 ptr_rtn_cred; /* pointer to return credentials */
DOM_CRED rtn_cred; /* return credentials */
uint16 logon_level;
NET_ID_INFO_CTR *ctr;
uint16 validation_level;
} DOM_SAM_INFO;
/* NET_Q_SAM_LOGON */
typedef struct net_q_sam_logon_info
{
DOM_SAM_INFO sam_id;
} NET_Q_SAM_LOGON;
/* NET_R_SAM_LOGON */
typedef struct net_r_sam_logon_info
{
uint32 buffer_creds; /* undocumented buffer pointer */
DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */
uint16 switch_value; /* 3 - indicates type of USER INFO */
NET_USER_INFO_3 *user;
uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */
uint32 status; /* return code */
} NET_R_SAM_LOGON;
/* NET_Q_SAM_LOGOFF */
typedef struct net_q_sam_logoff_info
{
DOM_SAM_INFO sam_id;
} NET_Q_SAM_LOGOFF;
/* NET_R_SAM_LOGOFF */
typedef struct net_r_sam_logoff_info
{
uint32 buffer_creds; /* undocumented buffer pointer */
DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */
uint32 status; /* return code */
} NET_R_SAM_LOGOFF;
#endif /* _RPC_NETLOGON_H */

141
source3/include/rpc_reg.h Normal file
View File

@ -0,0 +1,141 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _RPC_REG_H /* _RPC_REG_H */
#define _RPC_REG_H
/* winreg pipe defines */
#define REG_OPEN_POLICY 0x02
#define REG_OPEN_ENTRY 0x0f
#define REG_INFO 0x11
#define REG_CLOSE 0x05
/* REG_Q_OPEN_POLICY */
typedef struct q_reg_open_policy_info
{
uint32 ptr;
uint16 unknown_0; /* 0x5da0 - 16 bit unknown */
uint32 level; /* 0x0000 0001 - 32 bit unknown */
uint16 unknown_1; /* 0x0200 - 16 bit unknown */
} REG_Q_OPEN_POLICY;
/* REG_R_OPEN_POLICY */
typedef struct r_reg_open_policy_info
{
POLICY_HND pol; /* policy handle */
uint32 status; /* return status */
} REG_R_OPEN_POLICY;
/* REG_Q_CLOSE */
typedef struct reg_q_close_info
{
POLICY_HND pol; /* policy handle */
} REG_Q_CLOSE;
/* REG_R_CLOSE */
typedef struct reg_r_close_info
{
POLICY_HND pol; /* policy handle. should be all zeros. */
uint32 status; /* return code */
} REG_R_CLOSE;
/* REG_Q_INFO */
typedef struct q_reg_info_info
{
POLICY_HND pol; /* policy handle */
UNIHDR hdr_type; /* unicode product type header */
UNISTR2 uni_type; /* unicode product type - "ProductType" */
uint32 ptr1; /* pointer */
NTTIME time; /* current time? */
uint8 major_version1; /* 0x4 - os major version? */
uint8 minor_version1; /* 0x1 - os minor version? */
uint8 pad1[10]; /* padding - zeros */
uint32 ptr2; /* pointer */
uint8 major_version2; /* 0x4 - os major version? */
uint8 minor_version2; /* 0x1 - os minor version? */
uint8 pad2[2]; /* padding - zeros */
uint32 ptr3; /* pointer */
uint32 unknown; /* 0x0000 0000 */
} REG_Q_INFO;
/* REG_R_INFO */
typedef struct r_reg_info_info
{
uint32 ptr1; /* buffer pointer */
uint32 level; /* 0x1 - info level? */
uint32 ptr_type; /* pointer to o/s type */
UNINOTSTR2 uni_type; /* unicode string o/s type - "LanmanNT" */
uint32 ptr2; /* pointer to unknown_0 */
uint32 unknown_0; /* 0x12 */
uint32 ptr3; /* pointer to unknown_1 */
uint32 unknown_1; /* 0x12 */
uint32 status; /* return status */
} REG_R_INFO;
/* REG_Q_OPEN_ENTRY */
typedef struct q_reg_open_entry_info
{
POLICY_HND pol; /* policy handle */
UNIHDR hdr_name; /* unicode registry string header */
UNISTR2 uni_name; /* unicode registry string name */
uint32 unknown_0; /* 32 bit unknown - 0x0000 0000 */
uint16 unknown_1; /* 16 bit unknown - 0x0000 */
uint16 unknown_2; /* 16 bit unknown - 0x0200 */
} REG_Q_OPEN_ENTRY;
/* REG_R_OPEN_ENTRY */
typedef struct r_reg_open_entry_info
{
POLICY_HND pol; /* policy handle */
uint32 status; /* return status */
} REG_R_OPEN_ENTRY;
#endif /* _RPC_REG_H */

1023
source3/include/rpc_samr.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,540 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _RPC_SRVSVC_H /* _RPC_SRVSVC_H */
#define _RPC_SRVSVC_H
/* srvsvc pipe */
#define SRV_NETCONNENUM 0x08
#define SRV_NETFILEENUM 0x09
#define SRV_NETSESSENUM 0x0c
#define SRV_NETSHAREENUM 0x0f
#define SRV_NET_SRV_GET_INFO 0x15
#define SRV_NET_SRV_SET_INFO 0x16
/* SESS_INFO_0 (pointers to level 0 session info strings) */
typedef struct ptr_sess_info0
{
uint32 ptr_name; /* pointer to name. */
} SESS_INFO_0;
/* SESS_INFO_0_STR (level 0 session info strings) */
typedef struct str_sess_info0
{
UNISTR2 uni_name; /* unicode string of name */
} SESS_INFO_0_STR;
/* oops - this is going to take up a *massive* amount of stack. */
/* the UNISTR2s already have 1024 uint16 chars in them... */
#define MAX_SESS_ENTRIES 32
/* SRV_SESS_INFO_0 */
typedef struct srv_sess_info_0_info
{
uint32 num_entries_read; /* EntriesRead */
uint32 ptr_sess_info; /* Buffer */
uint32 num_entries_read2; /* EntriesRead */
SESS_INFO_0 info_0 [MAX_SESS_ENTRIES]; /* session entry pointers */
SESS_INFO_0_STR info_0_str[MAX_SESS_ENTRIES]; /* session entry strings */
} SRV_SESS_INFO_0;
/* SESS_INFO_1 (pointers to level 1 session info strings) */
typedef struct ptr_sess_info1
{
uint32 ptr_name; /* pointer to name. */
uint32 ptr_user; /* pointer to user name. */
uint32 num_opens;
uint32 open_time;
uint32 idle_time;
uint32 user_flags;
} SESS_INFO_1;
/* SESS_INFO_1_STR (level 1 session info strings) */
typedef struct str_sess_info1
{
UNISTR2 uni_name; /* unicode string of name */
UNISTR2 uni_user; /* unicode string of user */
} SESS_INFO_1_STR;
/* SRV_SESS_INFO_1 */
typedef struct srv_sess_info_1_info
{
uint32 num_entries_read; /* EntriesRead */
uint32 ptr_sess_info; /* Buffer */
uint32 num_entries_read2; /* EntriesRead */
SESS_INFO_1 info_1 [MAX_SESS_ENTRIES]; /* session entry pointers */
SESS_INFO_1_STR info_1_str[MAX_SESS_ENTRIES]; /* session entry strings */
} SRV_SESS_INFO_1;
/* SRV_SESS_INFO_CTR */
typedef struct srv_sess_info_ctr_info
{
uint32 switch_value; /* switch value */
uint32 ptr_sess_ctr; /* pointer to sess info union */
union
{
SRV_SESS_INFO_0 info0; /* session info level 0 */
SRV_SESS_INFO_1 info1; /* session info level 1 */
} sess;
} SRV_SESS_INFO_CTR;
/* SRV_Q_NET_SESS_ENUM */
typedef struct q_net_sess_enum_info
{
uint32 ptr_srv_name; /* pointer (to server name?) */
UNISTR2 uni_srv_name; /* server name */
uint32 ptr_qual_name; /* pointer (to qualifier name) */
UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */
uint32 sess_level; /* session level */
SRV_SESS_INFO_CTR *ctr;
uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
ENUM_HND enum_hnd;
} SRV_Q_NET_SESS_ENUM;
/* SRV_R_NET_SESS_ENUM */
typedef struct r_net_sess_enum_info
{
uint32 sess_level; /* share level */
SRV_SESS_INFO_CTR *ctr;
uint32 total_entries; /* total number of entries */
ENUM_HND enum_hnd;
uint32 status; /* return status */
} SRV_R_NET_SESS_ENUM;
/* CONN_INFO_0 (pointers to level 0 connection info strings) */
typedef struct ptr_conn_info0
{
uint32 id; /* connection id. */
} CONN_INFO_0;
/* oops - this is going to take up a *massive* amount of stack. */
/* the UNISTR2s already have 1024 uint16 chars in them... */
#define MAX_CONN_ENTRIES 32
/* SRV_CONN_INFO_0 */
typedef struct srv_conn_info_0_info
{
uint32 num_entries_read; /* EntriesRead */
uint32 ptr_conn_info; /* Buffer */
uint32 num_entries_read2; /* EntriesRead */
CONN_INFO_0 info_0 [MAX_CONN_ENTRIES]; /* connection entry pointers */
} SRV_CONN_INFO_0;
/* CONN_INFO_1 (pointers to level 1 connection info strings) */
typedef struct ptr_conn_info1
{
uint32 id; /* connection id */
uint32 type; /* 0x3 */
uint32 num_opens;
uint32 num_users;
uint32 open_time;
uint32 ptr_usr_name; /* pointer to user name. */
uint32 ptr_net_name; /* pointer to network name (e.g IPC$). */
} CONN_INFO_1;
/* CONN_INFO_1_STR (level 1 connection info strings) */
typedef struct str_conn_info1
{
UNISTR2 uni_usr_name; /* unicode string of user */
UNISTR2 uni_net_name; /* unicode string of name */
} CONN_INFO_1_STR;
/* SRV_CONN_INFO_1 */
typedef struct srv_conn_info_1_info
{
uint32 num_entries_read; /* EntriesRead */
uint32 ptr_conn_info; /* Buffer */
uint32 num_entries_read2; /* EntriesRead */
CONN_INFO_1 info_1 [MAX_CONN_ENTRIES]; /* connection entry pointers */
CONN_INFO_1_STR info_1_str[MAX_CONN_ENTRIES]; /* connection entry strings */
} SRV_CONN_INFO_1;
/* SRV_CONN_INFO_CTR */
typedef struct srv_conn_info_ctr_info
{
uint32 switch_value; /* switch value */
uint32 ptr_conn_ctr; /* pointer to conn info union */
union
{
SRV_CONN_INFO_0 info0; /* connection info level 0 */
SRV_CONN_INFO_1 info1; /* connection info level 1 */
} conn;
} SRV_CONN_INFO_CTR;
/* SRV_Q_NET_CONN_ENUM */
typedef struct q_net_conn_enum_info
{
uint32 ptr_srv_name; /* pointer (to server name) */
UNISTR2 uni_srv_name; /* server name "\\server" */
uint32 ptr_qual_name; /* pointer (to qualifier name) */
UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */
uint32 conn_level; /* connection level */
SRV_CONN_INFO_CTR *ctr;
uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
ENUM_HND enum_hnd;
} SRV_Q_NET_CONN_ENUM;
/* SRV_R_NET_CONN_ENUM */
typedef struct r_net_conn_enum_info
{
uint32 conn_level; /* share level */
SRV_CONN_INFO_CTR *ctr;
uint32 total_entries; /* total number of entries */
ENUM_HND enum_hnd;
uint32 status; /* return status */
} SRV_R_NET_CONN_ENUM;
/* oops - this is going to take up a *massive* amount of stack. */
/* the UNISTR2s already have 1024 uint16 chars in them... */
#define MAX_SHARE_ENTRIES 32
/* SH_INFO_1 (pointers to level 1 share info strings) */
typedef struct ptr_share_info1
{
uint32 ptr_netname; /* pointer to net name. */
uint32 type; /* ipc, print, disk ... */
uint32 ptr_remark; /* pointer to comment. */
} SH_INFO_1;
/* SH_INFO_1_STR (level 1 share info strings) */
typedef struct str_share_info1
{
UNISTR2 uni_netname; /* unicode string of net name */
UNISTR2 uni_remark; /* unicode string of comment */
} SH_INFO_1_STR;
/* SRV_SHARE_INFO_1 */
typedef struct share_info_1_info
{
uint32 num_entries_read; /* EntriesRead */
uint32 ptr_share_info; /* Buffer */
uint32 num_entries_read2; /* EntriesRead */
SH_INFO_1 info_1 [MAX_SHARE_ENTRIES]; /* share entry pointers */
SH_INFO_1_STR info_1_str[MAX_SHARE_ENTRIES]; /* share entry strings */
} SRV_SHARE_INFO_1;
/* SH_INFO_2 (pointers to level 2 share info strings) */
typedef struct ptr_share_info2
{
uint32 ptr_netname; /* pointer to net name. */
uint32 type; /* ipc, print, disk ... */
uint32 ptr_remark; /* pointer to comment. */
uint32 perms; /* permissions */
uint32 max_uses; /* maximum uses */
uint32 num_uses; /* current uses */
uint32 ptr_path; /* pointer to path name */
uint32 ptr_passwd; /* pointer to password */
} SH_INFO_2;
/* SH_INFO_2_STR (level 2 share info strings) */
typedef struct str_share_info2
{
UNISTR2 uni_netname; /* unicode string of net name (e.g NETLOGON) */
UNISTR2 uni_remark; /* unicode string of comment (e.g "Logon server share") */
UNISTR2 uni_path; /* unicode string of local path (e.g c:\winnt\system32\repl\import\scripts) */
UNISTR2 uni_passwd; /* unicode string of password - presumably for share level security (e.g NULL) */
} SH_INFO_2_STR;
/* SRV_SHARE_INFO_2 */
typedef struct share_info_2_info
{
uint32 num_entries_read; /* EntriesRead */
uint32 ptr_share_info; /* Buffer */
uint32 num_entries_read2; /* EntriesRead */
SH_INFO_2 info_2 [MAX_SHARE_ENTRIES]; /* share entry pointers */
SH_INFO_2_STR info_2_str[MAX_SHARE_ENTRIES]; /* share entry strings */
} SRV_SHARE_INFO_2;
/* SRV_SHARE_INFO_CTR */
typedef struct srv_share_info_1_info
{
uint32 switch_value; /* switch value */
uint32 ptr_share_ctr; /* pointer to share info union */
union
{
SRV_SHARE_INFO_1 info1; /* share info level 1 */
SRV_SHARE_INFO_2 info2; /* share info level 2 */
} share;
} SRV_SHARE_INFO_CTR;
/* SRV_Q_NET_SHARE_ENUM */
typedef struct q_net_share_enum_info
{
uint32 ptr_srv_name; /* pointer (to server name?) */
UNISTR2 uni_srv_name; /* server name */
uint32 share_level; /* share level */
SRV_SHARE_INFO_CTR *ctr; /* share info container */
uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
ENUM_HND enum_hnd;
} SRV_Q_NET_SHARE_ENUM;
/* SRV_R_NET_SHARE_ENUM */
typedef struct r_net_share_enum_info
{
uint32 share_level; /* share level */
SRV_SHARE_INFO_CTR *ctr; /* share info container */
uint32 total_entries; /* total number of entries */
ENUM_HND enum_hnd;
uint32 status; /* return status */
} SRV_R_NET_SHARE_ENUM;
/* FILE_INFO_3 (level 3 file info strings) */
typedef struct file_info3_info
{
uint32 id; /* file index */
uint32 perms; /* file permissions. don't know what format */
uint32 num_locks; /* file locks */
uint32 ptr_path_name; /* file name */
uint32 ptr_user_name; /* file owner */
} FILE_INFO_3;
/* FILE_INFO_3_STR (level 3 file info strings) */
typedef struct str_file_info3_info
{
UNISTR2 uni_path_name; /* unicode string of file name */
UNISTR2 uni_user_name; /* unicode string of file owner. */
} FILE_INFO_3_STR;
/* oops - this is going to take up a *massive* amount of stack. */
/* the UNISTR2s already have 1024 uint16 chars in them... */
#define MAX_FILE_ENTRIES 32
/* SRV_FILE_INFO_3 */
typedef struct srv_file_info_3
{
uint32 num_entries_read; /* EntriesRead */
uint32 ptr_file_info; /* Buffer */
uint32 num_entries_read2; /* EntriesRead */
FILE_INFO_3 info_3 [MAX_FILE_ENTRIES]; /* file entry details */
FILE_INFO_3_STR info_3_str[MAX_FILE_ENTRIES]; /* file entry strings */
} SRV_FILE_INFO_3;
/* SRV_FILE_INFO_CTR */
typedef struct srv_file_info_3_info
{
uint32 switch_value; /* switch value */
uint32 ptr_file_ctr; /* pointer to file info union */
union
{
SRV_FILE_INFO_3 info3; /* file info with 0 entries */
} file;
} SRV_FILE_INFO_CTR;
/* SRV_Q_NET_FILE_ENUM */
typedef struct q_net_file_enum_info
{
uint32 ptr_srv_name; /* pointer (to server name?) */
UNISTR2 uni_srv_name; /* server name */
uint32 ptr_qual_name; /* pointer (to qualifier name) */
UNISTR2 uni_qual_name; /* qualifier name "\\qualifier" */
uint32 file_level; /* file level */
SRV_FILE_INFO_CTR *ctr;
uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
ENUM_HND enum_hnd;
} SRV_Q_NET_FILE_ENUM;
/* SRV_R_NET_FILE_ENUM */
typedef struct r_net_file_enum_info
{
uint32 file_level; /* file level */
SRV_FILE_INFO_CTR *ctr;
uint32 total_entries; /* total number of files */
ENUM_HND enum_hnd;
uint32 status; /* return status */
} SRV_R_NET_FILE_ENUM;
/* SRV_INFO_101 */
typedef struct srv_info_101_info
{
uint32 platform_id; /* 0x500 */
uint32 ptr_name; /* pointer to server name */
uint32 ver_major; /* 0x4 */
uint32 ver_minor; /* 0x2 */
uint32 srv_type; /* browse etc type */
uint32 ptr_comment; /* pointer to server comment */
UNISTR2 uni_name; /* server name "server" */
UNISTR2 uni_comment; /* server comment "samba x.x.x blah" */
} SRV_INFO_101;
/* SRV_INFO_102 */
typedef struct srv_info_102_info
{
uint32 platform_id; /* 0x500 */
uint32 ptr_name; /* pointer to server name */
uint32 ver_major; /* 0x4 */
uint32 ver_minor; /* 0x2 */
uint32 srv_type; /* browse etc type */
uint32 ptr_comment; /* pointer to server comment */
uint32 users; /* 0xffff ffff*/
uint32 disc; /* 0xf */
uint32 hidden; /* 0x0 */
uint32 announce; /* 240 */
uint32 ann_delta; /* 3000 */
uint32 licenses; /* 0 */
uint32 ptr_usr_path; /* pointer to user path */
UNISTR2 uni_name; /* server name "server" */
UNISTR2 uni_comment; /* server comment "samba x.x.x blah" */
UNISTR2 uni_usr_path; /* "c:\" (eh?) */
} SRV_INFO_102;
/* SRV_INFO_CTR */
typedef struct srv_info_ctr_info
{
uint32 switch_value; /* switch value */
uint32 ptr_srv_ctr; /* pointer to server info */
union
{
SRV_INFO_102 sv102; /* server info level 102 */
SRV_INFO_101 sv101; /* server info level 101 */
} srv;
} SRV_INFO_CTR;
/* SRV_Q_NET_SRV_GET_INFO */
typedef struct q_net_srv_get_info
{
uint32 ptr_srv_name;
UNISTR2 uni_srv_name; /* "\\server" */
uint32 switch_value;
} SRV_Q_NET_SRV_GET_INFO;
/* SRV_R_NET_SRV_GET_INFO */
typedef struct r_net_srv_get_info
{
SRV_INFO_CTR *ctr;
uint32 status; /* return status */
} SRV_R_NET_SRV_GET_INFO;
/* SRV_Q_NET_SRV_SET_INFO */
typedef struct q_net_srv_set_info
{
uint32 ptr_srv_name;
UNISTR2 uni_srv_name; /* "\\server" */
uint32 switch_value;
SRV_INFO_CTR *ctr;
} SRV_Q_NET_SRV_SET_INFO;
/* SRV_R_NET_SRV_SET_INFO */
typedef struct r_net_srv_set_info
{
uint32 switch_value; /* switch value */
uint32 status; /* return status */
} SRV_R_NET_SRV_SET_INFO;
#endif /* _RPC_SRVSVC_H */

View File

@ -0,0 +1,73 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
Copyright (C) Paul Ashton 1997
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.
*/
#ifndef _RPC_WKS_H /* _RPC_WKS_H */
#define _RPC_WKS_H
/* wkssvc pipe */
#define WKS_QUERY_INFO 0x00
/* WKS_Q_QUERY_INFO - probably a capabilities request */
typedef struct q_wks_query_info_info
{
uint32 ptr_srv_name; /* pointer (to server name?) */
UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */
uint16 switch_value; /* info level 100 (0x64) */
} WKS_Q_QUERY_INFO;
/* WKS_INFO_100 - level 100 info */
typedef struct wks_info_100_info
{
uint32 platform_id; /* 0x0000 01f4 - unknown */
uint32 ptr_compname; /* pointer to server name */
uint32 ptr_lan_grp ; /* pointer to domain name */
uint32 ver_major; /* 4 - unknown */
uint32 ver_minor; /* 0 - unknown */
UNISTR2 uni_compname; /* unicode server name */
UNISTR2 uni_lan_grp ; /* unicode domain name */
} WKS_INFO_100;
/* WKS_R_QUERY_INFO - probably a capabilities request */
typedef struct r_wks_query_info_info
{
uint16 switch_value; /* 100 (0x64) - switch value */
/* for now, only level 100 is supported. this should be an enum container */
uint32 ptr_1; /* pointer 1 */
WKS_INFO_100 *wks100; /* workstation info level 100 */
uint32 status; /* return status */
} WKS_R_QUERY_INFO;
#endif /* _RPC_WKS_H */

File diff suppressed because it is too large Load Diff

370
source3/lib/membuffer.c Normal file
View File

@ -0,0 +1,370 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Samba memory buffer functions
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
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.
*/
/*******************************************************************
*
* Description: memory buffer / stream management.
* Author : Luke K C Leighton
* Created : Dec 1997
*
* this module is intended for use in streaming data in and out of
* buffers. it is intended that a single data stream be subdivided
* into manageable sections.
* for example, an rpc header contains a length field, but until the
* data has been created, the length is unknown. using this module,
* the header section can be tacked onto the front of the data memory
* list once the size of the data section preceding it is known.
* the "margin" can be used to over-run and retrospectively lengthen
* the buffer. this is to save time in some of the loops, where it is
* not particularly desirable to realloc data by 1, 2 or 4 bytes
* repetitively...
* each memory buffer contains a start and end offset. the end of
* one buffer should equal to the start of the next in the chain.
* (end - start = len, instead of end - start + 1 = len)
* the debug log levels are very high in some of the routines: you
* have no idea how boring it gets staring at debug output from these
********************************************************************/
#include "includes.h"
extern int DEBUGLEVEL;
/*******************************************************************
initialise a memory buffer.
********************************************************************/
void mem_init(struct mem_buf *buf, int margin)
{
buf->dynamic = True;
buf->data = NULL;
buf->data_size = 0;
buf->data_used = 0;
buf->margin = margin;
buf->next = NULL;
buf->offset.start = 0;
buf->offset.end = 0;
}
/*******************************************************************
initialise a memory buffer.
dynamic indicates memory has been dynamically allocated.
if mem_free is called, the memory will be freed.
********************************************************************/
void mem_create(struct mem_buf *buf, char *data, int size, int margin, BOOL dynamic)
{
buf->dynamic = dynamic;
buf->data = data;
buf->data_size = size;
buf->data_used = size;
buf->margin = margin;
buf->next = NULL;
buf->offset.start = 0;
buf->offset.end = size;
}
/*******************************************************************
takes a memory buffer out of one structure: puts it in the other.
NULLs the one that the buffer is being stolen from.
********************************************************************/
void mem_take(struct mem_buf *mem_to, struct mem_buf *mem_from)
{
memcpy(mem_to, mem_from, sizeof(*mem_to));
mem_init(mem_from, mem_from->margin);
}
/*******************************************************************
allocate a memory buffer. assume it's empty
********************************************************************/
BOOL mem_alloc_data(struct mem_buf *buf, int size)
{
if (!buf->dynamic)
{
DEBUG(3,("mem_alloc_data: warning - memory buffer type is set to static\n"));
}
buf->data_size = size + buf->margin;
buf->data_used = size;
buf->data = malloc(buf->data_size);
if (buf->data == NULL)
{
DEBUG(3,("mem_alloc: could not malloc size %d\n",
buf->data_size));
mem_init(buf, buf->margin);
return False;
}
bzero(buf->data, buf->data_size);
return True;
}
/*******************************************************************
allocates a memory buffer structure
********************************************************************/
BOOL mem_buf_copy(char *copy_into, struct mem_buf *buf,
uint32 offset, uint32 len)
{
uint32 end = offset + len;
char *q = NULL;
uint32 data_len = mem_buf_len(buf);
uint32 start_offset = offset;
struct mem_buf **bcp = &buf;
if (buf == NULL || copy_into == NULL) return False;
DEBUG(200,("mem_buf_copy: data[%d..%d] offset %d len %d\n",
buf->offset.start, data_len, offset, len));
/* there's probably an off-by-one bug, here, and i haven't even tested the code :-) */
while (offset < end && ((q = mem_data(bcp, offset)) != NULL))
{
uint32 copy_len = (*bcp)->offset.end - offset;
DEBUG(200,("\tdata[%d..%d] - offset %d len %d\n",
(*bcp)->offset.start, (*bcp)->offset.end,
offset, copy_len));
memcpy(copy_into, q, copy_len);
offset += copy_len;
copy_into += copy_len;
}
if ((*bcp) != NULL)
{
DEBUG(200,("mem_buf_copy: copied %d bytes\n", offset - start_offset));
}
else
{
DEBUG(200,("mem_buf_copy: failed\n"));
}
return buf != NULL;
}
/*******************************************************************
allocates a memory buffer structure
********************************************************************/
BOOL mem_buf_init(struct mem_buf **buf, uint32 margin)
{
if (buf == NULL) return False;
if ((*buf) == NULL)
{
(*buf) = malloc(sizeof(**buf));
if ((*buf) != NULL)
{
mem_init((*buf), margin);
return True;
}
}
else
{
(*buf)->margin = margin;
return True;
}
return False;
}
/*******************************************************************
frees up a memory buffer.
********************************************************************/
void mem_buf_free(struct mem_buf **buf)
{
if (buf == NULL) return;
if ((*buf) == NULL) return;
mem_free_data(*buf); /* delete memory data */
free(*buf); /* delete item */
(*buf) = NULL;
}
/*******************************************************************
frees a memory buffer chain. assumes that all items are malloced.
********************************************************************/
void mem_free_chain(struct mem_buf **buf)
{
if (buf == NULL) return;
if ((*buf) == NULL) return;
if ((*buf)->next != NULL)
{
mem_free_chain(&((*buf)->next)); /* delete all other items in chain */
}
mem_buf_free(buf);
}
/*******************************************************************
frees a memory buffer.
********************************************************************/
void mem_free_data(struct mem_buf *buf)
{
if (buf == NULL) return;
if (buf->data != NULL && buf->dynamic)
{
free(buf->data); /* delete data in this structure */
}
mem_init(buf, buf->margin);
}
/*******************************************************************
reallocate a memory buffer, including a safety margin
********************************************************************/
BOOL mem_realloc_data(struct mem_buf *buf, int new_size)
{
char *new_data;
if (!buf->dynamic)
{
DEBUG(3,("mem_realloc_data: memory buffer has not been dynamically allocated!\n"));
return False;
}
if (new_size == 0)
{
mem_free_data(buf);
return True;
}
new_data = Realloc(buf->data, new_size + buf->margin);
if (new_data != NULL)
{
buf->data = new_data;
buf->data_size = new_size + buf->margin;
buf->data_used = new_size;
}
else if (buf->data_size <= new_size)
{
DEBUG(3,("mem_realloc: warning - could not realloc to %d(+%d)\n",
new_size, buf->margin));
buf->data_used = new_size;
}
else
{
DEBUG(3,("mem_realloc: error - could not realloc to %d\n",
new_size));
mem_free_data(buf);
return False;
}
return True;
}
/*******************************************************************
reallocate a memory buffer, retrospectively :-)
********************************************************************/
BOOL mem_grow_data(struct mem_buf **buf, BOOL io, int new_size)
{
if (new_size + (*buf)->margin >= (*buf)->data_size)
{
if (io)
{
DEBUG(3,("mem_grow_data: cannot resize when reading from a data stream\n"));
}
else
{
return mem_realloc_data((*buf), new_size);
return False;
}
}
return True;
}
/*******************************************************************
search for a memory buffer that falls within the specified offset
********************************************************************/
BOOL mem_find(struct mem_buf **buf, uint32 offset)
{
struct mem_buf *f;
if (buf == NULL) return False;
f = *buf;
DEBUG(200,("mem_find: data[%d..%d] offset: %d\n",
f->offset.start, f->offset.end, offset));
while (f != NULL && offset >= f->offset.end)
{
f = f->next;
DEBUG(200,("mem_find: next[%d..%d]\n",
f->offset.start, f->offset.end));
}
(*buf) = f;
DEBUG(200,("mem_find: found data[%d..%d]\n",
(*buf)->offset.start,(*buf)->offset.end));
return f != NULL;
}
/*******************************************************************
add up the lengths of all sections.
********************************************************************/
uint32 mem_buf_len(struct mem_buf *buf)
{
int len = 0;
while (buf != NULL)
{
len += buf->offset.end - buf->offset.start;
buf = buf->next;
}
return len;
}
/*******************************************************************
return the memory location specified by offset. may return NULL.
********************************************************************/
char *mem_data(struct mem_buf **buf, uint32 offset)
{
if (mem_find(buf, offset))
{
return &((*buf)->data[offset - (*buf)->offset.start]);
}
return NULL;
}

View File

@ -4848,4 +4848,29 @@ char *tab_depth(int depth)
return spaces;
}
/*****************************************************************
Convert a domain SID to an ascii string. (non-reentrant).
*****************************************************************/
/* BIG NOTE: this function only does SIDS where the identauth is not >= 2^32 */
char *dom_sid_to_string(DOM_SID *sid)
{
static pstring sidstr;
char subauth[16];
int i;
uint32 ia = (sid->id_auth[5]) +
(sid->id_auth[4] << 8 ) +
(sid->id_auth[3] << 16) +
(sid->id_auth[2] << 24);
sprintf(sidstr, "S-%d-%d", sid->sid_rev_num, ia);
for (i = 0; i < sid->num_auths; i++)
{
sprintf(subauth, "-%d", sid->sub_auths[i]);
strcat(sidstr, subauth);
}
DEBUG(7,("dom_sid_to_string returning %s\n", sidstr));
return sidstr;
}

316
source3/lib/util_hnd.c Normal file
View File

@ -0,0 +1,316 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
*
* 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"
extern int DEBUGLEVEL;
#ifndef MAX_OPEN_POLS
#define MAX_OPEN_POLS 50
#endif
struct reg_info
{
/* for use by \PIPE\winreg */
fstring name; /* name of registry key */
};
struct samr_info
{
/* for use by the \PIPE\samr policy */
DOM_SID sid;
uint32 rid; /* relative id associated with the pol_hnd */
uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */
};
static struct
{
BOOL open;
POLICY_HND pol_hnd;
union
{
struct samr_info samr;
struct reg_info reg;
} dev;
} Policy[MAX_OPEN_POLS];
#define VALID_POL(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_POLS))
#define OPEN_POL(pnum) (VALID_POL(pnum) && Policy[pnum].open)
/****************************************************************************
create a unique policy handle
****************************************************************************/
void create_pol_hnd(POLICY_HND *hnd)
{
static uint32 pol_hnd_low = 0;
static uint32 pol_hnd_high = 0;
if (hnd == NULL) return;
/* i severely doubt that pol_hnd_high will ever be non-zero... */
pol_hnd_low++;
if (pol_hnd_low == 0) pol_hnd_high++;
SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
SIVAL(hnd->data, 4 , pol_hnd_low ); /* second bit is incrementing */
SIVAL(hnd->data, 8 , pol_hnd_high); /* second bit is incrementing */
SIVAL(hnd->data, 12, time(NULL)); /* something random */
SIVAL(hnd->data, 16, getpid()); /* something more random */
}
/****************************************************************************
initialise policy handle states...
****************************************************************************/
void init_lsa_policy_hnd(void)
{
int i;
for (i = 0; i < MAX_OPEN_POLS; i++)
{
Policy[i].open = False;
}
return;
}
/****************************************************************************
find first available policy slot. creates a policy handle for you.
****************************************************************************/
BOOL open_lsa_policy_hnd(POLICY_HND *hnd)
{
int i;
for (i = 0; i < MAX_OPEN_POLS; i++)
{
if (!Policy[i].open)
{
Policy[i].open = True;
create_pol_hnd(hnd);
memcpy(&(Policy[i].pol_hnd), hnd, sizeof(*hnd));
DEBUG(4,("Opened policy hnd[%x] ", i));
dump_data(4, hnd->data, sizeof(hnd->data));
return True;
}
}
/* i love obscure error messages. */
#if TERRY_PRATCHET_INTERESTING_TIMES
DEBUG(1,("+++ OUT OF CHEESE ERROR +++ REDO FROM START ... @?!*@@\n"));
#else
DEBUG(1,("ERROR - open_lsa_policy_hnd: out of Policy Handles!\n"));
#endif
return False;
}
/****************************************************************************
find policy index by handle
****************************************************************************/
int find_lsa_policy_by_hnd(POLICY_HND *hnd)
{
int i;
for (i = 0; i < MAX_OPEN_POLS; i++)
{
if (memcmp(&(Policy[i].pol_hnd), hnd, sizeof(*hnd)) == 0)
{
DEBUG(4,("Found policy hnd[%x] ", i));
dump_data(4, hnd->data, sizeof(hnd->data));
return i;
}
}
DEBUG(4,("Policy not found: "));
dump_data(4, hnd->data, sizeof(hnd->data));
return -1;
}
/****************************************************************************
set samr rid
****************************************************************************/
BOOL set_lsa_policy_samr_rid(POLICY_HND *hnd, uint32 rid)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy device rid=%x pnum=%x\n",
timestring(), rid, pnum));
Policy[pnum].dev.samr.rid = rid;
return True;
}
else
{
DEBUG(3,("%s Error setting policy rid=%x (pnum=%x)\n",
timestring(), rid, pnum));
return False;
}
}
/****************************************************************************
set samr pol status. absolutely no idea what this is.
****************************************************************************/
BOOL set_lsa_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy status=%x pnum=%x\n",
timestring(), pol_status, pnum));
Policy[pnum].dev.samr.status = pol_status;
return True;
}
else
{
DEBUG(3,("%s Error setting policy status=%x (pnum=%x)\n",
timestring(), pol_status, pnum));
return False;
}
}
/****************************************************************************
set samr sid
****************************************************************************/
BOOL set_lsa_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy sid=%s pnum=%x\n",
timestring(), dom_sid_to_string(sid), pnum));
memcpy(&(Policy[pnum].dev.samr.sid), sid, sizeof(*sid));
return True;
}
else
{
DEBUG(3,("%s Error setting policy sid=%s (pnum=%x)\n",
timestring(), dom_sid_to_string(sid), pnum));
return False;
}
}
/****************************************************************************
set samr rid
****************************************************************************/
uint32 get_lsa_policy_samr_rid(POLICY_HND *hnd)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
uint32 rid = Policy[pnum].dev.samr.rid;
DEBUG(3,("%s Getting policy device rid=%x pnum=%x\n",
timestring(), rid, pnum));
return rid;
}
else
{
DEBUG(3,("%s Error getting policy (pnum=%x)\n",
timestring(), pnum));
return 0xffffffff;
}
}
/****************************************************************************
set reg name
****************************************************************************/
BOOL set_lsa_policy_reg_name(POLICY_HND *hnd, fstring name)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy pnum=%x name=%s\n",
timestring(), pnum, name));
fstrcpy(Policy[pnum].dev.reg.name, name);
return True;
}
else
{
DEBUG(3,("%s Error setting policy (pnum=%x) name=%s\n",
timestring(), pnum, name));
return False;
}
}
/****************************************************************************
get reg name
****************************************************************************/
BOOL get_lsa_policy_reg_name(POLICY_HND *hnd, fstring name)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
fstrcpy(name, Policy[pnum].dev.reg.name);
DEBUG(3,("%s Getting policy pnum=%x name=%s\n",
timestring(), pnum, name));
return True;
}
else
{
DEBUG(3,("%s Error getting policy (pnum=%x)\n",
timestring(), pnum));
return False;
}
}
/****************************************************************************
close an lsa policy
****************************************************************************/
BOOL close_lsa_policy_hnd(POLICY_HND *hnd)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Closed policy name pnum=%x\n", timestring(), pnum));
Policy[pnum].open = False;
return True;
}
else
{
DEBUG(3,("%s Error closing policy pnum=%x\n", timestring(), pnum));
return False;
}
}

444
source3/lsarpcd/srv_lsa.c Normal file
View File

@ -0,0 +1,444 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
#include "nterr.h"
extern int DEBUGLEVEL;
/***************************************************************************
lsa_reply_open_policy
***************************************************************************/
static void lsa_reply_open_policy(prs_struct *rdata)
{
int i;
LSA_R_OPEN_POL r_o;
/* set up the LSA QUERY INFO response */
bzero(&(r_o.pol.data), POL_HND_SIZE);
for (i = 4; i < POL_HND_SIZE; i++)
{
r_o.pol.data[i] = i;
}
r_o.status = 0x0;
/* store the response in the SMB stream */
lsa_io_r_open_pol("", &r_o, rdata, 0);
}
/***************************************************************************
make_dom_query
***************************************************************************/
static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
{
int domlen = strlen(dom_name);
d_q->uni_dom_max_len = domlen * 2;
d_q->uni_dom_str_len = domlen * 2;
d_q->buffer_dom_name = 4; /* domain buffer pointer */
d_q->buffer_dom_sid = 2; /* domain sid pointer */
/* this string is supposed to be character short */
make_unistr2(&(d_q->uni_domain_name), dom_name, domlen);
make_dom_sid2(&(d_q->dom_sid), dom_sid);
}
/***************************************************************************
lsa_reply_query_info
***************************************************************************/
static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e,
prs_struct *rdata,
uint32 enum_context, char *dom_name, char *dom_sid)
{
LSA_R_ENUM_TRUST_DOM r_e;
/* set up the LSA QUERY INFO response */
make_r_enum_trust_dom(&r_e, enum_context, dom_name, dom_sid,
dom_name != NULL ? 0x0 : 0x80000000 | NT_STATUS_UNABLE_TO_FREE_VM);
/* store the response in the SMB stream */
lsa_io_r_enum_trust_dom("", &r_e, rdata, 0);
}
/***************************************************************************
lsa_reply_query_info
***************************************************************************/
static void lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata,
char *dom_name, char *dom_sid)
{
LSA_R_QUERY_INFO r_q;
/* set up the LSA QUERY INFO response */
r_q.undoc_buffer = 0x22000000; /* bizarre */
r_q.info_class = q_q->info_class;
make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
r_q.status = 0x0;
/* store the response in the SMB stream */
lsa_io_r_query("", &r_q, rdata, 0);
}
/***************************************************************************
make_dom_ref
pretty much hard-coded choice of "other" sids, unfortunately...
***************************************************************************/
static void make_dom_ref(DOM_R_REF *ref,
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
int len_dom_name = strlen(dom_name);
int len_other_sid1 = strlen(other_sid1);
int len_other_sid2 = strlen(other_sid2);
int len_other_sid3 = strlen(other_sid3);
ref->undoc_buffer = 1;
ref->num_ref_doms_1 = 4;
ref->buffer_dom_name = 1;
ref->max_entries = 32;
ref->num_ref_doms_2 = 4;
make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0);
make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
if (dom_name != NULL)
{
make_unistr(&(ref->uni_dom_name), dom_name);
}
make_dom_sid2(&(ref->ref_dom[0]), dom_sid );
make_dom_sid2(&(ref->ref_dom[1]), other_sid1);
make_dom_sid2(&(ref->ref_dom[2]), other_sid2);
make_dom_sid2(&(ref->ref_dom[3]), other_sid3);
}
/***************************************************************************
make_reply_lookup_rids
***************************************************************************/
static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
int i;
make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
other_sid1, other_sid2, other_sid3);
r_l->num_entries = num_entries;
r_l->undoc_buffer = 1;
r_l->num_entries2 = num_entries;
for (i = 0; i < num_entries; i++)
{
make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
}
r_l->num_entries3 = num_entries;
}
/***************************************************************************
make_lsa_trans_names
***************************************************************************/
static void make_lsa_trans_names(LSA_TRANS_NAME_ENUM *trn,
int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
uint32 *total)
{
uint32 status = 0x0;
int i;
(*total) = 0;
for (i = 0; i < num_entries; i++)
{
uint32 rid = 0xffffffff;
uint8 num_auths = sid[i].sid.num_auths;
fstring name;
uint32 type;
trn->ptr_name[i] = 0;
trn->ptr_name[(*total)] = 0;
/* find the rid to look up */
if (num_auths != 0)
{
rid = sid[i].sid.sub_auths[num_auths-1];
status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
status = (status != 0x0) ? lookup_user_name (rid, name, &type) : status;
status = (status != 0x0) ? lookup_group_name(rid, name, &type) : status;
status = (status != 0x0) ? lookup_alias_name(rid, name, &type) : status;
}
if (status == 0x0)
{
trn->ptr_name[i] = 1;
make_lsa_trans_name(&(trn->name[(*total)]), type, name, (*total));
(*total)++;
}
}
trn->num_entries = (*total);
trn->ptr_trans_names = 1;
trn->num_entries2 = (*total);
}
/***************************************************************************
make_reply_lookup_sids
***************************************************************************/
static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
uint32 mapped_count, uint32 status)
{
r_l->dom_ref = ref;
r_l->names = names;
r_l->mapped_count = mapped_count;
r_l->status = status;
}
/***************************************************************************
lsa_reply_lookup_sids
***************************************************************************/
static void lsa_reply_lookup_sids(prs_struct *rdata,
int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
LSA_R_LOOKUP_SIDS r_l;
DOM_R_REF ref;
LSA_TRANS_NAME_ENUM names;
uint32 mapped_count = 0;
/* set up the LSA Lookup SIDs response */
make_dom_ref(&ref, dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
make_lsa_trans_names(&names, num_entries, sid, &mapped_count);
make_reply_lookup_sids(&r_l, &ref, &names, mapped_count, 0x0);
/* store the response in the SMB stream */
lsa_io_r_lookup_sids("", &r_l, rdata, 0);
}
/***************************************************************************
lsa_reply_lookup_rids
***************************************************************************/
static void lsa_reply_lookup_rids(prs_struct *rdata,
int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
LSA_R_LOOKUP_RIDS r_l;
/* set up the LSA Lookup RIDs response */
make_reply_lookup_rids(&r_l, num_entries, dom_rids,
dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
r_l.status = 0x0;
/* store the response in the SMB stream */
lsa_io_r_lookup_rids("", &r_l, rdata, 0);
}
/***************************************************************************
api_lsa_open_policy
***************************************************************************/
static void api_lsa_open_policy( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_OPEN_POL q_o;
/* grab the server, object attributes and desired access flag...*/
lsa_io_q_open_pol("", &q_o, data, 0);
/* lkclXXXX having decoded it, ignore all fields in the open policy! */
/* return a 20 byte policy handle */
lsa_reply_open_policy(rdata);
}
/***************************************************************************
api_lsa_enum_trust_dom
***************************************************************************/
static void api_lsa_enum_trust_dom( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_ENUM_TRUST_DOM q_e;
/* grab the enum trust domain context etc. */
lsa_io_q_enum_trust_dom("", &q_e, data, 0);
/* construct reply. return status is always 0x0 */
lsa_reply_enum_trust_dom(&q_e, rdata,
0, NULL, NULL);
}
/***************************************************************************
api_lsa_query_info
***************************************************************************/
static void api_lsa_query_info( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_QUERY_INFO q_i;
pstring dom_name;
pstring dom_sid;
/* grab the info class and policy handle */
lsa_io_q_query("", &q_i, data, 0);
pstrcpy(dom_name, lp_workgroup());
pstrcpy(dom_sid , lp_domain_sid());
/* construct reply. return status is always 0x0 */
lsa_reply_query_info(&q_i, rdata, dom_name, dom_sid);
}
/***************************************************************************
api_lsa_lookup_sids
***************************************************************************/
static void api_lsa_lookup_sids( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_LOOKUP_SIDS q_l;
pstring dom_name;
pstring dom_sid;
/* grab the info class and policy handle */
lsa_io_q_lookup_sids("", &q_l, data, 0);
pstrcpy(dom_name, lp_workgroup());
pstrcpy(dom_sid , lp_domain_sid());
/* construct reply. return status is always 0x0 */
lsa_reply_lookup_sids(rdata,
q_l.sids.num_entries, q_l.sids.sid, /* SIDs */
dom_name, dom_sid, /* domain name, domain SID */
"S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
}
/***************************************************************************
api_lsa_lookup_names
***************************************************************************/
static void api_lsa_lookup_names( int uid, prs_struct *data,
prs_struct *rdata )
{
int i;
LSA_Q_LOOKUP_RIDS q_l;
pstring dom_name;
pstring dom_sid;
uint32 dom_rids[MAX_LOOKUP_SIDS];
uint32 dummy_g_rid;
/* grab the info class and policy handle */
lsa_io_q_lookup_rids("", &q_l, data, 0);
pstrcpy(dom_name, lp_workgroup());
pstrcpy(dom_sid , lp_domain_sid());
/* convert received RIDs to strings, so we can do them. */
for (i = 0; i < q_l.num_entries; i++)
{
char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
if (!name_to_rid(user_name, &dom_rids[i], &dummy_g_rid))
{
/* WHOOPS! we should really do something about this... */
dom_rids[i] = 0;
}
}
/* construct reply. return status is always 0x0 */
lsa_reply_lookup_rids(rdata,
q_l.num_entries, dom_rids, /* text-converted SIDs */
dom_name, dom_sid, /* domain name, domain SID */
"S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
}
/***************************************************************************
api_lsa_close
***************************************************************************/
static void api_lsa_close( int uid, prs_struct *data,
prs_struct *rdata)
{
/* XXXX this is NOT good */
char *q = mem_data(&(rdata->data), rdata->offset);
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
rdata->offset += 24;
}
/***************************************************************************
api_lsa_open_secret
***************************************************************************/
static void api_lsa_open_secret( int uid, prs_struct *data,
prs_struct *rdata)
{
/* XXXX this is NOT good */
char *q = mem_data(&(rdata->data), rdata->offset);
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND); q += 4;
rdata->offset += 24;
}
/***************************************************************************
\PIPE\ntlsa commands
***************************************************************************/
static struct api_struct api_lsa_cmds[] =
{
{ "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy },
{ "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info },
{ "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom },
{ "LSA_CLOSE" , LSA_CLOSE , api_lsa_close },
{ "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret },
{ "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids },
{ "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names },
{ NULL , 0 , NULL }
};
/***************************************************************************
api_ntLsarpcTNP
***************************************************************************/
BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data)
{
return api_rpcTNP(p, "api_ntlsa_rpc", api_lsa_cmds, data);
}

View File

@ -195,7 +195,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
* Let's ignore the SID.
*/
strcpy(ascuser, unistr(uniuser));
pstrcpy(ascuser, unistr(uniuser));
DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser));
strcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER. */
@ -203,12 +203,18 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
smb_pass = get_smbpwd_entry(ascuser, 0);
if(!smb_pass)
if(!smb_pass )
{
DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, not in password file\n",
unistr(unicomp),inet_ntoa(p->ip), ascuser));
return;
}
else if(smb_pass->acct_ctrl & ACB_DISABLED)
{
DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, accound disabled.\n",
unistr(unicomp),inet_ntoa(p->ip), ascuser));
return;
}
else
{
DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",

View File

@ -300,10 +300,12 @@ struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec
struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
{
if(subrec == unicast_subnet)
{
if(wins_server_subnet)
return wins_server_subnet;
else
return NULL;
}
if(wins_server_subnet && subrec == wins_server_subnet)
return NULL;

View File

@ -1260,12 +1260,13 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p,
}
}
for(; i < namerec->num_ips; i++)
for(j = 0; j < namerec->num_ips; j++)
{
if(i == same_net_index)
if(j == same_net_index)
continue;
set_nb_flags(&prdata[i*6],namerec->nb_flags);
putip((char *)&prdata[2+(i*6)], &namerec->ip[i]);
putip((char *)&prdata[2+(i*6)], &namerec->ip[j]);
i++;
}
reply_data_len = namerec->num_ips * 6;

View File

@ -461,7 +461,7 @@ static struct parm_struct parm_table[] =
{"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, 0},
{"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars, NULL, 0},
{"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL, NULL, FLAG_BASIC},
#ifdef NTDOMAIN
{"domain sid", P_USTRING, P_GLOBAL, &Globals.szDomainSID, NULL, NULL, 0},
{"domain other sids",P_STRING, P_GLOBAL, &Globals.szDomainOtherSIDs, NULL, NULL, 0},
{"domain groups", P_STRING, P_GLOBAL, &Globals.szDomainGroups, NULL, NULL, 0},
@ -472,7 +472,7 @@ static struct parm_struct parm_table[] =
{"domain allow hosts",P_STRING, P_GLOBAL, &Globals.szDomainHostsallow, NULL, NULL, 0},
{"domain hosts deny", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL, 0},
{"domain deny hosts", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL, 0},
#endif /* NTDOMAIN */
{"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, 0},
{"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set, NULL, 0},
{"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, 0},
@ -898,7 +898,6 @@ FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion)
FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases)
FN_GLOBAL_STRING(lp_driverfile,&Globals.szDriverFile)
#ifdef NTDOMAIN
FN_GLOBAL_STRING(lp_domain_sid,&Globals.szDomainSID)
FN_GLOBAL_STRING(lp_domain_other_sids,&Globals.szDomainOtherSIDs)
FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups)
@ -906,7 +905,6 @@ FN_GLOBAL_STRING(lp_domain_admin_users,&Globals.szDomainAdminUsers)
FN_GLOBAL_STRING(lp_domain_guest_users,&Globals.szDomainGuestUsers)
FN_GLOBAL_STRING(lp_domain_hostsallow,&Globals.szDomainHostsallow)
FN_GLOBAL_STRING(lp_domain_hostsdeny,&Globals.szDomainHostsdeny)
#endif /* NTDOMAIN */
FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy)
FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,395 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
NT Domain Authentication SMB / MSRPC client
Copyright (C) Andrew Tridgell 1994-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
#include "nterr.h"
extern int DEBUGLEVEL;
#if 0
if (!cli_initialise(cli, t_idx))
{
DEBUG(1,("do_nt_session_open: cli_initialise failed\n"));
return False;
}
DEBUG(1,("do_nt_session_open: server connect initialisation\n"));
if (!server_connect_init(cli, t_idx, myhostname, dest_ip, dest_host))
{
uint8 err_cls;
uint32 err_num;
cli_error(cli, t_idx, &err_cls, &err_num);
DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(cli, t_idx)));
return False;
}
DEBUG(1,("do_nt_session_open: server connect initialisation succeeded\n"));
if (!cli_session_setup(cli, t_idx, "", "", 1, NULL, 0, workgroup))
{
uint8 err_cls;
uint32 err_num;
cli_error(cli, t_idx, &err_cls, &err_num);
DEBUG(1,("session setup failed (%s)\n", cli_errstr(cli, t_idx)));
return False;
}
DEBUG(1,("do_nt_session_open: server session setup succeeded\n"));
if (!cli_send_tconX(cli, t_idx, "IPC$", "IPC", "", 1))
{
uint8 err_cls;
uint32 err_num;
cli_error(cli, t_idx, &err_cls, &err_num);
DEBUG(1,("cli_send_tconX failed (%s)\n", cli_errstr(cli, t_idx)));
return False;
}
DEBUG(1,("do_nt_session_open: server IPC$ connection succeeded\n"));
#endif
/****************************************************************************
experimental nt login.
****************************************************************************/
BOOL do_nt_session_open(struct cli_state *cli, int t_idx, uint16 *fnum,
char *dest_host, char *myhostname,
char *mach_acct,
char *username, char *workgroup,
uchar sess_key[16], DOM_CRED *clnt_cred)
{
DOM_CHAL clnt_chal;
DOM_CHAL srv_chal;
DOM_CHAL auth2_srv_chal;
UTIME zerotime;
char nt_owf_mach_pwd[16];
char nt_owf_prev_mpd[16];
RPC_IFACE abstract;
RPC_IFACE transfer;
fstring mach_pwd;
fstring prev_mpd;
fstring dest_srv;
/******************** initialise ********************************/
zerotime.time = 0;
DEBUG(1,("do_nt_session_open: %d\n", __LINE__));
/******************* open the \PIPE\NETLOGON file *****************/
if (((*fnum) = cli_open(cli, t_idx, PIPE_NETLOGON, O_CREAT, DENY_NONE,
NULL, NULL, NULL)) == 0xffff)
{
DEBUG(1,("do_nt_session_open: cli_open failed\n"));
return False;
}
/**************** Set Named Pipe State ***************/
if (!rpc_pipe_set_hnd_state(cli, t_idx, PIPE_NETLOGON, *fnum, 0x4300))
{
DEBUG(1,("do_nt_session_open: pipe hnd state failed\n"));
return False;
}
/******************* bind request on \PIPE\NETLOGON *****************/
if (!rpc_pipe_bind(cli, t_idx, PIPE_NETLOGON, *fnum,
&abstract, &transfer,
False, NULL, NULL))
{
DEBUG(1,("do_nt_session_open: rpc bind failed\n"));
return False;
}
/************ Check workstation trust account *******************/
/* default machine password is lower-case machine name (really secure) */
fstrcpy(mach_pwd, myhostname);
strlower(mach_pwd);
/* default machine password is lower-case machine name (really secure) */
fstrcpy(prev_mpd, myhostname);
strlower(prev_mpd);
/******************* Request Challenge ********************/
SIVAL(clnt_chal.data, 0, 0x11111111);
SIVAL(clnt_chal.data, 4, 0x22222222);
strcpy(dest_srv, "\\\\");
strcat(dest_srv, dest_host);
strupper(dest_srv);
/* send a client challenge; receive a server challenge */
if (!do_net_req_chal(cli, t_idx, *fnum, dest_srv, myhostname, &clnt_chal, &srv_chal))
{
DEBUG(1,("do_nt_session_open: request challenge failed\n"));
return False;
}
/**************** Long-term Session key **************/
#ifdef DEBUG_PASSWORD
DEBUG(100,("generating nt owf from initial machine pwd: %s\n", mach_pwd));
#endif
nt_owf_gen( mach_pwd, nt_owf_mach_pwd);
#ifdef DEBUG_PASSWORD
dump_data(6, nt_owf_mach_pwd, 16);
#endif
#ifdef DEBUG_PASSWORD
DEBUG(100,("generating nt owf from previous machine pwd: %s\n", prev_mpd));
#endif
nt_owf_gen( mach_pwd, nt_owf_prev_mpd);
#ifdef DEBUG_PASSWORD
dump_data(6, nt_owf_prev_mpd, 16);
#endif
/* calculate the session key */
cred_session_key(&clnt_chal, &srv_chal, nt_owf_mach_pwd, sess_key);
#if 0
cred_session_key(&clnt_chal, &srv_chal, nt_owf_prev_mpd, sess_key+8);
#else
bzero(sess_key+8, 8);
#endif
/******************* Authenticate 2 ********************/
/* calculate auth-2 credentials */
cred_create(sess_key, &clnt_chal, zerotime, &(clnt_cred->challenge));
/* send client auth-2 challenge; receive an auth-2 challenge */
if (!do_net_auth2(cli, t_idx, *fnum,
dest_srv, mach_acct,
SEC_CHAN_WKSTA, myhostname,
&(clnt_cred->challenge), 0x000001ff, &auth2_srv_chal))
{
DEBUG(1,("do_nt_session_open: request challenge failed\n"));
return False;
}
return True;
}
/****************************************************************************
server password set
****************************************************************************/
BOOL do_nt_srv_pwset(struct cli_state *cli, int t_idx, uint16 fnum,
uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
char *new_mach_pwd,
char *dest_host, char *mach_acct, char *myhostname)
{
/**************** Net Server Password Set **************/
DOM_CRED cred;
char nt_cypher[16];
uint8 mode = 1;
char nt_owf_new_mach_pwd[16];
#ifdef DEBUG_PASSWORD
DEBUG(100,("generating nt owf from new machine pwd: %s\n", new_mach_pwd));
#endif
nt_owf_gen(new_mach_pwd, nt_owf_new_mach_pwd);
#ifdef DEBUG_PASSWORD
dump_data(6, nt_owf_new_mach_pwd, 16);
#endif
if (!obfuscate_pwd(nt_cypher, nt_owf_new_mach_pwd, mode))
{
DEBUG(5,("do_nt_srv_pwset: encrypt mach pwd failed\n"));
return False;
}
clnt_cred->timestamp.time = time(NULL);
memcpy(&cred, clnt_cred, sizeof(cred));
/* calculate credentials */
cred_create(sess_key, &(clnt_cred->challenge),
cred.timestamp,
&(cred.challenge));
/* send client srv_pwset challenge */
return do_net_srv_pwset(cli, t_idx, fnum, sess_key, clnt_cred,
dest_host, mach_acct, 2, myhostname,
&cred, rtn_cred,
nt_cypher);
}
/****************************************************************************
make interactive sam login info
****************************************************************************/
void make_nt_login_interactive(NET_ID_INFO_CTR *ctr,
uchar sess_key[16],
char *workgroup, char *myhostname,
uint32 smb_userid, char *username)
{
/****************** SAM Info Preparation *******************/
char *smb_user_passwd = getpass("Enter NT Login Password:");
char lm_owf_user_pwd[16];
char nt_owf_user_pwd[16];
nt_lm_owf_gen(smb_user_passwd, nt_owf_user_pwd, lm_owf_user_pwd);
#ifdef DEBUG_PASSWORD
DEBUG(100,("nt owf of user password: "));
dump_data(100, lm_owf_user_pwd, 16);
DEBUG(100,("nt owf of user password: "));
dump_data(100, nt_owf_user_pwd, 16);
#endif
/* indicate an "interactive" login */
ctr->switch_value = 1;
/* this is used in both the SAM Logon and the SAM Logoff */
make_id_info1(&ctr->auth.id1, workgroup, 0,
smb_userid, 0,
username, myhostname,
sess_key, lm_owf_user_pwd, nt_owf_user_pwd);
}
/****************************************************************************
experimental nt login.
****************************************************************************/
BOOL do_nt_login(struct cli_state *cli, int t_idx, uint16 fnum,
uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
NET_ID_INFO_CTR *ctr, char *dest_host, char *myhostname,
NET_USER_INFO_3 *user_info3)
{
DOM_CRED sam_logon_rtn_cred;
DOM_CRED cred;
fstring dest_srv;
fstring my_host_name;
DEBUG(5,("do_nt_login: %d\n", __LINE__));
/*********************** SAM Logon **********************/
clnt_cred->timestamp.time = time(NULL);
memcpy(&cred, clnt_cred, sizeof(cred));
/* calculate sam logon credentials */
cred_create(sess_key, &(clnt_cred->challenge),
cred.timestamp,
&(cred.challenge));
strcpy(dest_srv, "\\\\");
strcat(dest_srv, dest_host);
strupper(dest_srv);
fstrcpy(my_host_name, myhostname);
strupper(my_host_name);
/* send client sam-logon challenge */
return do_net_sam_logon(cli, t_idx, fnum, sess_key, clnt_cred,
dest_srv, my_host_name,
&cred, &sam_logon_rtn_cred,
ctr->switch_value, ctr, 3, user_info3,
rtn_cred);
}
/****************************************************************************
nt sam logoff
****************************************************************************/
BOOL do_nt_logoff(struct cli_state *cli, int t_idx, uint16 fnum,
uint8 sess_key[16], DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
NET_ID_INFO_CTR *ctr, char *dest_host, char *myhostname)
{
DOM_CRED sam_logoff_rtn_cred;
DOM_CRED cred;
fstring dest_srv;
fstring my_host_name;
DEBUG(5,("do_nt_logoff: %d\n", __LINE__));
/*********************** SAM Logoff *********************/
clnt_cred->timestamp.time = time(NULL);
memcpy(&cred, clnt_cred, sizeof(cred));
/* calculate sam logoff credentials */
cred_create(sess_key, &(clnt_cred->challenge),
cred.timestamp,
&(cred.challenge));
strcpy(dest_srv, "\\\\");
strcat(dest_srv, dest_host);
strupper(dest_srv);
fstrcpy(my_host_name, myhostname);
strupper(my_host_name);
/* send client sam-logoff challenge; receive a sam-logoff challenge */
return do_net_sam_logoff(cli, t_idx, fnum, sess_key, clnt_cred,
dest_srv, my_host_name,
&cred, &sam_logoff_rtn_cred,
ctr->switch_value, ctr, 3,
rtn_cred);
}
#if 0
/* free memory used in all rpc transactions, above */
cli_shutdown(cli, t_idx);
#endif
/****************************************************************************
experimental nt login.
****************************************************************************/
void do_nt_session_close(struct cli_state *cli, int t_idx, uint16 fnum)
{
/******************** close the \PIPE\NETLOGON file **************/
if (fnum != 0xffff)
{
cli_close(cli, t_idx, fnum, 0);
}
}

View File

@ -0,0 +1,255 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
extern int DEBUGLEVEL;
/****************************************************************************
do a LSA Open Policy
****************************************************************************/
BOOL do_lsa_open_policy(struct cli_state *cli, int t_idx, uint16 fnum,
char *server_name, POLICY_HND *hnd)
{
prs_struct rbuf;
prs_struct buf;
LSA_Q_OPEN_POL q_o;
BOOL valid_pol = False;
if (hnd == NULL) return False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api LSA_OPENPOLICY */
DEBUG(4,("LSA Open Policy\n"));
/* store the parameters */
make_q_open_pol(&q_o, server_name, 0, 0, 0x1);
/* turn parameters into data stream */
lsa_io_q_open_pol("", &q_o, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_OPENPOLICY, &buf, &rbuf))
{
LSA_R_OPEN_POL r_o;
BOOL p;
lsa_io_r_open_pol("", &r_o, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("LSA_OPENPOLICY: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
/* ok, at last: we're happy. return the policy handle */
memcpy(hnd, r_o.pol.data, sizeof(hnd->data));
valid_pol = True;
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_pol;
}
/****************************************************************************
do a LSA Query Info Policy
****************************************************************************/
BOOL do_lsa_query_info_pol(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *hnd, uint16 info_class,
fstring domain_name, fstring domain_sid)
{
prs_struct rbuf;
prs_struct buf;
LSA_Q_QUERY_INFO q_q;
BOOL valid_response = False;
if (hnd == NULL || domain_name == NULL || domain_sid == NULL) return False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api LSA_QUERYINFOPOLICY */
DEBUG(4,("LSA Query Info Policy\n"));
/* store the parameters */
make_q_query(&q_q, hnd, info_class);
/* turn parameters into data stream */
lsa_io_q_query("", &q_q, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_QUERYINFOPOLICY, &buf, &rbuf))
{
LSA_R_QUERY_INFO r_q;
BOOL p;
lsa_io_r_query("", &r_q, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_q.status != 0)
{
/* report error code */
DEBUG(0,("LSA_QUERYINFOPOLICY: %s\n", get_nt_error_msg(r_q.status)));
p = False;
}
if (p && r_q.info_class != q_q.info_class)
{
/* report different info classes */
DEBUG(0,("LSA_QUERYINFOPOLICY: error info_class (q,r) differ - (%x,%x)\n",
q_q.info_class, r_q.info_class));
p = False;
}
if (p)
{
/* ok, at last: we're happy. */
switch (r_q.info_class)
{
case 3:
{
char *dom_name = unistrn2(r_q.dom.id3.uni_domain_name.buffer,
r_q.dom.id3.uni_domain_name.uni_str_len);
char *dom_sid = dom_sid_to_string(&(r_q.dom.id3.dom_sid.sid));
fstrcpy(domain_name, dom_name);
pstrcpy(domain_sid , dom_sid);
valid_response = True;
break;
}
case 5:
{
char *dom_name = unistrn2(r_q.dom.id5.uni_domain_name.buffer,
r_q.dom.id5.uni_domain_name.uni_str_len);
char *dom_sid = dom_sid_to_string(&(r_q.dom.id5.dom_sid.sid));
fstrcpy(domain_name, dom_name);
pstrcpy(domain_sid , dom_sid);
valid_response = True;
break;
}
default:
{
DEBUG(3,("LSA_QUERYINFOPOLICY: unknown info class\n"));
domain_name[0] = 0;
domain_sid [0] = 0;
break;
}
}
DEBUG(3,("LSA_QUERYINFOPOLICY (level %x): domain:%s domain sid:%s\n",
r_q.info_class, domain_name, domain_sid));
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_response;
}
/****************************************************************************
do a LSA Close
****************************************************************************/
BOOL do_lsa_close(struct cli_state *cli, int t_idx, uint16 fnum, POLICY_HND *hnd)
{
prs_struct rbuf;
prs_struct buf;
LSA_Q_CLOSE q_c;
BOOL valid_close = False;
if (hnd == NULL) return False;
/* create and send a MSRPC command with api LSA_OPENPOLICY */
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("LSA Close\n"));
/* store the parameters */
make_lsa_q_close(&q_c, hnd);
/* turn parameters into data stream */
lsa_io_q_close("", &q_c, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, LSA_CLOSE, &buf, &rbuf))
{
LSA_R_CLOSE r_c;
BOOL p;
lsa_io_r_close("", &r_c, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_c.status != 0)
{
/* report error code */
DEBUG(0,("LSA_CLOSE: %s\n", get_nt_error_msg(r_c.status)));
p = False;
}
if (p)
{
/* check that the returned policy handle is all zeros */
int i;
valid_close = True;
for (i = 0; i < sizeof(r_c.pol.data); i++)
{
if (r_c.pol.data[i] != 0)
{
valid_close = False;
break;
}
}
if (!valid_close)
{
DEBUG(0,("LSA_CLOSE: non-zero handle returned\n"));
}
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_close;
}

View File

@ -0,0 +1,461 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
extern int DEBUGLEVEL;
extern pstring username;
extern pstring workgroup;
#define CLIENT_TIMEOUT (30*1000)
/****************************************************************************
do a LSA Logon Control2
****************************************************************************/
BOOL do_net_logon_ctrl2(struct cli_state *cli, int t_idx, uint16 fnum,
char *host_name, uint32 status_level)
{
prs_struct rbuf;
prs_struct buf;
NET_Q_LOGON_CTRL2 q_l;
BOOL valid_ctrl2 = False;
fstring acct_name;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
if (host_name == NULL) return False;
strcpy(acct_name, "\\\\");
strcat(acct_name, host_name);
/* create and send a MSRPC command with api NET_LOGON_CTRL2 */
DEBUG(4,("LSA Logon Control2 from %s status level:%x\n",
host_name, status_level));
/* store the parameters */
make_q_logon_ctrl2(&q_l, acct_name, status_level);
/* turn parameters into data stream */
net_io_q_logon_ctrl2("", &q_l, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, NET_LOGON_CTRL2, &buf, &rbuf))
{
NET_R_LOGON_CTRL2 r_l;
BOOL p;
net_io_r_logon_ctrl2("", &r_l, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_l.status != 0)
{
/* report error code */
DEBUG(0,("NET_R_LOGON_CTRL: %s\n", get_nt_error_msg(r_l.status)));
p = False;
}
if (p)
{
valid_ctrl2 = True;
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_ctrl2;
}
/****************************************************************************
do a LSA Authenticate 2
****************************************************************************/
BOOL do_net_auth2(struct cli_state *cli, int t_idx, uint16 fnum,
char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name,
DOM_CHAL *clnt_chal, uint32 neg_flags, DOM_CHAL *srv_chal)
{
prs_struct rbuf;
prs_struct buf;
NET_Q_AUTH_2 q_a;
BOOL valid_chal = False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
if (srv_chal == NULL || clnt_chal == NULL) return False;
/* create and send a MSRPC command with api NET_AUTH2 */
DEBUG(4,("LSA Authenticate 2: srv:%s acct:%s sc:%x mc: %s chal %s neg: %lx\n",
logon_srv, acct_name, sec_chan, comp_name,
credstr(clnt_chal->data), neg_flags));
/* store the parameters */
make_q_auth_2(&q_a, logon_srv, acct_name, sec_chan, comp_name,
clnt_chal, neg_flags);
/* turn parameters into data stream */
net_io_q_auth_2("", &q_a, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, NET_AUTH2, &buf, &rbuf))
{
NET_R_AUTH_2 r_a;
BOOL p;
net_io_r_auth_2("", &r_a, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_a.status != 0)
{
/* report error code */
DEBUG(0,("NET_AUTH2: %s\n", get_nt_error_msg(r_a.status)));
p = False;
}
if (p && r_a.srv_flgs.neg_flags != q_a.clnt_flgs.neg_flags)
{
/* report different neg_flags */
DEBUG(0,("NET_AUTH2: error neg_flags (q,r) differ - (%lx,%lx)\n",
q_a.clnt_flgs.neg_flags, r_a.srv_flgs.neg_flags));
p = False;
}
if (p)
{
/* ok, at last: we're happy. return the challenge */
memcpy(srv_chal, r_a.srv_chal.data, sizeof(srv_chal->data));
valid_chal = True;
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_chal;
}
/****************************************************************************
do a LSA Request Challenge
****************************************************************************/
BOOL do_net_req_chal(struct cli_state *cli, int t_idx, uint16 fnum,
char *desthost, char *myhostname,
DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal)
{
prs_struct rbuf;
prs_struct buf;
NET_Q_REQ_CHAL q_c;
BOOL valid_chal = False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
if (srv_chal == NULL || clnt_chal == NULL) return False;
/* create and send a MSRPC command with api NET_REQCHAL */
DEBUG(4,("LSA Request Challenge from %s to %s: %s\n",
desthost, myhostname, credstr(clnt_chal->data)));
/* store the parameters */
make_q_req_chal(&q_c, desthost, myhostname, clnt_chal);
/* turn parameters into data stream */
net_io_q_req_chal("", &q_c, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, NET_REQCHAL, &buf, &rbuf))
{
NET_R_REQ_CHAL r_c;
BOOL p;
net_io_r_req_chal("", &r_c, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_c.status != 0)
{
/* report error code */
DEBUG(0,("NET_REQ_CHAL: %s\n", get_nt_error_msg(r_c.status)));
p = False;
}
if (p)
{
/* ok, at last: we're happy. return the challenge */
memcpy(srv_chal, r_c.srv_chal.data, sizeof(srv_chal->data));
valid_chal = True;
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_chal;
}
/***************************************************************************
do a LSA Server Password Set
****************************************************************************/
BOOL do_net_srv_pwset(struct cli_state *cli, int t_idx, uint16 fnum,
uchar sess_key[16], DOM_CRED *sto_clnt_cred,
char *logon_srv, char *mach_acct, uint16 sec_chan_type, char *comp_name,
DOM_CRED *clnt_cred, DOM_CRED *srv_cred,
uint8 nt_owf_new_mach_pwd[16])
{
prs_struct rbuf;
prs_struct buf;
NET_Q_SRV_PWSET q_s;
BOOL valid_cred = False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
if (srv_cred == NULL || clnt_cred == NULL) return False;
/* create and send a MSRPC command with api NET_SRV_PWSET */
DEBUG(4,("LSA Server Password Set: srv:%s acct:%s sc: %d mc: %s clnt %s %lx\n",
logon_srv, mach_acct, sec_chan_type, comp_name,
credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time));
/* store the parameters */
make_q_srv_pwset(&q_s,
sess_key,
logon_srv, mach_acct, sec_chan_type, comp_name,
clnt_cred,
nt_owf_new_mach_pwd);
/* turn parameters into data stream */
net_io_q_srv_pwset("", &q_s, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SRVPWSET, &buf, &rbuf))
{
NET_R_SRV_PWSET r_s;
BOOL p;
net_io_r_srv_pwset("", &r_s, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_s.status != 0)
{
/* report error code */
DEBUG(0,("NET_R_SRV_PWSET: %s\n", get_nt_error_msg(r_s.status)));
p = False;
}
if (p)
{
if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_cred)))
{
DEBUG(5, ("do_net_srv_pwset: server credential check OK\n"));
/* ok, at last: we're happy. return the challenge */
memcpy(srv_cred, &(r_s.srv_cred), sizeof(r_s.srv_cred));
valid_cred = True;
}
else
{
DEBUG(5, ("do_net_srv_pwset: server credential check failed\n"));
}
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_cred;
}
/***************************************************************************
do a LSA SAM Logon
****************************************************************************/
BOOL do_net_sam_logon(struct cli_state *cli, int t_idx, uint16 fnum,
uchar sess_key[8], DOM_CRED *sto_clnt_cred,
char *logon_srv, char *comp_name,
DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
uint16 logon_level, NET_ID_INFO_CTR *ctr, uint16 validation_level,
NET_USER_INFO_3 *user_info3,
DOM_CRED *srv_cred)
{
prs_struct rbuf;
prs_struct buf;
NET_Q_SAM_LOGON q_s;
BOOL valid_cred = False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
if (srv_cred == NULL || clnt_cred == NULL || rtn_cred == NULL || user_info3 == NULL) return False;
/* create and send a MSRPC command with api NET_SAMLOGON */
DEBUG(4,("LSA SAM Logon: srv:%s mc:%s clnt %s %lx rtn: %s %lx ll: %d\n",
logon_srv, comp_name,
credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time,
credstr(rtn_cred->challenge.data), rtn_cred ->timestamp.time,
logon_level));
/* store the parameters */
make_sam_info(&(q_s.sam_id), logon_srv, comp_name,
clnt_cred, rtn_cred,
logon_level, ctr, validation_level);
/* turn parameters into data stream */
net_io_q_sam_logon("", &q_s, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SAMLOGON, &buf, &rbuf))
{
NET_R_SAM_LOGON r_s;
BOOL p;
r_s.user = user_info3;
net_io_r_sam_logon("", &r_s, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_s.status != 0)
{
/* report error code */
DEBUG(0,("NET_SAMLOGON: %s\n", get_nt_error_msg(r_s.status)));
p = False;
}
if (p && r_s.switch_value != 3)
{
/* report different switch_value */
DEBUG(0,("NET_SAMLOGON: switch_value of 3 expected %x\n",
r_s.switch_value));
p = False;
}
if (p)
{
if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_creds)))
{
DEBUG(5, ("do_net_sam_logon: server credential check OK\n"));
/* ok, at last: we're happy. return the challenge */
memcpy(srv_cred, &(r_s.srv_creds), sizeof(r_s.srv_creds));
valid_cred = True;
}
else
{
DEBUG(5, ("do_net_sam_logon: server credential check failed\n"));
}
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_cred;
}
/***************************************************************************
do a LSA SAM Logoff
****************************************************************************/
BOOL do_net_sam_logoff(struct cli_state *cli, int t_idx, uint16 fnum,
uchar sess_key[8], DOM_CRED *sto_clnt_cred,
char *logon_srv, char *comp_name,
DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
uint16 logon_level, NET_ID_INFO_CTR *ctr, uint16 validation_level,
DOM_CRED *srv_cred)
{
prs_struct rbuf;
prs_struct buf;
NET_Q_SAM_LOGOFF q_s;
BOOL valid_cred = False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0, 4, SAFETY_MARGIN, True );
if (srv_cred == NULL || clnt_cred == NULL || rtn_cred == NULL) return False;
/* create and send a MSRPC command with api NET_SAMLOGON */
DEBUG(4,("LSA SAM Logoff: srv:%s mc:%s clnt %s %lx rtn: %s %lx ll: %d\n",
logon_srv, comp_name,
credstr(clnt_cred->challenge.data), clnt_cred->timestamp.time,
credstr(rtn_cred->challenge.data), rtn_cred ->timestamp.time,
logon_level));
/* store the parameters */
make_sam_info(&(q_s.sam_id), logon_srv, comp_name,
clnt_cred, rtn_cred,
logon_level, ctr, validation_level);
/* turn parameters into data stream */
net_io_q_sam_logoff("", &q_s, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, NET_SAMLOGOFF, &buf, &rbuf))
{
NET_R_SAM_LOGOFF r_s;
BOOL p;
net_io_r_sam_logoff("", &r_s, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_s.status != 0)
{
/* report error code */
DEBUG(0,("NET_SAMLOGOFF: %s\n", get_nt_error_msg(r_s.status)));
p = False;
}
if (p)
{
if (clnt_deal_with_creds(sess_key, sto_clnt_cred, &(r_s.srv_creds)))
{
DEBUG(5, ("do_net_sam_logoff: server credential check OK\n"));
/* ok, at last: we're happy. return the challenge */
memcpy(srv_cred, &(r_s.srv_creds), sizeof(r_s.srv_creds));
valid_cred = True;
}
else
{
DEBUG(5, ("do_net_sam_logoff: server credential check failed\n"));
}
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_cred;
}

View File

@ -0,0 +1,683 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1998,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
* Copyright (C) Paul Ashton 1998.
*
* 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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
extern int DEBUGLEVEL;
extern struct pipe_id_info pipe_names[];
/********************************************************************
rpc pipe call id
********************************************************************/
uint32 get_rpc_call_id(void)
{
static uint32 call_id = 1;
return ++call_id;
}
/*******************************************************************
uses SMBreadX to get rest of rpc data
********************************************************************/
static BOOL rpc_read(struct cli_state *cli, int t_idx, uint16 fnum,
prs_struct *rdata, uint32 data_to_read)
{
uint32 data_offset = rdata->data->data_used;
int size = 512;
int num_read;
char *data = rdata->data->data;
uint32 err;
data += rdata->data->data_used;
if (data_offset + data_to_read > rdata->data->data_size)
{
mem_grow_data(&rdata->data, True, rdata->data->data_used + data_to_read);
DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
}
do /* read data using SMBreadX */
{
if (size > data_to_read) size = data_to_read;
if (data_offset + size > rdata->data->data_size)
{
mem_grow_data(&rdata->data, True, rdata->data->data_used + size);
DEBUG(5,("rpc_read: grow buffer to %d\n", rdata->data->data_used));
}
num_read = cli_readx(cli, t_idx, fnum, data, data_offset, size);
DEBUG(5,("rpc_read: read offset: %d read: %d to read: %d\n",
data_offset, num_read, data_to_read));
data_to_read -= num_read;
data_offset += num_read;
data += num_read;
if (cli_error(cli, NULL, &err)) return False;
} while (num_read > 0 && data_to_read > 0); /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
mem_realloc_data(rdata->data, rdata->data->data_used);
rdata->data->offset.end = rdata->data->data_used;
DEBUG(5,("rpc_read: data supposedly left to read:0x%x\n", data_to_read));
return data_to_read == 0;
}
/****************************************************************************
checks the header
****************************************************************************/
static BOOL rpc_check_hdr(prs_struct *rdata, uint8 *pkt_type,
BOOL *first, BOOL *last, uint32 *len)
{
RPC_HDR rhdr;
smb_io_rpc_hdr ("rpc_hdr ", &rhdr , rdata, 0);
if (!rdata->offset || rdata->offset != 0x10)
{
DEBUG(5,("cli_pipe: error in rpc header\n"));
return False;
}
(*first ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
(*last ) = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
(*len ) = rhdr.frag_len - rdata->data->data_used;
(*pkt_type) = rhdr.pkt_type;
return True;
}
/****************************************************************************
send data on an rpc pipe, which *must* be in one fragment.
receive response data from an rpc pipe, which may be large...
read the first fragment: unfortunately have to use SMBtrans for the first
bit, then SMBreadX for subsequent bits.
if first fragment received also wasn't the last fragment, continue
getting fragments until we _do_ receive the last fragment.
[note: from a data abstraction viewpoint, this function is marginally
complicated by the return side of cli_api_pipe getting in the way
(i.e, the SMB header stuff). the proper way to do this is to split
cli_api_pipe down into receive / transmit. oh, and split cli_readx
down. in other words, state-based (kernel) techniques...]
****************************************************************************/
BOOL rpc_api_pipe(struct cli_state *cli, int t_idx,
uint16 cmd, uint16 fnum,
prs_struct *param , prs_struct *data,
prs_struct *rparam, prs_struct *rdata)
{
uint32 len;
uint16 setup[2]; /* only need 2 uint16 setup parameters */
uint32 err;
uint8 pkt_type = 0xff;
BOOL first = True;
BOOL last = True;
/* prepare return data and params */
/* create setup parameters. */
setup[0] = cmd;
setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */
/* send the data: receive a response. */
if (!cli_api_pipe(cli, t_idx, "\\PIPE\\\0\0\0", 8,
param != NULL ? param->data->data_used : 0,
data != NULL ? data ->data->data_used : 0,
2,
0,
data != NULL ? 1024 : 0 ,
param != NULL ? param->data->data : NULL,
data != NULL ? data ->data->data : NULL,
setup,
rparam != NULL ? rparam->data : NULL,
rdata != NULL ? rdata ->data : NULL))
{
DEBUG(5, ("cli_pipe: return critical error\n"));
return False;
}
if (cli_error(cli, NULL, &err)) return False;
if (rdata->data->data == NULL) return False;
/**** parse the header: check it's a response record */
rdata->data->offset.start = 0;
rdata->data->offset.end = rdata->data->data_used;
rdata->offset = 0;
if (!rpc_check_hdr(rdata, &pkt_type, &first, &last, &len)) return False;
if (pkt_type == RPC_RESPONSE)
{
RPC_HDR_RR rhdr_rr;
smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, rdata, 0);
}
if (first && last)
{
DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
return True;
}
/* check if data to be sent back was too large for one SMB. */
/* err status is only informational: the _real_ check is on the length */
if (len < rdata->data->data_used) /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */
{
if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False;
}
/* only one rpc fragment, and it has been read */
if (first && last) return True;
while (!last) /* read more fragments until we get the last one */
{
RPC_HDR rhdr;
RPC_HDR_RR rhdr_rr;
int num_read;
prs_struct hps;
prs_init(&hps, 0x18, 4, 0, True);
num_read = cli_readx(cli, t_idx, fnum, hps.data->data, 0, 0x18);
DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read));
if (num_read != 0x18) return False;
smb_io_rpc_hdr ("rpc_hdr ", &rhdr , &hps, 0);
smb_io_rpc_hdr_rr("rpc_hdr_rr", &rhdr_rr, &hps, 0);
prs_mem_free(&hps);
if (cli_error(cli, NULL, &err)) return False;
first = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_FIRST);
last = IS_BITS_SET_ALL(rhdr.flags, RPC_FLG_LAST );
if (first)
{
DEBUG(4,("rpc_api_pipe: wierd rpc header received\n"));
return False;
}
len = rhdr.frag_len - hps.offset;
if (!rpc_read(cli, t_idx, fnum, rdata, len)) return False;
}
return True;
}
/*******************************************************************
creates a DCE/RPC bind request
- initialises the parse structure.
- dynamically allocates the header data structure
- caller is expected to free the header data structure once used.
********************************************************************/
static BOOL create_rpc_bind_req(prs_struct *rhdr,
prs_struct *rhdr_rb,
prs_struct *auth_req,
RPC_IFACE *abstract, RPC_IFACE *transfer,
char *my_name, char *domain)
{
RPC_HDR_RB hdr_rb;
RPC_HDR hdr;
RPC_AUTH_NTLMSSP_REQ ntlmssp_req;
/* create the bind request RPC_HDR_RB */
make_rpc_hdr_rb(&hdr_rb,
0x1630, 0x1630, 0x0,
0x1, 0x0, 0x1,
abstract, transfer);
/* stream the bind request data */
smb_io_rpc_hdr_rb("", &hdr_rb, rhdr_rb, 0);
mem_realloc_data(rhdr_rb->data, rhdr_rb->offset);
if (auth_req != NULL)
{
make_rpc_auth_ntlmssp_req(&ntlmssp_req,
"NTLMSSP", 0x1,
0x0000b2b3,
my_name, domain);
smb_io_rpc_auth_ntlmssp_req("", &ntlmssp_req, auth_req, 0);
mem_realloc_data(auth_req->data, auth_req->offset);
}
/* create the request RPC_HDR */
make_rpc_hdr(&hdr, RPC_BIND, 0x0, get_rpc_call_id(),
rhdr_rb->offset,
auth_req != NULL ? auth_req->offset : 0);
smb_io_rpc_hdr("hdr" , &hdr , rhdr, 0);
mem_realloc_data(rhdr->data, rhdr->offset);
if (rhdr->data == NULL || rhdr_rb->data == NULL) return False;
/***/
/*** link rpc header, bind acknowledgment and authentication responses ***/
/***/
rhdr->data->offset.start = 0;
rhdr->data->offset.end = rhdr->offset;
rhdr->data->next = rhdr_rb->data;
if (auth_req != NULL)
{
rhdr_rb->data->offset.start = rhdr->offset;
rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
rhdr_rb->data->next = auth_req->data;
auth_req->data->offset.start = rhdr->offset + rhdr_rb->offset;
auth_req->data->offset.end = rhdr->offset + auth_req->offset + rhdr_rb->offset;
auth_req->data->next = NULL;
}
else
{
rhdr_rb->data->offset.start = rhdr->offset;
rhdr_rb->data->offset.end = rhdr->offset + rhdr_rb->offset;
rhdr_rb->data->next = NULL;
}
return True;
}
/*******************************************************************
creates a DCE/RPC bind request
- initialises the parse structure.
- dynamically allocates the header data structure
- caller is expected to free the header data structure once used.
********************************************************************/
static BOOL create_rpc_request(prs_struct *rhdr, uint8 op_num, int data_len)
{
RPC_HDR_RR hdr_rr;
RPC_HDR hdr;
DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n",
op_num, data_len));
/* create the rpc header RPC_HDR */
make_rpc_hdr (&hdr , RPC_REQUEST, RPC_FLG_FIRST | RPC_FLG_LAST,
get_rpc_call_id(), data_len + 0x18, 0);
/* create the rpc request RPC_HDR_RR */
make_rpc_hdr_rr(&hdr_rr, data_len, op_num);
/* stream-time... */
smb_io_rpc_hdr ("hdr" , &hdr , rhdr, 0);
smb_io_rpc_hdr_rr("hdr_rr", &hdr_rr, rhdr, 0);
if (rhdr->data == NULL || rhdr->offset != 0x18) return False;
rhdr->data->offset.start = 0;
rhdr->data->offset.end = rhdr->offset;
return True;
}
/****************************************************************************
send a request on an rpc pipe.
****************************************************************************/
BOOL rpc_api_pipe_req(struct cli_state *cli, int t_idx, uint16 fnum,
uint8 op_num,
prs_struct *data, prs_struct *rdata)
{
/* fudge this, at the moment: create the header; memcpy the data. oops. */
prs_struct rparam;
prs_struct hdr;
int data_len;
BOOL ret;
data_len = data->offset + 0x18;
data->data->offset.end = data->offset;
prs_init(&hdr , data_len, 4, SAFETY_MARGIN, False);
prs_init(&rparam, 0 , 4, 0 , True );
create_rpc_request(&hdr, op_num, data_len);
mem_realloc_data(hdr.data, data_len);
hdr.data->offset.end = data_len;
mem_buf_copy(mem_data(&(hdr.data), 0x18), data->data, 0, data->offset);
ret = rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &hdr, &rparam, rdata);
prs_mem_free(&rparam);
prs_mem_free(&hdr);
return ret;
}
/****************************************************************************
do an rpc bind
****************************************************************************/
BOOL rpc_pipe_set_hnd_state(struct cli_state *cli, int t_idx,
char *pipe_name, uint16 fnum, uint16 device_state)
{
prs_struct param;
prs_struct rdata;
prs_struct rparam;
BOOL state_set = False;
uint16 setup[2]; /* only need 2 uint16 setup parameters */
if (pipe_name == NULL) return False;
prs_init(&param , 2, 4, 0 , False);
prs_init(&rdata , 0, 4, SAFETY_MARGIN, True );
prs_init(&rparam, 0, 4, SAFETY_MARGIN, True );
param.data->offset.start = 0;
param.data->offset.end = 2;
DEBUG(5,("Set Handle state Pipe[%x]: %s - device state:%x\n",
fnum, pipe_name, device_state));
/* create data parameters: device state */
SSVAL(param.data->data, 0, device_state);
/* create setup parameters. */
setup[0] = 0x0001;
setup[1] = fnum; /* pipe file handle. got this from an SMBcreateX. */
/* send the data on \PIPE\ */
if (cli_api_pipe(cli, t_idx, "\\PIPE\\\0\0\0", 8,
2, 0, 2,
0, 1024,
param.data->data, NULL, setup,
rparam.data, rdata.data))
{
DEBUG(5, ("Set Handle state: return OK\n"));
state_set = True;
}
prs_mem_free(&param );
prs_mem_free(&rparam);
prs_mem_free(&rdata );
return state_set;
}
/****************************************************************************
check the rpc bind acknowledge response
****************************************************************************/
static BOOL valid_pipe_name(char *pipe_name,
RPC_IFACE *abstract, RPC_IFACE *transfer)
{
int pipe_idx = 0;
while (pipe_names[pipe_idx].client_pipe != NULL)
{
if (strcmp(pipe_name, pipe_names[pipe_idx].client_pipe ) == 0)
{
DEBUG(5,("Bind Abstract Syntax: "));
dump_data(5, (uchar*)&(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax));
DEBUG(5,("Bind Transfer Syntax: "));
dump_data(5, (uchar*)&(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax));
/* copy the required syntaxes out so we can do the right bind */
memcpy(transfer, &(pipe_names[pipe_idx].trans_syntax), sizeof(pipe_names[pipe_idx].trans_syntax));
memcpy(abstract, &(pipe_names[pipe_idx].abstr_syntax), sizeof(pipe_names[pipe_idx].abstr_syntax));
return True;
}
pipe_idx++;
};
DEBUG(5,("Bind RPC Pipe[%s] unsupported\n", pipe_name));
return False;
}
/****************************************************************************
check the rpc bind acknowledge response
****************************************************************************/
static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, char *pipe_name, RPC_IFACE *transfer)
{
int i = 0;
while ((pipe_names[i].client_pipe != NULL))
{
DEBUG(6,("bind_rpc_pipe: searching pipe name: client:%s server:%s\n",
pipe_names[i].client_pipe , pipe_names[i].server_pipe ));
if ((strcmp(pipe_name, pipe_names[i].client_pipe ) == 0))
{
if (strcmp(hdr_ba->addr.str, pipe_names[i].server_pipe ) == 0)
{
DEBUG(5,("bind_rpc_pipe: server pipe_name found: %s\n",
pipe_names[i].server_pipe ));
break;
}
else
{
DEBUG(2,("bind_rpc_pipe: pipe_name %s != expected pipe %s\n",
pipe_names[i].server_pipe , hdr_ba->addr.str));
return False;
}
}
else
{
i++;
}
}
if (pipe_names[i].server_pipe == NULL)
{
DEBUG(2,("bind_rpc_pipe: pipe name %s unsupported\n", hdr_ba->addr.str));
return False;
}
/* check the transfer syntax */
if (!((hdr_ba->transfer.version == transfer->version) &&
(memcmp(hdr_ba->transfer.data, transfer->data,
sizeof(transfer->version)) ==0)))
{
DEBUG(2,("bind_rpc_pipe: transfer syntax differs\n"));
return False;
}
/* lkclXXXX only accept one result: check the result(s) */
if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0)
{
DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
hdr_ba->res.num_results,
hdr_ba->res.reason));
}
DEBUG(5,("bind_rpc_pipe: accepted!\n"));
return True;
}
/****************************************************************************
do an rpc bind
****************************************************************************/
BOOL rpc_pipe_bind(struct cli_state *cli, int t_idx, char *pipe_name, uint16 fnum,
RPC_IFACE *abstract, RPC_IFACE *transfer, BOOL ntlmssp_auth,
char *my_name, char *domain)
{
prs_struct hdr;
prs_struct hdr_rb;
prs_struct auth_req;
prs_struct data;
prs_struct rdata;
prs_struct rparam;
BOOL valid_ack = False;
if (pipe_name == NULL || abstract == NULL || transfer == NULL) return False;
DEBUG(5,("Bind RPC Pipe[%x]: %s\n", fnum, pipe_name));
if (!valid_pipe_name(pipe_name, abstract, transfer)) return False;
prs_init(&hdr , 0x10 , 4, 0x0 , False);
prs_init(&hdr_rb , 1024 , 4, SAFETY_MARGIN, False);
prs_init(&auth_req, ntlmssp_auth ? 1024 : 0, 4, SAFETY_MARGIN, False);
prs_init(&rdata , 0 , 4, SAFETY_MARGIN, True );
prs_init(&rparam, 0 , 4, SAFETY_MARGIN, True );
create_rpc_bind_req(&hdr, &hdr_rb, ntlmssp_auth ? &auth_req : NULL,
abstract, transfer,
my_name, domain);
/* this is a hack due to limitations in rpc_api_pipe */
prs_init(&data, mem_buf_len(hdr.data), 4, 0x0, False);
mem_buf_copy(data.data->data, hdr.data, 0, mem_buf_len(hdr.data));
/* send data on \PIPE\. receive a response */
if (rpc_api_pipe(cli, t_idx, 0x0026, fnum, NULL, &data, &rparam, &rdata))
{
RPC_HDR_BA hdr_ba;
DEBUG(5, ("rpc_api_pipe: return OK\n"));
smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0);
if (rdata.offset != 0) valid_ack = check_bind_response(&hdr_ba, pipe_name, transfer);
}
prs_mem_free(&data );
prs_mem_free(&hdr );
prs_mem_free(&hdr_rb );
prs_mem_free(&auth_req);
prs_mem_free(&rdata );
prs_mem_free(&rparam );
return valid_ack;
}
/****************************************************************************
open a session
****************************************************************************/
BOOL do_session_open(struct cli_state *cli, int t_idx,
char *pipe_name, uint16 *fnum)
{
RPC_IFACE abstract;
RPC_IFACE transfer;
/******************* open the pipe *****************/
if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE,
NULL, NULL, NULL)) == 0xffff)
{
DEBUG(1,("do_session_open: cli_open failed\n"));
return False;
}
/**************** Set Named Pipe State ***************/
if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300))
{
DEBUG(1,("do_session_open: pipe hnd state failed\n"));
return False;
}
/******************* bind request on pipe *****************/
if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum),
&abstract, &transfer,
False, NULL, NULL))
{
DEBUG(1,("do_session_open: rpc bind failed\n"));
return False;
}
return True;
}
/****************************************************************************
open an encrypted session
****************************************************************************/
BOOL do_ntlm_session_open(struct cli_state *cli, int t_idx,
char *pipe_name, uint16 *fnum,
char *my_name, char *domain)
{
RPC_IFACE abstract;
RPC_IFACE transfer;
/******************* open the pipe *****************/
if (((*fnum) = cli_open(cli, t_idx, pipe_name, O_CREAT|O_RDONLY, DENY_NONE,
NULL, NULL, NULL)) == 0xffff)
{
DEBUG(1,("do_ntlm_session_open: cli_open failed\n"));
return False;
}
/**************** Set Named Pipe State ***************/
if (!rpc_pipe_set_hnd_state(cli, t_idx, pipe_name, (*fnum), 0x4300))
{
DEBUG(1,("do_ntlm_session_open: pipe hnd state failed\n"));
return False;
}
/******************* bind request on pipe *****************/
if (!rpc_pipe_bind(cli, t_idx, pipe_name, (*fnum),
&abstract, &transfer,
True, my_name, domain))
{
DEBUG(1,("do_ntlm_session_open: rpc bind failed\n"));
return False;
}
return True;
}
/****************************************************************************
close the session
****************************************************************************/
void do_session_close(struct cli_state *cli, int t_idx, uint16 fnum)
{
if (fnum != 0xffff)
{
cli_close(cli, t_idx, fnum, 0);
}
}

View File

@ -0,0 +1,695 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
NT Domain Authentication SMB / MSRPC client
Copyright (C) Andrew Tridgell 1994-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
#include "nterr.h"
extern int DEBUGLEVEL;
/****************************************************************************
do a SAMR query user groups
****************************************************************************/
BOOL get_samr_query_usergroups(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *pol_open_domain, uint32 user_rid,
uint32 *num_groups, DOM_GID *gid)
{
POLICY_HND pol_open_user;
if (pol_open_domain == NULL || num_groups == NULL || gid == NULL) return False;
/* send open domain (on user sid) */
if (!do_samr_open_user(cli, t_idx, fnum,
pol_open_domain,
0x02011b, user_rid,
&pol_open_user))
{
return False;
}
/* send user groups query */
if (!do_samr_query_usergroups(cli, t_idx, fnum,
&pol_open_user,
num_groups, gid))
{
DEBUG(5,("do_samr_query_usergroups: error in query user groups\n"));
}
return do_samr_close(cli, t_idx, fnum, &pol_open_user);
}
/****************************************************************************
do a SAMR query user info
****************************************************************************/
BOOL get_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *pol_open_domain,
uint32 info_level,
uint32 user_rid, SAM_USER_INFO_21 *usr)
{
POLICY_HND pol_open_user;
if (pol_open_domain == NULL || usr == NULL) return False;
bzero(usr, sizeof(*usr));
/* send open domain (on user sid) */
if (!do_samr_open_user(cli, t_idx, fnum,
pol_open_domain,
0x02011b, user_rid,
&pol_open_user))
{
return False;
}
/* send user info query */
if (!do_samr_query_userinfo(cli, t_idx, fnum,
&pol_open_user,
info_level, (void*)usr))
{
DEBUG(5,("do_samr_query_userinfo: error in query user info, level 0x%x\n",
info_level));
}
return do_samr_close(cli, t_idx, fnum, &pol_open_user);
}
/****************************************************************************
do a SAMR unknown 0x8 command
****************************************************************************/
BOOL do_samr_unknown_8(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *domain_pol, uint16 switch_value)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_UNKNOWN_8 q_e;
BOOL valid_un8 = False;
/* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Unknown 8 switch:%d\n", switch_value));
if (domain_pol == NULL || fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_unknown_8(&q_e, domain_pol, switch_value);
/* turn parameters into data stream */
samr_io_q_unknown_8("", &q_e, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_8, &data, &rdata))
{
#if 0
SAMR_R_UNKNOWN_8 r_e;
BOOL p;
samr_io_r_unknown_8("", &r_e, &rdata, 0);
p = rdata.offset != 0;
if (p && r_e.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_UNKNOWN_8: %s\n", get_nt_error_msg(r_e.status)));
p = False;
}
if (p)
{
valid_un8 = True;
}
#endif
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_un8;
}
/****************************************************************************
do a SAMR enumerate users
****************************************************************************/
BOOL do_samr_enum_dom_users(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *pol, uint16 num_entries, uint16 unk_0,
uint16 acb_mask, uint16 unk_1, uint32 size,
struct acct_info sam[MAX_SAM_ENTRIES],
int *num_sam_users)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_ENUM_DOM_USERS q_e;
BOOL valid_pol = False;
/* create and send a MSRPC command with api SAMR_ENUM_DOM_USERS */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Enum SAM DB max size:%x\n", size));
if (pol == NULL || sam == NULL || num_sam_users == NULL || fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_enum_dom_users(&q_e, pol,
num_entries, unk_0,
acb_mask, unk_1, size);
/* turn parameters into data stream */
samr_io_q_enum_dom_users("", &q_e, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_ENUM_DOM_USERS, &data, &rdata))
{
SAMR_R_ENUM_DOM_USERS r_e;
BOOL p;
samr_io_r_enum_dom_users("", &r_e, &rdata, 0);
p = rdata.offset != 0;
if (p && r_e.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_ENUM_DOM_USERS: %s\n", get_nt_error_msg(r_e.status)));
p = False;
}
if (p)
{
int i;
int name_idx = 0;
*num_sam_users = r_e.num_entries2;
if (*num_sam_users > MAX_SAM_ENTRIES)
{
*num_sam_users = MAX_SAM_ENTRIES;
DEBUG(2,("do_samr_enum_dom_users: sam user entries limited to %d\n",
*num_sam_users));
}
for (i = 0; i < *num_sam_users; i++)
{
sam[i].smb_userid = r_e.sam[i].rid;
if (r_e.sam[i].hdr_name.buffer)
{
char *acct_name = unistrn2(r_e.uni_acct_name[name_idx].buffer,
r_e.uni_acct_name[name_idx].uni_str_len);
fstrcpy(sam[i].acct_name, acct_name);
name_idx++;
}
else
{
bzero(sam[i].acct_name, sizeof(sam[i].acct_name));
}
DEBUG(5,("do_samr_enum_dom_users: idx: %4d rid: %8x acct: %s\n",
i, sam[i].smb_userid, sam[i].acct_name));
}
valid_pol = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_pol;
}
/****************************************************************************
do a SAMR Connect
****************************************************************************/
BOOL do_samr_connect(struct cli_state *cli, int t_idx, uint16 fnum,
char *srv_name, uint32 unknown_0,
POLICY_HND *connect_pol)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_CONNECT q_o;
BOOL valid_pol = False;
/* create and send a MSRPC command with api SAMR_CONNECT */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Open Policy server:%s undoc value:%x\n",
srv_name, unknown_0));
if (srv_name == NULL || connect_pol == NULL || fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_connect(&q_o, srv_name, unknown_0);
/* turn parameters into data stream */
samr_io_q_connect("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CONNECT, &data, &rdata))
{
SAMR_R_CONNECT r_o;
BOOL p;
samr_io_r_connect("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_CONNECT: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
memcpy(connect_pol, &r_o.connect_pol, sizeof(r_o.connect_pol));
valid_pol = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_pol;
}
/****************************************************************************
do a SAMR Open User
****************************************************************************/
BOOL do_samr_open_user(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *pol, uint32 unk_0, uint32 rid,
POLICY_HND *user_pol)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_OPEN_USER q_o;
BOOL valid_pol = False;
/* create and send a MSRPC command with api SAMR_OPEN_USER */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Open User. unk_0: %08x RID:%x\n",
unk_0, rid));
if (pol == NULL || user_pol == NULL || fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_open_user(&q_o, pol, unk_0, rid);
/* turn parameters into data stream */
samr_io_q_open_user("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_USER, &data, &rdata))
{
SAMR_R_OPEN_USER r_o;
BOOL p;
samr_io_r_open_user("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_OPEN_USER: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
memcpy(user_pol, &r_o.user_pol, sizeof(r_o.user_pol));
valid_pol = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_pol;
}
/****************************************************************************
do a SAMR Open Domain
****************************************************************************/
BOOL do_samr_open_domain(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *connect_pol, uint32 rid, char *sid,
POLICY_HND *domain_pol)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_OPEN_DOMAIN q_o;
BOOL valid_pol = False;
/* create and send a MSRPC command with api SAMR_OPEN_DOMAIN */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Open Domain. SID:%s RID:%x\n", sid, rid));
if (connect_pol == NULL || sid == NULL || domain_pol == NULL || fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_open_domain(&q_o, connect_pol, rid, sid);
/* turn parameters into data stream */
samr_io_q_open_domain("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_OPEN_DOMAIN, &data, &rdata))
{
SAMR_R_OPEN_DOMAIN r_o;
BOOL p;
samr_io_r_open_domain("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_OPEN_DOMAIN: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
memcpy(domain_pol, &r_o.domain_pol, sizeof(r_o.domain_pol));
valid_pol = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_pol;
}
/****************************************************************************
do a SAMR Query Unknown 12
****************************************************************************/
BOOL do_samr_query_unknown_12(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *pol, uint32 rid, uint32 num_gids, uint32 *gids,
uint32 *num_aliases,
fstring als_names [MAX_LOOKUP_SIDS],
uint32 num_als_users[MAX_LOOKUP_SIDS])
{
prs_struct data;
prs_struct rdata;
SAMR_Q_UNKNOWN_12 q_o;
BOOL valid_query = False;
/* create and send a MSRPC command with api SAMR_UNKNOWN_12 */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Query Unknown 12.\n"));
if (pol == NULL || rid == 0 || num_gids == 0 || gids == NULL ||
num_aliases == NULL || als_names == NULL || num_als_users == NULL ||
fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_unknown_12(&q_o, pol, rid, num_gids, gids);
/* turn parameters into data stream */
samr_io_q_unknown_12("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_UNKNOWN_12, &data, &rdata))
{
SAMR_R_UNKNOWN_12 r_o;
BOOL p;
samr_io_r_unknown_12("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_UNKNOWN_12: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
if (r_o.ptr_aliases != 0 && r_o.ptr_als_usrs != 0 &&
r_o.num_als_usrs1 == r_o.num_aliases1)
{
int i;
valid_query = True;
*num_aliases = r_o.num_aliases1;
for (i = 0; i < r_o.num_aliases1; i++)
{
fstrcpy(als_names[i], unistrn2(r_o.uni_als_name[i].buffer, r_o.uni_als_name[i].uni_str_len));
}
for (i = 0; i < r_o.num_als_usrs1; i++)
{
num_als_users[i] = r_o.num_als_usrs[i];
}
}
else if (r_o.ptr_aliases == 0 && r_o.ptr_als_usrs == 0)
{
valid_query = True;
*num_aliases = 0;
}
else
{
p = False;
}
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_query;
}
/****************************************************************************
do a SAMR Query User Groups
****************************************************************************/
BOOL do_samr_query_usergroups(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *pol, uint32 *num_groups, DOM_GID *gid)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_QUERY_USERGROUPS q_o;
BOOL valid_query = False;
/* create and send a MSRPC command with api SAMR_QUERY_USERGROUPS */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Query User Groups.\n"));
if (pol == NULL || gid == NULL || num_groups == 0|| fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_query_usergroups(&q_o, pol);
/* turn parameters into data stream */
samr_io_q_query_usergroups("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERGROUPS, &data, &rdata))
{
SAMR_R_QUERY_USERGROUPS r_o;
BOOL p;
/* get user info */
r_o.gid = gid;
samr_io_r_query_usergroups("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_QUERY_USERGROUPS: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p && r_o.ptr_0 != 0)
{
valid_query = True;
*num_groups = r_o.num_entries;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_query;
}
/****************************************************************************
do a SAMR Query User Info
****************************************************************************/
BOOL do_samr_query_userinfo(struct cli_state *cli, int t_idx, uint16 fnum,
POLICY_HND *pol, uint16 switch_value, void* usr)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_QUERY_USERINFO q_o;
BOOL valid_query = False;
/* create and send a MSRPC command with api SAMR_QUERY_USERINFO */
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
DEBUG(4,("SAMR Query User Info. level: %d\n", switch_value));
if (pol == NULL || usr == NULL || switch_value == 0|| fnum == 0xffff) return False;
/* store the parameters */
make_samr_q_query_userinfo(&q_o, pol, switch_value);
/* turn parameters into data stream */
samr_io_q_query_userinfo("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_QUERY_USERINFO, &data, &rdata))
{
SAMR_R_QUERY_USERINFO r_o;
BOOL p;
/* get user info */
r_o.info.id = usr;
samr_io_r_query_userinfo("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_R_QUERY_USERINFO: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p && r_o.switch_value != switch_value)
{
DEBUG(0,("SAMR_R_QUERY_USERINFO: received incorrect level %d\n",
r_o.switch_value));
}
if (p && r_o.ptr != 0)
{
valid_query = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_query;
}
/****************************************************************************
do a SAMR Close
****************************************************************************/
BOOL do_samr_close(struct cli_state *cli, int t_idx, uint16 fnum, POLICY_HND *hnd)
{
prs_struct data;
prs_struct rdata;
SAMR_Q_CLOSE_HND q_c;
BOOL valid_close = False;
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
if (hnd == NULL) return False;
/* create and send a MSRPC command with api SAMR_CLOSE_HND */
DEBUG(4,("SAMR Close\n"));
/* store the parameters */
make_samr_q_close_hnd(&q_c, hnd);
/* turn parameters into data stream */
samr_io_q_close_hnd("", &q_c, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SAMR_CLOSE_HND, &data, &rdata))
{
SAMR_R_CLOSE_HND r_c;
BOOL p;
samr_io_r_close_hnd("", &r_c, &rdata, 0);
p = rdata.offset != 0;
if (p && r_c.status != 0)
{
/* report error code */
DEBUG(0,("SAMR_CLOSE_HND: %s\n", get_nt_error_msg(r_c.status)));
p = False;
}
if (p)
{
/* check that the returned policy handle is all zeros */
int i;
valid_close = True;
for (i = 0; i < sizeof(r_c.pol.data); i++)
{
if (r_c.pol.data[i] != 0)
{
valid_close = False;
break;
}
}
if (!valid_close)
{
DEBUG(0,("SAMR_CLOSE_HND: non-zero handle returned\n"));
}
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_close;
}

View File

@ -0,0 +1,411 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
extern int DEBUGLEVEL;
/****************************************************************************
do a server net conn enum
****************************************************************************/
BOOL do_srv_net_srv_conn_enum(struct cli_state *cli, int t_idx, uint16 fnum,
char *server_name, char *qual_name,
uint32 switch_value, SRV_CONN_INFO_CTR *ctr,
uint32 preferred_len,
ENUM_HND *hnd)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_CONN_ENUM q_o;
BOOL valid_enum = False;
if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api SRV_NETCONNENUM */
DEBUG(4,("SRV Net Server Connection Enum(%s, %s), level %d, enum:%8x\n",
server_name, qual_name, switch_value, get_enum_hnd(hnd)));
ctr->switch_value = switch_value;
ctr->ptr_conn_ctr = 1;
ctr->conn.info0.num_entries_read = 0;
ctr->conn.info0.ptr_conn_info = 1;
/* store the parameters */
make_srv_q_net_conn_enum(&q_o, server_name, qual_name,
switch_value, ctr,
preferred_len,
hnd);
/* turn parameters into data stream */
srv_io_q_net_conn_enum("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETCONNENUM, &data, &rdata))
{
SRV_R_NET_CONN_ENUM r_o;
BOOL p;
r_o.ctr = ctr;
srv_io_r_net_conn_enum("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
p = 0;
}
if (p && r_o.ctr->switch_value != switch_value)
{
/* different switch levels. oops. */
DEBUG(0,("SRV_R_NET_SRV_CONN_ENUM: info class %d does not match request %d\n",
r_o.ctr->switch_value, switch_value));
p = 0;
}
if (p)
{
/* ok, at last: we're happy. */
valid_enum = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_enum;
}
/****************************************************************************
do a server net sess enum
****************************************************************************/
BOOL do_srv_net_srv_sess_enum(struct cli_state *cli, int t_idx, uint16 fnum,
char *server_name, char *qual_name,
uint32 switch_value, SRV_SESS_INFO_CTR *ctr,
uint32 preferred_len,
ENUM_HND *hnd)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_SESS_ENUM q_o;
BOOL valid_enum = False;
if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api SRV_NETSESSENUM */
DEBUG(4,("SRV Net Session Enum (%s), level %d, enum:%8x\n",
server_name, switch_value, get_enum_hnd(hnd)));
ctr->switch_value = switch_value;
ctr->ptr_sess_ctr = 1;
ctr->sess.info0.num_entries_read = 0;
ctr->sess.info0.ptr_sess_info = 1;
/* store the parameters */
make_srv_q_net_sess_enum(&q_o, server_name, qual_name,
switch_value, ctr,
preferred_len,
hnd);
/* turn parameters into data stream */
srv_io_q_net_sess_enum("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETSESSENUM, &data, &rdata))
{
SRV_R_NET_SESS_ENUM r_o;
BOOL p;
r_o.ctr = ctr;
srv_io_r_net_sess_enum("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
p = 0;
}
if (p && r_o.ctr->switch_value != switch_value)
{
/* different switch levels. oops. */
DEBUG(0,("SRV_R_NET_SRV_SESS_ENUM: info class %d does not match request %d\n",
r_o.ctr->switch_value, switch_value));
p = 0;
}
if (p)
{
/* ok, at last: we're happy. */
valid_enum = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_enum;
}
/****************************************************************************
do a server net share enum
****************************************************************************/
BOOL do_srv_net_srv_share_enum(struct cli_state *cli, int t_idx, uint16 fnum,
char *server_name,
uint32 switch_value, SRV_SHARE_INFO_CTR *ctr,
uint32 preferred_len,
ENUM_HND *hnd)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_SHARE_ENUM q_o;
BOOL valid_enum = False;
if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api SRV_NETSHAREENUM */
DEBUG(4,("SRV Get Share Info (%s), level %d, enum:%8x\n",
server_name, switch_value, get_enum_hnd(hnd)));
q_o.share_level = switch_value;
ctr->switch_value = switch_value;
ctr->ptr_share_ctr = 1;
ctr->share.info1.num_entries_read = 0;
ctr->share.info1.ptr_share_info = 1;
/* store the parameters */
make_srv_q_net_share_enum(&q_o, server_name,
switch_value, ctr,
preferred_len,
hnd);
/* turn parameters into data stream */
srv_io_q_net_share_enum("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETSHAREENUM, &data, &rdata))
{
SRV_R_NET_SHARE_ENUM r_o;
BOOL p;
r_o.ctr = ctr;
srv_io_r_net_share_enum("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
p = 0;
}
if (p && r_o.ctr->switch_value != switch_value)
{
/* different switch levels. oops. */
DEBUG(0,("SRV_R_NET_SRV_SHARE_ENUM: info class %d does not match request %d\n",
r_o.ctr->switch_value, switch_value));
p = 0;
}
if (p)
{
/* ok, at last: we're happy. */
valid_enum = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_enum;
}
/****************************************************************************
do a server net file enum
****************************************************************************/
BOOL do_srv_net_srv_file_enum(struct cli_state *cli, int t_idx, uint16 fnum,
char *server_name, char *qual_name,
uint32 switch_value, SRV_FILE_INFO_CTR *ctr,
uint32 preferred_len,
ENUM_HND *hnd)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_FILE_ENUM q_o;
BOOL valid_enum = False;
if (server_name == NULL || ctr == NULL || preferred_len == 0) return False;
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api SRV_NETFILEENUM */
DEBUG(4,("SRV Get File Info (%s), level %d, enum:%8x\n",
server_name, switch_value, get_enum_hnd(hnd)));
q_o.file_level = switch_value;
ctr->switch_value = switch_value;
ctr->ptr_file_ctr = 1;
ctr->file.info3.num_entries_read = 0;
ctr->file.info3.ptr_file_info = 1;
/* store the parameters */
make_srv_q_net_file_enum(&q_o, server_name, qual_name,
switch_value, ctr,
preferred_len,
hnd);
/* turn parameters into data stream */
srv_io_q_net_file_enum("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NETFILEENUM, &data, &rdata))
{
SRV_R_NET_FILE_ENUM r_o;
BOOL p;
r_o.ctr = ctr;
srv_io_r_net_file_enum("", &r_o, &rdata, 0);
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
p = 0;
}
if (p && r_o.ctr->switch_value != switch_value)
{
/* different switch levels. oops. */
DEBUG(0,("SRV_R_NET_SRV_FILE_ENUM: info class %d does not match request %d\n",
r_o.ctr->switch_value, switch_value));
p = 0;
}
if (p)
{
/* ok, at last: we're happy. */
valid_enum = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_enum;
}
/****************************************************************************
do a server get info
****************************************************************************/
BOOL do_srv_net_srv_get_info(struct cli_state *cli, int t_idx, uint16 fnum,
char *server_name, uint32 switch_value, SRV_INFO_CTR *ctr)
{
prs_struct data;
prs_struct rdata;
SRV_Q_NET_SRV_GET_INFO q_o;
BOOL valid_info = False;
if (server_name == NULL || switch_value == 0 || ctr == NULL) return False;
prs_init(&data , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rdata, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api SRV_NET_SRV_GET_INFO */
DEBUG(4,("SRV Get Server Info (%s), level %d\n", server_name, switch_value));
/* store the parameters */
make_srv_q_net_srv_get_info(&q_o, server_name, switch_value);
/* turn parameters into data stream */
srv_io_q_net_srv_get_info("", &q_o, &data, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, SRV_NET_SRV_GET_INFO, &data, &rdata))
{
SRV_R_NET_SRV_GET_INFO r_o;
BOOL p;
r_o.ctr = ctr;
srv_io_r_net_srv_get_info("", &r_o, &rdata, 0);
p = rdata.offset != 0;
p = rdata.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("SRV_R_NET_SRV_GET_INFO: %s\n", get_nt_error_msg(r_o.status)));
p = 0;
}
if (p && r_o.ctr->switch_value != q_o.switch_value)
{
/* different switch levels. oops. */
DEBUG(0,("SRV_R_NET_SRV_GET_INFO: info class %d does not match request %d\n",
r_o.ctr->switch_value, q_o.switch_value));
p = 0;
}
if (p)
{
/* ok, at last: we're happy. */
valid_info = True;
}
}
prs_mem_free(&data );
prs_mem_free(&rdata );
return valid_info;
}

View File

@ -0,0 +1,90 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
extern int DEBUGLEVEL;
/****************************************************************************
do a WKS Open Policy
****************************************************************************/
BOOL do_wks_query_info(struct cli_state *cli, int t_idx, uint16 fnum,
char *server_name, uint32 switch_value,
WKS_INFO_100 *wks100)
{
prs_struct rbuf;
prs_struct buf;
WKS_Q_QUERY_INFO q_o;
BOOL valid_info = False;
if (server_name == 0 || wks100 == NULL) return False;
prs_init(&buf , 1024, 4, SAFETY_MARGIN, False);
prs_init(&rbuf, 0 , 4, SAFETY_MARGIN, True );
/* create and send a MSRPC command with api WKS_QUERY_INFO */
DEBUG(4,("WKS Query Info\n"));
/* store the parameters */
make_wks_q_query_info(&q_o, server_name, switch_value);
/* turn parameters into data stream */
wks_io_q_query_info("", &q_o, &buf, 0);
/* send the data on \PIPE\ */
if (rpc_api_pipe_req(cli, t_idx, fnum, WKS_QUERY_INFO, &buf, &rbuf))
{
WKS_R_QUERY_INFO r_o;
BOOL p;
r_o.wks100 = wks100;
wks_io_r_query_info("", &r_o, &rbuf, 0);
p = rbuf.offset != 0;
if (p && r_o.status != 0)
{
/* report error code */
DEBUG(0,("WKS_R_QUERY_INFO: %s\n", get_nt_error_msg(r_o.status)));
p = False;
}
if (p)
{
valid_info = True;
}
}
prs_mem_free(&rbuf);
prs_mem_free(&buf );
return valid_info;
}

View File

@ -0,0 +1,167 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
NT Domain Authentication SMB / MSRPC client
Copyright (C) Andrew Tridgell 1994-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
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.
*/
#ifdef SYSLOG
#undef SYSLOG
#endif
#include "includes.h"
#include "nterr.h"
extern int DEBUGLEVEL;
/************************************************************************
check workstation trust account status
************************************************************************/
BOOL trust_account_check(struct in_addr dest_ip, char *dest_host,
char *myhostname, char *domain, fstring mach_acct,
fstring new_mach_pwd)
{
pstring tmp;
fstring mach_pwd;
struct cli_state cli_trust;
uchar lm_owf_mach_pwd[16];
uchar nt_owf_mach_pwd[16];
uchar lm_sess_pwd[24];
uchar nt_sess_pwd[24];
BOOL right_error_code = False;
uint8 err_cls;
uint32 err_num;
char *start_mach_pwd;
char *change_mach_pwd;
/* initial machine password */
fstrcpy(mach_pwd, myhostname);
strlower(mach_pwd);
sprintf(tmp, "Enter Workstation Trust Account password for [%s].\nDefault is [%s].\nPassword:",
mach_acct, mach_pwd);
start_mach_pwd = (char*)getpass(tmp);
if (start_mach_pwd[0] != 0)
{
fstrcpy(mach_pwd, start_mach_pwd);
}
sprintf(tmp, "Enter new Workstation Trust Account password for [%s]\nPress Return to leave at old value.\nNew Password:",
mach_acct);
change_mach_pwd = (char*)getpass(tmp);
if (change_mach_pwd[0] != 0)
{
fstrcpy(new_mach_pwd, change_mach_pwd);
}
else
{
DEBUG(1,("trust_account_check: password change not requested\n"));
change_mach_pwd[0] = 0;
}
DEBUG(1,("initialise cli_trust connection\n"));
if (!cli_initialise(&cli_trust))
{
DEBUG(1,("cli_initialise failed for cli_trust\n"));
return False;
}
DEBUG(1,("server connect for cli_trust\n"));
if (!server_connect_init(&cli_trust, myhostname, dest_ip, dest_host))
{
cli_error(&cli_trust, &err_cls, &err_num);
DEBUG(1,("server_connect_init failed (%s)\n", cli_errstr(&cli_trust)));
cli_shutdown(&cli_trust);
return False;
}
DEBUG(1,("server connect cli_trust succeeded\n"));
nt_lm_owf_gen(mach_pwd, nt_owf_mach_pwd, lm_owf_mach_pwd);
DEBUG(5,("generating nt owf from initial machine pwd: %s\n", mach_pwd));
#ifdef DEBUG_PASSWORD
DEBUG(100,("client cryptkey: "));
dump_data(100, cli_trust.cryptkey, sizeof(cli_trust.cryptkey));
#endif
SMBencrypt(nt_owf_mach_pwd, cli_trust.cryptkey, nt_sess_pwd);
#ifdef DEBUG_PASSWORD
DEBUG(100,("nt_owf_mach_pwd: "));
dump_data(100, nt_owf_mach_pwd, sizeof(lm_owf_mach_pwd));
DEBUG(100,("nt_sess_pwd: "));
dump_data(100, nt_sess_pwd, sizeof(nt_sess_pwd));
#endif
SMBencrypt(lm_owf_mach_pwd, cli_trust.cryptkey, lm_sess_pwd);
#ifdef DEBUG_PASSWORD
DEBUG(100,("lm_owf_mach_pwd: "));
dump_data(100, lm_owf_mach_pwd, sizeof(lm_owf_mach_pwd));
DEBUG(100,("lm_sess_pwd: "));
dump_data(100, lm_sess_pwd, sizeof(lm_sess_pwd));
#endif
right_error_code = False;
if (cli_session_setup(&cli_trust, mach_acct,
nt_owf_mach_pwd, sizeof(nt_owf_mach_pwd),
nt_owf_mach_pwd, sizeof(nt_owf_mach_pwd), domain))
{
DEBUG(0,("cli_session_setup: NO ERROR! AAAGH! BUG IN SERVER DETECTED!!!\n"));
cli_shutdown(&cli_trust);
return False;
}
cli_error(&cli_trust, &err_cls, &err_num);
if (err_num == (0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT))
{
DEBUG(1,("cli_send_tconX: valid workstation trust account exists\n"));
right_error_code = True;
}
if (err_num == (0xC0000000 | NT_STATUS_NO_SUCH_USER))
{
DEBUG(1,("cli_send_tconX: workstation trust account does not exist\n"));
right_error_code = False;
}
if (!right_error_code)
{
DEBUG(1,("server_validate failed (%s)\n", cli_errstr(&cli_trust)));
}
cli_shutdown(&cli_trust);
return right_error_code;
}

View File

@ -0,0 +1,567 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
#include "nterr.h"
extern int DEBUGLEVEL;
/*******************************************************************
creates a LSA_TRANS_NAME structure.
********************************************************************/
void make_lsa_trans_name(LSA_TRANS_NAME *trn, uint32 sid_name_use, char *name, uint32 idx)
{
int len_name = strlen(name);
trn->sid_name_use = sid_name_use;
make_uni_hdr(&(trn->hdr_name), len_name, len_name, len_name != 0);
make_unistr2(&(trn->uni_name), name, len_name);
trn->domain_idx = idx;
}
/*******************************************************************
reads or writes a LSA_TRANS_NAME structure.
********************************************************************/
void lsa_io_trans_name(char *desc, LSA_TRANS_NAME *trn, prs_struct *ps, int depth)
{
if (trn == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_trans_name");
depth++;
prs_align(ps);
prs_uint32("sid_name_use", ps, depth, &(trn->sid_name_use));
smb_io_unihdr ("hdr_name", &(trn->hdr_name), ps, depth);
smb_io_unistr2("uni_name", &(trn->uni_name), trn->hdr_name.buffer, ps, depth);
prs_uint32("domain_idx ", ps, depth, &(trn->domain_idx ));
}
/*******************************************************************
reads or writes a DOM_R_REF structure.
********************************************************************/
void lsa_io_dom_r_ref(char *desc, DOM_R_REF *r_r, prs_struct *ps, int depth)
{
int i;
prs_debug(ps, depth, desc, "smb_io_dom_r_ref");
depth++;
if (r_r == NULL) return;
prs_align(ps);
prs_uint32("undoc_buffer ", ps, depth, &(r_r->undoc_buffer)); /* undocumented buffer pointer. */
prs_uint32("num_ref_doms_1 ", ps, depth, &(r_r->num_ref_doms_1)); /* num referenced domains? */
prs_uint32("buffer_dom_name", ps, depth, &(r_r->buffer_dom_name)); /* undocumented domain name buffer pointer. */
prs_uint32("max_entries ", ps, depth, &(r_r->max_entries)); /* 32 - max number of entries */
prs_uint32("num_ref_doms_2 ", ps, depth, &(r_r->num_ref_doms_2)); /* 4 - num referenced domains? */
smb_io_unihdr2("", &(r_r->hdr_dom_name), ps, depth); /* domain name unicode string header */
for (i = 0; i < r_r->num_ref_doms_1-1; i++)
{
smb_io_unihdr2("", &(r_r->hdr_ref_dom[i]), ps, depth);
}
smb_io_unistr("", &(r_r->uni_dom_name), ps, depth); /* domain name unicode string */
for (i = 0; i < r_r->num_ref_doms_2; i++)
{
smb_io_dom_sid2("", &(r_r->ref_dom[i]), ps, depth); /* referenced domain SIDs */
}
}
/*******************************************************************
makes an LSA_OBJ_ATTR structure.
********************************************************************/
void make_lsa_obj_attr(LSA_OBJ_ATTR *attr, uint32 attributes, uint32 sec_qos)
{
if (attr == NULL) return;
DEBUG(5,("make_lsa_obj_attr\n"));
attr->len = 0x18; /* length of object attribute block, in bytes */
attr->ptr_root_dir = 0;
attr->ptr_obj_name = 0;
attr->attributes = attributes;
attr->ptr_sec_desc = 0;
attr->sec_qos = sec_qos;
}
/*******************************************************************
reads or writes an LSA_OBJ_ATTR structure.
********************************************************************/
void lsa_io_obj_attr(char *desc, LSA_OBJ_ATTR *attr, prs_struct *ps, int depth)
{
int start;
if (attr == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_obj_attr");
depth++;
prs_align(ps);
start = ps->offset;
/* these pointers had _better_ be zero, because we don't know
what they point to!
*/
prs_uint32("len" , ps, depth, &(attr->len )); /* 0x18 - length (in bytes) inc. the length field. */
prs_uint32("ptr_root_dir", ps, depth, &(attr->ptr_root_dir)); /* 0 - root directory (pointer) */
prs_uint32("ptr_obj_name", ps, depth, &(attr->ptr_obj_name)); /* 0 - object name (pointer) */
prs_uint32("attributes" , ps, depth, &(attr->attributes )); /* 0 - attributes (undocumented) */
prs_uint32("ptr_sec_desc", ps, depth, &(attr->ptr_sec_desc)); /* 0 - security descriptior (pointer) */
prs_uint32("sec_qos" , ps, depth, &(attr->sec_qos )); /* 0 - security quality of service */
if (attr->len != ps->offset - start)
{
DEBUG(3,("lsa_io_obj_attr: length %lx does not match size %lx\n",
attr->len, ps->offset - start));
}
}
/*******************************************************************
makes an LSA_Q_OPEN_POL structure.
********************************************************************/
void make_q_open_pol(LSA_Q_OPEN_POL *r_q, char *server_name,
uint32 attributes, uint32 sec_qos,
uint32 desired_access)
{
if (r_q == NULL) return;
DEBUG(5,("make_open_pol\n"));
r_q->ptr = 1; /* undocumented pointer */
make_unistr2 (&(r_q->uni_server_name), server_name, strlen(server_name));
make_lsa_obj_attr(&(r_q->attr ), attributes, sec_qos);
r_q->des_access = desired_access;
}
/*******************************************************************
reads or writes an LSA_Q_OPEN_POL structure.
********************************************************************/
void lsa_io_q_open_pol(char *desc, LSA_Q_OPEN_POL *r_q, prs_struct *ps, int depth)
{
if (r_q == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_q_open_pol");
depth++;
prs_uint32("ptr ", ps, depth, &(r_q->ptr ));
smb_io_unistr2 ("", &(r_q->uni_server_name), r_q->ptr, ps, depth);
lsa_io_obj_attr("", &(r_q->attr ), ps, depth);
prs_uint32("des_access", ps, depth, &(r_q->des_access));
}
/*******************************************************************
reads or writes an LSA_R_OPEN_POL structure.
********************************************************************/
void lsa_io_r_open_pol(char *desc, LSA_R_OPEN_POL *r_p, prs_struct *ps, int depth)
{
if (r_p == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_r_open_pol");
depth++;
smb_io_pol_hnd("", &(r_p->pol), ps, depth);
prs_uint32("status", ps, depth, &(r_p->status));
}
/*******************************************************************
makes an LSA_Q_QUERY_INFO structure.
********************************************************************/
void make_q_query(LSA_Q_QUERY_INFO *q_q, POLICY_HND *hnd, uint16 info_class)
{
if (q_q == NULL || hnd == NULL) return;
DEBUG(5,("make_q_query\n"));
memcpy(&(q_q->pol), hnd, sizeof(q_q->pol));
q_q->info_class = info_class;
}
/*******************************************************************
reads or writes an LSA_Q_QUERY_INFO structure.
********************************************************************/
void lsa_io_q_query(char *desc, LSA_Q_QUERY_INFO *q_q, prs_struct *ps, int depth)
{
if (q_q == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_q_query");
depth++;
smb_io_pol_hnd("", &(q_q->pol), ps, depth);
prs_uint16("info_class", ps, depth, &(q_q->info_class));
}
/*******************************************************************
reads or writes an LSA_Q_ENUM_TRUST_DOM structure.
********************************************************************/
void lsa_io_q_enum_trust_dom(char *desc, LSA_Q_ENUM_TRUST_DOM *q_e, prs_struct *ps, int depth)
{
if (q_e == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_q_enum_trust_dom");
depth++;
smb_io_pol_hnd("", &(q_e->pol), ps, depth);
prs_uint32("enum_context ", ps, depth, &(q_e->enum_context ));
prs_uint32("preferred_len", ps, depth, &(q_e->preferred_len));
}
/*******************************************************************
makes an LSA_R_ENUM_TRUST_DOM structure.
********************************************************************/
void make_r_enum_trust_dom(LSA_R_ENUM_TRUST_DOM *r_e,
uint32 enum_context, char *domain_name, char *domain_sid,
uint32 status)
{
if (r_e == NULL) return;
DEBUG(5,("make_r_enum_trust_dom\n"));
r_e->enum_context = enum_context;
if (status == 0)
{
int len_domain_name = strlen(domain_name);
r_e->num_domains = 1;
r_e->ptr_enum_domains = 1;
r_e->num_domains2 = 1;
make_uni_hdr2(&(r_e->hdr_domain_name ), len_domain_name, len_domain_name, 4);
make_unistr2 (&(r_e->uni_domain_name ), domain_name, len_domain_name);
make_dom_sid2(&(r_e->other_domain_sid), domain_sid);
}
else
{
r_e->num_domains = 0;
r_e->ptr_enum_domains = 0;
}
r_e->status = status;
}
/*******************************************************************
reads or writes an LSA_R_ENUM_TRUST_DOM structure.
********************************************************************/
void lsa_io_r_enum_trust_dom(char *desc, LSA_R_ENUM_TRUST_DOM *r_e, prs_struct *ps, int depth)
{
if (r_e == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_r_enum_trust_dom");
depth++;
prs_uint32("enum_context ", ps, depth, &(r_e->enum_context ));
prs_uint32("num_domains ", ps, depth, &(r_e->num_domains ));
prs_uint32("ptr_enum_domains", ps, depth, &(r_e->ptr_enum_domains));
if (r_e->ptr_enum_domains != 0)
{
prs_uint32("num_domains2", ps, depth, &(r_e->num_domains2));
smb_io_unihdr2 ("", &(r_e->hdr_domain_name ), ps, depth);
smb_io_unistr2 ("", &(r_e->uni_domain_name ), r_e->hdr_domain_name.buffer, ps, depth);
smb_io_dom_sid2("", &(r_e->other_domain_sid), ps, depth);
}
prs_uint32("status", ps, depth, &(r_e->status));
}
/*******************************************************************
makes an LSA_Q_CLOSE structure.
********************************************************************/
void make_lsa_q_close(LSA_Q_CLOSE *q_c, POLICY_HND *hnd)
{
if (q_c == NULL || hnd == NULL) return;
DEBUG(5,("make_lsa_q_close\n"));
memcpy(&(q_c->pol), hnd, sizeof(q_c->pol));
}
/*******************************************************************
reads or writes an LSA_Q_CLOSE structure.
********************************************************************/
void lsa_io_q_close(char *desc, LSA_Q_CLOSE *q_c, prs_struct *ps, int depth)
{
if (q_c == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_q_close");
depth++;
smb_io_pol_hnd("", &(q_c->pol), ps, depth);
}
/*******************************************************************
makes an LSA_R_CLOSE structure.
********************************************************************/
void make_lsa_r_close(LSA_R_CLOSE *q_r, POLICY_HND *hnd)
{
if (q_r == NULL || hnd == NULL) return;
DEBUG(5,("make_lsa_r_close\n"));
memcpy(&(q_r->pol), hnd, sizeof(q_r->pol));
}
/*******************************************************************
reads or writes an LSA_R_CLOSE structure.
********************************************************************/
void lsa_io_r_close(char *desc, LSA_R_CLOSE *r_c, prs_struct *ps, int depth)
{
if (r_c == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_r_close");
depth++;
smb_io_pol_hnd("", &(r_c->pol), ps, depth);
prs_uint32("status", ps, depth, &(r_c->status));
}
/*******************************************************************
reads or writes an LSA_Q_QUERY_INFO structure.
********************************************************************/
void lsa_io_r_query(char *desc, LSA_R_QUERY_INFO *r_q, prs_struct *ps, int depth)
{
if (r_q == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_r_query");
depth++;
prs_uint32("undoc_buffer", ps, depth, &(r_q->undoc_buffer));
if (r_q->undoc_buffer != 0)
{
prs_uint16("info_class", ps, depth, &(r_q->info_class));
switch (r_q->info_class)
{
case 3:
{
smb_io_dom_query_3("", &(r_q->dom.id3), ps, depth);
break;
}
case 5:
{
smb_io_dom_query_5("", &(r_q->dom.id3), ps, depth);
break;
}
default:
{
/* PANIC! */
break;
}
}
}
prs_uint32("status", ps, depth, &(r_q->status));
}
/*******************************************************************
reads or writes a LSA_SID_ENUM structure.
********************************************************************/
void lsa_io_sid_enum(char *desc, LSA_SID_ENUM *sen, prs_struct *ps, int depth)
{
int i;
if (sen == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_sid_enum");
depth++;
prs_align(ps);
prs_uint32("num_entries ", ps, depth, &(sen->num_entries));
prs_uint32("ptr_sid_enum", ps, depth, &(sen->ptr_sid_enum));
prs_uint32("num_entries2", ps, depth, &(sen->num_entries2));
for (i = 0; i < sen->num_entries; i++)
{
fstring temp;
sprintf(temp, "ptr_sid[%d]", i);
prs_uint32(temp, ps, depth, &(sen->ptr_sid[i])); /* domain SID pointers to be looked up. */
}
for (i = 0; i < sen->num_entries; i++)
{
fstring temp;
sprintf(temp, "sid[%d]", i);
smb_io_dom_sid2(temp, &(sen->sid[i]), ps, depth); /* domain SIDs to be looked up. */
}
}
/*******************************************************************
reads or writes a LSA_Q_LOOKUP_SIDS structure.
********************************************************************/
void lsa_io_q_lookup_sids(char *desc, LSA_Q_LOOKUP_SIDS *q_s, prs_struct *ps, int depth)
{
if (q_s == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_q_lookup_sids");
depth++;
prs_align(ps);
smb_io_pol_hnd ("pol_hnd", &(q_s->pol_hnd), ps, depth); /* policy handle */
lsa_io_sid_enum ("sids ", &(q_s->sids ), ps, depth); /* sids to be looked up */
lsa_io_trans_names ("names ", &(q_s->names ), ps, depth); /* translated names */
smb_io_lookup_level("switch ", &(q_s->level ), ps, depth); /* lookup level */
prs_uint32("mapped_count", ps, depth, &(q_s->mapped_count));
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void lsa_io_trans_names(char *desc, LSA_TRANS_NAME_ENUM *trn, prs_struct *ps, int depth)
{
int i;
int i2;
if (trn == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_trans_names");
depth++;
prs_align(ps);
prs_uint32("num_entries ", ps, depth, &(trn->num_entries));
prs_uint32("ptr_trans_names", ps, depth, &(trn->ptr_trans_names));
prs_uint32("num_entries2 ", ps, depth, &(trn->num_entries2));
for (i = 0; i < trn->num_entries; i++)
{
fstring temp;
sprintf(temp, "ptr_name[%d] ", i);
prs_uint32(temp, ps, depth, &(trn->ptr_name[i])); /* pointer to translated name */
}
for (i = 0; i < trn->num_entries2; i++)
{
if (trn->ptr_name[i] != 0)
{
fstring temp;
sprintf(temp, "name[%d] ", i);
lsa_io_trans_name(temp, &(trn->name[i2]), ps, depth); /* translated name */
i2++;
}
}
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void lsa_io_r_lookup_sids(char *desc, LSA_R_LOOKUP_SIDS *r_s, prs_struct *ps, int depth)
{
if (r_s == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_r_lookup_sids");
depth++;
prs_align(ps);
lsa_io_dom_r_ref ("dom_ref", r_s->dom_ref, ps, depth); /* domain reference info */
lsa_io_trans_names("names ", r_s->names , ps, depth); /* translated names */
prs_uint32("mapped_count", ps, depth, &(r_s->mapped_count));
prs_uint32("status ", ps, depth, &(r_s->status));
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void lsa_io_q_lookup_rids(char *desc, LSA_Q_LOOKUP_RIDS *q_r, prs_struct *ps, int depth)
{
int i;
if (q_r == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_q_lookup_rids");
depth++;
prs_align(ps);
smb_io_pol_hnd("", &(q_r->pol_hnd), ps, depth); /* policy handle */
prs_uint32("num_entries ", ps, depth, &(q_r->num_entries));
prs_uint32("num_entries2 ", ps, depth, &(q_r->num_entries2));
prs_uint32("buffer_dom_sid ", ps, depth, &(q_r->buffer_dom_sid)); /* undocumented domain SID buffer pointer */
prs_uint32("buffer_dom_name", ps, depth, &(q_r->buffer_dom_name)); /* undocumented domain name buffer pointer */
for (i = 0; i < q_r->num_entries; i++)
{
smb_io_dom_name("", &(q_r->lookup_name[i]), ps, depth); /* names to be looked up */
}
prs_uint8s (False, "undoc ", ps, depth, q_r->undoc, UNKNOWN_LEN);
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void lsa_io_r_lookup_rids(char *desc, LSA_R_LOOKUP_RIDS *r_r, prs_struct *ps, int depth)
{
int i;
if (r_r == NULL) return;
prs_debug(ps, depth, desc, "lsa_io_r_lookup_rids");
depth++;
prs_align(ps);
lsa_io_dom_r_ref("", &(r_r->dom_ref), ps, depth); /* domain reference info */
prs_uint32("num_entries ", ps, depth, &(r_r->num_entries));
prs_uint32("undoc_buffer", ps, depth, &(r_r->undoc_buffer));
prs_uint32("num_entries2", ps, depth, &(r_r->num_entries2));
for (i = 0; i < r_r->num_entries2; i++)
{
smb_io_dom_rid2("", &(r_r->dom_rid[i]), ps, depth); /* domain RIDs being looked up */
}
prs_uint32("num_entries3", ps, depth, &(r_r->num_entries3));
prs_uint32("status ", ps, depth, &(r_r->status));
}

View File

@ -0,0 +1,981 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
extern int DEBUGLEVEL;
/*******************************************************************
reads or writes a UTIME type.
********************************************************************/
void smb_io_utime(char *desc, UTIME *t, prs_struct *ps, int depth)
{
if (t == NULL) return;
prs_debug(ps, depth, desc, "smb_io_utime");
depth++;
prs_align(ps);
prs_uint32 ("time", ps, depth, &(t->time));
}
/*******************************************************************
reads or writes an NTTIME structure.
********************************************************************/
void smb_io_time(char *desc, NTTIME *nttime, prs_struct *ps, int depth)
{
if (nttime == NULL) return;
prs_debug(ps, depth, desc, "smb_io_time");
depth++;
prs_align(ps);
prs_uint32("low ", ps, depth, &(nttime->low )); /* low part */
prs_uint32("high", ps, depth, &(nttime->high)); /* high part */
}
/*******************************************************************
reads or writes a LOOKUP_LEVEL structure.
********************************************************************/
void smb_io_lookup_level(char *desc, LOOKUP_LEVEL *level, prs_struct *ps, int depth)
{
if (level == NULL) return;
prs_debug(ps, depth, desc, "smb_io_lookup_level");
depth++;
prs_align(ps);
prs_uint16("value", ps, depth, &(level->value));
prs_align(ps);
}
/*******************************************************************
gets an enumeration handle from an ENUM_HND structure.
********************************************************************/
uint32 get_enum_hnd(ENUM_HND *enh)
{
return (enh && enh->ptr_hnd != 0) ? enh->handle : 0;
}
/*******************************************************************
makes an ENUM_HND structure.
********************************************************************/
void make_enum_hnd(ENUM_HND *enh, uint32 hnd)
{
if (enh == NULL) return;
DEBUG(5,("smb_io_enum_hnd\n"));
enh->ptr_hnd = (hnd != 0) ? 1 : 0;
enh->handle = hnd;
}
/*******************************************************************
reads or writes an ENUM_HND structure.
********************************************************************/
void smb_io_enum_hnd(char *desc, ENUM_HND *hnd, prs_struct *ps, int depth)
{
if (hnd == NULL) return;
prs_debug(ps, depth, desc, "smb_io_enum_hnd");
depth++;
prs_align(ps);
prs_uint32("ptr_hnd", ps, depth, &(hnd->ptr_hnd)); /* pointer */
if (hnd->ptr_hnd != 0)
{
prs_uint32("handle ", ps, depth, &(hnd->handle )); /* enum handle */
}
}
/*******************************************************************
creates a DOM_SID structure.
BIG NOTE: this function only does SIDS where the identauth is not >= 2^32
identauth >= 2^32 can be detected because it will be specified in hex
********************************************************************/
void make_dom_sid(DOM_SID *sid, char *str_sid)
{
pstring domsid;
int identauth;
char *p;
if (sid == NULL) return;
if (domsid == NULL)
{
DEBUG(4,("netlogon domain SID: none\n"));
sid->sid_rev_num = 0;
sid->num_auths = 0;
return;
}
pstrcpy(domsid, str_sid);
DEBUG(4,("make_dom_sid %d SID: %s\n", __LINE__, domsid));
/* assume, but should check, that domsid starts "S-" */
p = strtok(domsid+2,"-");
sid->sid_rev_num = atoi(p);
/* identauth in decimal should be < 2^32 */
/* identauth in hex should be >= 2^32 */
identauth = atoi(strtok(0,"-"));
DEBUG(4,("netlogon rev %d\n", sid->sid_rev_num));
DEBUG(4,("netlogon %s ia %d\n", p, identauth));
sid->id_auth[0] = 0;
sid->id_auth[1] = 0;
sid->id_auth[2] = (identauth & 0xff000000) >> 24;
sid->id_auth[3] = (identauth & 0x00ff0000) >> 16;
sid->id_auth[4] = (identauth & 0x0000ff00) >> 8;
sid->id_auth[5] = (identauth & 0x000000ff);
sid->num_auths = 0;
while ((p = strtok(0, "-")) != NULL && sid->num_auths < MAXSUBAUTHS)
{
sid->sub_auths[sid->num_auths++] = atoi(p);
}
DEBUG(4,("make_dom_sid: %d SID: %s\n", __LINE__, domsid));
}
/*******************************************************************
reads or writes a DOM_SID structure.
********************************************************************/
void smb_io_dom_sid(char *desc, DOM_SID *sid, prs_struct *ps, int depth)
{
int i;
if (sid == NULL) return;
prs_debug(ps, depth, desc, "smb_io_dom_sid");
depth++;
prs_align(ps);
prs_uint8 ("sid_rev_num", ps, depth, &(sid->sid_rev_num));
prs_uint8 ("num_auths ", ps, depth, &(sid->num_auths));
for (i = 0; i < 6; i++)
{
fstring tmp;
sprintf(tmp, "id_auth[%d] ", i);
prs_uint8 (tmp, ps, depth, &(sid->id_auth[i]));
}
/* oops! XXXX should really issue a warning here... */
if (sid->num_auths > MAXSUBAUTHS) sid->num_auths = MAXSUBAUTHS;
prs_uint32s(False, "sub_auths ", ps, depth, sid->sub_auths, sid->num_auths);
}
/*******************************************************************
creates a DOM_SID2 structure.
********************************************************************/
void make_dom_sid2(DOM_SID2 *sid, char *str_sid)
{
make_dom_sid(&(sid->sid), str_sid);
sid->num_auths = sid->sid.num_auths;
}
/*******************************************************************
reads or writes a DOM_SID2 structure.
********************************************************************/
void smb_io_dom_sid2(char *desc, DOM_SID2 *sid, prs_struct *ps, int depth)
{
if (sid == NULL) return;
prs_debug(ps, depth, desc, "smb_io_dom_sid2");
depth++;
prs_align(ps);
prs_uint32("num_auths", ps, depth, &(sid->num_auths));
smb_io_dom_sid("sid", &(sid->sid), ps, depth);
}
/*******************************************************************
creates a STRHDR structure.
********************************************************************/
void make_str_hdr(STRHDR *hdr, int max_len, int len, uint32 buffer)
{
hdr->str_max_len = max_len;
hdr->str_str_len = len;
hdr->buffer = buffer;
}
/*******************************************************************
reads or writes a STRHDR structure.
********************************************************************/
void smb_io_strhdr(char *desc, STRHDR *hdr, prs_struct *ps, int depth)
{
if (hdr == NULL) return;
prs_debug(ps, depth, desc, "smb_io_strhdr");
depth++;
prs_align(ps);
prs_uint16("str_str_len", ps, depth, &(hdr->str_str_len));
prs_uint16("str_max_len", ps, depth, &(hdr->str_max_len));
prs_uint32("buffer ", ps, depth, &(hdr->buffer ));
/* oops! XXXX maybe issue a warning that this is happening... */
if (hdr->str_max_len > MAX_STRINGLEN) hdr->str_max_len = MAX_STRINGLEN;
if (hdr->str_str_len > MAX_STRINGLEN) hdr->str_str_len = MAX_STRINGLEN;
}
/*******************************************************************
creates a UNIHDR structure.
********************************************************************/
void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint32 buffer)
{
hdr->uni_max_len = 2 * max_len;
hdr->uni_str_len = 2 * len;
hdr->buffer = buffer;
}
/*******************************************************************
reads or writes a UNIHDR structure.
********************************************************************/
void smb_io_unihdr(char *desc, UNIHDR *hdr, prs_struct *ps, int depth)
{
if (hdr == NULL) return;
prs_debug(ps, depth, desc, "smb_io_unihdr");
depth++;
prs_align(ps);
prs_uint16("uni_str_len", ps, depth, &(hdr->uni_str_len));
prs_uint16("uni_max_len", ps, depth, &(hdr->uni_max_len));
prs_uint32("buffer ", ps, depth, &(hdr->buffer ));
/* oops! XXXX maybe issue a warning that this is happening... */
if (hdr->uni_max_len > MAX_UNISTRLEN) hdr->uni_max_len = MAX_UNISTRLEN;
if (hdr->uni_str_len > MAX_UNISTRLEN) hdr->uni_str_len = MAX_UNISTRLEN;
}
/*******************************************************************
creates a UNIHDR2 structure.
********************************************************************/
void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate)
{
make_uni_hdr(&(hdr->unihdr), max_len, len, terminate);
hdr->buffer = len > 0 ? 1 : 0;
}
/*******************************************************************
reads or writes a UNIHDR2 structure.
********************************************************************/
void smb_io_unihdr2(char *desc, UNIHDR2 *hdr2, prs_struct *ps, int depth)
{
if (hdr2 == NULL) return;
prs_debug(ps, depth, desc, "smb_io_unihdr2");
depth++;
prs_align(ps);
smb_io_unihdr("hdr", &(hdr2->unihdr), ps, depth);
prs_uint32("buffer", ps, depth, &(hdr2->buffer));
}
/*******************************************************************
creates a UNISTR structure.
********************************************************************/
void make_unistr(UNISTR *str, char *buf)
{
/* store the string (null-terminated copy) */
struni2(str->buffer, buf);
}
/*******************************************************************
reads or writes a UNISTR structure.
XXXX NOTE: UNISTR structures NEED to be null-terminated.
********************************************************************/
void smb_io_unistr(char *desc, UNISTR *uni, prs_struct *ps, int depth)
{
if (uni == NULL) return;
prs_debug(ps, depth, desc, "smb_io_unistr");
depth++;
prs_align(ps);
prs_unistr("unistr", ps, depth, uni);
}
/*******************************************************************
creates a UNINOTSTR2 structure.
********************************************************************/
void make_uninotstr2(UNINOTSTR2 *str, char *buf, int len)
{
/* set up string lengths. add one if string is not null-terminated */
str->uni_max_len = (len+1)*2;
str->undoc = 0;
str->uni_buf_len = (len+1)*2;
/* store the string (null-terminated copy) */
struni2(str->buffer, buf);
}
/*******************************************************************
reads or writes a UNINOTSTR2 structure.
XXXX NOTE: UNISTR2 structures need NOT be null-terminated.
the uni_str_len member tells you how long the string is;
the uni_max_len member tells you how large the buffer is.
********************************************************************/
void smb_io_uninotstr2(char *desc, UNINOTSTR2 *uni2, uint32 buffer, prs_struct *ps, int depth)
{
if (uni2 == NULL) return;
if (buffer)
{
prs_debug(ps, depth, desc, "smb_io_uninotstr2");
depth++;
prs_align(ps);
prs_uint32("uni_max_len", ps, depth, &(uni2->uni_max_len));
prs_uint32("undoc ", ps, depth, &(uni2->undoc ));
prs_uint32("uni_buf_len", ps, depth, &(uni2->uni_buf_len));
/* oops! XXXX maybe issue a warning that this is happening... */
if (uni2->uni_max_len > MAX_UNISTRLEN) uni2->uni_max_len = MAX_UNISTRLEN;
if (uni2->uni_buf_len > MAX_UNISTRLEN) uni2->uni_buf_len = MAX_UNISTRLEN;
/* buffer advanced by indicated length of string
NOT by searching for null-termination */
prs_uninotstr2(True, "buffer ", ps, depth, uni2);
}
else
{
prs_debug(ps, depth, desc, "smb_io_uninotstr2 - NULL");
depth++;
bzero(uni2, sizeof(*uni2));
}
}
/*******************************************************************
creates a UNISTR2 structure: sets up the buffer, too
********************************************************************/
void make_buf_unistr2(UNISTR2 *str, uint32 *ptr, char *buf)
{
if (buf != NULL)
{
*ptr = 1;
make_unistr2(str, buf, strlen(buf));
}
else
{
*ptr = 0;
make_unistr2(str, "", 0);
}
}
/*******************************************************************
copies a UNISTR2 structure.
********************************************************************/
void copy_unistr2(UNISTR2 *str, UNISTR2 *from)
{
/* set up string lengths. add one if string is not null-terminated */
str->uni_max_len = from->uni_max_len;
str->undoc = from->undoc;
str->uni_str_len = from->uni_str_len;
/* copy the string */
memcpy(str->buffer, from->buffer, sizeof(from->buffer));
}
/*******************************************************************
creates a STRING2 structure.
********************************************************************/
void make_string2(STRING2 *str, char *buf, int len)
{
/* set up string lengths. add one if string is not null-terminated */
str->str_max_len = len+1;
str->undoc = 0;
str->str_str_len = len+1;
/* store the string */
memcpy(str->buffer, buf, len);
}
/*******************************************************************
reads or writes a STRING2 structure.
XXXX NOTE: STRING2 structures need NOT be null-terminated.
the str_str_len member tells you how long the string is;
the str_max_len member tells you how large the buffer is.
********************************************************************/
void smb_io_string2(char *desc, STRING2 *str2, uint32 buffer, prs_struct *ps, int depth)
{
if (str2 == NULL) return;
if (buffer)
{
prs_debug(ps, depth, desc, "smb_io_string2");
depth++;
prs_align(ps);
prs_uint32("str_max_len", ps, depth, &(str2->str_max_len));
prs_uint32("undoc ", ps, depth, &(str2->undoc ));
prs_uint32("str_str_len", ps, depth, &(str2->str_str_len));
/* oops! XXXX maybe issue a warning that this is happening... */
if (str2->str_max_len > MAX_STRINGLEN) str2->str_max_len = MAX_STRINGLEN;
if (str2->str_str_len > MAX_STRINGLEN) str2->str_str_len = MAX_STRINGLEN;
/* buffer advanced by indicated length of string
NOT by searching for null-termination */
prs_string2(True, "buffer ", ps, depth, str2);
}
else
{
prs_debug(ps, depth, desc, "smb_io_string2 - NULL");
depth++;
bzero(str2, sizeof(*str2));
}
}
/*******************************************************************
creates a UNISTR2 structure.
********************************************************************/
void make_unistr2(UNISTR2 *str, char *buf, int len)
{
/* set up string lengths. add one if string is not null-terminated */
str->uni_max_len = len+1;
str->undoc = 0;
str->uni_str_len = len+1;
/* store the string (null-terminated 8 bit chars into 16 bit chars) */
struni2(str->buffer, buf);
}
/*******************************************************************
reads or writes a UNISTR2 structure.
XXXX NOTE: UNISTR2 structures need NOT be null-terminated.
the uni_str_len member tells you how long the string is;
the uni_max_len member tells you how large the buffer is.
********************************************************************/
void smb_io_unistr2(char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct *ps, int depth)
{
if (uni2 == NULL) return;
if (buffer)
{
prs_debug(ps, depth, desc, "smb_io_unistr2");
depth++;
prs_align(ps);
prs_uint32("uni_max_len", ps, depth, &(uni2->uni_max_len));
prs_uint32("undoc ", ps, depth, &(uni2->undoc ));
prs_uint32("uni_str_len", ps, depth, &(uni2->uni_str_len));
/* oops! XXXX maybe issue a warning that this is happening... */
if (uni2->uni_max_len > MAX_UNISTRLEN) uni2->uni_max_len = MAX_UNISTRLEN;
if (uni2->uni_str_len > MAX_UNISTRLEN) uni2->uni_str_len = MAX_UNISTRLEN;
/* buffer advanced by indicated length of string
NOT by searching for null-termination */
prs_unistr2(True, "buffer ", ps, depth, uni2);
}
else
{
prs_debug(ps, depth, desc, "smb_io_unistr2 - NULL");
depth++;
bzero(uni2, sizeof(*uni2));
}
}
/*******************************************************************
creates a DOM_RID2 structure.
********************************************************************/
void make_dom_rid2(DOM_RID2 *rid2, uint32 rid)
{
rid2->type = 0x5;
rid2->undoc = 0x5;
rid2->rid = rid;
rid2->rid_idx = 0;
}
/*******************************************************************
reads or writes a DOM_RID2 structure.
********************************************************************/
void smb_io_dom_rid2(char *desc, DOM_RID2 *rid2, prs_struct *ps, int depth)
{
if (rid2 == NULL) return;
prs_debug(ps, depth, desc, "smb_io_dom_rid2");
depth++;
prs_align(ps);
/* should be value 5, so enforce it */
rid2->type = 5;
/* should be value 5, so enforce it */
rid2->undoc = 5;
prs_uint32("type ", ps, depth, &(rid2->type));
prs_uint32("undoc ", ps, depth, &(rid2->undoc ));
prs_uint32("rid ", ps, depth, &(rid2->rid ));
prs_uint32("rid_idx", ps, depth, &(rid2->rid_idx ));
}
/*******************************************************************
creates a DOM_RID3 structure.
********************************************************************/
void make_dom_rid3(DOM_RID3 *rid3, uint32 rid)
{
rid3->rid = rid;
rid3->type1 = 0x1;
rid3->ptr_type = 0x1; /* non-zero, basically. */
rid3->type2 = 0x1;
}
/*******************************************************************
reads or writes a DOM_RID3 structure.
********************************************************************/
void smb_io_dom_rid3(char *desc, DOM_RID3 *rid3, prs_struct *ps, int depth)
{
if (rid3 == NULL) return;
prs_debug(ps, depth, desc, "smb_io_dom_rid3");
depth++;
prs_align(ps);
prs_uint32("rid ", ps, depth, &(rid3->rid ));
prs_uint32("type1 ", ps, depth, &(rid3->type1 ));
prs_uint32("ptr_type", ps, depth, &(rid3->ptr_type));
prs_uint32("type2 ", ps, depth, &(rid3->type2 ));
}
/*******************************************************************
creates a DOM_RID4 structure.
********************************************************************/
void make_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid)
{
rid4->unknown = unknown;
rid4->attr = attr;
rid4->rid = rid;
}
/*******************************************************************
reads or writes a DOM_RID4 structure.
********************************************************************/
void smb_io_dom_rid4(char *desc, DOM_RID4 *rid4, prs_struct *ps, int depth)
{
if (rid4 == NULL) return;
prs_debug(ps, depth, desc, "smb_io_dom_rid4. XXXX !check size of unknown! XXXX");
depth++;
prs_align(ps);
prs_uint32("unknown", ps, depth, &(rid4->unknown));
prs_uint16("attr ", ps, depth, &(rid4->attr ));
prs_uint32("rid ", ps, depth, &(rid4->rid ));
}
/*******************************************************************
makes a DOM_CLNT_SRV structure.
********************************************************************/
void make_clnt_srv(DOM_CLNT_SRV *log, char *logon_srv, char *comp_name)
{
if (log == NULL) return;
DEBUG(5,("make_clnt_srv: %d\n", __LINE__));
if (logon_srv != NULL)
{
log->undoc_buffer = 1;
make_unistr2(&(log->uni_logon_srv), logon_srv, strlen(logon_srv));
}
else
{
log->undoc_buffer = 0;
}
if (comp_name != NULL)
{
log->undoc_buffer2 = 1;
make_unistr2(&(log->uni_comp_name), comp_name, strlen(comp_name));
}
else
{
log->undoc_buffer2 = 0;
}
}
/*******************************************************************
reads or writes a DOM_CLNT_SRV structure.
********************************************************************/
void smb_io_clnt_srv(char *desc, DOM_CLNT_SRV *log, prs_struct *ps, int depth)
{
if (log == NULL) return;
prs_debug(ps, depth, desc, "smb_io_clnt_srv");
depth++;
prs_align(ps);
prs_uint32("undoc_buffer ", ps, depth, &(log->undoc_buffer ));
if (log->undoc_buffer != 0)
{
smb_io_unistr2("unistr2", &(log->uni_logon_srv), log->undoc_buffer, ps, depth);
}
prs_align(ps);
prs_uint32("undoc_buffer2", ps, depth, &(log->undoc_buffer2));
if (log->undoc_buffer2 != 0)
{
smb_io_unistr2("unistr2", &(log->uni_comp_name), log->undoc_buffer2, ps, depth);
}
}
/*******************************************************************
makes a DOM_LOG_INFO structure.
********************************************************************/
void make_log_info(DOM_LOG_INFO *log, char *logon_srv, char *acct_name,
uint16 sec_chan, char *comp_name)
{
if (log == NULL) return;
DEBUG(5,("make_log_info %d\n", __LINE__));
log->undoc_buffer = 1;
make_unistr2(&(log->uni_logon_srv), logon_srv, strlen(logon_srv));
make_unistr2(&(log->uni_acct_name), acct_name, strlen(acct_name));
log->sec_chan = sec_chan;
make_unistr2(&(log->uni_comp_name), comp_name, strlen(comp_name));
}
/*******************************************************************
reads or writes a DOM_LOG_INFO structure.
********************************************************************/
void smb_io_log_info(char *desc, DOM_LOG_INFO *log, prs_struct *ps, int depth)
{
if (log == NULL) return;
prs_debug(ps, depth, desc, "smb_io_log_info");
depth++;
prs_align(ps);
prs_uint32("undoc_buffer", ps, depth, &(log->undoc_buffer));
smb_io_unistr2("unistr2", &(log->uni_logon_srv), True, ps, depth);
smb_io_unistr2("unistr2", &(log->uni_acct_name), True, ps, depth);
prs_uint16("sec_chan", ps, depth, &(log->sec_chan));
smb_io_unistr2("unistr2", &(log->uni_comp_name), True, ps, depth);
}
/*******************************************************************
reads or writes a DOM_CHAL structure.
********************************************************************/
void smb_io_chal(char *desc, DOM_CHAL *chal, prs_struct *ps, int depth)
{
if (chal == NULL) return;
prs_debug(ps, depth, desc, "smb_io_chal");
depth++;
prs_align(ps);
prs_uint8s (False, "data", ps, depth, chal->data, 8);
}
/*******************************************************************
reads or writes a DOM_CRED structure.
********************************************************************/
void smb_io_cred(char *desc, DOM_CRED *cred, prs_struct *ps, int depth)
{
if (cred == NULL) return;
prs_debug(ps, depth, desc, "smb_io_cred");
depth++;
prs_align(ps);
smb_io_chal ("", &(cred->challenge), ps, depth);
smb_io_utime("", &(cred->timestamp), ps, depth);
}
/*******************************************************************
makes a DOM_CLNT_INFO2 structure.
********************************************************************/
void make_clnt_info2(DOM_CLNT_INFO2 *clnt,
char *logon_srv, char *comp_name,
DOM_CRED *clnt_cred)
{
if (clnt == NULL) return;
DEBUG(5,("make_clnt_info: %d\n", __LINE__));
make_clnt_srv(&(clnt->login), logon_srv, comp_name);
if (clnt_cred != NULL)
{
clnt->ptr_cred = 1;
memcpy(&(clnt->cred), clnt_cred, sizeof(clnt->cred));
}
else
{
clnt->ptr_cred = 0;
}
}
/*******************************************************************
reads or writes a DOM_CLNT_INFO2 structure.
********************************************************************/
void smb_io_clnt_info2(char *desc, DOM_CLNT_INFO2 *clnt, prs_struct *ps, int depth)
{
if (clnt == NULL) return;
prs_debug(ps, depth, desc, "smb_io_clnt_info2");
depth++;
prs_align(ps);
smb_io_clnt_srv("", &(clnt->login), ps, depth);
prs_align(ps);
prs_uint32("ptr_cred", ps, depth, &(clnt->ptr_cred));
smb_io_cred ("", &(clnt->cred ), ps, depth);
}
/*******************************************************************
makes a DOM_CLNT_INFO structure.
********************************************************************/
void make_clnt_info(DOM_CLNT_INFO *clnt,
char *logon_srv, char *acct_name,
uint16 sec_chan, char *comp_name,
DOM_CRED *cred)
{
if (clnt == NULL || cred == NULL) return;
DEBUG(5,("make_clnt_info\n"));
make_log_info(&(clnt->login), logon_srv, acct_name, sec_chan, comp_name);
memcpy(&(clnt->cred), cred, sizeof(clnt->cred));
}
/*******************************************************************
reads or writes a DOM_CLNT_INFO structure.
********************************************************************/
void smb_io_clnt_info(char *desc, DOM_CLNT_INFO *clnt, prs_struct *ps, int depth)
{
if (clnt == NULL) return;
prs_debug(ps, depth, desc, "smb_io_clnt_info");
depth++;
prs_align(ps);
smb_io_log_info("", &(clnt->login), ps, depth);
smb_io_cred ("", &(clnt->cred ), ps, depth);
}
/*******************************************************************
makes a DOM_LOGON_ID structure.
********************************************************************/
void make_logon_id(DOM_LOGON_ID *log, uint32 log_id_low, uint32 log_id_high)
{
if (log == NULL) return;
DEBUG(5,("make_logon_id: %d\n", __LINE__));
log->low = log_id_low;
log->high = log_id_high;
}
/*******************************************************************
reads or writes a DOM_LOGON_ID structure.
********************************************************************/
void smb_io_logon_id(char *desc, DOM_LOGON_ID *log, prs_struct *ps, int depth)
{
if (log == NULL) return;
prs_debug(ps, depth, desc, "smb_io_logon_id");
depth++;
prs_align(ps);
prs_uint32("low ", ps, depth, &(log->low ));
prs_uint32("high", ps, depth, &(log->high));
}
/*******************************************************************
makes an ARC4_OWF structure.
********************************************************************/
void make_arc4_owf(ARC4_OWF *hash, uint8 data[16])
{
if (hash == NULL) return;
DEBUG(5,("make_arc4_owf: %d\n", __LINE__));
if (data != NULL)
{
memcpy(hash->data, data, sizeof(hash->data));
}
else
{
bzero(hash->data, sizeof(hash->data));
}
}
/*******************************************************************
reads or writes an ARC4_OWF structure.
********************************************************************/
void smb_io_arc4_owf(char *desc, ARC4_OWF *hash, prs_struct *ps, int depth)
{
if (hash == NULL) return;
prs_debug(ps, depth, desc, "smb_io_arc4_owf");
depth++;
prs_align(ps);
prs_uint8s (False, "data", ps, depth, hash->data, 16);
}
/*******************************************************************
reads or writes a DOM_GID structure.
********************************************************************/
void smb_io_gid(char *desc, DOM_GID *gid, prs_struct *ps, int depth)
{
if (gid == NULL) return;
prs_debug(ps, depth, desc, "smb_io_gid");
depth++;
prs_align(ps);
prs_uint32("g_rid", ps, depth, &(gid->g_rid));
prs_uint32("attr ", ps, depth, &(gid->attr ));
}
/*******************************************************************
reads or writes an POLICY_HND structure.
********************************************************************/
void smb_io_pol_hnd(char *desc, POLICY_HND *pol, prs_struct *ps, int depth)
{
if (pol == NULL) return;
prs_debug(ps, depth, desc, "smb_io_pol_hnd");
depth++;
prs_align(ps);
prs_uint8s (False, "data", ps, depth, pol->data, POL_HND_SIZE);
}
/*******************************************************************
reads or writes a dom query structure.
********************************************************************/
void smb_io_dom_query_3(char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth)
{
smb_io_dom_query("", d_q, ps, depth);
}
/*******************************************************************
reads or writes a dom query structure.
********************************************************************/
void smb_io_dom_query_5(char *desc, DOM_QUERY_3 *d_q, prs_struct *ps, int depth)
{
smb_io_dom_query("", d_q, ps, depth);
}
/*******************************************************************
reads or writes a dom query structure.
********************************************************************/
void smb_io_dom_query(char *desc, DOM_QUERY *d_q, prs_struct *ps, int depth)
{
if (d_q == NULL) return;
prs_debug(ps, depth, desc, "smb_io_dom_query");
depth++;
prs_align(ps);
prs_uint16("uni_dom_max_len", ps, depth, &(d_q->uni_dom_max_len)); /* domain name string length * 2 */
prs_uint16("uni_dom_str_len", ps, depth, &(d_q->uni_dom_str_len)); /* domain name string length * 2 */
prs_uint32("buffer_dom_name", ps, depth, &(d_q->buffer_dom_name)); /* undocumented domain name string buffer pointer */
prs_uint32("buffer_dom_sid ", ps, depth, &(d_q->buffer_dom_sid )); /* undocumented domain SID string buffer pointer */
smb_io_unistr2("unistr2", &(d_q->uni_domain_name), d_q->buffer_dom_name, ps, depth); /* domain name (unicode string) */
if (d_q->buffer_dom_sid != 0)
{
smb_io_dom_sid2("", &(d_q->dom_sid), ps, depth); /* domain SID */
}
else
{
bzero(&(d_q->dom_sid), sizeof(d_q->dom_sid));
}
}
/*******************************************************************
reads or writes a DOM_NAME structure.
********************************************************************/
void smb_io_dom_name(char *desc, DOM_NAME *name, prs_struct *ps, int depth)
{
if (name == NULL) return;
prs_debug(ps, depth, desc, "smb_io_dom_name");
depth++;
prs_align(ps);
prs_uint32("uni_str_len", ps, depth, &(name->uni_str_len));
/* don't know if len is specified by uni_str_len member... */
/* assume unicode string is unicode-null-terminated, instead */
smb_io_unistr("", &(name->str), ps, depth);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,290 @@
/*
Unix SMB/Netbios implementation.
Version 1.9.
Samba memory buffer functions
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) Luke Kenneth Casson Leighton 1996-1997
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.
*/
extern int DEBUGLEVEL;
#include "includes.h"
/*******************************************************************
debug output for parsing info.
XXXX side-effect of this function is to increase the debug depth XXXX
********************************************************************/
void prs_debug(prs_struct *ps, int depth, char *desc, char *fn_name)
{
DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->offset, fn_name, desc));
}
/*******************************************************************
initialise a parse structure
********************************************************************/
void prs_init(prs_struct *ps, uint32 size,
uint8 align, uint32 margin,
BOOL io)
{
ps->io = io;
ps->align = align;
ps->offset = 0;
ps->data = NULL;
mem_buf_init(&(ps->data), margin);
if (size != 0)
{
mem_alloc_data(ps->data, size);
ps->data->offset.start = 0;
ps->data->offset.end = 0xffffffff;
}
}
/*******************************************************************
initialise a parse structure
********************************************************************/
void prs_mem_free(prs_struct *ps)
{
mem_buf_free(&(ps->data));
}
/*******************************************************************
align a pointer to a multiple of align_offset bytes. looks like it
will work for offsets of 0, 2 and 4...
********************************************************************/
void prs_align(prs_struct *ps)
{
int mod = ps->offset & (ps->align-1);
if (ps->align != 0 && mod != 0)
{
ps->offset += ps->align - mod;
}
}
/*******************************************************************
attempt, if appropriate, to grow a data buffer.
depends on the data stream mode (io)
********************************************************************/
BOOL prs_grow(prs_struct *ps)
{
return mem_grow_data(&(ps->data), ps->io, ps->offset);
}
/*******************************************************************
stream a uint8
********************************************************************/
BOOL prs_uint8(char *name, prs_struct *ps, int depth, uint8 *data8)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_CVAL(name, depth, ps->offset, ps->io, q, *data8)
ps->offset += 1;
return True;
}
/*******************************************************************
stream a uint16
********************************************************************/
BOOL prs_uint16(char *name, prs_struct *ps, int depth, uint16 *data16)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_SVAL(name, depth, ps->offset, ps->io, q, *data16)
ps->offset += 2;
return True;
}
/*******************************************************************
stream a uint32
********************************************************************/
BOOL prs_uint32(char *name, prs_struct *ps, int depth, uint32 *data32)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_IVAL(name, depth, ps->offset, ps->io, q, *data32)
ps->offset += 4;
return True;
}
/******************************************************************
stream an array of uint8s. length is number of uint8s
********************************************************************/
BOOL prs_uint8s(BOOL charmode, char *name, prs_struct *ps, int depth, uint8 *data8s, int len)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, data8s, len)
ps->offset += len;
return True;
}
/******************************************************************
stream an array of uint16s. length is number of uint16s
********************************************************************/
BOOL prs_uint16s(BOOL charmode, char *name, prs_struct *ps, int depth, uint16 *data16s, int len)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, data16s, len)
ps->offset += len * sizeof(uint16);
return True;
}
/******************************************************************
stream an array of uint32s. length is number of uint32s
********************************************************************/
BOOL prs_uint32s(BOOL charmode, char *name, prs_struct *ps, int depth, uint32 *data32s, int len)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_PIVAL(charmode, name, depth, ps->offset, ps->io, q, data32s, len)
ps->offset += len * sizeof(uint32);
return True;
}
/******************************************************************
stream a "not" unicode string, length/buffer specified separately,
in byte chars
********************************************************************/
BOOL prs_uninotstr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNINOTSTR2 *str)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_max_len)
ps->offset += str->uni_buf_len;
return True;
}
/******************************************************************
stream a string, length/buffer specified separately,
in uint8 chars.
********************************************************************/
BOOL prs_string2(BOOL charmode, char *name, prs_struct *ps, int depth, STRING2 *str)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_PCVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->str_max_len)
ps->offset += str->str_str_len * sizeof(uint8);
return True;
}
/******************************************************************
stream a unicode string, length/buffer specified separately,
in uint16 chars.
********************************************************************/
BOOL prs_unistr2(BOOL charmode, char *name, prs_struct *ps, int depth, UNISTR2 *str)
{
char *q = mem_data(&(ps->data), ps->offset);
if (q == NULL) return False;
DBG_RW_PSVAL(charmode, name, depth, ps->offset, ps->io, q, str->buffer, str->uni_max_len)
ps->offset += str->uni_str_len * sizeof(uint16);
return True;
}
/*******************************************************************
stream a unicode null-terminated string
********************************************************************/
BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
{
char *q = mem_data(&(ps->data), ps->offset);
int i = 0;
uint8 *start = (uint8*)q;
if (q == NULL) return False;
do
{
RW_SVAL(ps->io, q, str->buffer[i],0);
q += 2;
i++;
} while ((i < sizeof(str->buffer) / sizeof(str->buffer[0])) &&
(str->buffer[i] != 0));
ps->offset += i*2;
dump_data(5+depth, start, ps->offset);
return True;
}
/*******************************************************************
stream a null-terminated string. len is strlen, and therefore does
not include the null-termination character.
len == 0 indicates variable length string
(up to max size of pstring - 1024 chars).
********************************************************************/
BOOL prs_string(char *name, prs_struct *ps, int depth, char *str, uint16 len)
{
char *q = mem_data(&(ps->data), ps->offset);
uint8 *start = (uint8*)q;
int i = -1; /* start off at zero after 1st i++ */
if (q == NULL) return False;
do
{
i++;
if (i < len || len == 0)
{
RW_CVAL(ps->io, q, str[i],0);
}
else
{
uint8 dummy = 0;
RW_CVAL(ps->io, q, dummy,0);
}
q++;
} while (i < sizeof(pstring) && (len == 0 ? str[i] != 0 : i < len) );
ps->offset += i+1;
dump_data(5+depth, start, ps->offset);
return True;
}

View File

@ -0,0 +1,335 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
extern int DEBUGLEVEL;
/*******************************************************************
creates a structure.
********************************************************************/
void make_reg_q_open_policy(REG_Q_OPEN_POLICY *r_q,
uint16 unknown_0, uint32 level, uint16 unknown_1)
{
r_q->ptr = 1;
r_q->unknown_0 = unknown_0;
r_q->level = level;
r_q->unknown_1 = unknown_1;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_q_open_policy(char *desc, REG_Q_OPEN_POLICY *r_q, prs_struct *ps, int depth)
{
if (r_q == NULL) return;
prs_debug(ps, depth, desc, "reg_io_q_open_policy");
depth++;
prs_align(ps);
prs_uint32("ptr ", ps, depth, &(r_q->ptr ));
if (r_q->ptr != 0)
{
prs_uint16("unknown_0", ps, depth, &(r_q->unknown_0));
prs_uint32("level ", ps, depth, &(r_q->level ));
prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1));
}
}
/*******************************************************************
creates a structure.
********************************************************************/
void make_reg_r_open_policy(REG_R_OPEN_POLICY *r_r,
POLICY_HND *pol, uint32 status)
{
if (r_r == NULL) return;
memcpy(&(r_r->pol), pol, sizeof(r_r->pol));
r_r->status = status;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_r_open_policy(char *desc, REG_R_OPEN_POLICY *r_r, prs_struct *ps, int depth)
{
if (r_r == NULL) return;
prs_debug(ps, depth, desc, "reg_io_r_open_policy");
depth++;
prs_align(ps);
smb_io_pol_hnd("", &(r_r->pol), ps, depth);
prs_uint32("status", ps, depth, &(r_r->status));
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_q_close(char *desc, REG_Q_CLOSE *q_u, prs_struct *ps, int depth)
{
if (q_u == NULL) return;
prs_debug(ps, depth, desc, "reg_io_q_unknown_1");
depth++;
prs_align(ps);
smb_io_pol_hnd("", &(q_u->pol), ps, depth);
prs_align(ps);
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_r_close(char *desc, REG_R_CLOSE *r_u, prs_struct *ps, int depth)
{
if (r_u == NULL) return;
prs_debug(ps, depth, desc, "reg_io_r_unknown_1");
depth++;
prs_align(ps);
smb_io_pol_hnd("", &(r_u->pol), ps, depth);
prs_align(ps);
prs_uint32("status", ps, depth, &(r_u->status));
}
/*******************************************************************
creates a structure.
********************************************************************/
void make_reg_q_info(REG_Q_INFO *r_q,
POLICY_HND *pol, char *product_type,
NTTIME *prod_time, uint8 major_version, uint8 minor_version,
uint32 unknown)
{
int type_len = strlen(product_type);
memcpy(&(r_q->pol), pol, sizeof(r_q->pol));
make_uni_hdr(&(r_q->hdr_type), type_len, type_len, 1);
make_unistr2(&(r_q->uni_type), product_type, type_len);
r_q->ptr1 = 1;
memcpy(&(r_q->time), prod_time, sizeof(r_q->time));
r_q->major_version1 = major_version;
r_q->minor_version1 = minor_version;
bzero(&(r_q->pad1), sizeof(r_q->pad1));
r_q->ptr2 = 1;
r_q->major_version2 = major_version;
r_q->minor_version2 = minor_version;
bzero(&(r_q->pad2), sizeof(r_q->pad2));
r_q->ptr3 = 1;
r_q->unknown = unknown;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_q_info(char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth)
{
if (r_q == NULL) return;
prs_debug(ps, depth, desc, "reg_io_q_info");
depth++;
prs_align(ps);
smb_io_pol_hnd("", &(r_q->pol), ps, depth);
smb_io_unihdr ("", &(r_q->hdr_type), ps, depth);
smb_io_unistr2("", &(r_q->uni_type), r_q->hdr_type.buffer, ps, depth);
prs_uint32("ptr1", ps, depth, &(r_q->ptr1));
if (r_q->ptr1 != 0)
{
smb_io_time("", &(r_q->time), ps, depth);
prs_uint8 ("major_version1", ps, depth, &(r_q->major_version1));
prs_uint8 ("minor_version1", ps, depth, &(r_q->minor_version1));
prs_uint8s(False, "pad1", ps, depth, r_q->pad1, sizeof(r_q->pad1));
}
prs_uint32("ptr2", ps, depth, &(r_q->ptr2));
if (r_q->ptr2 != 0)
{
prs_uint8 ("major_version2", ps, depth, &(r_q->major_version2));
prs_uint8 ("minor_version2", ps, depth, &(r_q->minor_version2));
prs_uint8s(False, "pad2", ps, depth, r_q->pad2, sizeof(r_q->pad2));
}
prs_uint32("ptr3", ps, depth, &(r_q->ptr3));
if (r_q->ptr3 != 0)
{
prs_uint32("unknown", ps, depth, &(r_q->unknown));
}
}
/*******************************************************************
creates a structure.
********************************************************************/
void make_reg_r_info(REG_R_INFO *r_r,
uint32 level, char *os_type,
uint32 unknown_0, uint32 unknown_1,
uint32 status)
{
int type_len = strlen(os_type);
r_r->ptr1 = 1;
r_r->level = level;
r_r->ptr_type = 1;
make_uninotstr2(&(r_r->uni_type), os_type, type_len);
r_r->ptr2 = 1;
r_r->unknown_0 = unknown_0;
r_r->ptr3 = 1;
r_r->unknown_1 = unknown_1;
r_r->status = status;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_r_info(char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth)
{
if (r_r == NULL) return;
prs_debug(ps, depth, desc, "reg_io_r_info");
depth++;
prs_align(ps);
prs_uint32("ptr1", ps, depth, &(r_r->ptr1));
if (r_r->ptr1 != 0)
{
prs_uint32("level", ps, depth, &(r_r->level));
prs_uint32("ptr_type", ps, depth, &(r_r->ptr_type));
smb_io_uninotstr2("", &(r_r->uni_type), r_r->ptr_type, ps, depth);
prs_align(ps);
prs_uint32("ptr2", ps, depth, &(r_r->ptr2));
if (r_r->ptr2 != 0)
{
prs_uint32("unknown_0", ps, depth, &(r_r->unknown_0));
}
prs_uint32("ptr3", ps, depth, &(r_r->ptr3));
if (r_r->ptr3 != 0)
{
prs_uint32("unknown_1", ps, depth, &(r_r->unknown_1));
}
}
prs_uint32("status", ps, depth, &(r_r->status));
}
/*******************************************************************
creates a structure.
********************************************************************/
void make_reg_q_open_entry(REG_Q_OPEN_ENTRY *r_q,
POLICY_HND *pol, char *name,
uint32 unknown_0, uint32 unknown_1, uint16 unknown_2)
{
int len_name = strlen(name);
memcpy(&(r_q->pol), pol, sizeof(r_q->pol));
make_uni_hdr(&(r_q->hdr_name), len_name, len_name, 1);
make_unistr2(&(r_q->uni_name), name, len_name);
r_q->unknown_0 = unknown_0;
r_q->unknown_1 = unknown_1;
r_q->unknown_2 = unknown_2;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_q_open_entry(char *desc, REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int depth)
{
if (r_q == NULL) return;
prs_debug(ps, depth, desc, "reg_io_q_entry");
depth++;
prs_align(ps);
smb_io_pol_hnd("", &(r_q->pol), ps, depth);
smb_io_unihdr ("", &(r_q->hdr_name), ps, depth);
smb_io_unistr2("", &(r_q->uni_name), r_q->hdr_name.buffer, ps, depth);
prs_uint32("unknown_0", ps, depth, &(r_q->unknown_0));
prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1));
prs_uint16("unknown_2", ps, depth, &(r_q->unknown_2));
}
/*******************************************************************
creates a structure.
********************************************************************/
void make_reg_r_open_entry(REG_R_OPEN_ENTRY *r_r,
POLICY_HND *pol, uint32 status)
{
if (r_r == NULL) return;
memcpy(&(r_r->pol), pol, sizeof(r_r->pol));
r_r->status = status;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void reg_io_r_open_entry(char *desc, REG_R_OPEN_ENTRY *r_r, prs_struct *ps, int depth)
{
if (r_r == NULL) return;
prs_debug(ps, depth, desc, "reg_io_r_open_entry");
depth++;
prs_align(ps);
smb_io_pol_hnd("", &(r_r->pol), ps, depth);
prs_uint32("status", ps, depth, &(r_r->status));
}

View File

@ -0,0 +1,528 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
extern int DEBUGLEVEL;
/*******************************************************************
interface/version dce/rpc pipe identification
********************************************************************/
#define TRANS_SYNT_V2 \
{ \
{ \
0x04, 0x5d, 0x88, 0x8a, \
0xeb, 0x1c, 0xc9, 0x11, \
0x9f, 0xe8, 0x08, 0x00, \
0x2b, 0x10, 0x48, 0x60 \
}, 0x02 \
} \
#define SYNT_NETLOGON_V2 \
{ \
{ \
0x04, 0x5d, 0x88, 0x8a, \
0xeb, 0x1c, 0xc9, 0x11, \
0x9f, 0xe8, 0x08, 0x00, \
0x2b, 0x10, 0x48, 0x60 \
}, 0x02 \
} \
#define SYNT_WKSSVC_V1 \
{ \
{ \
0x98, 0xd0, 0xff, 0x6b, \
0x12, 0xa1, 0x10, 0x36, \
0x98, 0x33, 0x46, 0xc3, \
0xf8, 0x7e, 0x34, 0x5a \
}, 0x01 \
} \
#define SYNT_SRVSVC_V3 \
{ \
{ \
0xc8, 0x4f, 0x32, 0x4b, \
0x70, 0x16, 0xd3, 0x01, \
0x12, 0x78, 0x5a, 0x47, \
0xbf, 0x6e, 0xe1, 0x88 \
}, 0x03 \
} \
#define SYNT_LSARPC_V0 \
{ \
{ \
0x78, 0x57, 0x34, 0x12, \
0x34, 0x12, 0xcd, 0xab, \
0xef, 0x00, 0x01, 0x23, \
0x45, 0x67, 0x89, 0xab \
}, 0x00 \
} \
#define SYNT_SAMR_V1 \
{ \
{ \
0x78, 0x57, 0x34, 0x12, \
0x34, 0x12, 0xcd, 0xab, \
0xef, 0x00, 0x01, 0x23, \
0x45, 0x67, 0x89, 0xac \
}, 0x01 \
} \
#define SYNT_NETLOGON_V1 \
{ \
{ \
0x78, 0x56, 0x34, 0x12, \
0x34, 0x12, 0xcd, 0xab, \
0xef, 0x00, 0x01, 0x23, \
0x45, 0x67, 0xcf, 0xfb \
}, 0x01 \
} \
#define SYNT_WINREG_V1 \
{ \
{ \
0x01, 0xd0, 0x8c, 0x33, \
0x44, 0x22, 0xf1, 0x31, \
0xaa, 0xaa, 0x90, 0x00, \
0x38, 0x00, 0x10, 0x03 \
}, 0x01 \
} \
#define SYNT_NONE_V0 \
{ \
{ \
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00 \
}, 0x00 \
} \
/* pipe string names */
#define PIPE_SRVSVC "\\PIPE\\srvsvc"
#define PIPE_SAMR "\\PIPE\\samr"
#define PIPE_WINREG "\\PIPE\\winreg"
#define PIPE_WKSSVC "\\PIPE\\wkssvc"
#define PIPE_NETLOGON "\\PIPE\\NETLOGON"
#define PIPE_NTLSA "\\PIPE\\ntlsa"
#define PIPE_NTSVCS "\\PIPE\\ntsvcs"
#define PIPE_LSASS "\\PIPE\\lsass"
#define PIPE_LSARPC "\\PIPE\\lsarpc"
struct pipe_id_info pipe_names [] =
{
/* client pipe , abstract syntax , server pipe , transfer syntax */
{ PIPE_LSARPC , SYNT_LSARPC_V0 , PIPE_LSASS , TRANS_SYNT_V2 },
{ PIPE_SAMR , SYNT_SAMR_V1 , PIPE_LSASS , TRANS_SYNT_V2 },
{ PIPE_NETLOGON, SYNT_NETLOGON_V1, PIPE_LSASS , TRANS_SYNT_V2 },
{ PIPE_SRVSVC , SYNT_SRVSVC_V3 , PIPE_NTSVCS , TRANS_SYNT_V2 },
{ PIPE_WKSSVC , SYNT_WKSSVC_V1 , PIPE_NTSVCS , TRANS_SYNT_V2 },
{ PIPE_WINREG , SYNT_WINREG_V1 , PIPE_WINREG , TRANS_SYNT_V2 },
{ NULL , SYNT_NONE_V0 , NULL , SYNT_NONE_V0 }
};
/*******************************************************************
creates an RPC_HDR structure.
********************************************************************/
void make_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 flags,
uint32 call_id, int data_len, int auth_len)
{
if (hdr == NULL) return;
hdr->major = 5; /* RPC version 5 */
hdr->minor = 0; /* minor version 0 */
hdr->pkt_type = pkt_type; /* RPC packet type */
hdr->flags = flags; /* dce/rpc flags */
hdr->pack_type = 0x10; /* packed data representation */
hdr->frag_len = data_len; /* fragment length, fill in later */
hdr->auth_len = auth_len; /* authentication length */
hdr->call_id = call_id; /* call identifier - match incoming RPC */
}
/*******************************************************************
reads or writes an RPC_HDR structure.
********************************************************************/
void smb_io_rpc_hdr(char *desc, RPC_HDR *rpc, prs_struct *ps, int depth)
{
if (rpc == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_hdr");
depth++;
prs_uint8 ("major ", ps, depth, &(rpc->major));
prs_uint8 ("minor ", ps, depth, &(rpc->minor));
prs_uint8 ("pkt_type ", ps, depth, &(rpc->pkt_type));
prs_uint8 ("flags ", ps, depth, &(rpc->flags));
prs_uint32("pack_type ", ps, depth, &(rpc->pack_type));
prs_uint16("frag_len ", ps, depth, &(rpc->frag_len));
prs_uint16("auth_len ", ps, depth, &(rpc->auth_len));
prs_uint32("call_id ", ps, depth, &(rpc->call_id));
}
/*******************************************************************
creates an RPC_IFACE structure.
********************************************************************/
void make_rpc_iface(RPC_IFACE *ifc, char data[16], uint32 version)
{
if (ifc == NULL || data == NULL) return;
memcpy(ifc->data, data, sizeof(ifc->data)); /* 16 bytes of number */
ifc->version = version; /* the interface number */
}
/*******************************************************************
reads or writes an RPC_IFACE structure.
********************************************************************/
void smb_io_rpc_iface(char *desc, RPC_IFACE *ifc, prs_struct *ps, int depth)
{
if (ifc == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_iface");
depth++;
prs_align(ps);
prs_uint8s (False, "data ", ps, depth, ifc->data, sizeof(ifc->data));
prs_uint32 ( "version", ps, depth, &(ifc->version));
}
/*******************************************************************
creates an RPC_ADDR_STR structure.
********************************************************************/
void make_rpc_addr_str(RPC_ADDR_STR *str, char *name)
{
if (str == NULL || name == NULL) return;
str->len = strlen(name) + 1;
fstrcpy(str->str, name);
}
/*******************************************************************
reads or writes an RPC_ADDR_STR structure.
********************************************************************/
void smb_io_rpc_addr_str(char *desc, RPC_ADDR_STR *str, prs_struct *ps, int depth)
{
if (str == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_addr_str");
depth++;
prs_align(ps);
prs_uint16 ( "len", ps, depth, &(str->len));
prs_uint8s (True, "str", ps, depth, (uchar*)str->str, str->len);
}
/*******************************************************************
creates an RPC_HDR_BBA structure.
********************************************************************/
void make_rpc_hdr_bba(RPC_HDR_BBA *bba, uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid)
{
if (bba == NULL) return;
bba->max_tsize = max_tsize; /* maximum transmission fragment size (0x1630) */
bba->max_rsize = max_rsize; /* max receive fragment size (0x1630) */
bba->assoc_gid = assoc_gid; /* associated group id (0x0) */
}
/*******************************************************************
reads or writes an RPC_HDR_BBA structure.
********************************************************************/
void smb_io_rpc_hdr_bba(char *desc, RPC_HDR_BBA *rpc, prs_struct *ps, int depth)
{
if (rpc == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_hdr_bba");
depth++;
prs_uint16("max_tsize", ps, depth, &(rpc->max_tsize));
prs_uint16("max_rsize", ps, depth, &(rpc->max_rsize));
prs_uint32("assoc_gid", ps, depth, &(rpc->assoc_gid));
}
/*******************************************************************
creates an RPC_HDR_RB structure.
********************************************************************/
void make_rpc_hdr_rb(RPC_HDR_RB *rpc,
uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid,
uint32 num_elements, uint16 context_id, uint8 num_syntaxes,
RPC_IFACE *abstract, RPC_IFACE *transfer)
{
if (rpc == NULL) return;
make_rpc_hdr_bba(&(rpc->bba), max_tsize, max_rsize, assoc_gid);
rpc->num_elements = num_elements ; /* the number of elements (0x1) */
rpc->context_id = context_id ; /* presentation context identifier (0x0) */
rpc->num_syntaxes = num_syntaxes ; /* the number of syntaxes (has always been 1?)(0x1) */
/* num and vers. of interface client is using */
memcpy(&(rpc->abstract), abstract, sizeof(rpc->abstract));
/* num and vers. of interface to use for replies */
memcpy(&(rpc->transfer), transfer, sizeof(rpc->transfer));
}
/*******************************************************************
reads or writes an RPC_HDR_RB structure.
********************************************************************/
void smb_io_rpc_hdr_rb(char *desc, RPC_HDR_RB *rpc, prs_struct *ps, int depth)
{
if (rpc == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_hdr_rb");
depth++;
smb_io_rpc_hdr_bba("", &(rpc->bba), ps, depth);
prs_uint32("num_elements", ps, depth, &(rpc->num_elements));
prs_uint16("context_id ", ps, depth, &(rpc->context_id ));
prs_uint8 ("num_syntaxes", ps, depth, &(rpc->num_syntaxes));
smb_io_rpc_iface("", &(rpc->abstract), ps, depth);
smb_io_rpc_iface("", &(rpc->transfer), ps, depth);
}
/*******************************************************************
creates an RPC_RESULTS structure.
lkclXXXX only one reason at the moment!
********************************************************************/
void make_rpc_results(RPC_RESULTS *res,
uint8 num_results, uint16 result, uint16 reason)
{
if (res == NULL) return;
res->num_results = num_results; /* the number of results (0x01) */
res->result = result ; /* result (0x00 = accept) */
res->reason = reason ; /* reason (0x00 = no reason specified) */
}
/*******************************************************************
reads or writes an RPC_RESULTS structure.
lkclXXXX only one reason at the moment!
********************************************************************/
void smb_io_rpc_results(char *desc, RPC_RESULTS *res, prs_struct *ps, int depth)
{
if (res == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_results");
depth++;
prs_align(ps);
prs_uint8 ("num_results", ps, depth, &(res->num_results));
prs_align(ps);
prs_uint16("result ", ps, depth, &(res->result ));
prs_uint16("reason ", ps, depth, &(res->reason ));
}
/*******************************************************************
creates an RPC_HDR_BA structure.
lkclXXXX only one reason at the moment!
********************************************************************/
void make_rpc_hdr_ba(RPC_HDR_BA *rpc,
uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid,
char *pipe_addr,
uint8 num_results, uint16 result, uint16 reason,
RPC_IFACE *transfer)
{
if (rpc == NULL || transfer == NULL || pipe_addr == NULL) return;
make_rpc_hdr_bba (&(rpc->bba ), max_tsize, max_rsize, assoc_gid);
make_rpc_addr_str(&(rpc->addr), pipe_addr);
make_rpc_results (&(rpc->res ), num_results, result, reason);
/* the transfer syntax from the request */
memcpy(&(rpc->transfer), transfer, sizeof(rpc->transfer));
}
/*******************************************************************
reads or writes an RPC_HDR_BA structure.
********************************************************************/
void smb_io_rpc_hdr_ba(char *desc, RPC_HDR_BA *rpc, prs_struct *ps, int depth)
{
if (rpc == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_hdr_ba");
depth++;
smb_io_rpc_hdr_bba ("", &(rpc->bba) , ps, depth);
smb_io_rpc_addr_str("", &(rpc->addr) , ps, depth);
smb_io_rpc_results ("", &(rpc->res) , ps, depth);
smb_io_rpc_iface ("", &(rpc->transfer), ps, depth);
}
/*******************************************************************
creates an RPC_HDR_RR structure.
********************************************************************/
void make_rpc_hdr_rr(RPC_HDR_RR *hdr, uint32 data_len, uint8 opnum)
{
if (hdr == NULL) return;
hdr->alloc_hint = data_len - 0x18; /* allocation hint */
hdr->context_id = 0; /* presentation context identifier */
hdr->cancel_count = 0; /* cancel count */
hdr->opnum = opnum; /* opnum */
hdr->reserved = 0; /* 0 - reserved */
}
/*******************************************************************
reads or writes an RPC_HDR_RR structure.
********************************************************************/
void smb_io_rpc_hdr_rr(char *desc, RPC_HDR_RR *rpc, prs_struct *ps, int depth)
{
if (rpc == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_hdr_rr");
depth++;
prs_uint32("alloc_hint", ps, depth, &(rpc->alloc_hint));
prs_uint8 ("context_id", ps, depth, &(rpc->context_id));
prs_uint8 ("cancel_ct ", ps, depth, &(rpc->cancel_count));
prs_uint8 ("opnum ", ps, depth, &(rpc->opnum));
prs_uint8 ("reserved ", ps, depth, &(rpc->reserved));
}
/*******************************************************************
creates an RPC_AUTH_NTLMSSP_REQ structure.
********************************************************************/
void make_rpc_auth_ntlmssp_req(RPC_AUTH_NTLMSSP_REQ *req,
fstring ntlmssp_str, uint32 ntlmssp_ver,
uint32 unknown_0, fstring myname, fstring domain)
{
int len_myname = strlen(myname);
int len_domain = strlen(domain);
if (req == NULL) return;
fstrcpy(req->ntlmssp_str, ntlmssp_str); /* "NTLMSSP" */
req->ntlmssp_ver = ntlmssp_ver; /* 0x0000 0001 */
req->unknown_0 = unknown_0 ; /* 0x00b2b3 */
make_str_hdr(&req->hdr_myname, len_myname, len_myname, 1);
make_str_hdr(&req->hdr_domain, len_domain, len_domain, 1);
fstrcpy(req->myname, myname);
fstrcpy(req->domain, domain);
}
/*******************************************************************
reads or writes an RPC_AUTH_NTLMSSP_REQ structure.
********************************************************************/
void smb_io_rpc_auth_ntlmssp_req(char *desc, RPC_AUTH_NTLMSSP_REQ *req, prs_struct *ps, int depth)
{
if (req == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_req");
depth++;
prs_string("ntlmssp_str", ps, depth, req->ntlmssp_str, 0); /* "NTLMSSP" */
prs_uint32("ntlmssp_ver", ps, depth, &(req->ntlmssp_ver ));
prs_uint32("unknown_0 ", ps, depth, &(req->unknown_0 ));
smb_io_strhdr("hdr_myname", &(req->hdr_myname), ps, depth);
smb_io_strhdr("hdr_domain", &(req->hdr_domain), ps, depth);
prs_string("myname", ps, depth, req->myname, req->hdr_myname.str_str_len);
prs_string("domain", ps, depth, req->domain, req->hdr_domain.str_str_len);
}
/*******************************************************************
creates an RPC_AUTH_NTLMSSP_RESP structure.
********************************************************************/
void make_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp,
uint8 auth_type, uint8 auth_level, uint8 stub_type_len,
fstring ntlmssp_str, uint32 ntlmssp_ver,
uint32 unknown_1, uint32 unknown_2, uint32 unknown_3,
uint8 data[16])
{
if (rsp == NULL) return;
rsp->auth_type = auth_type; /* nt lm ssp 0x0a */
rsp->auth_level = auth_level; /* 0x06 */
rsp->stub_type_len = stub_type_len; /* dunno. */
rsp->padding = 0; /* padding */
rsp->ptr_0 = 1; /* non-zero pointer to something */
fstrcpy(rsp->ntlmssp_str, ntlmssp_str); /* "NTLMSSP" */
rsp->ntlmssp_ver = ntlmssp_ver; /* 0x0000 0002 */
rsp->unknown_1 = unknown_1; /* 0x0000 0000 */
rsp->unknown_2 = unknown_2; /* 0x00b2b3 */
rsp->unknown_3 = unknown_3; /* 0x0082b1 */
memcpy(rsp->data, data, sizeof(rsp->data)); /* 0x10 bytes of something, 8 of which are zeros */
}
/*******************************************************************
reads or writes an RPC_AUTH_NTLMSSP_RESP structure.
********************************************************************/
void smb_io_rpc_auth_ntlmssp_resp(char *desc, RPC_AUTH_NTLMSSP_RESP *rsp, prs_struct *ps, int depth)
{
if (rsp == NULL) return;
prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_resp");
depth++;
prs_uint8("auth_type", ps, depth, &(rsp->auth_type)); /* nt lm ssp 0x0a */
prs_uint8("auth_level", ps, depth, &(rsp->auth_level));/* 0x06 */
prs_uint8("stub_type_len", ps, depth, &(rsp->stub_type_len));
prs_uint8("padding", ps, depth, &(rsp->padding));
prs_uint32("ptr_0", ps, depth, &(rsp->ptr_0 )); /* non-zero pointer to something */
prs_string("ntlmssp_str", ps, depth, rsp->ntlmssp_str, 0); /* "NTLMSSP" */
prs_uint32("ntlmssp_ver", ps, depth, &(rsp->ntlmssp_ver )); /* 0x0000 0002 */
prs_uint32("unknown_1", ps, depth, &(rsp->unknown_1)); /* 0x0000 0000 */
prs_uint32("unknown_2", ps, depth, &(rsp->unknown_2)); /* 0x00b2b3 */
prs_uint32("unknown_3", ps, depth, &(rsp->unknown_3)); /* 0x0082b1 */
prs_uint8s (False, "data", ps, depth, rsp->data, sizeof(rsp->data));
}
#if 0
/* attached to the end of encrypted rpc requests and responses */
/* RPC_AUTH_NTLMSSP_CHK */
typedef struct rpc_auth_ntlmssp_chk_info
{
uint32 ver; /* 0x1 */
uint8 data[12];
} RPC_AUTH_NTLMSSP_CHK;
#endif /* 0 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,146 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
extern int DEBUGLEVEL;
/*******************************************************************
make_wks_q_query_info
********************************************************************/
void make_wks_q_query_info(WKS_Q_QUERY_INFO *q_u,
char *server, uint16 switch_value)
{
DEBUG(5,("make_wks_q_query_info: %d\n", __LINE__));
make_buf_unistr2(&(q_u->uni_srv_name), &(q_u->ptr_srv_name), server);
q_u->switch_value = switch_value;
}
/*******************************************************************
reads or writes a WKS_Q_QUERY_INFO structure.
********************************************************************/
void wks_io_q_query_info(char *desc, WKS_Q_QUERY_INFO *q_u, prs_struct *ps, int depth)
{
if (q_u == NULL) return;
prs_debug(ps, depth, desc, "wks_io_q_query_info");
depth++;
prs_align(ps);
prs_uint32("ptr_srv_name", ps, depth, &(q_u->ptr_srv_name));
smb_io_unistr2("", &(q_u->uni_srv_name), q_u->ptr_srv_name, ps, depth);
prs_align(ps);
prs_uint16("switch_value", ps, depth, &(q_u->switch_value));
prs_align(ps);
}
/*******************************************************************
wks_info_100
********************************************************************/
void make_wks_info_100(WKS_INFO_100 *inf,
uint32 platform_id, uint32 ver_major, uint32 ver_minor,
char *my_name, char *domain_name)
{
DEBUG(5,("WKS_INFO_100: %d\n", __LINE__));
inf->platform_id = platform_id; /* 0x0000 01f4 - unknown */
inf->ver_major = ver_major; /* os major version */
inf->ver_minor = ver_minor; /* os minor version */
make_buf_unistr2(&(inf->uni_compname), &(inf->ptr_compname), my_name );
make_buf_unistr2(&(inf->uni_lan_grp ), &(inf->ptr_lan_grp ), domain_name);
}
/*******************************************************************
reads or writes a WKS_INFO_100 structure.
********************************************************************/
void wks_io_wks_info_100(char *desc, WKS_INFO_100 *inf, prs_struct *ps, int depth)
{
if (inf == NULL) return;
prs_debug(ps, depth, desc, "wks_io_wks_info_100");
depth++;
prs_align(ps);
prs_uint32("platform_id ", ps, depth, &(inf->platform_id )); /* 0x0000 01f4 - unknown */
prs_uint32("ptr_compname", ps, depth, &(inf->ptr_compname)); /* pointer to computer name */
prs_uint32("ptr_lan_grp ", ps, depth, &(inf->ptr_lan_grp )); /* pointer to LAN group name */
prs_uint32("ver_major ", ps, depth, &(inf->ver_major )); /* 4 - major os version */
prs_uint32("ver_minor ", ps, depth, &(inf->ver_minor )); /* 0 - minor os version */
smb_io_unistr2("", &(inf->uni_compname), inf->ptr_compname, ps, depth);
prs_align(ps);
smb_io_unistr2("", &(inf->uni_lan_grp ), inf->ptr_lan_grp , ps, depth);
prs_align(ps);
}
/*******************************************************************
make_wks_r_query_info
only supports info level 100 at the moment.
********************************************************************/
void make_wks_r_query_info(WKS_R_QUERY_INFO *r_u,
uint32 switch_value, WKS_INFO_100 *wks100,
int status)
{
DEBUG(5,("make_wks_r_unknown_0: %d\n", __LINE__));
r_u->switch_value = switch_value; /* same as in request */
r_u->ptr_1 = 1; /* pointer 1 */
r_u->wks100 = wks100;
r_u->status = status;
}
/*******************************************************************
reads or writes a structure.
********************************************************************/
void wks_io_r_query_info(char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int depth)
{
if (r_u == NULL) return;
prs_debug(ps, depth, desc, "wks_io_r_query_info");
depth++;
prs_align(ps);
prs_uint16("switch_value", ps, depth, &(r_u->switch_value)); /* level 100 (0x64) */
prs_align(ps);
prs_uint32("ptr_1 ", ps, depth, &(r_u->ptr_1 )); /* pointer 1 */
wks_io_wks_info_100("inf", r_u->wks100, ps, depth);
prs_uint32("status ", ps, depth, &(r_u->status));
}

View File

@ -0,0 +1,444 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
#include "nterr.h"
extern int DEBUGLEVEL;
/***************************************************************************
lsa_reply_open_policy
***************************************************************************/
static void lsa_reply_open_policy(prs_struct *rdata)
{
int i;
LSA_R_OPEN_POL r_o;
/* set up the LSA QUERY INFO response */
bzero(&(r_o.pol.data), POL_HND_SIZE);
for (i = 4; i < POL_HND_SIZE; i++)
{
r_o.pol.data[i] = i;
}
r_o.status = 0x0;
/* store the response in the SMB stream */
lsa_io_r_open_pol("", &r_o, rdata, 0);
}
/***************************************************************************
make_dom_query
***************************************************************************/
static void make_dom_query(DOM_QUERY *d_q, char *dom_name, char *dom_sid)
{
int domlen = strlen(dom_name);
d_q->uni_dom_max_len = domlen * 2;
d_q->uni_dom_str_len = domlen * 2;
d_q->buffer_dom_name = 4; /* domain buffer pointer */
d_q->buffer_dom_sid = 2; /* domain sid pointer */
/* this string is supposed to be character short */
make_unistr2(&(d_q->uni_domain_name), dom_name, domlen);
make_dom_sid2(&(d_q->dom_sid), dom_sid);
}
/***************************************************************************
lsa_reply_query_info
***************************************************************************/
static void lsa_reply_enum_trust_dom(LSA_Q_ENUM_TRUST_DOM *q_e,
prs_struct *rdata,
uint32 enum_context, char *dom_name, char *dom_sid)
{
LSA_R_ENUM_TRUST_DOM r_e;
/* set up the LSA QUERY INFO response */
make_r_enum_trust_dom(&r_e, enum_context, dom_name, dom_sid,
dom_name != NULL ? 0x0 : 0x80000000 | NT_STATUS_UNABLE_TO_FREE_VM);
/* store the response in the SMB stream */
lsa_io_r_enum_trust_dom("", &r_e, rdata, 0);
}
/***************************************************************************
lsa_reply_query_info
***************************************************************************/
static void lsa_reply_query_info(LSA_Q_QUERY_INFO *q_q, prs_struct *rdata,
char *dom_name, char *dom_sid)
{
LSA_R_QUERY_INFO r_q;
/* set up the LSA QUERY INFO response */
r_q.undoc_buffer = 0x22000000; /* bizarre */
r_q.info_class = q_q->info_class;
make_dom_query(&r_q.dom.id5, dom_name, dom_sid);
r_q.status = 0x0;
/* store the response in the SMB stream */
lsa_io_r_query("", &r_q, rdata, 0);
}
/***************************************************************************
make_dom_ref
pretty much hard-coded choice of "other" sids, unfortunately...
***************************************************************************/
static void make_dom_ref(DOM_R_REF *ref,
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
int len_dom_name = strlen(dom_name);
int len_other_sid1 = strlen(other_sid1);
int len_other_sid2 = strlen(other_sid2);
int len_other_sid3 = strlen(other_sid3);
ref->undoc_buffer = 1;
ref->num_ref_doms_1 = 4;
ref->buffer_dom_name = 1;
ref->max_entries = 32;
ref->num_ref_doms_2 = 4;
make_uni_hdr2(&(ref->hdr_dom_name ), len_dom_name , len_dom_name , 0);
make_uni_hdr2(&(ref->hdr_ref_dom[0]), len_other_sid1, len_other_sid1, 0);
make_uni_hdr2(&(ref->hdr_ref_dom[1]), len_other_sid2, len_other_sid2, 0);
make_uni_hdr2(&(ref->hdr_ref_dom[2]), len_other_sid3, len_other_sid3, 0);
if (dom_name != NULL)
{
make_unistr(&(ref->uni_dom_name), dom_name);
}
make_dom_sid2(&(ref->ref_dom[0]), dom_sid );
make_dom_sid2(&(ref->ref_dom[1]), other_sid1);
make_dom_sid2(&(ref->ref_dom[2]), other_sid2);
make_dom_sid2(&(ref->ref_dom[3]), other_sid3);
}
/***************************************************************************
make_reply_lookup_rids
***************************************************************************/
static void make_reply_lookup_rids(LSA_R_LOOKUP_RIDS *r_l,
int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
int i;
make_dom_ref(&(r_l->dom_ref), dom_name, dom_sid,
other_sid1, other_sid2, other_sid3);
r_l->num_entries = num_entries;
r_l->undoc_buffer = 1;
r_l->num_entries2 = num_entries;
for (i = 0; i < num_entries; i++)
{
make_dom_rid2(&(r_l->dom_rid[i]), dom_rids[i]);
}
r_l->num_entries3 = num_entries;
}
/***************************************************************************
make_lsa_trans_names
***************************************************************************/
static void make_lsa_trans_names(LSA_TRANS_NAME_ENUM *trn,
int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
uint32 *total)
{
uint32 status = 0x0;
int i;
(*total) = 0;
for (i = 0; i < num_entries; i++)
{
uint32 rid = 0xffffffff;
uint8 num_auths = sid[i].sid.num_auths;
fstring name;
uint32 type;
trn->ptr_name[i] = 0;
trn->ptr_name[(*total)] = 0;
/* find the rid to look up */
if (num_auths != 0)
{
rid = sid[i].sid.sub_auths[num_auths-1];
status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
status = (status != 0x0) ? lookup_user_name (rid, name, &type) : status;
status = (status != 0x0) ? lookup_group_name(rid, name, &type) : status;
status = (status != 0x0) ? lookup_alias_name(rid, name, &type) : status;
}
if (status == 0x0)
{
trn->ptr_name[i] = 1;
make_lsa_trans_name(&(trn->name[(*total)]), type, name, (*total));
(*total)++;
}
}
trn->num_entries = (*total);
trn->ptr_trans_names = 1;
trn->num_entries2 = (*total);
}
/***************************************************************************
make_reply_lookup_sids
***************************************************************************/
static void make_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
uint32 mapped_count, uint32 status)
{
r_l->dom_ref = ref;
r_l->names = names;
r_l->mapped_count = mapped_count;
r_l->status = status;
}
/***************************************************************************
lsa_reply_lookup_sids
***************************************************************************/
static void lsa_reply_lookup_sids(prs_struct *rdata,
int num_entries, DOM_SID2 sid[MAX_LOOKUP_SIDS],
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
LSA_R_LOOKUP_SIDS r_l;
DOM_R_REF ref;
LSA_TRANS_NAME_ENUM names;
uint32 mapped_count = 0;
/* set up the LSA Lookup SIDs response */
make_dom_ref(&ref, dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
make_lsa_trans_names(&names, num_entries, sid, &mapped_count);
make_reply_lookup_sids(&r_l, &ref, &names, mapped_count, 0x0);
/* store the response in the SMB stream */
lsa_io_r_lookup_sids("", &r_l, rdata, 0);
}
/***************************************************************************
lsa_reply_lookup_rids
***************************************************************************/
static void lsa_reply_lookup_rids(prs_struct *rdata,
int num_entries, uint32 dom_rids[MAX_LOOKUP_SIDS],
char *dom_name, char *dom_sid,
char *other_sid1, char *other_sid2, char *other_sid3)
{
LSA_R_LOOKUP_RIDS r_l;
/* set up the LSA Lookup RIDs response */
make_reply_lookup_rids(&r_l, num_entries, dom_rids,
dom_name, dom_sid, other_sid1, other_sid2, other_sid3);
r_l.status = 0x0;
/* store the response in the SMB stream */
lsa_io_r_lookup_rids("", &r_l, rdata, 0);
}
/***************************************************************************
api_lsa_open_policy
***************************************************************************/
static void api_lsa_open_policy( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_OPEN_POL q_o;
/* grab the server, object attributes and desired access flag...*/
lsa_io_q_open_pol("", &q_o, data, 0);
/* lkclXXXX having decoded it, ignore all fields in the open policy! */
/* return a 20 byte policy handle */
lsa_reply_open_policy(rdata);
}
/***************************************************************************
api_lsa_enum_trust_dom
***************************************************************************/
static void api_lsa_enum_trust_dom( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_ENUM_TRUST_DOM q_e;
/* grab the enum trust domain context etc. */
lsa_io_q_enum_trust_dom("", &q_e, data, 0);
/* construct reply. return status is always 0x0 */
lsa_reply_enum_trust_dom(&q_e, rdata,
0, NULL, NULL);
}
/***************************************************************************
api_lsa_query_info
***************************************************************************/
static void api_lsa_query_info( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_QUERY_INFO q_i;
pstring dom_name;
pstring dom_sid;
/* grab the info class and policy handle */
lsa_io_q_query("", &q_i, data, 0);
pstrcpy(dom_name, lp_workgroup());
pstrcpy(dom_sid , lp_domain_sid());
/* construct reply. return status is always 0x0 */
lsa_reply_query_info(&q_i, rdata, dom_name, dom_sid);
}
/***************************************************************************
api_lsa_lookup_sids
***************************************************************************/
static void api_lsa_lookup_sids( int uid, prs_struct *data,
prs_struct *rdata )
{
LSA_Q_LOOKUP_SIDS q_l;
pstring dom_name;
pstring dom_sid;
/* grab the info class and policy handle */
lsa_io_q_lookup_sids("", &q_l, data, 0);
pstrcpy(dom_name, lp_workgroup());
pstrcpy(dom_sid , lp_domain_sid());
/* construct reply. return status is always 0x0 */
lsa_reply_lookup_sids(rdata,
q_l.sids.num_entries, q_l.sids.sid, /* SIDs */
dom_name, dom_sid, /* domain name, domain SID */
"S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
}
/***************************************************************************
api_lsa_lookup_names
***************************************************************************/
static void api_lsa_lookup_names( int uid, prs_struct *data,
prs_struct *rdata )
{
int i;
LSA_Q_LOOKUP_RIDS q_l;
pstring dom_name;
pstring dom_sid;
uint32 dom_rids[MAX_LOOKUP_SIDS];
uint32 dummy_g_rid;
/* grab the info class and policy handle */
lsa_io_q_lookup_rids("", &q_l, data, 0);
pstrcpy(dom_name, lp_workgroup());
pstrcpy(dom_sid , lp_domain_sid());
/* convert received RIDs to strings, so we can do them. */
for (i = 0; i < q_l.num_entries; i++)
{
char *user_name = unistr2(q_l.lookup_name[i].str.buffer);
if (!name_to_rid(user_name, &dom_rids[i], &dummy_g_rid))
{
/* WHOOPS! we should really do something about this... */
dom_rids[i] = 0;
}
}
/* construct reply. return status is always 0x0 */
lsa_reply_lookup_rids(rdata,
q_l.num_entries, dom_rids, /* text-converted SIDs */
dom_name, dom_sid, /* domain name, domain SID */
"S-1-1", "S-1-3", "S-1-5"); /* the three other SIDs */
}
/***************************************************************************
api_lsa_close
***************************************************************************/
static void api_lsa_close( int uid, prs_struct *data,
prs_struct *rdata)
{
/* XXXX this is NOT good */
char *q = mem_data(&(rdata->data), rdata->offset);
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
rdata->offset += 24;
}
/***************************************************************************
api_lsa_open_secret
***************************************************************************/
static void api_lsa_open_secret( int uid, prs_struct *data,
prs_struct *rdata)
{
/* XXXX this is NOT good */
char *q = mem_data(&(rdata->data), rdata->offset);
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0); q += 4;
SIVAL(q, 0, 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND); q += 4;
rdata->offset += 24;
}
/***************************************************************************
\PIPE\ntlsa commands
***************************************************************************/
static struct api_struct api_lsa_cmds[] =
{
{ "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy },
{ "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info },
{ "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom },
{ "LSA_CLOSE" , LSA_CLOSE , api_lsa_close },
{ "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret },
{ "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids },
{ "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names },
{ NULL , 0 , NULL }
};
/***************************************************************************
api_ntLsarpcTNP
***************************************************************************/
BOOL api_ntlsa_rpc(pipes_struct *p, prs_struct *data)
{
return api_rpcTNP(p, "api_ntlsa_rpc", api_lsa_cmds, data);
}

View File

@ -0,0 +1,316 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
*
* 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"
extern int DEBUGLEVEL;
#ifndef MAX_OPEN_POLS
#define MAX_OPEN_POLS 50
#endif
struct reg_info
{
/* for use by \PIPE\winreg */
fstring name; /* name of registry key */
};
struct samr_info
{
/* for use by the \PIPE\samr policy */
DOM_SID sid;
uint32 rid; /* relative id associated with the pol_hnd */
uint32 status; /* some sort of flag. best to record it. comes from opnum 0x39 */
};
static struct
{
BOOL open;
POLICY_HND pol_hnd;
union
{
struct samr_info samr;
struct reg_info reg;
} dev;
} Policy[MAX_OPEN_POLS];
#define VALID_POL(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_POLS))
#define OPEN_POL(pnum) (VALID_POL(pnum) && Policy[pnum].open)
/****************************************************************************
create a unique policy handle
****************************************************************************/
void create_pol_hnd(POLICY_HND *hnd)
{
static uint32 pol_hnd_low = 0;
static uint32 pol_hnd_high = 0;
if (hnd == NULL) return;
/* i severely doubt that pol_hnd_high will ever be non-zero... */
pol_hnd_low++;
if (pol_hnd_low == 0) pol_hnd_high++;
SIVAL(hnd->data, 0 , 0x0); /* first bit must be null */
SIVAL(hnd->data, 4 , pol_hnd_low ); /* second bit is incrementing */
SIVAL(hnd->data, 8 , pol_hnd_high); /* second bit is incrementing */
SIVAL(hnd->data, 12, time(NULL)); /* something random */
SIVAL(hnd->data, 16, getpid()); /* something more random */
}
/****************************************************************************
initialise policy handle states...
****************************************************************************/
void init_lsa_policy_hnd(void)
{
int i;
for (i = 0; i < MAX_OPEN_POLS; i++)
{
Policy[i].open = False;
}
return;
}
/****************************************************************************
find first available policy slot. creates a policy handle for you.
****************************************************************************/
BOOL open_lsa_policy_hnd(POLICY_HND *hnd)
{
int i;
for (i = 0; i < MAX_OPEN_POLS; i++)
{
if (!Policy[i].open)
{
Policy[i].open = True;
create_pol_hnd(hnd);
memcpy(&(Policy[i].pol_hnd), hnd, sizeof(*hnd));
DEBUG(4,("Opened policy hnd[%x] ", i));
dump_data(4, hnd->data, sizeof(hnd->data));
return True;
}
}
/* i love obscure error messages. */
#if TERRY_PRATCHET_INTERESTING_TIMES
DEBUG(1,("+++ OUT OF CHEESE ERROR +++ REDO FROM START ... @?!*@@\n"));
#else
DEBUG(1,("ERROR - open_lsa_policy_hnd: out of Policy Handles!\n"));
#endif
return False;
}
/****************************************************************************
find policy index by handle
****************************************************************************/
int find_lsa_policy_by_hnd(POLICY_HND *hnd)
{
int i;
for (i = 0; i < MAX_OPEN_POLS; i++)
{
if (memcmp(&(Policy[i].pol_hnd), hnd, sizeof(*hnd)) == 0)
{
DEBUG(4,("Found policy hnd[%x] ", i));
dump_data(4, hnd->data, sizeof(hnd->data));
return i;
}
}
DEBUG(4,("Policy not found: "));
dump_data(4, hnd->data, sizeof(hnd->data));
return -1;
}
/****************************************************************************
set samr rid
****************************************************************************/
BOOL set_lsa_policy_samr_rid(POLICY_HND *hnd, uint32 rid)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy device rid=%x pnum=%x\n",
timestring(), rid, pnum));
Policy[pnum].dev.samr.rid = rid;
return True;
}
else
{
DEBUG(3,("%s Error setting policy rid=%x (pnum=%x)\n",
timestring(), rid, pnum));
return False;
}
}
/****************************************************************************
set samr pol status. absolutely no idea what this is.
****************************************************************************/
BOOL set_lsa_policy_samr_pol_status(POLICY_HND *hnd, uint32 pol_status)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy status=%x pnum=%x\n",
timestring(), pol_status, pnum));
Policy[pnum].dev.samr.status = pol_status;
return True;
}
else
{
DEBUG(3,("%s Error setting policy status=%x (pnum=%x)\n",
timestring(), pol_status, pnum));
return False;
}
}
/****************************************************************************
set samr sid
****************************************************************************/
BOOL set_lsa_policy_samr_sid(POLICY_HND *hnd, DOM_SID *sid)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy sid=%s pnum=%x\n",
timestring(), dom_sid_to_string(sid), pnum));
memcpy(&(Policy[pnum].dev.samr.sid), sid, sizeof(*sid));
return True;
}
else
{
DEBUG(3,("%s Error setting policy sid=%s (pnum=%x)\n",
timestring(), dom_sid_to_string(sid), pnum));
return False;
}
}
/****************************************************************************
set samr rid
****************************************************************************/
uint32 get_lsa_policy_samr_rid(POLICY_HND *hnd)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
uint32 rid = Policy[pnum].dev.samr.rid;
DEBUG(3,("%s Getting policy device rid=%x pnum=%x\n",
timestring(), rid, pnum));
return rid;
}
else
{
DEBUG(3,("%s Error getting policy (pnum=%x)\n",
timestring(), pnum));
return 0xffffffff;
}
}
/****************************************************************************
set reg name
****************************************************************************/
BOOL set_lsa_policy_reg_name(POLICY_HND *hnd, fstring name)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Setting policy pnum=%x name=%s\n",
timestring(), pnum, name));
fstrcpy(Policy[pnum].dev.reg.name, name);
return True;
}
else
{
DEBUG(3,("%s Error setting policy (pnum=%x) name=%s\n",
timestring(), pnum, name));
return False;
}
}
/****************************************************************************
get reg name
****************************************************************************/
BOOL get_lsa_policy_reg_name(POLICY_HND *hnd, fstring name)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
fstrcpy(name, Policy[pnum].dev.reg.name);
DEBUG(3,("%s Getting policy pnum=%x name=%s\n",
timestring(), pnum, name));
return True;
}
else
{
DEBUG(3,("%s Error getting policy (pnum=%x)\n",
timestring(), pnum));
return False;
}
}
/****************************************************************************
close an lsa policy
****************************************************************************/
BOOL close_lsa_policy_hnd(POLICY_HND *hnd)
{
int pnum = find_lsa_policy_by_hnd(hnd);
if (OPEN_POL(pnum))
{
DEBUG(3,("%s Closed policy name pnum=%x\n", timestring(), pnum));
Policy[pnum].open = False;
return True;
}
else
{
DEBUG(3,("%s Error closing policy pnum=%x\n", timestring(), pnum));
return False;
}
}

View File

@ -0,0 +1,832 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
#include "nterr.h"
extern int DEBUGLEVEL;
extern BOOL sam_logon_in_ssb;
extern pstring samlogon_user;
/*************************************************************************
make_net_r_req_chal:
*************************************************************************/
static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c,
DOM_CHAL *srv_chal, int status)
{
DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__));
memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
r_c->status = status;
}
/*************************************************************************
net_reply_req_chal:
*************************************************************************/
static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata,
DOM_CHAL *srv_chal, uint32 srv_time)
{
NET_R_REQ_CHAL r_c;
DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
/* set up the LSA REQUEST CHALLENGE response */
make_net_r_req_chal(&r_c, srv_chal, srv_time);
/* store the response in the SMB stream */
net_io_r_req_chal("", &r_c, rdata, 0);
DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
}
/*************************************************************************
net_reply_logon_ctrl2:
*************************************************************************/
static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata,
uint32 flags, uint32 pdc_status, uint32 logon_attempts,
uint32 tc_status, char *trust_domain_name)
{
NET_R_LOGON_CTRL2 r_l;
DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
/* set up the Logon Control2 response */
make_r_logon_ctrl2(&r_l, q_l->query_level,
flags, pdc_status, logon_attempts,
tc_status, trust_domain_name);
/* store the response in the SMB stream */
net_io_r_logon_ctrl2("", &r_l, rdata, 0);
DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
}
/*************************************************************************
net_reply_trust_dom_list:
*************************************************************************/
static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata,
uint32 num_trust_domains, char *trust_domain_name)
{
NET_R_TRUST_DOM_LIST r_t;
DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__));
/* set up the Trusted Domain List response */
make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name);
/* store the response in the SMB stream */
net_io_r_trust_dom("", &r_t, rdata, 0);
DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__));
}
/*************************************************************************
make_net_r_auth_2:
*************************************************************************/
static void make_net_r_auth_2(NET_R_AUTH_2 *r_a,
DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
{
memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs));
r_a->status = status;
}
/*************************************************************************
net_reply_auth_2:
*************************************************************************/
static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata,
DOM_CHAL *resp_cred, int status)
{
NET_R_AUTH_2 r_a;
/* set up the LSA AUTH 2 response */
make_net_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
/* store the response in the SMB stream */
net_io_r_auth_2("", &r_a, rdata, 0);
}
/***********************************************************************************
make_net_r_srv_pwset:
***********************************************************************************/
static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
DOM_CRED *srv_cred, int status)
{
DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred));
r_s->status = status;
DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
}
/*************************************************************************
net_reply_srv_pwset:
*************************************************************************/
static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata,
DOM_CRED *srv_cred, int status)
{
NET_R_SRV_PWSET r_s;
DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
/* set up the LSA Server Password Set response */
make_net_r_srv_pwset(&r_s, srv_cred, status);
/* store the response in the SMB stream */
net_io_r_srv_pwset("", &r_s, rdata, 0);
DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
}
/*************************************************************************
net_reply_sam_logon:
*************************************************************************/
static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata,
DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info,
uint32 status)
{
NET_R_SAM_LOGON r_s;
/* XXXX maybe we want to say 'no', reject the client's credentials */
r_s.buffer_creds = 1; /* yes, we have valid server credentials */
memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
/* store the user information, if there is any. */
r_s.user = user_info;
if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0)
{
r_s.switch_value = 3; /* indicates type of validation user info */
}
else
{
r_s.switch_value = 0; /* indicates no info */
}
r_s.status = status;
r_s.auth_resp = 1; /* authoritative response */
/* store the response in the SMB stream */
net_io_r_sam_logon("", &r_s, rdata, 0);
}
/*************************************************************************
net_reply_sam_logoff:
*************************************************************************/
static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata,
DOM_CRED *srv_cred,
uint32 status)
{
NET_R_SAM_LOGOFF r_s;
/* XXXX maybe we want to say 'no', reject the client's credentials */
r_s.buffer_creds = 1; /* yes, we have valid server credentials */
memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
r_s.status = status;
/* store the response in the SMB stream */
net_io_r_sam_logoff("", &r_s, rdata, 0);
}
/******************************************************************
gets a machine password entry. checks access rights of the host.
******************************************************************/
static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct)
{
struct smb_passwd *smb_pass;
if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
client_name(), client_addr()))
{
DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
return False;
}
become_root(True);
smb_pass = get_smbpwd_entry(mach_acct, 0);
unbecome_root(True);
if (smb_pass != NULL)
{
memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
dump_data(5, md4pw, 16);
return True;
}
DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
return False;
}
/*************************************************************************
api_net_req_chal:
*************************************************************************/
static void api_net_req_chal( int uid,
prs_struct *data,
prs_struct *rdata)
{
NET_Q_REQ_CHAL q_r;
uint32 status = 0x0;
fstring mach_acct;
fstring mach_name;
user_struct *vuser;
DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, uid));
if ((vuser = get_valid_user_struct(uid)) == NULL) return;
/* grab the challenge... */
net_io_q_req_chal("", &q_r, data, 0);
fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer,
q_r.uni_logon_clnt.uni_str_len));
fstrcpy(mach_name, mach_acct);
strlower(mach_name);
strcat(mach_acct, "$");
if (get_md4pw(vuser->dc.md4pw, mach_name, mach_acct))
{
/* copy the client credentials */
memcpy(vuser->dc.clnt_chal.data , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
/* create a server challenge for the client */
/* PAXX: set these to random values. */
/* lkcl: paul, you mentioned that it doesn't really matter much */
SIVAL(vuser->dc.srv_chal.data, 0, 0x11111111);
SIVAL(vuser->dc.srv_chal.data, 4, 0x11111111);
memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8);
bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key));
/* from client / server challenges and md4 password, generate sess key */
cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
vuser->dc.md4pw, vuser->dc.sess_key);
}
else
{
/* lkclXXXX take a guess at a good error message to return :-) */
status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
}
/* construct reply. */
net_reply_req_chal(&q_r, rdata,
&(vuser->dc.srv_chal), status);
}
/*************************************************************************
api_net_auth_2:
*************************************************************************/
static void api_net_auth_2( int uid,
prs_struct *data,
prs_struct *rdata)
{
NET_Q_AUTH_2 q_a;
uint32 status = 0x0;
DOM_CHAL srv_cred;
UTIME srv_time;
user_struct *vuser;
if ((vuser = get_valid_user_struct(uid)) == NULL) return;
srv_time.time = 0;
/* grab the challenge... */
net_io_q_auth_2("", &q_a, data, 0);
/* check that the client credentials are valid */
if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
&(vuser->dc.clnt_cred.challenge), srv_time))
{
/* create server challenge for inclusion in the reply */
cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred);
/* copy the received client credentials for use next time */
memcpy(vuser->dc.clnt_cred.challenge.data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data));
memcpy(vuser->dc.srv_cred.challenge.data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data));
}
else
{
status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
}
/* construct reply. */
net_reply_auth_2(&q_a, rdata, &srv_cred, status);
}
/*************************************************************************
api_net_srv_pwset:
*************************************************************************/
static void api_net_srv_pwset( int uid,
prs_struct *data,
prs_struct *rdata)
{
NET_Q_SRV_PWSET q_a;
uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
DOM_CRED srv_cred;
#ifdef ALLOW_SRV_PWSET
pstring mach_acct;
struct smb_passwd *smb_pass;
BOOL ret;
#endif
user_struct *vuser;
if ((vuser = get_valid_user_struct(uid)) == NULL) return;
/* grab the challenge and encrypted password ... */
net_io_q_srv_pwset("", &q_a, data, 0);
/* checks and updates credentials. creates reply credentials */
if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
&(q_a.clnt_id.cred), &srv_cred))
{
memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
#ifdef ALLOW_SRV_PWSET
pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
q_a.clnt_id.login.uni_acct_name.uni_str_len));
DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
become_root(True);
smb_pass = get_smbpwd_entry(mach_acct, 0);
unbecome_root(True);
if (smb_pass != NULL)
{
unsigned char pwd[16];
uint8 mode = 2;
memcpy(pwd, q_a.pwd, 16);
if (obfuscate_pwd(pwd, vuser->dc.sess_key, mode))
{
/* lies! nt and lm passwords are _not_ the same: don't care */
smb_pass->smb_passwd = pwd;
smb_pass->smb_nt_passwd = pwd;
smb_pass->acct_ctrl = ACB_WSTRUST;
become_root(True);
ret = mod_smbpwd_entry(smb_pass);
unbecome_root(True);
if (ret)
{
/* hooray! */
status = 0x0;
}
}
}
DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
#else
DEBUG(5,("api_net_srv_pwset: server password set being denied\n"));
#endif
}
else
{
/* lkclXXXX take a guess at a sensible error code to return... */
status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
}
/* construct reply. always indicate failure. nt keeps going... */
net_reply_srv_pwset(&q_a, rdata,
&srv_cred, status);
}
/*************************************************************************
api_net_sam_logoff:
*************************************************************************/
static void api_net_sam_logoff( int uid,
prs_struct *data,
prs_struct *rdata)
{
NET_Q_SAM_LOGOFF q_l;
NET_ID_INFO_CTR ctr;
DOM_CRED srv_cred;
user_struct *vuser;
if ((vuser = get_valid_user_struct(uid)) == NULL) return;
/* the DOM_ID_INFO_1 structure is a bit big. plus we might want to
dynamically allocate it inside net_io_q_sam_logon, at some point */
q_l.sam_id.ctr = &ctr;
/* grab the challenge... */
net_io_q_sam_logoff("", &q_l, data, 0);
/* checks and updates credentials. creates reply credentials */
deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
&(q_l.sam_id.client.cred), &srv_cred);
memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
/* construct reply. always indicate success */
net_reply_sam_logoff(&q_l, rdata,
&srv_cred,
0x0);
}
/*************************************************************************
net_login_interactive:
*************************************************************************/
static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
struct smb_passwd *smb_pass,
user_struct *vuser)
{
uint32 status = 0x0;
#ifdef USE_ARCFOUR
extern void arcfour(uint8 key[16], uint8 out[16], uint8 in[16]);
char nt_pwd[16];
char lm_pwd[16];
unsigned char arc4_key[16];
memset(arc4_key, 0, 16);
memcpy(arc4_key, vuser->dc.sess_key, 8);
arcfour(arc4_key, lm_pwd, id1->arc4_lm_owf.data);
arcfour(arc4_key, nt_pwd, id1->arc4_nt_owf.data);
#ifdef DEBUG_PASSWORD
DEBUG(100,("arcfour decrypt of lm owf password:"));
dump_data(100, lm_pwd, 16);
DEBUG(100,("arcfour decrypt of nt owf password:"));
dump_data(100, nt_pwd, 16);
#endif
if (memcmp(smb_pass->smb_passwd , lm_pwd, 16) != 0 &&
memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
{
status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
}
#else
/* sorry. have to assume that the password is always ok.
this _is_ ok, because the LSA SAM Logon is nothing to do
with SMB connections to shares.
*/
DEBUG(3,("SAM Logon. Password not being checked\n"));
#endif
return status;
}
/*************************************************************************
net_login_network:
*************************************************************************/
static uint32 net_login_network(NET_ID_INFO_2 *id2,
struct smb_passwd *smb_pass,
user_struct *vuser)
{
if ((id2->lm_chal_resp.str_str_len == 24 ||
id2->lm_chal_resp.str_str_len == 0) &&
id2->nt_chal_resp.str_str_len == 24 &&
(((smb_pass->smb_nt_passwd != NULL) &&
smb_password_check(id2->nt_chal_resp.buffer, smb_pass->smb_nt_passwd,
id2->lm_chal)) ||
smb_password_check(id2->lm_chal_resp.buffer, smb_pass->smb_passwd,
id2->lm_chal)))
{
return 0x0;
}
return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
}
/*************************************************************************
api_net_sam_logon:
*************************************************************************/
static void api_net_sam_logon( int uid,
prs_struct *data,
prs_struct *rdata)
{
NET_Q_SAM_LOGON q_l;
NET_ID_INFO_CTR ctr;
NET_USER_INFO_3 usr_info;
uint32 status = 0x0;
DOM_CRED srv_cred;
struct smb_passwd *smb_pass = NULL;
UNISTR2 *uni_samlogon_user = NULL;
user_struct *vuser = NULL;
if ((vuser = get_valid_user_struct(uid)) == NULL) return;
q_l.sam_id.ctr = &ctr;
net_io_q_sam_logon("", &q_l, data, 0);
/* checks and updates credentials. creates reply credentials */
if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
&(q_l.sam_id.client.cred), &srv_cred))
{
status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
}
else
{
memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
}
/* find the username */
if (status == 0x0)
{
switch (q_l.sam_id.logon_level)
{
case 1:
{
uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
uni_samlogon_user->uni_str_len));
DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. User:[%s]\n",
lp_workgroup(), samlogon_user));
break;
}
case 2:
{
uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
uni_samlogon_user->uni_str_len));
DEBUG(3,("SAM Logon (Network). Domain:[%s]. User:[%s]\n",
lp_workgroup(), samlogon_user));
break;
}
default:
{
DEBUG(2,("SAM Logon: unsupported switch value\n"));
status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
break;
}
}
}
/* check username exists */
if (status == 0x0)
{
pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
uni_samlogon_user->uni_str_len));
become_root(True);
smb_pass = get_smbpwd_entry(samlogon_user, 0);
unbecome_root(True);
if (smb_pass == NULL)
{
status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
}
}
/* validate password. */
if (status == 0x0)
{
switch (q_l.sam_id.logon_level)
{
case 1:
{
/* interactive login. passwords arcfour'd with session key */
status = net_login_interactive(&q_l.sam_id.ctr->auth.id1,
smb_pass, vuser);
break;
}
case 2:
{
/* network login. lm challenge and 24 byte responses */
status = net_login_network(&q_l.sam_id.ctr->auth.id2,
smb_pass, vuser);
break;
}
}
}
/* lkclXXXX this is the point at which, if the login was
successful, that the SAM Local Security Authority should
record that the user is logged in to the domain.
*/
/* return the profile plus other bits :-) */
if (status == 0x0)
{
DOM_GID gids[LSA_MAX_GROUPS];
int num_gids = 0;
NTTIME dummy_time;
pstring logon_script;
pstring profile_path;
pstring home_dir;
pstring home_drive;
pstring my_name;
pstring my_workgroup;
pstring domain_groups;
pstring dom_sid;
pstring other_sids;
extern pstring myname;
uint32 r_uid;
uint32 r_gid;
/* set up pointer indicating user/password failed to be found */
usr_info.ptr_user_info = 0;
dummy_time.low = 0xffffffff;
dummy_time.high = 0x7fffffff;
get_myname(myname, NULL);
/* XXXX hack to get standard_sub_basic() to use sam logon username */
/* possibly a better way would be to do a become_user() call */
sam_logon_in_ssb = True;
pstrcpy(logon_script, lp_logon_script ());
pstrcpy(profile_path, lp_logon_path ());
pstrcpy(dom_sid , lp_domain_sid ());
pstrcpy(other_sids , lp_domain_other_sids());
pstrcpy(my_workgroup, lp_workgroup ());
pstrcpy(home_drive , lp_logon_drive ());
pstrcpy(home_dir , lp_logon_home ());
pstrcpy(my_name , myname );
strupper(my_name);
get_domain_user_groups(domain_groups, samlogon_user);
num_gids = make_dom_gids(domain_groups, gids);
sam_logon_in_ssb = False;
if (name_to_rid(samlogon_user, &r_uid, &r_gid))
{
make_net_user_info3(&usr_info,
&dummy_time, /* logon_time */
&dummy_time, /* logoff_time */
&dummy_time, /* kickoff_time */
&dummy_time, /* pass_last_set_time */
&dummy_time, /* pass_can_change_time */
&dummy_time, /* pass_must_change_time */
samlogon_user , /* user_name */
vuser->real_name, /* full_name */
logon_script , /* logon_script */
profile_path , /* profile_path */
home_dir , /* home_dir */
home_drive , /* dir_drive */
0, /* logon_count */
0, /* bad_pw_count */
r_uid , /* RID user_id */
r_gid , /* RID group_id */
num_gids, /* uint32 num_groups */
gids , /* DOM_GID *gids */
0x20 , /* uint32 user_flgs (?) */
NULL, /* char sess_key[16] */
my_name , /* char *logon_srv */
my_workgroup, /* char *logon_dom */
dom_sid, /* char *dom_sid */
other_sids); /* char *other_sids */
}
else
{
status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
}
}
net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
}
/*************************************************************************
api_net_trust_dom_list:
*************************************************************************/
static void api_net_trust_dom_list( int uid,
prs_struct *data,
prs_struct *rdata)
{
NET_Q_TRUST_DOM_LIST q_t;
char *trusted_domain = "test_domain";
DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
/* grab the lsa trusted domain list query... */
net_io_q_trust_dom("", &q_t, data, 0);
/* construct reply. */
net_reply_trust_dom_list(&q_t, rdata,
1, trusted_domain);
DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
}
/*************************************************************************
error messages cropping up when using nltest.exe...
*************************************************************************/
#define ERROR_NO_SUCH_DOMAIN 0x54b
#define ERROR_NO_LOGON_SERVERS 0x51f
/*************************************************************************
api_net_logon_ctrl2:
*************************************************************************/
static void api_net_logon_ctrl2( int uid,
prs_struct *data,
prs_struct *rdata)
{
NET_Q_LOGON_CTRL2 q_l;
/* lkclXXXX - guess what - absolutely no idea what these are! */
uint32 flags = 0x0;
uint32 pdc_connection_status = 0x0;
uint32 logon_attempts = 0x0;
uint32 tc_status = ERROR_NO_LOGON_SERVERS;
char *trusted_domain = "test_domain";
DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
/* grab the lsa netlogon ctrl2 query... */
net_io_q_logon_ctrl2("", &q_l, data, 0);
/* construct reply. */
net_reply_logon_ctrl2(&q_l, rdata,
flags, pdc_connection_status, logon_attempts,
tc_status, trusted_domain);
DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
}
/*******************************************************************
array of \PIPE\NETLOGON operations
********************************************************************/
static struct api_struct api_net_cmds [] =
{
{ "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal },
{ "NET_AUTH2" , NET_AUTH2 , api_net_auth_2 },
{ "NET_SRVPWSET" , NET_SRVPWSET , api_net_srv_pwset },
{ "NET_SAMLOGON" , NET_SAMLOGON , api_net_sam_logon },
{ "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff },
{ "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 },
{ "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
{ NULL , 0 , NULL }
};
/*******************************************************************
receives a netlogon pipe and responds.
********************************************************************/
BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
{
return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
}

View File

@ -0,0 +1,315 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
*
* 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 PIPE "\\PIPE\\"
#define PIPELEN strlen(PIPE)
extern int DEBUGLEVEL;
static int chain_pnum = -1;
#ifndef MAX_OPEN_PIPES
#define MAX_OPEN_PIPES 50
#endif
#define PIPE_HANDLE_OFFSET 0x800
pipes_struct Pipes[MAX_OPEN_PIPES];
#define P_OPEN(p) ((p)->open)
#define P_OK(p,c) (P_OPEN(p) && (c)==((p)->cnum))
#define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES))
#define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && P_OPEN(&(Pipes[pnum])))
#define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum)
/****************************************************************************
reset pipe chain handle number
****************************************************************************/
void reset_chain_pnum(void)
{
chain_pnum = -1;
}
/****************************************************************************
sets chain pipe-file handle
****************************************************************************/
void set_chain_pnum(int new_pnum)
{
chain_pnum = new_pnum;
}
/****************************************************************************
initialise pipe handle states...
****************************************************************************/
void init_rpc_pipe_hnd(void)
{
int i;
/* we start at 1 here for an obscure reason I can't now remember,
but I think is important :-) */
for (i = 1; i < MAX_OPEN_PIPES; i++)
{
Pipes[i].open = False;
Pipes[i].name[0] = 0;
Pipes[i].pipe_srv_name[0] = 0;
Pipes[i].rhdr.data = NULL;
Pipes[i].rdata.data = NULL;
Pipes[i].rhdr.offset = 0;
Pipes[i].rdata.offset = 0;
Pipes[i].max_rdata_len = 0;
Pipes[i].hdr_offsets = 0;
}
return;
}
/****************************************************************************
find first available file slot
****************************************************************************/
int open_rpc_pipe_hnd(char *pipe_name, int cnum, uint16 vuid)
{
int i;
/* we start at 1 here for an obscure reason I can't now remember,
but I think is important :-) */
for (i = 1; i < MAX_OPEN_PIPES; i++)
{
if (!Pipes[i].open)
{
Pipes[i].open = True;
Pipes[i].device_state = 0;
Pipes[i].cnum = cnum;
Pipes[i].uid = vuid;
Pipes[i].rhdr.data = NULL;
Pipes[i].rdata.data = NULL;
Pipes[i].rhdr.offset = 0;
Pipes[i].rdata.offset = 0;
Pipes[i].max_rdata_len = 0;
Pipes[i].hdr_offsets = 0;
fstrcpy(Pipes[i].name, pipe_name);
DEBUG(4,("Opened pipe %s with handle %x\n",
pipe_name, i + PIPE_HANDLE_OFFSET));
set_chain_pnum(i);
return(i);
}
}
DEBUG(1,("ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES?\n"));
return(-1);
}
/****************************************************************************
reads data from a pipe.
headers are interspersed with the data at regular intervals. by the time
this function is called, the start of the data could possibly have been
read by an SMBtrans (max_rdata_len != 0).
calling create_rpc_request() here is a fudge. the data should already
have been prepared into arrays of headers + data stream sections.
****************************************************************************/
int read_pipe(uint16 pnum, char *data, uint32 pos, int n)
{
int data_pos = pos;
pipes_struct *p = &Pipes[pnum - PIPE_HANDLE_OFFSET];
DEBUG(6,("read_pipe: %x", pnum));
if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
{
DEBUG(6,("name: %s cnum: %d open: %s data_pos: %lx len: %lx",
p->name,
p->cnum,
BOOLSTR(p->open),
data_pos, n));
}
if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
{
int num;
int len;
uint32 rpc_frag_pos;
DEBUG(6,("OK\n"));
if (p->rhdr.data == NULL || p->rhdr.data->data == NULL ||
p->rhdr.data->data_used == 0)
{
return 0;
}
/* the read request starts from where the SMBtrans2 left off. */
data_pos += p->max_rdata_len;
/* headers accumulate an offset */
data_pos -= p->hdr_offsets;
len = mem_buf_len(p->rhdr.data);
num = len - (int)data_pos;
if (num > n) num = n;
if (!IS_BITS_SET_ALL(p->hdr.flags, RPC_FLG_LAST))
{
rpc_frag_pos = data_pos % p->hdr.frag_len;
if (rpc_frag_pos == 0)
{
/* create and copy in a new header. */
create_rpc_reply(p, data_pos, p->rdata.offset);
mem_buf_copy(data, p->rhdr.data, 0, 0x18);
/* make room in data stream for header */
p->hdr_offsets += 0x18;
}
}
if (num > 0)
{
mem_buf_copy(data, p->rhdr.data, data_pos, num);
return num;
}
return 0;
}
else
{
DEBUG(6,("NOT\n"));
return -1;
}
}
/****************************************************************************
gets the name of a pipe
****************************************************************************/
BOOL get_rpc_pipe(int pnum, pipes_struct **p)
{
DEBUG(6,("get_rpc_pipe: "));
/* mapping is PIPE_HANDLE_OFFSET up... */
if (VALID_PNUM(pnum - PIPE_HANDLE_OFFSET))
{
DEBUG(6,("name: %s cnum: %d open: %s ",
Pipes[pnum - PIPE_HANDLE_OFFSET].name,
Pipes[pnum - PIPE_HANDLE_OFFSET].cnum,
BOOLSTR(Pipes[pnum - PIPE_HANDLE_OFFSET].open)));
}
if (OPEN_PNUM(pnum - PIPE_HANDLE_OFFSET))
{
DEBUG(6,("OK\n"));
(*p) = &(Pipes[pnum - PIPE_HANDLE_OFFSET]);
return True;
}
else
{
DEBUG(6,("NOT\n"));
return False;
}
}
/****************************************************************************
gets the name of a pipe
****************************************************************************/
char *get_rpc_pipe_hnd_name(int pnum)
{
pipes_struct *p = NULL;
get_rpc_pipe(pnum, &p);
return p != NULL ? p->name : NULL;
}
/****************************************************************************
set device state on a pipe. exactly what this is for is unknown...
****************************************************************************/
BOOL set_rpc_pipe_hnd_state(pipes_struct *p, uint16 device_state)
{
if (p == NULL) return False;
if (P_OPEN(p))
{
DEBUG(3,("%s Setting pipe device state=%x on pipe (name=%s cnum=%d)\n",
timestring(), device_state, p->name, p->cnum));
p->device_state = device_state;
return True;
}
else
{
DEBUG(3,("%s Error setting pipe device state=%x (name=%s cnum=%d)\n",
timestring(), device_state, p->name, p->cnum));
return False;
}
}
/****************************************************************************
close an rpc pipe
****************************************************************************/
BOOL close_rpc_pipe_hnd(int pnum, int cnum)
{
pipes_struct *p = NULL;
get_rpc_pipe(pnum, &p);
/* mapping is PIPE_HANDLE_OFFSET up... */
if (p != NULL && P_OK(p, cnum))
{
DEBUG(3,("%s Closed pipe name %s pnum=%x cnum=%d\n",
timestring(),Pipes[pnum-PIPE_HANDLE_OFFSET].name, pnum,cnum));
p->open = False;
p->rdata.offset = 0;
p->rhdr.offset = 0;
mem_buf_free(&(p->rdata.data));
mem_buf_free(&(p->rhdr .data));
return True;
}
else
{
DEBUG(3,("%s Error closing pipe pnum=%x cnum=%d\n",
timestring(),pnum, cnum));
return False;
}
}
/****************************************************************************
close an rpc pipe
****************************************************************************/
int get_rpc_pipe_num(char *buf, int where)
{
return (chain_pnum != -1 ? chain_pnum : SVAL(buf,where));
}

View File

@ -0,0 +1,240 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
#include "nterr.h"
extern int DEBUGLEVEL;
/*******************************************************************
reg_reply_unknown_1
********************************************************************/
static void reg_reply_close(REG_Q_CLOSE *q_r,
prs_struct *rdata)
{
REG_R_CLOSE r_u;
/* set up the REG unknown_1 response */
bzero(&(r_u.pol.data), POL_HND_SIZE);
/* close the policy handle */
if (close_lsa_policy_hnd(&(q_r->pol)))
{
r_u.status = 0;
}
else
{
r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
}
DEBUG(5,("reg_unknown_1: %d\n", __LINE__));
/* store the response in the SMB stream */
reg_io_r_close("", &r_u, rdata, 0);
DEBUG(5,("reg_unknown_1: %d\n", __LINE__));
}
/*******************************************************************
api_reg_close
********************************************************************/
static void api_reg_close( int uid, prs_struct *data,
prs_struct *rdata )
{
REG_Q_CLOSE q_r;
/* grab the reg unknown 1 */
reg_io_q_close("", &q_r, data, 0);
/* construct reply. always indicate success */
reg_reply_close(&q_r, rdata);
}
/*******************************************************************
reg_reply_open
********************************************************************/
static void reg_reply_open(REG_Q_OPEN_POLICY *q_r,
prs_struct *rdata)
{
REG_R_OPEN_POLICY r_u;
r_u.status = 0x0;
/* get a (unique) handle. open a policy on it. */
if (r_u.status == 0x0 && !open_lsa_policy_hnd(&(r_u.pol)))
{
r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
DEBUG(5,("reg_open: %d\n", __LINE__));
/* store the response in the SMB stream */
reg_io_r_open_policy("", &r_u, rdata, 0);
DEBUG(5,("reg_open: %d\n", __LINE__));
}
/*******************************************************************
api_reg_open
********************************************************************/
static void api_reg_open( int uid, prs_struct *data,
prs_struct *rdata )
{
REG_Q_OPEN_POLICY q_u;
/* grab the reg open */
reg_io_q_open_policy("", &q_u, data, 0);
/* construct reply. always indicate success */
reg_reply_open(&q_u, rdata);
}
/*******************************************************************
reg_reply_open_entry
********************************************************************/
static void reg_reply_open_entry(REG_Q_OPEN_ENTRY *q_u,
prs_struct *rdata)
{
uint32 status = 0;
POLICY_HND pol;
REG_R_OPEN_ENTRY r_u;
fstring name;
DEBUG(5,("reg_open_entry: %d\n", __LINE__));
if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1)
{
status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
}
if (status == 0x0 && !open_lsa_policy_hnd(&pol))
{
status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
}
fstrcpy(name, unistrn2(q_u->uni_name.buffer, q_u->uni_name.uni_str_len));
if (status == 0x0)
{
DEBUG(5,("reg_open_entry: %s\n", name));
/* lkcl XXXX do a check on the name, here */
}
if (status == 0x0 && !set_lsa_policy_reg_name(&pol, name))
{
status = 0xC000000 | NT_STATUS_TOO_MANY_SECRETS; /* ha ha very droll */
}
make_reg_r_open_entry(&r_u, &pol, status);
/* store the response in the SMB stream */
reg_io_r_open_entry("", &r_u, rdata, 0);
DEBUG(5,("reg_open_entry: %d\n", __LINE__));
}
/*******************************************************************
api_reg_open_entry
********************************************************************/
static void api_reg_open_entry( int uid, prs_struct *data,
prs_struct *rdata )
{
REG_Q_OPEN_ENTRY q_u;
/* grab the reg open entry */
reg_io_q_open_entry("", &q_u, data, 0);
/* construct reply. */
reg_reply_open_entry(&q_u, rdata);
}
/*******************************************************************
reg_reply_info
********************************************************************/
static void reg_reply_info(REG_Q_INFO *q_u,
prs_struct *rdata)
{
uint32 status = 0;
REG_R_INFO r_u;
DEBUG(5,("reg_info: %d\n", __LINE__));
if (status == 0 && find_lsa_policy_by_hnd(&(q_u->pol)) == -1)
{
status = 0xC000000 | NT_STATUS_INVALID_HANDLE;
}
if (status == 0)
{
}
make_reg_r_info(&r_u, 1, "LanmanNT", 0x12, 0x12, status);
/* store the response in the SMB stream */
reg_io_r_info("", &r_u, rdata, 0);
DEBUG(5,("reg_open_entry: %d\n", __LINE__));
}
/*******************************************************************
api_reg_info
********************************************************************/
static void api_reg_info( int uid, prs_struct *data,
prs_struct *rdata )
{
REG_Q_INFO q_u;
/* grab the reg unknown 0x11*/
reg_io_q_info("", &q_u, data, 0);
/* construct reply. always indicate success */
reg_reply_info(&q_u, rdata);
}
/*******************************************************************
array of \PIPE\reg operations
********************************************************************/
static struct api_struct api_reg_cmds[] =
{
{ "REG_CLOSE" , REG_CLOSE , api_reg_close },
{ "REG_OPEN_ENTRY" , REG_OPEN_ENTRY , api_reg_open_entry },
{ "REG_OPEN" , REG_OPEN_POLICY , api_reg_open },
{ "REG_INFO" , REG_INFO , api_reg_info },
{ NULL, 0 , NULL }
};
/*******************************************************************
receives a reg pipe and responds.
********************************************************************/
BOOL api_reg_rpc(pipes_struct *p, prs_struct *data)
{
return api_rpcTNP(p, "api_reg_rpc", api_reg_cmds, data);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,477 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1998
* Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
* Copyright (C) Paul Ashton 1997-1998.
*
* 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 module apparently provides an implementation of DCE/RPC over a
* named pipe (IPC$ connection using SMBtrans). details of DCE/RPC
* documentation are available (in on-line form) from the X-Open group.
*
* this module should provide a level of abstraction between SMB
* and DCE/RPC, while minimising the amount of mallocs, unnecessary
* data copies, and network traffic.
*
* in this version, which takes a "let's learn what's going on and
* get something running" approach, there is additional network
* traffic generated, but the code should be easier to understand...
*
* ... if you read the docs. or stare at packets for weeks on end.
*
*/
#include "includes.h"
#include "nterr.h"
extern int DEBUGLEVEL;
/* array lookup of well-known RID aliases. the purpose of these escapes me.. */
/* XXXX this structure should not have the well-known RID groups added to it,
i.e the DOMAIN_GROUP_RID_ADMIN/USER/GUEST. */
rid_name domain_alias_rids[] =
{
{ DOMAIN_ALIAS_RID_ADMINS , "admins" },
{ DOMAIN_ALIAS_RID_USERS , "users" },
{ DOMAIN_ALIAS_RID_GUESTS , "guests" },
{ DOMAIN_ALIAS_RID_POWER_USERS , "power_users" },
{ DOMAIN_ALIAS_RID_ACCOUNT_OPS , "account_ops" },
{ DOMAIN_ALIAS_RID_SYSTEM_OPS , "system_ops" },
{ DOMAIN_ALIAS_RID_PRINT_OPS , "print_ops" },
{ DOMAIN_ALIAS_RID_BACKUP_OPS , "backup_ops" },
{ DOMAIN_ALIAS_RID_REPLICATOR , "replicator" },
{ 0 , NULL }
};
/* array lookup of well-known Domain RID groups. */
rid_name domain_group_rids[] =
{
{ DOMAIN_GROUP_RID_ADMINS , "domain admins" },
{ DOMAIN_GROUP_RID_USERS , "domain users" },
{ DOMAIN_GROUP_RID_GUESTS , "domain guests" },
{ 0 , NULL }
};
int make_dom_gids(char *gids_str, DOM_GID *gids)
{
char *ptr;
pstring s2;
int count;
DEBUG(4,("make_dom_gids: %s\n", gids_str));
if (gids_str == NULL || *gids_str == 0) return 0;
for (count = 0, ptr = gids_str; next_token(&ptr, s2, NULL) && count < LSA_MAX_GROUPS; count++)
{
/* the entries are of the form GID/ATTR, ATTR being optional.*/
char *attr;
uint32 rid = 0;
int i;
attr = strchr(s2,'/');
if (attr) *attr++ = 0;
if (!attr || !*attr) attr = "7"; /* default value for attribute is 7 */
/* look up the RID string and see if we can turn it into a rid number */
for (i = 0; domain_alias_rids[i].name != NULL; i++)
{
if (strequal(domain_alias_rids[i].name, s2))
{
rid = domain_alias_rids[i].rid;
break;
}
}
if (rid == 0) rid = atoi(s2);
if (rid == 0)
{
DEBUG(1,("make_dom_gids: unknown well-known alias RID %s/%s\n",
s2, attr));
count--;
}
else
{
gids[count].g_rid = rid;
gids[count].attr = atoi(attr);
DEBUG(5,("group id: %d attr: %d\n",
gids[count].g_rid,
gids[count].attr));
}
}
return count;
}
/*******************************************************************
gets a domain user's groups
********************************************************************/
void get_domain_user_groups(char *domain_groups, char *user)
{
pstring tmp;
if (domain_groups == NULL || user == NULL) return;
/* any additional groups this user is in. e.g power users */
pstrcpy(domain_groups, lp_domain_groups());
/* can only be a user or a guest. cannot be guest _and_ admin */
if (user_in_list(user, lp_domain_guest_users()))
{
sprintf(tmp, " %ld/7 ", DOMAIN_GROUP_RID_GUESTS);
strcat(domain_groups, tmp);
DEBUG(3,("domain guest access %s granted\n", tmp));
}
else
{
sprintf(tmp, " %ld/7 ", DOMAIN_GROUP_RID_USERS);
strcat(domain_groups, tmp);
DEBUG(3,("domain user access %s granted\n", tmp));
if (user_in_list(user, lp_domain_admin_users()))
{
sprintf(tmp, " %ld/7 ", DOMAIN_GROUP_RID_ADMINS);
strcat(domain_groups, tmp);
DEBUG(3,("domain admin access %s granted\n", tmp));
}
}
}
/*******************************************************************
turns a DCE/RPC request into a DCE/RPC reply
this is where the data really should be split up into an array of
headers and data sections.
********************************************************************/
BOOL create_rpc_reply(pipes_struct *p,
uint32 data_start, uint32 data_end)
{
mem_buf_init(&(p->rhdr.data), 0);
mem_alloc_data(p->rhdr.data, 0x18);
p->rhdr.align = 4;
p->rhdr.io = False;
p->hdr_rr.alloc_hint = data_end - data_start; /* calculate remaining data to be sent */
p->hdr.pkt_type = RPC_RESPONSE; /* mark header as an rpc response */
/* set up rpc header (fragmentation issues) */
if (data_start == 0)
{
p->hdr.flags = RPC_FLG_FIRST;
}
else
{
p->hdr.flags = 0;
}
if (p->hdr_rr.alloc_hint + 0x18 <= p->hdr_ba.bba.max_tsize)
{
p->hdr.flags |= RPC_FLG_LAST;
p->hdr.frag_len = p->hdr_rr.alloc_hint + 0x18;
}
else
{
p->hdr.frag_len = p->hdr_ba.bba.max_tsize;
}
p->rhdr.data->offset.start = 0;
p->rhdr.data->offset.end = 0x18;
/* store the header in the data stream */
p->rhdr.offset = 0;
smb_io_rpc_hdr ("hdr", &(p->hdr ), &(p->rhdr), 0);
smb_io_rpc_hdr_rr("rr" , &(p->hdr_rr), &(p->rhdr), 0);
return p->rhdr.data != NULL && p->rhdr.offset == 0x18;
}
/*******************************************************************
receives a netlogon pipe and responds.
********************************************************************/
static BOOL api_rpc_command(pipes_struct *p,
char *rpc_name, struct api_struct *api_rpc_cmds,
prs_struct *data)
{
int fn_num;
DEBUG(4,("api_rpc_command: %s op 0x%x - ", rpc_name, p->hdr_rr.opnum));
for (fn_num = 0; api_rpc_cmds[fn_num].name; fn_num++)
{
if (api_rpc_cmds[fn_num].opnum == p->hdr_rr.opnum && api_rpc_cmds[fn_num].fn != NULL)
{
DEBUG(3,("api_rpc_command: %s\n", api_rpc_cmds[fn_num].name));
break;
}
}
if (api_rpc_cmds[fn_num].name == NULL)
{
DEBUG(4, ("unknown\n"));
return False;
}
/* start off with 1024 bytes, and a large safety margin too */
mem_buf_init(&(p->rdata.data), SAFETY_MARGIN);
mem_alloc_data(p->rdata.data, 1024);
p->rdata.io = False;
p->rdata.align = 4;
p->rdata.data->offset.start = 0;
p->rdata.data->offset.end = 0xffffffff;
/* do the actual command */
p->rdata.offset = 0;
api_rpc_cmds[fn_num].fn(p->uid, data, &(p->rdata));
if (p->rdata.data == NULL || p->rdata.offset == 0)
{
mem_free_data(p->rdata.data);
return False;
}
mem_realloc_data(p->rdata.data, p->rdata.offset);
DEBUG(10,("called %s\n", rpc_name));
return True;
}
/*******************************************************************
receives a netlogon pipe and responds.
********************************************************************/
BOOL api_rpcTNP(pipes_struct *p, char *rpc_name, struct api_struct *api_rpc_cmds,
prs_struct *data)
{
if (data == NULL || data->data == NULL)
{
DEBUG(2,("%s: NULL data received\n", rpc_name));
return False;
}
/* read the rpc header */
smb_io_rpc_hdr_rr("", &(p->hdr_rr), data, 0);
/* interpret the command */
if (!api_rpc_command(p, rpc_name, api_rpc_cmds, data))
{
return False;
}
/* create the rpc header */
if (!create_rpc_reply(p, 0, p->rdata.offset))
{
return False;
}
/* set up the data chain */
p->rhdr.data->offset.start = 0;
p->rhdr.data->offset.end = p->rhdr.offset;
p->rhdr.data->next = p->rdata.data;
p->rdata.data->offset.start = p->rhdr.data->offset.end;
p->rdata.data->offset.end = p->rhdr.data->offset.end + p->rdata.offset;
p->rdata.data->next = NULL;
return True;
}
extern rid_name domain_group_rids[];
/*******************************************************************
lookup_group_name
********************************************************************/
uint32 lookup_group_name(uint32 rid, char *group_name, uint32 *type)
{
int i = 0;
(*type) = SID_NAME_DOM_GRP;
while (domain_group_rids[i].rid != rid && domain_group_rids[i].rid != 0)
{
i++;
}
if (domain_group_rids[i].rid != 0)
{
fstrcpy(group_name, domain_group_rids[i].name);
return 0x0;
}
return 0xC0000000 | NT_STATUS_NONE_MAPPED;
}
extern rid_name domain_alias_rids[];
/*******************************************************************
lookup_alias_name
********************************************************************/
uint32 lookup_alias_name(uint32 rid, char *alias_name, uint32 *type)
{
int i = 0;
(*type) = SID_NAME_WKN_GRP;
while (domain_alias_rids[i].rid != rid && domain_alias_rids[i].rid != 0)
{
i++;
}
if (domain_alias_rids[i].rid != 0)
{
fstrcpy(alias_name, domain_alias_rids[i].name);
return 0x0;
}
return 0xC0000000 | NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
lookup_user_name
********************************************************************/
uint32 lookup_user_name(uint32 rid, char *user_name, uint32 *type)
{
struct smb_passwd *smb_pass;
(*type) = SID_NAME_USER;
/* find the user account */
become_root(True);
smb_pass = get_smbpwd_entry(NULL, rid); /* lkclXXXX SHOULD use rid mapping here! */
unbecome_root(True);
if (smb_pass != NULL)
{
fstrcpy(user_name, smb_pass->smb_name);
return 0x0;
}
return 0xC0000000 | NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
lookup_group_rid
********************************************************************/
uint32 lookup_group_rid(char *group_name, uint32 *rid)
{
char *grp_name;
int i = -1; /* start do loop at -1 */
do /* find, if it exists, a group rid for the group name*/
{
i++;
(*rid) = domain_group_rids[i].rid;
grp_name = domain_group_rids[i].name;
} while (grp_name != NULL && !strequal(grp_name, group_name));
return (grp_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
lookup_alias_rid
********************************************************************/
uint32 lookup_alias_rid(char *alias_name, uint32 *rid)
{
char *als_name;
int i = -1; /* start do loop at -1 */
do /* find, if it exists, a alias rid for the alias name*/
{
i++;
(*rid) = domain_alias_rids[i].rid;
als_name = domain_alias_rids[i].name;
} while (als_name != NULL && !strequal(als_name, alias_name));
return (als_name != NULL) ? 0 : 0xC0000000 | NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
lookup_user_rid
********************************************************************/
uint32 lookup_user_rid(char *user_name, uint32 *rid)
{
struct smb_passwd *smb_pass;
(*rid) = 0;
/* find the user account */
become_root(True);
smb_pass = get_smbpwd_entry(user_name, 0);
unbecome_root(True);
if (smb_pass != NULL)
{
/* lkclXXXX SHOULD use name_to_rid() here! */
(*rid) = smb_pass->smb_userid;
return 0x0;
}
return 0xC0000000 | NT_STATUS_NONE_MAPPED;
}
/*******************************************************************
Group and User RID username mapping function
********************************************************************/
BOOL name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
{
struct passwd *pw = Get_Pwnam(user_name, False);
if (u_rid == NULL || g_rid == NULL || user_name == NULL)
{
return False;
}
if (!pw)
{
DEBUG(1,("Username %s is invalid on this system\n", user_name));
return False;
}
if (user_in_list(user_name, lp_domain_guest_users()))
{
*u_rid = DOMAIN_USER_RID_GUEST;
}
else if (user_in_list(user_name, lp_domain_admin_users()))
{
*u_rid = DOMAIN_USER_RID_ADMIN;
}
else
{
/* turn the unix UID into a Domain RID. this is what the posix
sub-system does (adds 1000 to the uid) */
*u_rid = (uint32)(pw->pw_uid + 1000);
}
/* absolutely no idea what to do about the unix GID to Domain RID mapping */
*g_rid = (uint32)(pw->pw_gid + 1000);
return True;
}

View File

@ -0,0 +1,113 @@
/*
* Unix SMB/Netbios implementation.
* Version 1.9.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-1997,
* Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
* Copyright (C) Paul Ashton 1997.
*
* 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"
#include "nterr.h"
extern int DEBUGLEVEL;
/*******************************************************************
create_wks_info_100
********************************************************************/
static void create_wks_info_100(WKS_INFO_100 *inf)
{
extern pstring myname;
pstring my_name;
pstring domain;
DEBUG(5,("create_wks_info_100: %d\n", __LINE__));
get_myname(myname, NULL);
pstrcpy (my_name, myname);
strupper(my_name);
pstrcpy (domain , lp_workgroup());
strupper(domain);
make_wks_info_100(inf,
0x000001f4, /* platform id info */
lp_major_announce_version(),
lp_minor_announce_version(),
my_name, domain);
}
/*******************************************************************
wks_reply_query_info
only supports info level 100 at the moment.
********************************************************************/
static void wks_reply_query_info(WKS_Q_QUERY_INFO *q_u,
prs_struct *rdata,
int status)
{
WKS_R_QUERY_INFO r_u;
WKS_INFO_100 wks100;
DEBUG(5,("wks_query_info: %d\n", __LINE__));
create_wks_info_100(&wks100);
make_wks_r_query_info(&r_u, q_u->switch_value, &wks100, status);
/* store the response in the SMB stream */
wks_io_r_query_info("", &r_u, rdata, 0);
DEBUG(5,("wks_query_info: %d\n", __LINE__));
}
/*******************************************************************
api_wks_query_info
********************************************************************/
static void api_wks_query_info( int uid, prs_struct *data,
prs_struct *rdata )
{
WKS_Q_QUERY_INFO q_u;
/* grab the net share enum */
wks_io_q_query_info("", &q_u, data, 0);
/* construct reply. always indicate success */
wks_reply_query_info(&q_u, rdata, 0x0);
}
/*******************************************************************
\PIPE\wkssvc commands
********************************************************************/
struct api_struct api_wks_cmds[] =
{
{ "WKS_Q_QUERY_INFO", WKS_QUERY_INFO, api_wks_query_info },
{ NULL , 0 , NULL }
};
/*******************************************************************
receives a wkssvc pipe and responds.
********************************************************************/
BOOL api_wkssvc_rpc(pipes_struct *p, prs_struct *data)
{
return api_rpcTNP(p, "api_wkssvc_rpc", api_wks_cmds, data);
}

View File

@ -64,7 +64,7 @@ BEGIN {
next;
}
!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|arc4_key/ {
!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|^arc4_key|^FILE/ {
next;
}

View File

@ -422,6 +422,12 @@ BOOL check_lanman_password(char *user, unsigned char *pass1,
return False;
}
if(smbpw->acct_ctrl & ACB_DISABLED)
{
DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
return False;
}
if(smbpw->smb_passwd == NULL)
{
DEBUG(0,("check_lanman_password: no lanman password !\n"));
@ -462,6 +468,12 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi
return False;
}
if(smbpw->acct_ctrl & ACB_DISABLED)
{
DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name));
return False;
}
if(smbpw->smb_passwd == NULL)
{
DEBUG(0,("change_lanman_password: no lanman password !\n"));

View File

@ -27,6 +27,7 @@
*/
#include "includes.h"
#include "nterr.h"
#ifdef CHECK_TYPES
#undef CHECK_TYPES
@ -131,79 +132,128 @@ static BOOL prefix_ok(char *str,char *prefix)
return(strncmp(str,prefix,strlen(prefix)) == 0);
}
/*******************************************************************
copies parameters and data, as needed, into the smb buffer
*both* the data and params sections should be aligned. this
is fudged in the rpc pipes by
at present, only the data section is. this may be a possible
cause of some of the ipc problems being experienced. lkcl26dec97
******************************************************************/
static void copy_trans_params_and_data(char *outbuf, int align,
struct mem_buf *rparam, struct mem_buf *rdata,
int param_offset, int data_offset,
int param_len, int data_len)
{
char *copy_into = smb_buf(outbuf);
DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
param_offset, param_offset + param_len,
data_offset , data_offset + data_len));
if (param_len) mem_buf_copy(copy_into, rparam, param_offset, param_len);
copy_into += param_len + align;
if (data_len ) mem_buf_copy(copy_into, rdata , data_offset , data_len);
}
/****************************************************************************
send a trans reply
****************************************************************************/
static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
int ldata,int lparam,int lsetup)
static void send_trans_reply(char *outbuf,
struct mem_buf *rdata,
struct mem_buf *rparam,
uint16 *setup, int lsetup, int max_data_ret)
{
int i;
int this_ldata,this_lparam;
int tot_data=0,tot_param=0;
int align;
int i;
int this_ldata,this_lparam;
int tot_data=0,tot_param=0;
int align;
this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
int ldata = rdata ? mem_buf_len(rdata ) : 0;
int lparam = rparam ? mem_buf_len(rparam) : 0;
BOOL buffer_too_large = max_data_ret ? ldata > max_data_ret : False;
if (buffer_too_large)
{
DEBUG(5,("send_trans_reply: buffer %d too large %d\n", ldata, max_data_ret));
ldata = max_data_ret;
}
this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
/* if you don't want Net Monitor to decode your packets, do this!!! */
align = ((this_lparam+1)%4);
/* if you don't want Net Monitor to decode your packets, do this!!! */
align = ((this_lparam+1)%4);
#else
align = (this_lparam%4);
align = (this_lparam%4);
#endif
set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
if (this_lparam)
memcpy(smb_buf(outbuf),param,this_lparam);
if (this_ldata)
memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
SSVAL(outbuf,smb_vwv0,lparam);
SSVAL(outbuf,smb_vwv1,ldata);
SSVAL(outbuf,smb_vwv3,this_lparam);
SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
SSVAL(outbuf,smb_vwv5,0);
SSVAL(outbuf,smb_vwv6,this_ldata);
SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
SSVAL(outbuf,smb_vwv8,0);
SSVAL(outbuf,smb_vwv9,lsetup);
for (i=0;i<lsetup;i++)
SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
if (buffer_too_large)
{
/* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
}
show_msg(outbuf);
send_smb(Client,outbuf);
copy_trans_params_and_data(outbuf, align,
rparam , rdata,
tot_param , tot_data,
this_lparam, this_ldata);
tot_data = this_ldata;
tot_param = this_lparam;
SSVAL(outbuf,smb_vwv0,lparam);
SSVAL(outbuf,smb_vwv1,ldata);
SSVAL(outbuf,smb_vwv3,this_lparam);
SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
SSVAL(outbuf,smb_vwv5,0);
SSVAL(outbuf,smb_vwv6,this_ldata);
SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
SSVAL(outbuf,smb_vwv8,0);
SSVAL(outbuf,smb_vwv9,lsetup);
while (tot_data < ldata || tot_param < lparam)
{
this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
for (i=0;i<lsetup;i++)
{
SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
}
align = (this_lparam%4);
show_msg(outbuf);
send_smb(Client,outbuf);
set_message(outbuf,10,this_ldata+this_lparam+align,False);
if (this_lparam)
memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
if (this_ldata)
memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
tot_data = this_ldata;
tot_param = this_lparam;
SSVAL(outbuf,smb_vwv3,this_lparam);
SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
SSVAL(outbuf,smb_vwv5,tot_param);
SSVAL(outbuf,smb_vwv6,this_ldata);
SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
SSVAL(outbuf,smb_vwv8,tot_data);
SSVAL(outbuf,smb_vwv9,0);
while (tot_data < ldata || tot_param < lparam)
{
this_lparam = MIN(lparam-tot_param, max_send - 500); /* hack */
this_ldata = MIN(ldata -tot_data , max_send - (500+this_lparam));
show_msg(outbuf);
send_smb(Client,outbuf);
align = (this_lparam%4);
tot_data += this_ldata;
tot_param += this_lparam;
}
set_message(outbuf,10,this_ldata+this_lparam+align,False);
copy_trans_params_and_data(outbuf, align,
rparam , rdata,
tot_param , tot_data,
this_lparam, this_ldata);
SSVAL(outbuf,smb_vwv3,this_lparam);
SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
SSVAL(outbuf,smb_vwv5,tot_param);
SSVAL(outbuf,smb_vwv6,this_ldata);
SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
SSVAL(outbuf,smb_vwv8,tot_data);
SSVAL(outbuf,smb_vwv9,0);
show_msg(outbuf);
send_smb(Client,outbuf);
tot_data += this_ldata;
tot_param += this_lparam;
}
}
struct pack_desc {
@ -1252,6 +1302,39 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
return(True);
}
/****************************************************************************
command 0x34 - suspected of being a "Lookup Names" stub api
****************************************************************************/
static BOOL api_RNetGroupGetUsers(int cnum, uint16 vuid, char *param, char *data,
int mdrcnt, int mprcnt, char **rdata,
char **rparam, int *rdata_len, int *rparam_len)
{
char *str1 = param+2;
char *str2 = skip_string(str1,1);
char *p = skip_string(str2,1);
int uLevel = SVAL(p,0);
int buf_len = SVAL(p,2);
int counted=0;
int missed=0;
DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
str1, str2, p, uLevel, buf_len));
if (!prefix_ok(str1,"zWrLeh")) return False;
*rdata_len = 0;
*rdata = NULL;
*rparam_len = 8;
*rparam = REALLOC(*rparam,*rparam_len);
SSVAL(*rparam,0,0x08AC); /* informational warning message */
SSVAL(*rparam,2,0);
SSVAL(*rparam,4,counted);
SSVAL(*rparam,6,counted+missed);
return(True);
}
/****************************************************************************
get info about a share
@ -2185,8 +2268,11 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
char *p2;
/* get NIS home of a previously validated user - simeon */
/* With share level security vuid will always be zero.
Don't depend on vuser being non-null !!. JRA */
user_struct *vuser = get_valid_user_struct(vuid);
DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
if(vuser != NULL)
DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
*rparam_len = 6;
*rparam = REALLOC(*rparam,*rparam_len);
@ -2236,7 +2322,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
/* EEK! the cifsrap.txt doesn't have this in!!!! */
SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
strcpy(p2,vuser->real_name); /* simeon */
strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
p2 = skip_string(p2,1);
}
@ -2292,7 +2378,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
{
SIVAL(p,60,0); /* auth_flags */
SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
strcpy(p2,vuser->real_name); /* simeon */
strcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
p2 = skip_string(p2,1);
SIVAL(p,68,0); /* urs_comment */
SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
@ -2920,30 +3006,253 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
return(True);
}
struct
struct api_cmd
{
char * name;
char * pipe_clnt_name;
#ifdef NTDOMAIN
char * pipe_srv_name;
#endif
int subcommand;
BOOL (*fn) ();
} api_fd_commands [] =
{
#ifdef NTDOMAIN
{ "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP },
{ "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP },
{ "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP },
{ "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP },
{ "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP },
{ NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported }
#else
{ "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP },
{ NULL, NULL, -1, (BOOL (*)())api_Unsupported }
#endif
};
BOOL (*fn) (pipes_struct *, prs_struct *);
};
static struct api_cmd api_fd_commands[] =
{
{ "lsarpc", "lsass", api_ntlsa_rpc },
{ "samr", "lsass", api_samr_rpc },
{ "srvsvc", "ntsvcs", api_srvsvc_rpc },
{ "wkssvc", "ntsvcs", api_wkssvc_rpc },
{ "NETLOGON", "lsass", api_netlog_rpc },
{ "winreg", "winreg", api_reg_rpc },
{ NULL, NULL, NULL }
};
static BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *pd)
{
BOOL ntlmssp_auth = False;
fstring ack_pipe_name;
int i = 0;
DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
{
if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
api_fd_commands[i].fn != NULL)
{
DEBUG(3,("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
api_fd_commands[i].pipe_clnt_name,
api_fd_commands[i].pipe_srv_name));
fstrcpy(p->pipe_srv_name, api_fd_commands[i].pipe_srv_name);
break;
}
}
if (api_fd_commands[i].fn == NULL) return False;
/* decode the bind request */
smb_io_rpc_hdr_rb("", &p->hdr_rb, pd, 0);
if (pd->offset == 0) return False;
if (p->hdr.auth_len != 0)
{
/* decode the authentication verifier */
smb_io_rpc_auth_ntlmssp_req("", &p->ntlmssp_req, pd, 0);
if (pd->offset == 0) return False;
/* ignore the version number for now */
ntlmssp_auth = strequal(p->ntlmssp_req.ntlmssp_str, "NTLMSSP");
}
/* name has to be \PIPE\xxxxx */
strcpy(ack_pipe_name, "\\PIPE\\");
strcat(ack_pipe_name, p->pipe_srv_name);
DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
prs_init(&(p->rdata), 1024, 4, 0, False);
prs_init(&(p->rhdr ), 0x10, 4, 0, False);
prs_init(&(p->rauth), 1024, 4, 0, False);
/***/
/*** do the bind ack first ***/
/***/
make_rpc_hdr_ba(&p->hdr_ba,
p->hdr_rb.bba.max_tsize,
p->hdr_rb.bba.max_rsize,
p->hdr_rb.bba.assoc_gid,
ack_pipe_name,
0x1, 0x0, 0x0,
&(p->hdr_rb.transfer));
smb_io_rpc_hdr_ba("", &p->hdr_ba, &p->rdata, 0);
mem_realloc_data(p->rdata.data, p->rdata.offset);
/***/
/*** now the authentication ***/
/***/
if (ntlmssp_auth)
{
uint8 data[16];
bzero(data, sizeof(data)); /* first 8 bytes are non-zero */
make_rpc_auth_ntlmssp_resp(&p->ntlmssp_resp,
0x0a, 0x06, 0,
"NTLMSSP", 2,
0x00000000, 0x0000b2b3, 0x000082b1,
data);
smb_io_rpc_auth_ntlmssp_resp("", &p->ntlmssp_resp, &p->rauth, 0);
mem_realloc_data(p->rauth.data, p->rauth.offset);
}
/***/
/*** then do the header, now we know the length ***/
/***/
make_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
p->hdr.call_id,
p->rdata.offset + p->rauth.offset,
p->rauth.offset);
smb_io_rpc_hdr("", &p->hdr, &p->rhdr, 0);
mem_realloc_data(p->rhdr.data, p->rdata.offset);
/***/
/*** link rpc header, bind acknowledgment and authentication responses ***/
/***/
p->rhdr.data->offset.start = 0;
p->rhdr.data->offset.end = p->rhdr.offset;
p->rhdr.data->next = p->rdata.data;
if (ntlmssp_auth)
{
p->rdata.data->offset.start = p->rhdr.offset;
p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
p->rdata.data->next = p->rauth.data;
p->rauth.data->offset.start = p->rhdr.offset + p->rdata.offset;
p->rauth.data->offset.end = p->rhdr.offset + p->rauth.offset + p->rdata.offset;
p->rauth.data->next = NULL;
}
else
{
p->rdata.data->offset.start = p->rhdr.offset;
p->rdata.data->offset.end = p->rhdr.offset + p->rdata.offset;
p->rdata.data->next = NULL;
}
return True;
}
static BOOL api_pipe_request(pipes_struct *p, prs_struct *pd)
{
int i = 0;
for (i = 0; api_fd_commands[i].pipe_clnt_name; i++)
{
if (strequal(api_fd_commands[i].pipe_clnt_name, p->name) &&
api_fd_commands[i].fn != NULL)
{
DEBUG(3,("Doing \\PIPE\\%s\n", api_fd_commands[i].pipe_clnt_name));
return api_fd_commands[i].fn(p, pd);
}
}
return False;
}
static BOOL api_dce_rpc_command(char *outbuf,
pipes_struct *p,
prs_struct *pd)
{
BOOL reply = False;
if (pd->data == NULL) return False;
/* process the rpc header */
smb_io_rpc_hdr("", &p->hdr, pd, 0);
if (pd->offset == 0) return False;
switch (p->hdr.pkt_type)
{
case RPC_BIND :
{
reply = api_pipe_bind_req(p, pd);
break;
}
case RPC_REQUEST:
{
reply = api_pipe_request (p, pd);
break;
}
}
if (reply)
{
/* now send the reply */
send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->max_rdata_len);
if (mem_buf_len(p->rhdr.data) <= p->max_rdata_len)
{
/* all of data was sent: no need to wait for SMBreadX calls */
mem_free_data(p->rhdr .data);
mem_free_data(p->rdata.data);
}
}
return reply;
}
/****************************************************************************
SetNamedPipeHandleState
****************************************************************************/
static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param)
{
uint16 id;
if (!param) return False;
id = param[0] + (param[1] << 8);
DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n", id));
if (set_rpc_pipe_hnd_state(p, id))
{
/* now send the reply */
send_trans_reply(outbuf, NULL, NULL, NULL, 0, p->max_rdata_len);
return True;
}
return False;
}
/****************************************************************************
when no reply is generated, indicate unsupported.
****************************************************************************/
static BOOL api_no_reply(char *outbuf, int max_rdata_len)
{
struct mem_buf rparam;
mem_init(&rparam, 0);
mem_alloc_data(&rparam, 4);
rparam.offset.start = 0;
rparam.offset.end = 4;
/* unsupported */
SSVAL(rparam.data,0,NERR_notsupported);
SSVAL(rparam.data,2,0); /* converter word */
DEBUG(3,("Unsupported API fd command\n"));
/* now send the reply */
send_trans_reply(outbuf, NULL, &rparam, NULL, 0, max_rdata_len);
mem_free_data(&rparam);
return(-1);
}
/****************************************************************************
handle remote api calls delivered to a named pipe already opened.
@ -2952,144 +3261,77 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
uint16 *setup,char *data,char *params,
int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
{
char *rdata = NULL;
char *rparam = NULL;
int rdata_len = 0;
int rparam_len = 0;
BOOL reply = False;
BOOL reply = False;
BOOL bind_req = False;
BOOL set_nphs = False;
int pnum;
int subcommand;
pipes_struct *p = NULL;
prs_struct pd;
struct mem_buf data_buf;
int i;
int fd;
int subcommand;
char *pipe_name;
DEBUG(5,("api_fd_reply\n"));
/* First find out the name of this file. */
if (suwcnt != 2)
{
DEBUG(0,("Unexpected named pipe transaction.\n"));
return(-1);
}
/* Get the file handle and hence the file name. */
fd = setup[1];
subcommand = setup[0];
pipe_name = get_rpc_pipe_hnd_name(fd);
DEBUG(5,("api_fd_reply\n"));
if (pipe_name == NULL)
{
DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd));
}
/* fake up a data buffer from the api_fd_reply data parameters */
mem_create(&data_buf, data, tdscnt, 0, False);
data_buf.offset.start = 0;
data_buf.offset.end = tdscnt;
DEBUG(3,("Got API command %d on pipe %s (fd %x)",
subcommand, pipe_name, fd));
DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
for (i = 0; api_fd_commands[i].name; i++)
{
if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) &&
api_fd_commands[i].subcommand == subcommand &&
api_fd_commands[i].fn)
{
DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
break;
}
}
rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
#ifdef NTDOMAIN
/* RPC Pipe command 0x26. */
if (data != NULL && api_fd_commands[i].subcommand == 0x26)
{
RPC_HDR hdr;
/* fake up a parsing structure */
pd.data = &data_buf;
pd.align = 4;
pd.io = True;
pd.offset = 0;
/* process the rpc header */
char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
/* bind request received */
if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
{
RPC_HDR_RB hdr_rb;
/* First find out the name of this file. */
if (suwcnt != 2)
{
DEBUG(0,("Unexpected named pipe transaction.\n"));
return(-1);
}
/* decode the bind request */
char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
/* Get the file handle and hence the file name. */
pnum = setup[1];
subcommand = setup[0];
get_rpc_pipe(pnum, &p);
if ((bind_req = (p != NULL)))
{
RPC_HDR_BA hdr_ba;
fstring ack_pipe_name;
if (p != NULL)
{
DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)",
subcommand, p->name, pnum));
DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
/* name has to be \PIPE\xxxxx */
strcpy(ack_pipe_name, "\\PIPE\\");
strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name);
/* record maximum data length that can be transmitted in an SMBtrans */
p->max_rdata_len = mdrcnt;
/* make a bind acknowledgement */
make_rpc_hdr_ba(&hdr_ba,
hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
ack_pipe_name,
0x1, 0x0, 0x0,
&(hdr_rb.transfer));
switch (subcommand)
{
case 0x26:
{
/* dce/rpc command */
reply = api_dce_rpc_command(outbuf, p, &pd);
break;
}
case 0x01:
{
/* Set Named Pipe Handle state */
reply = api_SNPHS(outbuf, p, params);
break;
}
}
}
else
{
DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
}
p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
rdata_len = PTR_DIFF(p, rdata);
make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
reply = (p != NULL);
}
}
}
#endif
/* Set Named Pipe Handle state */
if (subcommand == 0x1)
{
set_nphs = True;
reply = api_LsarpcSNPHS(fd, cnum, params);
}
if (!bind_req && !set_nphs)
{
DEBUG(10,("calling api_fd_command\n"));
reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
DEBUG(10,("called api_fd_command\n"));
}
if (rdata_len > mdrcnt || rparam_len > mprcnt)
{
reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
}
/* if we get False back then it's actually unsupported */
if (!reply)
{
api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
}
/* now send the reply */
send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
if (rdata ) free(rdata );
if (rparam) free(rparam);
return(-1);
if (!reply)
{
return api_no_reply(outbuf, mdrcnt);
}
return -1;
}
/****************************************************************************
the buffer was too small
****************************************************************************/
@ -3145,6 +3387,7 @@ struct
{"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
{"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
{"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
{"RNetGroupGetUsers", 52, (BOOL (*)())api_RNetGroupGetUsers,0},
{"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
{"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
{"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
@ -3177,6 +3420,8 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
{
int api_command = SVAL(params,0);
struct mem_buf rdata_buf;
struct mem_buf rparam_buf;
char *rdata = NULL;
char *rparam = NULL;
int rdata_len = 0;
@ -3216,14 +3461,20 @@ static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
&rdata,&rparam,&rdata_len,&rparam_len);
mem_create(&rdata_buf , rdata , rdata_len , 0, False);
mem_create(&rparam_buf, rparam, rparam_len, 0, False);
rdata_buf.offset.start = 0;
rdata_buf.offset.end = rdata_len;
rparam_buf.offset.start = 0;
rparam_buf.offset.end = rparam_len;
/* now send the reply */
send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
send_trans_reply(outbuf, &rdata_buf, &rparam_buf, NULL, 0, 0);
if (rdata)
free(rdata);
if (rparam)
free(rparam);
if (rdata ) free(rdata);
if (rparam) free(rparam);
return(-1);
}

View File

@ -876,6 +876,68 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha
return (memcmp(p24, password, 24) == 0);
}
/****************************************************************************
Do a specific test for an smb password being correct, given a smb_password and
the lanman and NT responses.
****************************************************************************/
BOOL smb_password_ok(struct smb_passwd *smb_pass,
uchar lm_pass[24], uchar nt_pass[24])
{
uchar challenge[8];
if (!lm_pass || !smb_pass) return(False);
if(smb_pass->acct_ctrl & ACB_DISABLED)
{
DEBUG(3,("smb_password_ok: account for user %s was disabled.\n", smb_pass->smb_name));
return(False);
}
if (!last_challenge(challenge))
{
DEBUG(1,("smb_password_ok: no challenge done - password failed\n"));
return False;
}
DEBUG(4,("smb_password_ok: Checking SMB password for user %s\n", smb_pass->smb_name));
if ((Protocol >= PROTOCOL_NT1) && (smb_pass->smb_nt_passwd != NULL))
{
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
DEBUG(4,("smb_password_ok: Checking NT MD4 password\n"));
if (smb_password_check(nt_pass, smb_pass->smb_nt_passwd, challenge))
{
DEBUG(4,("smb_password_ok: NT MD4 password check succeeded\n"));
return(True);
}
DEBUG(4,("smb_password_ok: NT MD4 password check failed\n"));
}
/* Try against the lanman password. smb_pass->smb_passwd == NULL means
no password, allow access. */
DEBUG(4,("Checking LM MD4 password\n"));
if((smb_pass->smb_passwd == NULL) && (smb_pass->acct_ctrl & ACB_PWNOTREQ))
{
DEBUG(4,("smb_password_ok: no password required for user %s\n", smb_pass->smb_name));
return True;
}
if((smb_pass->smb_passwd != NULL) && smb_password_check(lm_pass, smb_pass->smb_passwd, challenge))
{
DEBUG(4,("smb_password_ok: LM MD4 password check succeeded\n"));
return(True);
}
DEBUG(4,("smb_password_ok: LM MD4 password check failed\n"));
return False;
}
/****************************************************************************
check if a username/password is OK
****************************************************************************/
@ -940,6 +1002,13 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
return(False);
}
/* Quit if the account was disabled. */
if(smb_pass->acct_ctrl & ACB_DISABLED)
{
DEBUG(3,("password_ok: account for user %s was disabled.\n", user));
return(False);
}
/* Ensure the uid's match */
if (smb_pass->smb_userid != pass->pw_uid)
{
@ -947,35 +1016,13 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
return(False);
}
if (Protocol >= PROTOCOL_NT1)
{
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
if (smb_pass->smb_nt_passwd != NULL)
{
DEBUG(4,("Checking NT MD4 password\n"));
if (smb_password_check(password,
smb_pass->smb_nt_passwd,
(unsigned char *)challenge))
{
update_protected_database(user,True);
return(True);
}
DEBUG(4,("NT MD4 password check failed\n"));
}
}
if(smb_password_ok( smb_pass, password, password))
{
update_protected_database(user,True);
return(True);
}
/* Try against the lanman password */
if (smb_password_check(password,
smb_pass->smb_passwd,
(unsigned char *)challenge)) {
update_protected_database(user,True);
return(True);
}
DEBUG(3,("Error smb_password_check failed\n"));
DEBUG(3,("Error smb_password_check failed\n"));
}
DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));

View File

@ -51,17 +51,7 @@ extern fstring myworkgroup;
a packet to ensure chaining works correctly */
#define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where))
char * known_pipes [] =
{
"lsarpc",
#if NTDOMAIN
"NETLOGON",
"srvsvc",
"wkssvc",
"samr",
#endif
NULL
};
extern struct pipe_id_info pipe_names[];
/****************************************************************************
reply to an open and X on a named pipe
@ -72,7 +62,8 @@ char * known_pipes [] =
int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
pstring fname;
int cnum = SVAL(inbuf,smb_tid);
uint16 cnum = SVAL(inbuf, smb_tid);
uint16 vuid = SVAL(inbuf, smb_uid);
int pnum = -1;
int smb_ofun = SVAL(inbuf,smb_vwv8);
int size=0,fmode=0,mtime=0,rmode=0;
@ -89,23 +80,23 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
DEBUG(4,("Opening pipe %s.\n", fname));
/* Strip \PIPE\ off the name. */
pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
/* See if it is one we want to handle. */
for( i = 0; known_pipes[i] ; i++ )
if( strcmp(fname,known_pipes[i]) == 0 )
for( i = 0; pipe_names[i].client_pipe ; i++ )
if( strcmp(fname,pipe_names[i].client_pipe) == 0 )
break;
if ( known_pipes[i] == NULL )
if ( pipe_names[i].client_pipe == NULL )
return(ERROR(ERRSRV,ERRaccess));
/* Strip \PIPE\ off the name. */
pstrcpy(fname,smb_buf(inbuf) + PIPELEN);
/* Known pipes arrive with DIR attribs. Remove it so a regular file */
/* can be opened and add it in after the open. */
DEBUG(3,("Known pipe %s opening.\n",fname));
smb_ofun |= 0x10; /* Add Create it not exists flag */
pnum = open_rpc_pipe_hnd(fname, cnum);
pnum = open_rpc_pipe_hnd(fname, cnum, vuid);
if (pnum < 0) return(ERROR(ERRSRV,ERRnofids));
/* Prepare the reply */
@ -132,6 +123,53 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
}
/****************************************************************************
reply to a read and X
This code is basically stolen from reply_read_and_X with some
wrinkles to handle pipes.
****************************************************************************/
int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
int pnum = get_rpc_pipe_num(inbuf,smb_vwv2);
uint32 smb_offs = IVAL(inbuf,smb_vwv3);
int smb_maxcnt = SVAL(inbuf,smb_vwv5);
int smb_mincnt = SVAL(inbuf,smb_vwv6);
int cnum;
int nread = -1;
char *data;
BOOL ok = False;
cnum = SVAL(inbuf,smb_tid);
/*
CHECK_FNUM(fnum,cnum);
CHECK_READ(fnum);
CHECK_ERROR(fnum);
*/
set_message(outbuf,12,0,True);
data = smb_buf(outbuf);
nread = read_pipe(pnum, data, smb_offs, smb_maxcnt);
ok = True;
if (nread < 0)
return(UNIXERROR(ERRDOS,ERRnoaccess));
SSVAL(outbuf,smb_vwv5,nread);
SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
SSVAL(smb_buf(outbuf),-2,nread);
DEBUG(3,("%s readX pnum=%04x cnum=%d min=%d max=%d nread=%d\n",
timestring(),pnum,cnum,
smb_mincnt,smb_maxcnt,nread));
set_chain_pnum(pnum);
return chain_reply(inbuf,outbuf,length,bufsize);
}
/****************************************************************************
reply to a close
****************************************************************************/
@ -148,175 +186,3 @@ int reply_pipe_close(char *inbuf,char *outbuf)
return(outsize);
}
/****************************************************************************
api_LsarpcSNPHS
SetNamedPipeHandleState on \PIPE\lsarpc.
****************************************************************************/
BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param)
{
uint16 id;
if (!param) return False;
id = param[0] + (param[1] << 8);
DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
return set_rpc_pipe_hnd_state(pnum, cnum, id);
}
/****************************************************************************
api_LsarpcTNP
TransactNamedPipe on \PIPE\lsarpc.
****************************************************************************/
static void LsarpcTNP1(char *data,char **rdata, int *rdata_len)
{
uint32 dword1, dword2;
char pname[] = "\\PIPE\\lsass";
/* All kinds of mysterious numbers here */
*rdata_len = 68;
*rdata = REALLOC(*rdata,*rdata_len);
dword1 = IVAL(data,0xC);
dword2 = IVAL(data,0x10);
SIVAL(*rdata,0,0xc0005);
SIVAL(*rdata,4,0x10);
SIVAL(*rdata,8,0x44);
SIVAL(*rdata,0xC,dword1);
SIVAL(*rdata,0x10,dword2);
SIVAL(*rdata,0x14,0x15);
SSVAL(*rdata,0x18,sizeof(pname));
strcpy(*rdata + 0x1a,pname);
SIVAL(*rdata,0x28,1);
memcpy(*rdata + 0x30, data + 0x34, 0x14);
}
static void LsarpcTNP2(char *data,char **rdata, int *rdata_len)
{
uint32 dword1;
/* All kinds of mysterious numbers here */
*rdata_len = 48;
*rdata = REALLOC(*rdata,*rdata_len);
dword1 = IVAL(data,0xC);
SIVAL(*rdata,0,0x03020005);
SIVAL(*rdata,4,0x10);
SIVAL(*rdata,8,0x30);
SIVAL(*rdata,0xC,dword1);
SIVAL(*rdata,0x10,0x18);
SIVAL(*rdata,0x1c,0x44332211);
SIVAL(*rdata,0x20,0x88776655);
SIVAL(*rdata,0x24,0xCCBBAA99);
SIVAL(*rdata,0x28,0x11FFEEDD);
}
static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
{
uint32 dword1;
uint16 word1;
char * workgroup = myworkgroup;
int wglen = strlen(workgroup);
int i;
/* All kinds of mysterious numbers here */
*rdata_len = 90 + 2 * wglen;
*rdata = REALLOC(*rdata,*rdata_len);
dword1 = IVAL(data,0xC);
word1 = SVAL(data,0x2C);
SIVAL(*rdata,0,0x03020005);
SIVAL(*rdata,4,0x10);
SIVAL(*rdata,8,0x60);
SIVAL(*rdata,0xC,dword1);
SIVAL(*rdata,0x10,0x48);
SSVAL(*rdata,0x18,0x5988); /* This changes */
SSVAL(*rdata,0x1A,0x15);
SSVAL(*rdata,0x1C,word1);
SSVAL(*rdata,0x20,6);
SSVAL(*rdata,0x22,8);
SSVAL(*rdata,0x24,0x8E8); /* So does this */
SSVAL(*rdata,0x26,0x15);
SSVAL(*rdata,0x28,0x4D48); /* And this */
SSVAL(*rdata,0x2A,0x15);
SIVAL(*rdata,0x2C,4);
SIVAL(*rdata,0x34,wglen);
for ( i = 0 ; i < wglen ; i++ )
(*rdata)[0x38 + i * 2] = workgroup[i];
/* Now fill in the rest */
i = 0x38 + wglen * 2;
SSVAL(*rdata,i,0x648);
SIVAL(*rdata,i+2,4);
SIVAL(*rdata,i+6,0x401);
SSVAL(*rdata,i+0xC,0x500);
SIVAL(*rdata,i+0xE,0x15);
SIVAL(*rdata,i+0x12,0x2372FE1);
SIVAL(*rdata,i+0x16,0x7E831BEF);
SIVAL(*rdata,i+0x1A,0x4B454B2);
}
static void LsarpcTNP4(char *data,char **rdata, int *rdata_len)
{
uint32 dword1;
/* All kinds of mysterious numbers here */
*rdata_len = 48;
*rdata = REALLOC(*rdata,*rdata_len);
dword1 = IVAL(data,0xC);
SIVAL(*rdata,0,0x03020005);
SIVAL(*rdata,4,0x10);
SIVAL(*rdata,8,0x30);
SIVAL(*rdata,0xC,dword1);
SIVAL(*rdata,0x10,0x18);
}
BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
int *rdata_len,int *rparam_len)
{
uint32 id,id2;
id = IVAL(data,0);
DEBUG(4,("lsarpc TransactNamedPipe id %lx\n",id));
switch (id)
{
case 0xb0005:
LsarpcTNP1(data,rdata,rdata_len);
break;
case 0x03000005:
id2 = IVAL(data,8);
DEBUG(4,("\t- Suboperation %lx\n",id2));
switch (id2 & 0xF)
{
case 8:
LsarpcTNP2(data,rdata,rdata_len);
break;
case 0xC:
LsarpcTNP4(data,rdata,rdata_len);
break;
case 0xE:
LsarpcTNP3(data,rdata,rdata_len);
break;
}
break;
}
return(True);
}

View File

@ -366,6 +366,74 @@ int reply_ioctl(char *inbuf,char *outbuf)
#endif
}
/****************************************************************************
always return an error: it's just a matter of which one...
****************************************************************************/
static int session_trust_account(char *inbuf, char *outbuf, char *user,
char *smb_passwd, int smb_passlen,
char *smb_nt_passwd, int smb_nt_passlen)
{
struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
if (lp_security() == SEC_USER)
{
smb_trust_acct = get_smbpwd_entry(user, 0);
}
else
{
DEBUG(3,("Trust account %s only supported with security = user\n", user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
}
if (smb_trust_acct == NULL)
{
/* lkclXXXX: workstation entry doesn't exist */
DEBUG(4,("Trust account %s user doesn't exist\n",user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
}
else
{
if ((smb_passlen != 24) || (smb_nt_passlen != 24))
{
DEBUG(4,("Trust account %s - password length wrong.\n", user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
}
if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd))
{
DEBUG(4,("Trust Account %s - password failed\n", user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
}
if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
{
DEBUG(4,("Domain trust account %s denied by server\n",user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
}
if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
{
DEBUG(4,("Server trust account %s denied by server\n",user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
}
if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
{
DEBUG(4,("Wksta trust account %s denied by server\n", user));
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
}
}
/* don't know what to do: indicate logon failure */
SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
}
/****************************************************************************
reply to a session setup command
@ -386,7 +454,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
BOOL valid_nt_password = False;
pstring user;
BOOL guest=False;
BOOL computer_id=False;
static BOOL done_sesssetup = False;
BOOL doencrypt = SMBENCRYPT();
char *domain = "";
@ -496,48 +563,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
/* If name ends in $ then I think it's asking about whether a */
/* computer with that name (minus the $) has access. For now */
/* say yes to everything ending in $. */
if (user[strlen(user) - 1] == '$')
if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
{
#ifdef NTDOMAIN
struct smb_passwd *smb_pass; /* To check if machine account exists */
/*
PAXX: Ack. We don't want to do this. The workstation trust account
with a $ on the end should exist in the local password database
or be mapped to something generic, but not modified. For NT
domain support we must reject this used in certain circumstances
with a code to indicate to the client that it is an invalid use
of a workstation trust account. NTWKS needs this error to join
a domain. This may be the source of future bugs if we cannot
be sure whether to reject this or not.
*/
/* non-null user name indicates search by username not by smb userid */
smb_pass = get_smbpwd_entry(user, 0);
if (!smb_pass)
{
/* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */
DEBUG(4,("Workstation trust account %s doesn't exist.",user));
SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */
}
else
{
/* PAXX: This is the NO LOGON workstation trust account stuff */
/* lkclXXXX: if the workstation *does* exist, indicate failure differently! */
DEBUG(4,("No Workstation trust account %s",user));
SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */
}
computer_id = True;
#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
user[strlen(user) - 1] = '\0';
#endif
return session_trust_account(inbuf, outbuf, user,
smb_apasswd, smb_apasslen,
smb_ntpasswd, smb_ntpasslen);
}
/* If no username is sent use the guest account */
if (!*user)
{
@ -583,7 +615,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
}
if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
{
if (!computer_id && lp_security() >= SEC_USER) {
if (lp_security() >= SEC_USER) {
#if (GUEST_SESSSETUP == 0)
return(ERROR(ERRSRV,ERRbadpw));
#endif
@ -643,7 +675,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
uid = pw->pw_uid;
}
if (guest && !computer_id)
if (guest)
SSVAL(outbuf,smb_vwv2,1);
/* register the name and uid as being validated, so further connections

View File

@ -3955,7 +3955,7 @@ reply for the nt protocol
int reply_nt1(char *outbuf)
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|CAP_RPC_REMOTE_APIS;
/*
other valid capabilities which we may support at some time...
CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
@ -5190,10 +5190,8 @@ static void init_structs(void )
/* for RPC pipes */
init_rpc_pipe_hnd();
#ifdef NTDOMAIN
/* for LSA handles */
init_lsa_policy_hnd();
#endif
init_dptrs();
}

View File

@ -400,7 +400,7 @@ static void usage(char *name)
chmod(pfile, 0600);
/* Lock the smbpasswd file for write. */
if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) {
if ((lockfd = pw_file_lock(fileno(fp), F_WRLCK, 5)) < 0) {
err = errno;
fprintf(stderr, "%s: Failed to lock password file %s.\n",
argv[0], pfile);