diff options
author | Shirish Kalele <kalele@samba.org> | 2000-05-18 18:43:53 +0000 |
---|---|---|
committer | Shirish Kalele <kalele@samba.org> | 2000-05-18 18:43:53 +0000 |
commit | 74d677ec591a715e28dba29a33ee40e1b1c2f830 (patch) | |
tree | 110c04458f574ca708fe3616b40ed2ba32d2cbaf | |
parent | 7b49e6ac6c1b1d9e3fe0e4498a1def63b9532906 (diff) | |
download | samba-74d677ec591a715e28dba29a33ee40e1b1c2f830.tar.gz samba-74d677ec591a715e28dba29a33ee40e1b1c2f830.tar.bz2 samba-74d677ec591a715e28dba29a33ee40e1b1c2f830.zip |
Added the NETDFS pipe to allow remote administration of the msdfs symlinks
on the samba server.
(This used to be commit 15e7d8f6c5cddf6ce409ee2505744250d181ec34)
-rw-r--r-- | source3/Makefile.in | 4 | ||||
-rw-r--r-- | source3/include/msdfs.h | 2 | ||||
-rw-r--r-- | source3/include/ntdomain.h | 1 | ||||
-rw-r--r-- | source3/include/proto.h | 41 | ||||
-rw-r--r-- | source3/include/rpc_dfs.h | 202 | ||||
-rw-r--r-- | source3/include/smb.h | 1 | ||||
-rw-r--r-- | source3/msdfs/msdfs.c | 235 | ||||
-rw-r--r-- | source3/rpc_client/cli_reg.c | 5 | ||||
-rw-r--r-- | source3/rpc_parse/parse_dfs.c | 429 | ||||
-rw-r--r-- | source3/rpc_parse/parse_rpc.c | 10 | ||||
-rw-r--r-- | source3/rpc_server/srv_dfs.c | 456 | ||||
-rw-r--r-- | source3/rpc_server/srv_pipe.c | 3 | ||||
-rw-r--r-- | source3/rpcclient/cmd_reg.c | 2 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 3 |
14 files changed, 1352 insertions, 42 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 192514cf87..b0d44e4a29 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -130,7 +130,7 @@ RPC_SERVER_OBJ = rpc_server/srv_lsa.o \ rpc_server/srv_pipe_hnd.o rpc_server/srv_reg.o \ rpc_server/srv_samr.o rpc_server/srv_srvsvc.o \ rpc_server/srv_util.o rpc_server/srv_wkssvc.o \ - rpc_server/srv_pipe.o \ + rpc_server/srv_pipe.o rpc_server/srv_dfs.o \ rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_misc.o \ @@ -138,7 +138,7 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_misc.o \ rpc_parse/parse_reg.o rpc_parse/parse_rpc.o \ rpc_parse/parse_samr.o rpc_parse/parse_srv.o \ rpc_parse/parse_wks.o rpc_parse/parse_sec.o \ - rpc_parse/parse_spoolss.o + rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o RPC_CLIENT_OBJ = \ rpc_client/cli_login.o \ diff --git a/source3/include/msdfs.h b/source3/include/msdfs.h index ac054307b5..5323b8749a 100644 --- a/source3/include/msdfs.h +++ b/source3/include/msdfs.h @@ -38,7 +38,7 @@ struct referral { - pstring alternate_path; /* contains the path referred (UNICODE?) */ + pstring alternate_path; /* contains the path referred */ uint32 proximity; uint32 ttl; /* how long should client cache referral */ }; diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 8f5332e2ec..3a3bea16fb 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -236,6 +236,7 @@ struct acct_info #include "rpc_srvsvc.h" #include "rpc_wkssvc.h" #include "rpc_spoolss.h" +#include "rpc_dfs.h" #include "sids.h" #endif /* _NT_DOMAIN_H */ diff --git a/source3/include/proto.h b/source3/include/proto.h index 45fd66cd09..9dec5f16e0 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -873,11 +873,16 @@ BOOL posix_locking_end(void); /*The following definitions come from msdfs/msdfs.c */ +BOOL remove_msdfs_link(struct junction_map* jn); +BOOL create_msdfs_link(struct junction_map* jn, BOOL exists); BOOL is_msdfs_volume(connection_struct* conn, char* path); +BOOL get_referred_path(struct junction_map* junction); BOOL dfs_redirect(char* pathname, connection_struct* conn); BOOL dfs_findfirst_redirect(char* pathname, connection_struct* conn); +BOOL create_junction(char* pathname, struct junction_map* jn); int setup_dfs_referral(char* pathname, int max_referral_level, char** ppdata); +int enum_msdfs_junctions(struct junction_map* jn); int dfs_path_error(char* inbuf, char* outbuf); int setup_dfs_referral(char* pathname, int max_referral_level, char** ppdata); @@ -1731,7 +1736,7 @@ BOOL do_reg_query_key(struct cli_state *cli, POLICY_HND *hnd, uint32 *sec_desc, NTTIME *mod_time); BOOL do_reg_unknown_1a(struct cli_state *cli, POLICY_HND *hnd, uint32 *unk); BOOL do_reg_query_info(struct cli_state *cli, POLICY_HND *hnd, - char *type, uint32 *unk_0, uint32 *unk_1); + char *key_value, uint32* key_type); BOOL do_reg_set_key_sec(struct cli_state *cli, POLICY_HND *hnd, SEC_DESC_BUF *sec_desc_buf); BOOL do_reg_get_key_sec(struct cli_state *cli, POLICY_HND *hnd, uint32 *sec_buf_size, SEC_DESC_BUF **ppsec_desc_buf); BOOL do_reg_delete_val(struct cli_state *cli, POLICY_HND *hnd, char *val_name); @@ -1869,6 +1874,36 @@ BOOL create_user_creds( prs_struct *ps, uint32 pid, const struct user_creds *usr); +/*The following definitions come from rpc_parse/parse_dfs.c */ + +BOOL dfs_io_r_dfs_exist(char *desc, DFS_R_DFS_EXIST *q_d, prs_struct *ps, + int depth); +BOOL make_dfs_q_dfs_remove(DFS_Q_DFS_REMOVE *q_d, char *entrypath, + char *servername, char *sharename); +BOOL dfs_io_q_dfs_remove(char *desc, DFS_Q_DFS_REMOVE *q_d, prs_struct *ps, + int depth); +BOOL dfs_io_r_dfs_remove(char *desc, DFS_R_DFS_REMOVE *r_d, prs_struct *ps, + int depth); +BOOL make_dfs_q_dfs_add(DFS_Q_DFS_ADD *q_d, char *entrypath, char *servername, + char *sharename, char *comment, uint32 flags); +BOOL dfs_io_q_dfs_add(char *desc, DFS_Q_DFS_ADD *q_d, prs_struct *ps, + int depth); +BOOL dfs_io_r_dfs_add(char *desc, DFS_R_DFS_ADD *r_d, prs_struct *ps, + int depth); +BOOL dfs_io_q_dfs_get_info(char* desc, DFS_Q_DFS_GET_INFO* q_i, + prs_struct* ps, int depth); +BOOL dfs_io_r_dfs_get_info(char* desc, DFS_R_DFS_GET_INFO* r_i, + prs_struct* ps, int depth); +BOOL make_dfs_q_dfs_enum(DFS_Q_DFS_ENUM *q_d, uint32 level, DFS_INFO_CTR *ctr); +BOOL dfs_io_q_dfs_enum(char *desc, DFS_Q_DFS_ENUM *q_d, prs_struct *ps, + int depth); +BOOL dfs_io_dfs_info_ctr(char* desc, DFS_INFO_CTR* ctr, uint32 num_entries, + uint32 level, + prs_struct* ps, int depth); +BOOL dfs_io_r_dfs_enum(char *desc, DFS_R_DFS_ENUM *q_d, prs_struct *ps, int depth); +BOOL dfs_io_dfs_storage_info(char *desc, DFS_INFO_3* info3, + prs_struct *ps, int depth); + /*The following definitions come from rpc_parse/parse_lsa.c */ void init_lsa_trans_name(LSA_TRANS_NAME *trn, UNISTR2 *uni_name, @@ -2686,6 +2721,10 @@ void init_wks_r_query_info(WKS_R_QUERY_INFO *r_u, int status) ; BOOL wks_io_r_query_info(char *desc, WKS_R_QUERY_INFO *r_u, prs_struct *ps, int depth); +/*The following definitions come from rpc_server/srv_dfs.c */ + +BOOL api_netdfs_rpc(pipes_struct *p, prs_struct *data); + /*The following definitions come from rpc_server/srv_lsa.c */ #if OLD_NTDOMAIN diff --git a/source3/include/rpc_dfs.h b/source3/include/rpc_dfs.h new file mode 100644 index 0000000000..e85a39eabb --- /dev/null +++ b/source3/include/rpc_dfs.h @@ -0,0 +1,202 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + Samba parameters and setup + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Luke Kenneth Casson Leighton 1996 - 2000 + Copyright (C) Shirish Kalele 2000 + + 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_DFS_H +#define _RPC_DFS_H + +/* NETDFS pipe: calls */ +#define DFS_EXIST 0x00 +#define DFS_ADD 0x01 +#define DFS_REMOVE 0x02 +#define DFS_GET_INFO 0x04 +#define DFS_ENUM 0x05 + +/* dfsadd flags */ +#define DFSFLAG_ADD_VOLUME 0x00000001 +#define DFSFLAG_RESTORE_VOLUME 0x00000002 + +/* API errors from lmerr.h */ +#ifndef NERR_BASE +#define NERR_BASE (2100) +#endif + +#define NERR_DfsNoSuchVolume (NERR_BASE+562) +#define NERR_DfsNoSuchShare (NERR_BASE+565) +#define NERR_DfsNoSuchServer (NERR_BASE+573) +#define NERR_DfsInternalError (NERR_BASE+590) +#define NERR_DfsCantCreateJunctionPoint (NERR_BASE+569) + +typedef struct dfs_r_dfs_exist +{ + uint32 dfs_exist_flag; +} +DFS_R_DFS_EXIST; + +typedef struct dfs_q_dfs_add +{ + uint32 ptr_DfsEntryPath; + UNISTR2 DfsEntryPath; + uint32 ptr_ServerName; + UNISTR2 ServerName; + uint32 ptr_ShareName; + UNISTR2 ShareName; + uint32 ptr_Comment; + UNISTR2 Comment; + uint32 Flags; +} +DFS_Q_DFS_ADD; + +typedef struct dfs_r_dfs_add +{ + uint32 status; +} +DFS_R_DFS_ADD; + +/********************************************/ +typedef struct dfs_q_dfs_remove +{ + UNISTR2 DfsEntryPath; + uint32 ptr_ServerName; + UNISTR2 ServerName; + uint32 ptr_ShareName; + UNISTR2 ShareName; +} +DFS_Q_DFS_REMOVE; + +typedef struct dfs_r_dfs_remove +{ + uint32 status; +} +DFS_R_DFS_REMOVE; + +/********************************************/ +typedef struct dfs_info_1 +{ + uint32 ptr_entrypath; + UNISTR2 entrypath; +} +DFS_INFO_1; + +typedef struct dfs_info_2 +{ + uint32 ptr_entrypath; + UNISTR2 entrypath; + uint32 ptr_comment; + UNISTR2 comment; + uint32 state; + uint32 num_storages; +} +DFS_INFO_2; + +typedef struct dfs_storage_info +{ + uint32 state; + uint32 ptr_servername; + UNISTR2 servername; + uint32 ptr_sharename; + UNISTR2 sharename; +} +DFS_STORAGE_INFO; + +typedef struct dfs_info_3 +{ + uint32 ptr_entrypath; + UNISTR2 entrypath; + uint32 ptr_comment; + UNISTR2 comment; + uint32 state; + uint32 num_storages; + uint32 ptr_storages; + uint32 num_storage_infos; + DFS_STORAGE_INFO* storages; +} +DFS_INFO_3; + +typedef struct dfs_info_ctr +{ + + uint32 switch_value; + uint32 num_entries; + uint32 ptr_dfs_ctr; /* pointer to dfs info union */ + union + { + DFS_INFO_1 *info1; + DFS_INFO_2 *info2; + DFS_INFO_3 *info3; + } dfs; +} +DFS_INFO_CTR; + +typedef struct dfs_q_dfs_get_info +{ + UNISTR2 uni_path; + + uint32 ptr_server; + UNISTR2 uni_server; + + uint32 ptr_share; + UNISTR2 uni_share; + + uint32 level; +} +DFS_Q_DFS_GET_INFO; + +typedef struct dfs_r_dfs_get_info +{ + uint32 level; + uint32 ptr_ctr; + DFS_INFO_CTR ctr; + uint32 status; +} +DFS_R_DFS_GET_INFO; + +typedef struct dfs_q_dfs_enum +{ + uint32 level; + uint32 maxpreflen; + uint32 ptr_buffer; + uint32 level2; + uint32 ptr_num_entries; + uint32 num_entries; + uint32 ptr_num_entries2; + uint32 num_entries2; + ENUM_HND reshnd; +} +DFS_Q_DFS_ENUM; + +typedef struct dfs_r_dfs_enum +{ + DFS_INFO_CTR *ctr; + uint32 ptr_buffer; + uint32 level; + uint32 level2; + uint32 ptr_num_entries; + uint32 num_entries; + uint32 ptr_num_entries2; + uint32 num_entries2; + ENUM_HND reshnd; + uint32 status; +} +DFS_R_DFS_ENUM; + +#endif diff --git a/source3/include/smb.h b/source3/include/smb.h index 62cb8e55b4..e6fee32b80 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -278,6 +278,7 @@ typedef smb_ucs2_t wfstring[128]; #define PIPE_LSASS "\\PIPE\\lsass" #define PIPE_LSARPC "\\PIPE\\lsarpc" #define PIPE_SPOOLSS "\\PIPE\\spoolss" +#define PIPE_NETDFS "\\PIPE\\netdfs" /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ typedef struct nttime_info diff --git a/source3/msdfs/msdfs.c b/source3/msdfs/msdfs.c index 1f39aa79fd..25bc5cc17f 100644 --- a/source3/msdfs/msdfs.c +++ b/source3/msdfs/msdfs.c @@ -27,6 +27,9 @@ extern uint32 global_client_caps; #ifdef MS_DFS +/********************************************************************** + Create a tcon relative path from a dfs_path structure + **********************************************************************/ static void create_nondfs_path(char* pathname, struct dfs_path* pdp) { pstrcpy(pathname,pdp->volumename); @@ -34,8 +37,10 @@ static void create_nondfs_path(char* pathname, struct dfs_path* pdp) pstrcat(pathname,pdp->restofthepath); } -/* Parse the pathname of the form \hostname\service\volume\restofthepath - into the dfs_path structure */ +/********************************************************************** + Parse the pathname of the form \hostname\service\volume\restofthepath + into the dfs_path structure + **********************************************************************/ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) { pstring pathname_local; @@ -88,6 +93,82 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) return True; } + +static BOOL form_path_from_junction(struct junction_map* jn, char* path, + int max_pathlen) +{ + int snum; + + if(!path || !jn) + return False; + + snum = lp_servicenumber(jn->service_name); + if(snum < 0) + return False; + + safe_strcpy(path, lp_pathname(snum), max_pathlen-1); + safe_strcat(path, "/", max_pathlen-1); + strlower(jn->volume_name); + safe_strcat(path, jn->volume_name, max_pathlen-1); + return True; +} + +BOOL remove_msdfs_link(struct junction_map* jn) +{ + pstring path; + pstring msdfs_link; + int i=0; + + if(!form_path_from_junction(jn, path, sizeof(path))) + return False; + + if(unlink(path)!=0) + return False; + + return True; +} + +BOOL create_msdfs_link(struct junction_map* jn, BOOL exists) +{ + pstring path; + pstring msdfs_link; + int i=0; + + if(!form_path_from_junction(jn, path, sizeof(path))) + return False; + + /* form the msdfs_link contents */ + pstrcpy(msdfs_link, "msdfs:"); + for(i=0; i<jn->referral_count; i++) + { + char* refpath = jn->referral_list[i].alternate_path; + + trim_string(refpath, "\\", "\\"); + if(*refpath == '\0') + continue; + + if(i>0) + pstrcat(msdfs_link, ","); + + pstrcat(msdfs_link, refpath); + } + + DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", + path, msdfs_link)); + + if(exists) + if(unlink(path)!=0) + return False; + + if(symlink(msdfs_link, path) < 0) + { + DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n", + path, msdfs_link, strerror(errno))); + return False; + } + return True; +} + /********************************************************************** Parse the contents of a symlink to verify if it is an msdfs referral A valid referral is of the form: msdfs:server1\share1,server2\share2 @@ -127,6 +208,10 @@ static BOOL parse_symlink(char* buf,struct referral** preflist, int* refcount) for(i=0;i<count;i++) { + /* replace / in the alternate path by a \ */ + char* p = strchr(alt_path[i],'/'); + if(p) *p = '\\'; + pstrcpy(reflist[i].alternate_path, "\\"); pstrcat(reflist[i].alternate_path, alt_path[i]); reflist[i].proximity = 0; @@ -157,7 +242,7 @@ BOOL is_msdfs_volume(connection_struct* conn, char* path) return False; } - if(st.st_mode & S_IFLNK) + if(S_ISLNK(st.st_mode)) { /* open the link and read it */ readlink(path, referral, sizeof(pstring)); @@ -168,20 +253,14 @@ BOOL is_msdfs_volume(connection_struct* conn, char* path) return False; } -static BOOL get_referred_path(struct junction_map* junction) +BOOL get_referred_path(struct junction_map* junction) { fstring path; pstring buf; SMB_STRUCT_STAT st; - int snum = lp_servicenumber(junction->service_name); - - /* form the path */ - fstrcpy(path, lp_pathname(snum)); - fstrcat(path, "/"); - - strlower(junction->volume_name); - - fstrcat(path, junction->volume_name); + + if(!form_path_from_junction(junction, path, sizeof(path))) + return False; DEBUG(5,("get_referred_path: lstat target: %s\n", path)); @@ -191,14 +270,14 @@ static BOOL get_referred_path(struct junction_map* junction) return False; } - if(st.st_mode & S_IFLNK) + if(S_ISLNK(st.st_mode)) { /* open the link and read it to get the dfs referral */ readlink(path, buf, sizeof(buf)); DEBUG(5,("get_referred_path: Referral: %s\n",buf)); if(parse_symlink(buf, &junction->referral_list, &junction->referral_count)) - return True; + return True; } return False; } @@ -451,42 +530,52 @@ static int setup_ver3_dfs_referral(char* pathname, char** ppdata, return reply_size; } -/****************************************************************** - * Set up the Dfs referral for the dfs pathname - ******************************************************************/ -int setup_dfs_referral(char* pathname, int max_referral_level, - char** ppdata) +/********************************************************************** + Creates a junction structure from the Dfs pathname + **********************************************************************/ +BOOL create_junction(char* pathname, struct junction_map* jn) { struct dfs_path dp; - struct junction_map junction; - - BOOL self_referral; - - int reply_size = 0; - - ZERO_STRUCT(junction); - parse_dfs_path(pathname,&dp); /* check if path is dfs : check hostname is the first token */ if(global_myname && (strcasecmp(global_myname,dp.hostname)!=0)) { - DEBUG(4,("setup_dfs_referral: Invalid DFS referral request for %s\n", - pathname)); - return -1; + DEBUG(4,("create_junction: Invalid hostname %s in dfs path %s\n", + dp.hostname, pathname)); + return False; } /* Check for a non-DFS share */ if(!lp_msdfs_root(lp_servicenumber(dp.servicename))) { - DEBUG(4,("setup_dfs_referral: %s is not an msdfs root.\n", + DEBUG(4,("create_junction: %s is not an msdfs root.\n", dp.servicename)); - return -1; + return False; } - pstrcpy(junction.service_name,dp.servicename); - pstrcpy(junction.volume_name,dp.volumename); + pstrcpy(jn->service_name,dp.servicename); + pstrcpy(jn->volume_name,dp.volumename); + return True; +} + +/****************************************************************** + * Set up the Dfs referral for the dfs pathname + ******************************************************************/ +int setup_dfs_referral(char* pathname, int max_referral_level, + char** ppdata) +{ + struct junction_map junction; + + BOOL self_referral; + + int reply_size = 0; + + ZERO_STRUCT(junction); + + if(!create_junction(pathname, &junction)) + return -1; /* get the junction entry */ if(!get_referred_path(&junction)) @@ -552,6 +641,82 @@ int setup_dfs_referral(char* pathname, int max_referral_level, } +static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) +{ + int cnt = *jn_count; + DIR *dirp; + char* dname; + + char* connect_path = lp_pathname(snum); + char* service_name = lp_servicename(snum); + + if(*connect_path == '\0') + return False; + + /* form a junction for the msdfs root - convention */ + /* + pstrpcy(jn[cnt].service_name, service_name); + jn[cnt].volume_name[0] = '\0'; + jn[cnt].referral_count = 1; + + slprintf(alt_path,"\\\\%s\\%s", global_myname, service_name); + jn[cnt].referral_l + */ + + dirp = opendir(connect_path); + if(!dirp) + return False; + + while((dname = readdirname(dirp)) != NULL) + { + SMB_STRUCT_STAT st; + pstring pathreal; + fstring buf; + int buflen = 0; + pstrcpy(pathreal, connect_path); + pstrcat(pathreal, "/"); + pstrcat(pathreal, dname); + + if(lstat(pathreal,&st) != 0) + { + DEBUG(4,("lstat error for %s: %s\n",pathreal, strerror(errno))); + continue; + } + if(S_ISLNK(st.st_mode)) + { + buflen = readlink(pathreal, buf, sizeof(fstring)); + buf[buflen] = '\0'; + if(parse_symlink(buf, &(jn[cnt].referral_list), + &(jn[cnt].referral_count))) + { + pstrcpy(jn[cnt].service_name, service_name); + pstrcpy(jn[cnt].volume_name, dname); + cnt++; + } + } + } + + closedir(dirp); + *jn_count = cnt; + return True; +} + +int enum_msdfs_junctions(struct junction_map* jn) +{ + int i=0; + int jn_count = 0; + + if(!lp_host_msdfs()) + return -1; + + for(i=0;*lp_servicename(i);i++) + { + if(lp_msdfs_root(i)) + form_junctions(i,jn,&jn_count); + } + return jn_count; +} + int dfs_path_error(char* inbuf, char* outbuf) { enum remote_arch_types ra_type = get_remote_arch(); diff --git a/source3/rpc_client/cli_reg.c b/source3/rpc_client/cli_reg.c index c92f3f3857..d8b6931b42 100644 --- a/source3/rpc_client/cli_reg.c +++ b/source3/rpc_client/cli_reg.c @@ -389,7 +389,7 @@ BOOL do_reg_unknown_1a(struct cli_state *cli, POLICY_HND *hnd, uint32 *unk) do a REG Query Info ****************************************************************************/ BOOL do_reg_query_info(struct cli_state *cli, POLICY_HND *hnd, - char *type, uint32 *unk_0, uint32 *unk_1) + char *key_value, uint32* key_type) { prs_struct rbuf; prs_struct buf; @@ -438,7 +438,8 @@ BOOL do_reg_query_info(struct cli_state *cli, POLICY_HND *hnd, return False; } - fstrcpy(type, dos_buffer2_to_str(r_o.uni_val)); + fstrcpy(key_value, dos_buffer2_to_str(r_o.uni_val)); + *key_type = r_o.type; prs_mem_free(&rbuf); diff --git a/source3/rpc_parse/parse_dfs.c b/source3/rpc_parse/parse_dfs.c new file mode 100644 index 0000000000..71e866e59a --- /dev/null +++ b/source3/rpc_parse/parse_dfs.c @@ -0,0 +1,429 @@ +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * MSDfs RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + * Copyright (C) Shirish Kalele 2000. + * + * 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" +#include "rpc_parse.h" + +extern int DEBUGLEVEL; + +/************************************************************* + Read/write a DFS_R_DFS_EXIST structure + ************************************************************/ +BOOL dfs_io_r_dfs_exist(char *desc, DFS_R_DFS_EXIST *q_d, prs_struct *ps, + int depth) +{ + if(q_d == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_r_dfs_exist"); + depth++; + + prs_align(ps); + + prs_uint32("exist flag", ps, 0, &(q_d->dfs_exist_flag)); + return True; +} + +/******************************************************************* +Make a DFS_Q_DFS_REMOVE structure +*******************************************************************/ +BOOL make_dfs_q_dfs_remove(DFS_Q_DFS_REMOVE *q_d, char *entrypath, + char *servername, char *sharename) +{ + DEBUG(5,("make_dfs_q_dfs_remove\n")); + init_unistr2(&(q_d->DfsEntryPath), entrypath, strlen(entrypath)+1); + init_unistr2(&(q_d->ServerName), servername, strlen(servername)+1); + init_unistr2(&(q_d->ShareName), sharename, strlen(sharename)+1); + q_d->ptr_ServerName = q_d->ptr_ShareName = 1; + return True; +} + +/******************************************************************* +Read/write a DFS_Q_DFS_REMOVE structure +*******************************************************************/ +BOOL dfs_io_q_dfs_remove(char *desc, DFS_Q_DFS_REMOVE *q_d, prs_struct *ps, + int depth) +{ + if(q_d == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_q_dfs_remove"); + depth++; + + prs_align(ps); + + smb_io_unistr2("DfsEntryPath",&(q_d->DfsEntryPath), 1, ps, depth); + prs_align(ps); + + prs_uint32("ptr_ServerName", ps, depth, &(q_d->ptr_ServerName)); + if(q_d->ptr_ServerName) + smb_io_unistr2("ServerName",&(q_d->ServerName), q_d->ptr_ServerName, + ps, depth); + prs_align(ps); + + prs_uint32("ptr_ShareName", ps, depth, &(q_d->ptr_ShareName)); + if(q_d->ptr_ShareName) + smb_io_unistr2("ShareName",&(q_d->ShareName), q_d->ptr_ShareName, + ps, depth); + prs_align(ps); + + return True; +} + +/******************************************************************* +Read/write a DFS_R_DFS_REMOVE structure +*******************************************************************/ +BOOL dfs_io_r_dfs_remove(char *desc, DFS_R_DFS_REMOVE *r_d, prs_struct *ps, + int depth) +{ + if(r_d == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_r_dfs_remove"); + depth++; + + prs_uint32("status", ps, depth, &(r_d->status)); + + return True; +} + +/******************************************************************* +Make a DFS_Q_DFS_ADD structure +*******************************************************************/ +BOOL make_dfs_q_dfs_add(DFS_Q_DFS_ADD *q_d, char *entrypath, char *servername, + char *sharename, char *comment, uint32 flags) +{ + DEBUG(5,("make_dfs_q_dfs_add\n")); + q_d->ptr_DfsEntryPath = q_d->ptr_ServerName = q_d->ptr_ShareName = 1; + init_unistr2(&(q_d->DfsEntryPath), entrypath, strlen(entrypath)+1); + init_unistr2(&(q_d->ServerName), servername, strlen(servername)+1); + init_unistr2(&(q_d->ShareName), sharename, strlen(sharename)+1); + if(comment != NULL) + { + init_unistr2(&(q_d->Comment), comment, strlen(comment)+1); + q_d->ptr_Comment = 1; + } + else + { + q_d->ptr_Comment = 0; + } + + q_d->Flags = flags; + return True; +} + +/************************************************************ + Read/write a DFS_Q_DFS_ADD structure + ************************************************************/ +BOOL dfs_io_q_dfs_add(char *desc, DFS_Q_DFS_ADD *q_d, prs_struct *ps, + int depth) +{ + if(q_d == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_q_dfs_add"); + depth++; + + prs_align(ps); + + smb_io_unistr2("DfsEntryPath",&(q_d->DfsEntryPath), 1, ps, depth); + prs_align(ps); + + smb_io_unistr2("ServerName",&(q_d->ServerName), 1, ps, depth); + prs_align(ps); + + prs_uint32("ptr_ShareName", ps, depth, &(q_d->ptr_ShareName)); + smb_io_unistr2("ShareName",&(q_d->ShareName), 1, ps, depth); + prs_align(ps); + + prs_uint32("ptr_Comment", ps, depth, &(q_d->ptr_Comment)); + smb_io_unistr2("",&(q_d->Comment), q_d->ptr_Comment , ps, depth); + prs_align(ps); + + prs_uint32("Flags", ps, depth, &(q_d->Flags)); + return True; +} + +/************************************************************ + Read/write a DFS_R_DFS_ADD structure + ************************************************************/ +BOOL dfs_io_r_dfs_add(char *desc, DFS_R_DFS_ADD *r_d, prs_struct *ps, + int depth) +{ + if(r_d == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_r_dfs_add"); + depth++; + + prs_uint32("status", ps, depth, &(r_d->status)); + + return True; +} + +/************************************************************ + Read/write a DFS_Q_GET_INFO structure + ************************************************************/ +BOOL dfs_io_q_dfs_get_info(char* desc, DFS_Q_DFS_GET_INFO* q_i, + prs_struct* ps, int depth) +{ + if(q_i == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_q_dfs_get_info"); + depth++; + + smb_io_unistr2("",&(q_i->uni_path), 1, ps, depth); + prs_align(ps); + + prs_uint32("ptr_server", ps, depth, &(q_i->ptr_server)); + if(q_i->ptr_server) + smb_io_unistr2("",&(q_i->uni_server), q_i->ptr_server, ps, depth); + prs_align(ps); + + prs_uint32("ptr_share", ps, depth, &(q_i->ptr_share)); + if(q_i->ptr_share) + smb_io_unistr2("", &(q_i->uni_share), q_i->ptr_share, ps, depth); + prs_align(ps); + + prs_uint32("level", ps, depth, &(q_i->level)); + return True; +} + +/************************************************************ + Read/write a DFS_R_GET_INFO structure + ************************************************************/ +BOOL dfs_io_r_dfs_get_info(char* desc, DFS_R_DFS_GET_INFO* r_i, + prs_struct* ps, int depth) +{ + if(r_i == NULL) return False; + + prs_uint32("level", ps, depth, &(r_i->level)); + prs_uint32("ptr_ctr", ps, depth, &(r_i->ptr_ctr)); + + dfs_io_dfs_info_ctr("", &(r_i->ctr), 1, r_i->level, ps, depth); + prs_uint32("status", ps, depth, &(r_i->status)); + return True; +} + +/************************************************************ + Make a DFS_Q_DFS_ENUM structure + ************************************************************/ +BOOL make_dfs_q_dfs_enum(DFS_Q_DFS_ENUM *q_d, uint32 level, DFS_INFO_CTR *ctr) +{ + q_d->level = level; + q_d->maxpreflen = -1; + q_d->ptr_buffer = 1; + q_d->level2 = level; + + q_d->ptr_num_entries = 1; + q_d->num_entries = 0; + q_d->num_entries2 = 0; + q_d->reshnd.ptr_hnd = 1; + q_d->reshnd.handle = 0; + return True; +} + +/************************************************************ + Read or write the DFS_Q_DFS_ENUM structure + ************************************************************/ +BOOL dfs_io_q_dfs_enum(char *desc, DFS_Q_DFS_ENUM *q_d, prs_struct *ps, + int depth) +{ + if(q_d == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_q_dfs_enum"); + depth++; + + prs_align(ps); + + prs_uint32("level", ps, depth, &(q_d->level)); + prs_uint32("maxpreflen", ps, depth, &(q_d->maxpreflen)); + prs_uint32("ptr_buffer", ps, depth, &(q_d->ptr_buffer)); + prs_uint32("level2", ps, depth, &(q_d->level2)); + prs_uint32("level3", ps, depth, &(q_d->level2)); + + prs_uint32("ptr_num_entries", ps, depth, &(q_d->ptr_num_entries)); + prs_uint32("num_entries", ps, depth, &(q_d->num_entries)); + prs_uint32("num_entries2", ps, depth, &(q_d->num_entries2)); + smb_io_enum_hnd("resume_hnd",&(q_d->reshnd), ps, depth); + return True; +} + +/************************************************************ + Read/write a DFS_INFO_CTR structure + ************************************************************/ +BOOL dfs_io_dfs_info_ctr(char* desc, DFS_INFO_CTR* ctr, uint32 num_entries, + uint32 level, + prs_struct* ps, int depth) +{ + switch(level) + { + case 1: + { + int i=0; + + depth++; + /* should depend on whether marshalling or unmarshalling! */ + if(UNMARSHALLING(ps)) + ctr->dfs.info1 = g_new0(DFS_INFO_1, num_entries); + + for(i=0;i<num_entries;i++) + { + prs_uint32("ptr_entrypath",ps, depth, &(ctr->dfs.info1[i].ptr_entrypath)); + } + for(i=0;i<num_entries;i++) + { + smb_io_unistr2("", &(ctr->dfs.info1[i].entrypath), + ctr->dfs.info1[i].ptr_entrypath, + ps, depth); + prs_align(ps); + } + depth--; + break; + } + case 2: + { + int i=0; + depth++; + if(UNMARSHALLING(ps)) + ctr->dfs.info2 = g_new0(DFS_INFO_2, num_entries); + + for(i=0;i<num_entries;i++) + { + prs_uint32("ptr_entrypath", ps, depth, + &(ctr->dfs.info2[i].ptr_entrypath)); + prs_uint32("ptr_comment", ps, depth, + &(ctr->dfs.info2[i].ptr_comment)); + prs_uint32("state", ps, depth, &(ctr->dfs.info2[i].state)); + prs_uint32("num_storages", ps, depth, + &(ctr->dfs.info2[i].num_storages)); + } + for(i=0;i<num_entries;i++) + { + smb_io_unistr2("", &(ctr->dfs.info2[i].entrypath), + ctr->dfs.info2[i].ptr_entrypath, ps, depth); + prs_align(ps); + smb_io_unistr2("",&(ctr->dfs.info2[i].comment), + ctr->dfs.info2[i].ptr_comment, ps, depth); + prs_align(ps); + } + depth--; + break; + } + case 3: + { + int i=0; + depth++; + if(UNMARSHALLING(ps)) + ctr->dfs.info3 = g_new0(DFS_INFO_3, num_entries); + + for(i=0;i<num_entries;i++) + { + prs_uint32("ptr_entrypath", ps, depth, + &(ctr->dfs.info3[i].ptr_entrypath)); + prs_uint32("ptr_comment", ps, depth, + &(ctr->dfs.info3[i].ptr_comment)); + prs_uint32("state", ps, depth, &(ctr->dfs.info3[i].state)); + prs_uint32("num_storages", ps, depth, + &(ctr->dfs.info3[i].num_storages)); + prs_uint32("ptr_storages", ps, depth, + &(ctr->dfs.info3[i].ptr_storages)); + } + for(i=0;i<num_entries;i++) + { + smb_io_unistr2("", &(ctr->dfs.info3[i].entrypath), + ctr->dfs.info3[i].ptr_entrypath, ps, depth); + prs_align(ps); + smb_io_unistr2("", &(ctr->dfs.info3[i].comment), + ctr->dfs.info3[i].ptr_comment, ps, depth); + prs_align(ps); + prs_uint32("num_storage_infos", ps, depth, + &(ctr->dfs.info3[i].num_storage_infos)); + if(!dfs_io_dfs_storage_info("storage_info", + &(ctr->dfs.info3[i]), + ps, depth)) + return False; + } + } + } + return True; +} +/************************************************************ + Read/write a DFS_R_DFS_ENUM structure + ************************************************************/ +BOOL dfs_io_r_dfs_enum(char *desc, DFS_R_DFS_ENUM *q_d, prs_struct *ps, int depth) +{ + DFS_INFO_CTR *ctr; + if(q_d == NULL) return False; + ctr = q_d->ctr; + if(ctr == NULL) return False; + + prs_debug(ps, depth, desc, "dfs_io_r_dfs_enum"); + depth++; + + prs_align(ps); + + prs_uint32("ptr_buffer", ps, depth, &(q_d->ptr_buffer)); + prs_uint32("level", ps, depth, &(q_d->level)); + prs_uint32("level2", ps, depth, &(ctr->switch_value)); + prs_uint32("ptr_num_entries", ps, depth, &(q_d->ptr_num_entries)); + if(q_d->ptr_num_entries) + prs_uint32("num_entries", ps, depth, &(q_d->num_entries)); + prs_uint32("ptr_num_entries2", ps, depth, &(q_d->ptr_num_entries2)); + if(q_d->ptr_num_entries2) + prs_uint32("num_entries2", ps, depth, &(ctr->num_entries)); + + dfs_io_dfs_info_ctr("", ctr, q_d->num_entries, q_d->level, ps, depth); + + smb_io_enum_hnd("resume_hnd", &(q_d->reshnd), ps, depth); + prs_uint32("status", ps, depth, &(q_d->status)); + return True; +} + +BOOL dfs_io_dfs_storage_info(char *desc, DFS_INFO_3* info3, + prs_struct *ps, int depth) +{ + int i=0; + if(info3 == NULL) return False; + + prs_debug(ps, depth, desc, "smb_io_dfs_storage_info"); + depth++; + + if(UNMARSHALLING(ps)) + info3->storages = g_new0(DFS_STORAGE_INFO, info3->num_storage_infos); + + for(i=0;i<info3->num_storage_infos;i++) + { + prs_uint32("storage_state", ps, depth, &(info3->storages[i].state)); + prs_uint32("ptr_servername", ps, depth, + &(info3->storages[i].ptr_servername)); + prs_uint32("ptr_sharename", ps, depth, + &(info3->storages[i].ptr_sharename)); + } + for(i=0;i<info3->num_storage_infos;i++) + { + smb_io_unistr2("servername", &(info3->storages[i].servername), + info3->storages[i].ptr_servername, ps, depth); + prs_align(ps); + smb_io_unistr2("sharename", &(info3->storages[i].sharename), + info3->storages[i].ptr_sharename, ps, depth); + prs_align(ps); + } + return True; +} diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 8d39b6e7c0..af0569fd61 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -123,6 +123,15 @@ interface/version dce/rpc pipe identification }, 0x00 \ } +#define SYNT_NETDFS_V3 \ +{ \ + { \ + 0x4fc742e0, 0x4a10, 0x11cf, \ + { 0x82, 0x73, 0x00, 0xaa, \ + 0x00, 0x4a, 0xe6, 0x73 } \ + }, 0x03 \ +} + struct pipe_id_info pipe_names [] = { /* client pipe , abstract syntax , server pipe , transfer syntax */ @@ -133,6 +142,7 @@ struct pipe_id_info pipe_names [] = { PIPE_WKSSVC , SYNT_WKSSVC_V1 , PIPE_NTSVCS , TRANS_SYNT_V2 }, { PIPE_WINREG , SYNT_WINREG_V1 , PIPE_WINREG , TRANS_SYNT_V2 }, { PIPE_SPOOLSS , SYNT_SPOOLSS_V1 , PIPE_SPOOLSS , TRANS_SYNT_V2 }, + { PIPE_NETDFS , SYNT_NETDFS_V3 , PIPE_NETDFS , TRANS_SYNT_V2 }, { NULL , SYNT_NONE_V0 , NULL , SYNT_NONE_V0 } }; diff --git a/source3/rpc_server/srv_dfs.c b/source3/rpc_server/srv_dfs.c new file mode 100644 index 0000000000..9f78b7db37 --- /dev/null +++ b/source3/rpc_server/srv_dfs.c @@ -0,0 +1,456 @@ + +/* + * Unix SMB/Netbios implementation. + * Version 1.9. + * RPC Pipe client / server routines for Dfs + * Copyright (C) Andrew Tridgell 1992-1997, + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, + * Copyright (C) Shirish Kalele 2000. + * + * 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" + +#define MAX_MSDFS_JUNCTIONS 256 + +extern int DEBUGLEVEL; +extern pstring global_myname; + +#ifdef MS_DFS + +/********************************************************************** + api_dfs_exist + **********************************************************************/ +static BOOL api_dfs_exist( prs_struct *data, + prs_struct *rdata) +{ + DFS_R_DFS_EXIST r_d; + + if(lp_host_msdfs()) + r_d.dfs_exist_flag = 1; + else + r_d.dfs_exist_flag = 0; + + return dfs_io_r_dfs_exist("", &r_d, rdata, 0); +} + +static uint32 init_reply_dfs_add(DFS_Q_DFS_ADD* q_a) +{ + struct junction_map jn; + struct referral* old_referral_list = NULL; + BOOL exists = False; + + pstring dfspath, servername, sharename; + pstring altpath; + + unistr2_to_ascii(dfspath, &(q_a->DfsEntryPath), sizeof(dfspath)-1); + unistr2_to_ascii(servername, &(q_a->ServerName), sizeof(servername)-1); + unistr2_to_ascii(sharename, &(q_a->ShareName), sizeof(sharename)-1); + + DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n", + dfspath, servername, sharename)); + + pstrcpy(altpath, servername); + pstrcat(altpath, "\\"); + pstrcat(altpath, sharename); + + if(!create_junction(dfspath, &jn)) + return NERR_DfsNoSuchServer; + + if(get_referred_path(&jn)) + { + exists = True; + jn.referral_count += 1; + old_referral_list = jn.referral_list; + } + else + jn.referral_count = 1; + + jn.referral_list = (struct referral*) malloc(jn.referral_count + * sizeof(struct referral)); + + if(jn.referral_list == NULL) + { + DEBUG(0,("init_reply_dfs_add: malloc failed for referral list!\n")); + return NERR_DfsInternalError; + } + + if(old_referral_list) + { + memcpy(jn.referral_list, old_referral_list, + sizeof(struct referral)*jn.referral_count-1); + free(old_referral_list); + } + + jn.referral_list[jn.referral_count-1].proximity = 0; + jn.referral_list[jn.referral_count-1].ttl = REFERRAL_TTL; + + pstrcpy(jn.referral_list[jn.referral_count-1].alternate_path, altpath); + + if(!create_msdfs_link(&jn, exists)) + return NERR_DfsCantCreateJunctionPoint; + + return 0; +} +/***************************************************************** + api_dfs_add + *****************************************************************/ +static BOOL api_dfs_add(prs_struct* data, prs_struct* rdata) +{ + DFS_Q_DFS_ADD q_a; + DFS_R_DFS_ADD r_a; + + if(!dfs_io_q_dfs_add("", &q_a, data, 0)) + return False; + + r_a.status = init_reply_dfs_add(&q_a); + + dfs_io_r_dfs_add("", &r_a, rdata, 0); + + return True; +} + +static uint32 init_reply_dfs_remove(DFS_Q_DFS_REMOVE* q_r) +{ + struct junction_map jn; + BOOL found = False; + + pstring dfspath, servername, sharename; + pstring altpath; + + unistr2_to_ascii(dfspath, &(q_r->DfsEntryPath), sizeof(dfspath)-1); + if(q_r->ptr_ServerName) + unistr2_to_ascii(servername, &(q_r->ServerName), sizeof(servername)-1); + + if(q_r->ptr_ShareName) + unistr2_to_ascii(sharename, &(q_r->ShareName), sizeof(sharename)-1); + + if(q_r->ptr_ServerName && q_r->ptr_ShareName) + { + pstrcpy(altpath, servername); + pstrcat(altpath, "\\"); + pstrcat(altpath, sharename); + } + + DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n", + dfspath, servername, sharename)); + + if(!create_junction(dfspath, &jn)) + return NERR_DfsNoSuchServer; + + if(!get_referred_path(&jn)) + return NERR_DfsNoSuchVolume; + + /* if no server-share pair given, remove the msdfs link completely */ + if(!q_r->ptr_ServerName && !q_r->ptr_ShareName) + { + if(!remove_msdfs_link(&jn)) + return NERR_DfsNoSuchVolume; + } + else + { + int i=0; + /* compare each referral in the list with the one to remove */ + for(i=0;i<jn.referral_count;i++) + { + pstring refpath; + pstrcpy(refpath,jn.referral_list[i].alternate_path); + trim_string(refpath, "\\", "\\"); + if(strequal(refpath, altpath)) + { + *(jn.referral_list[i].alternate_path)='\0'; + found = True; + } + } + if(!found) + return NERR_DfsNoSuchShare; + + /* Only one referral, remove it */ + if(jn.referral_count == 1) + { + if(!remove_msdfs_link(&jn)) + return NERR_DfsNoSuchVolume; + } + else + { + if(!create_msdfs_link(&jn, True)) + return NERR_DfsCantCreateJunctionPoint; + } + } + + return 0; +} + +/***************************************************************** + api_dfs_remove + *****************************************************************/ +static BOOL api_dfs_remove(prs_struct* data, prs_struct* rdata) +{ + DFS_Q_DFS_REMOVE q_r; + DFS_R_DFS_REMOVE r_r; + + if(!dfs_io_q_dfs_remove("", &q_r, data, 0)) + return False; + + r_r.status = init_reply_dfs_remove(&q_r); + + dfs_io_r_dfs_remove("", &r_r, rdata, 0); + + return True; +} + +static BOOL init_reply_dfs_info_1(struct junction_map* j, DFS_INFO_1* dfs1, int num_j) +{ + int i=0; + for(i=0;i<num_j;i++) + { + pstring str; + dfs1[i].ptr_entrypath = 1; + slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname, + j[i].service_name, j[i].volume_name); + DEBUG(5,("init_reply_dfs_info_1: %d) initing entrypath: %s\n",i,str)); + init_unistr2(&dfs1[i].entrypath,str,strlen(str)+1); + } + return True; +} + +static BOOL init_reply_dfs_info_2(struct junction_map* j, DFS_INFO_2* dfs2, int num_j) +{ + int i=0; + for(i=0;i<num_j;i++) + { + pstring str; + dfs2[i].ptr_entrypath = 1; + slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname, + j[i].service_name, j[i].volume_name); + init_unistr2(&dfs2[i].entrypath, str, strlen(str)+1); + dfs2[i].ptr_comment = 0; + dfs2[i].state = 1; /* set up state of dfs junction as OK */ + dfs2[i].num_storages = j[i].referral_count; + } + return True; +} + +static BOOL init_reply_dfs_info_3(struct junction_map* j, DFS_INFO_3* dfs3, int num_j) +{ + int i=0,ii=0; + for(i=0;i<num_j;i++) + { + pstring str; + dfs3[i].ptr_entrypath = 1; + slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname, + j[i].service_name, j[i].volume_name); + init_unistr2(&dfs3[i].entrypath, str, strlen(str)+1); + dfs3[i].ptr_comment = 1; + init_unistr2(&dfs3[i].comment, "", 1); + dfs3[i].state = 1; + dfs3[i].num_storages = dfs3[i].num_storage_infos = j[i].referral_count; + dfs3[i].ptr_storages = 1; + + /* also enumerate the storages */ + dfs3[i].storages = (DFS_STORAGE_INFO*) malloc(j[i].referral_count * + sizeof(DFS_STORAGE_INFO)); + for(ii=0;ii<j[i].referral_count;ii++) + { + char* p; + pstring path; + DFS_STORAGE_INFO* stor = &(dfs3[i].storages[ii]); + struct referral* ref = &(j[i].referral_list[ii]); + + pstrcpy(path, ref->alternate_path); + trim_string(path,"\\",""); + p = strrchr(path,'\\'); + if(p==NULL) + { + DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path)); + continue; + } + *p = '\0'; + DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1)); + stor->state = 2; /* set all storages as ONLINE */ + init_unistr2(&stor->servername, path, strlen(path)+1); + init_unistr2(&stor->sharename, p+1, strlen(p+1)+1); + stor->ptr_servername = stor->ptr_sharename = 1; + } + } + return True; +} + +static uint32 init_reply_dfs_ctr(uint32 level, DFS_INFO_CTR* ctr, + struct junction_map* jn, int num_jn) +{ + /* do the levels */ + switch(level) + { + case 1: + { + DFS_INFO_1* dfs1; + dfs1 = (DFS_INFO_1*) malloc(num_jn * sizeof(DFS_INFO_1)); + init_reply_dfs_info_1(jn, dfs1, num_jn); + ctr->dfs.info1 = dfs1; + break; + } + case 2: + { + DFS_INFO_2* dfs2; + dfs2 = (DFS_INFO_2*) malloc(num_jn * sizeof(DFS_INFO_2)); + init_reply_dfs_info_2(jn, dfs2, num_jn); + ctr->dfs.info2 = dfs2; + break; + } + case 3: + { + DFS_INFO_3* dfs3; + dfs3 = (DFS_INFO_3*) malloc(num_jn * sizeof(DFS_INFO_3)); + init_reply_dfs_info_3(jn, dfs3, num_jn); + ctr->dfs.info3 = dfs3; + } + } + return 0; +} + +static uint32 init_reply_dfs_enum(uint32 level, DFS_R_DFS_ENUM *q_r) +{ + struct junction_map jn[MAX_MSDFS_JUNCTIONS]; + int num_jn = 0; + int i=0; + + num_jn = enum_msdfs_junctions(jn); + + DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", + num_jn, level)); + + q_r->ptr_buffer = level; + q_r->level = q_r->level2 = level; + q_r->ptr_num_entries = q_r->ptr_num_entries2 = 1; + q_r->num_entries = q_r->num_entries2 = num_jn; + q_r->reshnd.ptr_hnd = 1; + q_r->reshnd.handle = num_jn; + + q_r->ctr = (DFS_INFO_CTR*) malloc(sizeof(DFS_INFO_CTR)); + q_r->ctr->switch_value = level; + q_r->ctr->num_entries = num_jn; + q_r->ctr->ptr_dfs_ctr = 1; + + init_reply_dfs_ctr(level, q_r->ctr, jn, num_jn); + + for(i=0;i<num_jn;i++) + free(jn[i].referral_list); + + return 0; +} + +static uint32 init_reply_dfs_get_info(UNISTR2* uni_path, uint32 level, + DFS_R_DFS_GET_INFO* r_i) +{ + pstring path; + struct junction_map jn; + + unistr2_to_ascii(path, uni_path, sizeof(path)-1); + if(!create_junction(path, &jn)) + return NERR_DfsNoSuchServer; + + if(!get_referred_path(&jn)) + return NERR_DfsNoSuchVolume; + + r_i->level = level; + r_i->ptr_ctr = 1; + r_i->status = init_reply_dfs_ctr(level, &(r_i->ctr), &jn, 1); + + free(jn.referral_list); + return 0; +} +/******************************************************************* + api_dfs_get_info + *******************************************************************/ +static BOOL api_dfs_get_info(prs_struct* data, prs_struct* rdata) +{ + DFS_Q_DFS_GET_INFO q_i; + DFS_R_DFS_GET_INFO r_i; + + ZERO_STRUCT(r_i); + + if(!dfs_io_q_dfs_get_info("", &q_i, data, 0)) + return False; + + r_i.status = init_reply_dfs_get_info(&q_i.uni_path, q_i.level, &r_i); + + if(!dfs_io_r_dfs_get_info("", &r_i, rdata, 0)) + return False; + + switch(r_i.level) { + case 1: free(r_i.ctr.dfs.info1); break; + case 2: free(r_i.ctr.dfs.info2); break; + case 3: + { + free(r_i.ctr.dfs.info3->storages); + free(r_i.ctr.dfs.info3); + break; + } + } + return True; +} + +/******************************************************************* + api_dfs_enum + *******************************************************************/ +static BOOL api_dfs_enum(prs_struct* data, prs_struct* rdata) +{ + DFS_Q_DFS_ENUM q_e; + DFS_R_DFS_ENUM q_r; + + if(!dfs_io_q_dfs_enum("", &q_e, data, 0)) + return False; + + q_r.status = init_reply_dfs_enum(q_e.level, &q_r); + + if(!dfs_io_r_dfs_enum("", &q_r, rdata, 0)) + return False; + switch(q_e.level) { + case 1: + free(q_r.ctr->dfs.info1); break; + case 2: + free(q_r.ctr->dfs.info2); break; + case 3: + free(q_r.ctr->dfs.info3->storages); free(q_r.ctr->dfs.info3); break; + } + free(q_r.ctr); + return True; +} + +/******************************************************************* +\pipe\netdfs commands +********************************************************************/ +struct api_struct api_netdfs_cmds[] = +{ + {"DFS_EXIST", DFS_EXIST, api_dfs_exist }, + {"DFS_ADD", DFS_ADD, api_dfs_add }, + {"DFS_REMOVE", DFS_REMOVE, api_dfs_remove }, + {"DFS_GET_INFO", DFS_GET_INFO, api_dfs_get_info }, + {"DFS_ENUM", DFS_ENUM, api_dfs_enum }, + {NULL, 0, NULL } +}; + +/******************************************************************* +receives a netdfs pipe and responds. +********************************************************************/ +BOOL api_netdfs_rpc(pipes_struct *p, prs_struct *data) +{ + return api_rpcTNP(p, "api_netdfs_rpc", api_netdfs_cmds, data); +} + +#endif diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 06743d8d16..aef0c9d23b 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -474,6 +474,9 @@ static struct api_cmd api_fd_commands[] = { "NETLOGON", "lsass", api_netlog_rpc }, { "winreg", "winreg", api_reg_rpc }, { "spoolss", "spoolss", api_spoolss_rpc }, +#ifdef MS_DFS + { "netdfs", "netdfs" , api_netdfs_rpc }, +#endif { NULL, NULL, NULL } }; diff --git a/source3/rpcclient/cmd_reg.c b/source3/rpcclient/cmd_reg.c index dfbfcf0cd1..89b53c823f 100644 --- a/source3/rpcclient/cmd_reg.c +++ b/source3/rpcclient/cmd_reg.c @@ -344,7 +344,7 @@ void cmd_reg_create_val(struct client_info *info) uint32 unk_1; /* query it */ res1 = res1 ? do_reg_query_info(smb_cli, &val_pol, - type, &unk_0, &unk_1) : False; + val_name, *val_type) : False; #endif DEBUG(5, ("cmd_reg_create_val: smb_cli->fd:%d\n", smb_cli->fd)); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e98187de25..5f58962799 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -44,6 +44,9 @@ static char *known_nt_pipes[] = { "\\lsarpc", "\\winreg", "\\spoolss", +#ifdef MS_DFS + "\\netdfs", +#endif NULL }; |