1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4 
5    Copyright (C) Tim Potter 2000
6    Copyright (C) Jelmer Vernooij       2005.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include "includes.h"
23 #include "rpcclient.h"
24 #include "../librpc/gen_ndr/ndr_dfs_c.h"
25 
26 /* Check DFS is supported by the remote server */
27 
cmd_dfs_version(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)28 static WERROR cmd_dfs_version(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
29 			      int argc, const char **argv)
30 {
31 	enum dfs_ManagerVersion version;
32 	NTSTATUS result;
33 	struct dcerpc_binding_handle *b = cli->binding_handle;
34 
35 	if (argc != 1) {
36 		printf("Usage: %s\n", argv[0]);
37 		return WERR_OK;
38 	}
39 
40 	result = dcerpc_dfs_GetManagerVersion(b, mem_ctx, &version);
41 
42 	if (!NT_STATUS_IS_OK(result)) {
43 		return ntstatus_to_werror(result);
44 	}
45 
46 	if (version > 0) {
47 		printf("dfs is present (%d)\n", version);
48 	} else {
49 		printf("dfs is not present\n");
50 	}
51 
52 	return WERR_OK;
53 }
54 
cmd_dfs_add(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)55 static WERROR cmd_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
56 			  int argc, const char **argv)
57 {
58 	NTSTATUS result;
59 	WERROR werr;
60 	const char *path, *servername, *sharename, *comment;
61 	uint32_t flags = 0;
62 	struct dcerpc_binding_handle *b = cli->binding_handle;
63 
64 	if (argc != 5) {
65 		printf("Usage: %s path servername sharename comment\n",
66 		       argv[0]);
67 		return WERR_OK;
68 	}
69 
70 	path = argv[1];
71 	servername = argv[2];
72 	sharename = argv[3];
73 	comment = argv[4];
74 
75 	result = dcerpc_dfs_Add(b, mem_ctx, path, servername,
76 				sharename, comment, flags, &werr);
77 	if (!NT_STATUS_IS_OK(result)) {
78 		return ntstatus_to_werror(result);
79 	}
80 
81 	return werr;
82 }
83 
cmd_dfs_remove(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)84 static WERROR cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
85 			     int argc, const char **argv)
86 {
87 	NTSTATUS result;
88 	WERROR werr;
89 	const char *path, *servername, *sharename;
90 	struct dcerpc_binding_handle *b = cli->binding_handle;
91 
92 	if (argc != 4) {
93 		printf("Usage: %s path servername sharename\n", argv[0]);
94 		return WERR_OK;
95 	}
96 
97 	path = argv[1];
98 	servername = argv[2];
99 	sharename = argv[3];
100 
101 	result = dcerpc_dfs_Remove(b, mem_ctx, path, servername,
102 				   sharename, &werr);
103 	if (!NT_STATUS_IS_OK(result)) {
104 		return ntstatus_to_werror(result);
105 	}
106 
107 	return werr;
108 }
109 
110 /* Display a DFS_INFO_1 structure */
111 
display_dfs_info_1(struct dfs_Info1 * info1)112 static void display_dfs_info_1(struct dfs_Info1 *info1)
113 {
114 	printf("path: %s\n", info1->path);
115 }
116 
117 /* Display a DFS_INFO_2 structure */
118 
display_dfs_info_2(struct dfs_Info2 * info2)119 static void display_dfs_info_2(struct dfs_Info2 *info2)
120 {
121 	printf("path: %s\n", info2->path);
122 	printf("\tcomment: %s\n", info2->comment);
123 
124 	printf("\tstate: %d\n", info2->state);
125 	printf("\tnum_stores: %d\n", info2->num_stores);
126 }
127 
128 /* Display a DFS_INFO_3 structure */
129 
display_dfs_info_3(struct dfs_Info3 * info3)130 static void display_dfs_info_3(struct dfs_Info3 *info3)
131 {
132 	int i;
133 
134 	printf("path: %s\n", info3->path);
135 
136 	printf("\tcomment: %s\n", info3->comment);
137 
138 	printf("\tstate: %d\n", info3->state);
139 	printf("\tnum_stores: %d\n", info3->num_stores);
140 
141 	for (i = 0; i < info3->num_stores; i++) {
142 		struct dfs_StorageInfo *dsi = &info3->stores[i];
143 
144 		printf("\t\tstorage[%d] server: %s\n", i, dsi->server);
145 
146 		printf("\t\tstorage[%d] share: %s\n", i, dsi->share);
147 	}
148 }
149 
150 
151 /* Display a DFS_INFO_CTR structure */
display_dfs_info(uint32_t level,union dfs_Info * ctr)152 static void display_dfs_info(uint32_t level, union dfs_Info *ctr)
153 {
154 	switch (level) {
155 		case 0x01:
156 			display_dfs_info_1(ctr->info1);
157 			break;
158 		case 0x02:
159 			display_dfs_info_2(ctr->info2);
160 			break;
161 		case 0x03:
162 			display_dfs_info_3(ctr->info3);
163 			break;
164 		default:
165 			printf("unsupported info level %d\n",
166 			       level);
167 			break;
168 	}
169 }
170 
display_dfs_enumstruct(struct dfs_EnumStruct * ctr)171 static void display_dfs_enumstruct(struct dfs_EnumStruct *ctr)
172 {
173 	int i;
174 
175 	/* count is always the first element, so we can just use info1 here */
176 	for (i = 0; i < ctr->e.info1->count; i++) {
177 		switch (ctr->level) {
178 		case 1: display_dfs_info_1(&ctr->e.info1->s[i]); break;
179 		case 2: display_dfs_info_2(&ctr->e.info2->s[i]); break;
180 		case 3: display_dfs_info_3(&ctr->e.info3->s[i]); break;
181 		default:
182 				printf("unsupported info level %d\n",
183 			       ctr->level);
184 				return;
185 		}
186 	}
187 }
188 
189 /* Enumerate dfs shares */
190 
cmd_dfs_enum(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)191 static WERROR cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
192 			   int argc, const char **argv)
193 {
194 	struct dfs_EnumStruct str;
195 	struct dfs_EnumArray1 info1;
196 	struct dfs_EnumArray2 info2;
197 	struct dfs_EnumArray3 info3;
198 	struct dfs_EnumArray4 info4;
199 	struct dfs_EnumArray200 info200;
200 	struct dfs_EnumArray300 info300;
201 	struct dcerpc_binding_handle *b = cli->binding_handle;
202 
203 	NTSTATUS result;
204 	WERROR werr;
205 	uint32_t total = 0;
206 
207 	if (argc > 2) {
208 		printf("Usage: %s [info_level]\n", argv[0]);
209 		return WERR_OK;
210 	}
211 
212 	str.level = 1;
213 	if (argc == 2)
214 		str.level = atoi(argv[1]);
215 
216 	switch (str.level) {
217 	case 1: str.e.info1 = &info1; ZERO_STRUCT(info1); break;
218 	case 2: str.e.info2 = &info2; ZERO_STRUCT(info2); break;
219 	case 3: str.e.info3 = &info3; ZERO_STRUCT(info3); break;
220 	case 4: str.e.info4 = &info4; ZERO_STRUCT(info4); break;
221 	case 200: str.e.info200 = &info200; ZERO_STRUCT(info200); break;
222 	case 300: str.e.info300 = &info300; ZERO_STRUCT(info300); break;
223 	default:
224 			  printf("Unknown info level %d\n", str.level);
225 			  break;
226 	}
227 
228 	result = dcerpc_dfs_Enum(b, mem_ctx, str.level, 0xFFFFFFFF, &str,
229 				 &total, &werr);
230 	if (!NT_STATUS_IS_OK(result)) {
231 		return ntstatus_to_werror(result);
232 	}
233 	if (W_ERROR_IS_OK(werr)) {
234 		display_dfs_enumstruct(&str);
235 	}
236 
237 	return werr;
238 }
239 
240 /* Enumerate dfs shares */
241 
cmd_dfs_enumex(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)242 static WERROR cmd_dfs_enumex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
243 			     int argc, const char **argv)
244 {
245 	struct dfs_EnumStruct str;
246 	struct dfs_EnumArray1 info1;
247 	struct dfs_EnumArray2 info2;
248 	struct dfs_EnumArray3 info3;
249 	struct dfs_EnumArray4 info4;
250 	struct dfs_EnumArray200 info200;
251 	struct dfs_EnumArray300 info300;
252 	struct dcerpc_binding_handle *b = cli->binding_handle;
253 
254 	NTSTATUS result;
255 	WERROR werr;
256 	uint32_t total = 0;
257 
258 	if (argc < 2 || argc > 3) {
259 		printf("Usage: %s dfs_name [info_level]\n", argv[0]);
260 		return WERR_OK;
261 	}
262 
263 	str.level = 1;
264 
265 	if (argc == 3)
266 		str.level = atoi(argv[2]);
267 
268 	switch (str.level) {
269 	case 1: str.e.info1 = &info1; ZERO_STRUCT(info1); break;
270 	case 2: str.e.info2 = &info2; ZERO_STRUCT(info2); break;
271 	case 3: str.e.info3 = &info3; ZERO_STRUCT(info3); break;
272 	case 4: str.e.info4 = &info4; ZERO_STRUCT(info4); break;
273 	case 200: str.e.info200 = &info200; ZERO_STRUCT(info200); break;
274 	case 300: str.e.info300 = &info300; ZERO_STRUCT(info300); break;
275 	default:
276 		  printf("Unknown info level %d\n", str.level);
277 		  break;
278 	}
279 
280 	result = dcerpc_dfs_EnumEx(b, mem_ctx, argv[1], str.level,
281 				   0xFFFFFFFF, &str, &total, &werr);
282 	if (!NT_STATUS_IS_OK(result)) {
283 		return ntstatus_to_werror(result);
284 	}
285 	if (W_ERROR_IS_OK(werr)) {
286 		display_dfs_enumstruct(&str);
287 	}
288 
289 	return werr;
290 }
291 
292 
cmd_dfs_getinfo(struct rpc_pipe_client * cli,TALLOC_CTX * mem_ctx,int argc,const char ** argv)293 static WERROR cmd_dfs_getinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
294 			      int argc, const char **argv)
295 {
296 	NTSTATUS result;
297 	WERROR werr;
298 	const char *path, *servername, *sharename;
299 	uint32_t info_level = 1;
300 	union dfs_Info ctr;
301 	struct dcerpc_binding_handle *b = cli->binding_handle;
302 
303 	if (argc < 4 || argc > 5) {
304 		printf("Usage: %s path servername sharename "
305                        "[info_level]\n", argv[0]);
306 		return WERR_OK;
307 	}
308 
309 	path = argv[1];
310 	servername = argv[2];
311 	sharename = argv[3];
312 
313 	if (argc == 5)
314 		info_level = atoi(argv[4]);
315 
316 	result = dcerpc_dfs_GetInfo(b, mem_ctx, path, servername,
317 				    sharename, info_level, &ctr, &werr);
318 	if (!NT_STATUS_IS_OK(result)) {
319 		return ntstatus_to_werror(result);
320 	}
321 	if (W_ERROR_IS_OK(werr)) {
322 		display_dfs_info(info_level, &ctr);
323 	}
324 
325 	return werr;
326 }
327 
328 /* List of commands exported by this module */
329 
330 struct cmd_set dfs_commands[] = {
331 
332 	{ .name = "DFS" },
333 
334 	{
335 		.name               = "dfsversion",
336 		.returntype         = RPC_RTYPE_WERROR,
337 		.ntfn               = NULL,
338 		.wfn                = cmd_dfs_version,
339 		.table              = &ndr_table_netdfs,
340 		.rpc_pipe           = NULL,
341 		.description        = "Query DFS support",
342 		.usage              = "",
343 	},
344 	{
345 		.name               = "dfsadd",
346 		.returntype         = RPC_RTYPE_WERROR,
347 		.ntfn               = NULL,
348 		.wfn                = cmd_dfs_add,
349 		.table              = &ndr_table_netdfs,
350 		.rpc_pipe           = NULL,
351 		.description        = "Add a DFS share",
352 		.usage              = "",
353 	},
354 	{
355 		.name               = "dfsremove",
356 		.returntype         = RPC_RTYPE_WERROR,
357 		.ntfn               = NULL,
358 		.wfn                = cmd_dfs_remove,
359 		.table              = &ndr_table_netdfs,
360 		.rpc_pipe           = NULL,
361 		.description        = "Remove a DFS share",
362 		.usage              = "",
363 	},
364 	{
365 		.name               = "dfsgetinfo",
366 		.returntype         = RPC_RTYPE_WERROR,
367 		.ntfn               = NULL,
368 		.wfn                = cmd_dfs_getinfo,
369 		.table              = &ndr_table_netdfs,
370 		.rpc_pipe           = NULL,
371 		.description        = "Query DFS share info",
372 		.usage              = "",
373 	},
374 	{
375 		.name               = "dfsenum",
376 		.returntype         = RPC_RTYPE_WERROR,
377 		.ntfn               = NULL,
378 		.wfn                = cmd_dfs_enum,
379 		.table              = &ndr_table_netdfs,
380 		.rpc_pipe           = NULL,
381 		.description        = "Enumerate dfs shares",
382 		.usage              = "",
383 	},
384 	{
385 		.name               = "dfsenumex",
386 		.returntype         = RPC_RTYPE_WERROR,
387 		.ntfn               = NULL,
388 		.wfn                = cmd_dfs_enumex,
389 		.table              = &ndr_table_netdfs,
390 		.rpc_pipe           = NULL,
391 		.description        = "Enumerate dfs shares",
392 		.usage              = "",
393 	},
394 
395 	{ .name = NULL }
396 };
397