1 /*
2    Unix SMB/CIFS implementation.
3    RPC pipe client
4 
5    Copyright (C) Volker Lendecke 2009
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "includes.h"
22 #include "rpcclient.h"
23 #include "../librpc/gen_ndr/ndr_epmapper_c.h"
24 #include "librpc/ndr/ndr_table.h"
25 
cmd_epmapper_map(struct rpc_pipe_client * p,TALLOC_CTX * mem_ctx,int argc,const char ** argv)26 static NTSTATUS cmd_epmapper_map(struct rpc_pipe_client *p,
27 				 TALLOC_CTX *mem_ctx,
28 				 int argc, const char **argv)
29 {
30 	struct dcerpc_binding_handle *b = p->binding_handle;
31 	struct dcerpc_binding *map_binding;
32 	struct epm_twr_t map_tower;
33 	struct epm_twr_p_t towers[500];
34 	struct policy_handle entry_handle;
35 	struct ndr_syntax_id abstract_syntax;
36 	uint32_t num_towers;
37 	TALLOC_CTX *tmp_ctx = talloc_stackframe();
38 	NTSTATUS status;
39 	uint32_t result;
40 	uint32_t i;
41 	const struct ndr_interface_list *l;
42 	const char *interface_name = "lsarpc";
43 	enum dcerpc_transport_t transport = NCACN_NP;
44 	bool ok = false;
45 	struct GUID object_uuid = GUID_zero();
46 
47 	if (argc > 4) {
48 		d_fprintf(stderr,
49 			  "Usage: %s [interface_name] [transport] "
50 			  "[object_uuid]\n",
51 			  argv[0]);
52 		return NT_STATUS_OK;
53 	}
54 
55 	if (argc >= 2) {
56 		interface_name = argv[1];
57 	}
58 
59 	for (l = ndr_table_list(); l != NULL; l = l->next) {
60 
61 		ok = strequal(interface_name, l->table->name);
62 		if (ok) {
63 			abstract_syntax = l->table->syntax_id;
64 			break;
65 		}
66 	}
67 
68 	if (!ok) {
69 		d_fprintf(stderr, "unknown interface: %s\n",
70 			interface_name);
71 		status = NT_STATUS_UNSUCCESSFUL;
72 		goto done;
73 	}
74 
75 	if (argc >= 3) {
76 		transport = dcerpc_transport_by_name(argv[2]);
77 		if (transport == NCA_UNKNOWN) {
78 			d_fprintf(stderr, "unknown transport: %s\n",
79 				argv[2]);
80 			status = NT_STATUS_UNSUCCESSFUL;
81 			goto done;
82 		}
83 	}
84 
85 	if (argc >= 4) {
86 		status = GUID_from_string(argv[3], &object_uuid);
87 		if (!NT_STATUS_IS_OK(status)) {
88 			goto done;
89 		}
90 	}
91 
92 	/* 127.0.0.1[0] => correct? needed? */
93 	status = dcerpc_parse_binding(tmp_ctx, "ncacn_np:127.0.0.1[0]",
94 				      &map_binding);
95 	if (!NT_STATUS_IS_OK(status)) {
96 		d_fprintf(stderr, "dcerpc_parse_binding returned %s\n",
97 			  nt_errstr(status));
98 		goto done;
99 	}
100 
101 	status = dcerpc_binding_set_transport(map_binding, transport);
102 	if (!NT_STATUS_IS_OK(status)) {
103 		d_fprintf(stderr, "dcerpc_binding_set_transport returned %s\n",
104 			  nt_errstr(status));
105 		goto done;
106 	}
107 
108 	status = dcerpc_binding_set_abstract_syntax(map_binding,
109 						    &abstract_syntax);
110 	if (!NT_STATUS_IS_OK(status)) {
111 		d_fprintf(stderr, "dcerpc_binding_set_abstract_syntax returned %s\n",
112 			  nt_errstr(status));
113 		goto done;
114 	}
115 
116 	status = dcerpc_binding_build_tower(tmp_ctx, map_binding,
117 					    &map_tower.tower);
118 	if (!NT_STATUS_IS_OK(status)) {
119 		d_fprintf(stderr, "dcerpc_binding_build_tower returned %s\n",
120 			  nt_errstr(status));
121 		goto done;
122 	}
123 
124 	ZERO_STRUCT(towers);
125 	ZERO_STRUCT(entry_handle);
126 
127 	status = dcerpc_epm_Map(
128 		b, tmp_ctx, &object_uuid,
129 		&map_tower, &entry_handle, ARRAY_SIZE(towers),
130 		&num_towers, towers, &result);
131 	if (!NT_STATUS_IS_OK(status)) {
132 		d_fprintf(stderr, "dcerpc_epm_Map returned %s\n",
133 			  nt_errstr(status));
134 		goto done;
135 	}
136 
137 	if (result != EPMAPPER_STATUS_OK) {
138 		d_fprintf(stderr, "epm_Map returned %u (0x%08X)\n",
139 			  result, result);
140 		status = NT_STATUS_UNSUCCESSFUL;
141 		goto done;
142 	}
143 
144 	d_printf("num_tower[%u]\n", num_towers);
145 
146 	for (i=0; i < num_towers; i++) {
147 		struct dcerpc_binding *binding;
148 
149 		if (towers[i].twr == NULL) {
150 			d_fprintf(stderr, "tower[%u] NULL\n", i);
151 			break;
152 		}
153 
154 		status = dcerpc_binding_from_tower(tmp_ctx, &towers[i].twr->tower,
155 						   &binding);
156 		if (!NT_STATUS_IS_OK(status)) {
157 			break;
158 		}
159 
160 		d_printf("tower[%u] %s\n", i, dcerpc_binding_string(tmp_ctx, binding));
161 	}
162 done:
163 	TALLOC_FREE(tmp_ctx);
164 	return status;
165 }
166 
cmd_epmapper_lookup(struct rpc_pipe_client * p,TALLOC_CTX * mem_ctx,int argc,const char ** argv)167 static NTSTATUS cmd_epmapper_lookup(struct rpc_pipe_client *p,
168 				    TALLOC_CTX *mem_ctx,
169 				    int argc, const char **argv)
170 {
171 	struct dcerpc_binding_handle *b = p->binding_handle;
172 	struct policy_handle entry_handle;
173 
174 	ZERO_STRUCT(entry_handle);
175 
176 	while (true) {
177 		TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
178 		uint32_t num_entries;
179 		struct epm_entry_t entry;
180 		NTSTATUS status;
181 		char *guid_string;
182 		struct dcerpc_binding *binding;
183 		uint32_t result;
184 
185 		status = dcerpc_epm_Lookup(b, tmp_ctx,
186 				   0, /* rpc_c_ep_all */
187 				   NULL,
188 				   NULL,
189 				   0, /* rpc_c_vers_all */
190 				   &entry_handle,
191 				   1, /* max_ents */
192 				   &num_entries, &entry,
193 				   &result);
194 		if (!NT_STATUS_IS_OK(status)) {
195 			d_fprintf(stderr, "dcerpc_epm_Lookup returned %s\n",
196 				  nt_errstr(status));
197 			break;
198 		}
199 
200 		if (result == EPMAPPER_STATUS_NO_MORE_ENTRIES) {
201 			d_fprintf(stderr, "epm_Lookup no more entries\n");
202 			break;
203 		}
204 
205 		if (result != EPMAPPER_STATUS_OK) {
206 			d_fprintf(stderr, "epm_Lookup returned %u (0x%08X)\n",
207 				  result, result);
208 			break;
209 		}
210 
211 		if (num_entries != 1) {
212 			d_fprintf(stderr, "epm_Lookup returned %d "
213 				  "entries, expected one\n", (int)num_entries);
214 			break;
215 		}
216 
217 		guid_string = GUID_string(tmp_ctx, &entry.object);
218 		if (guid_string == NULL) {
219 			break;
220 		}
221 
222 		status = dcerpc_binding_from_tower(tmp_ctx, &entry.tower->tower,
223 						   &binding);
224 		if (!NT_STATUS_IS_OK(status)) {
225 			break;
226 		}
227 
228 		d_printf("%s %s: %s\n", guid_string,
229 			 dcerpc_binding_string(tmp_ctx, binding),
230 			 entry.annotation);
231 
232 		TALLOC_FREE(tmp_ctx);
233 	}
234 
235 	return NT_STATUS_OK;
236 }
237 
238 
239 /* List of commands exported by this module */
240 
241 struct cmd_set epmapper_commands[] = {
242 
243 	{
244 		.name = "EPMAPPER",
245 	},
246 
247 	{
248 		.name               = "epmmap",
249 		.returntype         = RPC_RTYPE_NTSTATUS,
250 		.ntfn               = cmd_epmapper_map,
251 		.wfn                = NULL,
252 		.table              = &ndr_table_epmapper,
253 		.rpc_pipe           = NULL,
254 		.description        = "Map a binding",
255 		.usage              = "",
256 	},
257 	{
258 		.name               = "epmlookup",
259 		.returntype         = RPC_RTYPE_NTSTATUS,
260 		.ntfn               = cmd_epmapper_lookup,
261 		.wfn                = NULL,
262 		.table              = &ndr_table_epmapper,
263 		.rpc_pipe           = NULL,
264 		.description        = "Lookup bindings",
265 		.usage              = "",
266 	},
267 	{
268 		.name = NULL,
269 	},
270 };
271