1/*
2 * SAMR test
3 *
4 * Jim Doyle, jrd@bu.edu, 09-05-1998
5 * Stefan Metzmacher, metze@samba.org, 2008
6 *
7 */
8#if HAVE_CONFIG_H
9#include <config.h>
10#endif
11
12#define getopt getopt_system
13
14#include <stdio.h>
15#include <string.h>
16#include <stdlib.h>
17#include <compat/dcerpc.h>
18#include "samrt.h"
19#include <misc.h>
20
21#undef getopt
22
23#ifdef HAVE_GETOPT_H
24#include <getopt.h>
25#endif
26
27#define MAX_USER_INPUT 128
28#define MAX_LINE 128
29
30/*
31 * Forward declarations
32 */
33
34static int
35get_client_rpc_binding(rpc_binding_handle_t *, const char *,
36		       rpc_if_handle_t, const char *, const char *, const char *);
37
38/*
39 * usage()
40 */
41
42static void usage(void)
43{
44  printf("usage:   samrt [-h hostname] [-u] [-t] [-k]\n");
45  printf("         -u:  use UDP protocol \n");
46  printf("         -t:  use TCP protocol (default) \n");
47  printf("         -v:  more verbosity\n");
48  printf("         -k:  use gss_mskrb\n");
49  printf("         -h:  specify host where RPC server lives \n");
50  exit(0);
51}
52
53int main(int argc, char *argv[])
54{
55
56  /*
57   * command line processing and options stuff
58   */
59
60  extern char *optarg;
61  extern int optind, opterr, optopt;
62  int c;
63
64  int verbose = 1;
65  int use_udp = 0;
66  int use_tcp = 0;
67  char mech[128] = "spnego";
68  char level[128] = "connect";
69  char rpc_host[128] = "localhost";
70  const char * protocol;
71
72  /*
73   * stuff needed to make RPC calls
74   */
75
76  unsigned32 status;
77  rpc_binding_handle_t     samr_server;
78  long ntstatus = 0;
79  void *handle = NULL;
80  unsigned32 authn_protocol;
81  void *mech_ctx;
82
83  /*
84   * Process the cmd line args
85   */
86
87    while ((c = getopt(argc, argv, "h:l:m:utvv:")) != EOF)
88    {
89      switch (c)
90	{
91	 case 'u':
92	   use_udp = 1;
93	   break;
94	 case 't':
95	   use_tcp = 1;
96	   break;
97	 case 'v':
98	   verbose = 0;
99	   break;
100	 case 'm':
101	   strncpy(mech, optarg, sizeof(level)-1);
102	   break;
103	 case 'l':
104	   strncpy(level, optarg, sizeof(level)-1);
105	   break;
106   	 case 'h':
107	   strncpy(rpc_host, optarg, sizeof(rpc_host)-1);
108	   break;
109	 default:
110	   usage();
111	}
112    }
113
114  if (!use_tcp && !use_udp) use_tcp=1;
115
116  if (use_udp)
117    protocol = "udp";
118  else
119    protocol = "tcp";
120
121  /*
122   * Get a binding handle to the server using the following params:
123   *
124   *  1. the hostname where the server lives
125   *  2. the interface description structure of the IDL interface
126   *  3. the desired transport protocol (UDP or TCP)
127   */
128
129  if (get_client_rpc_binding(&samr_server,
130		      rpc_host,
131		      samrt_v1_0_c_ifspec,
132		      protocol, mech, level) == 0)
133    {
134      printf ("Couldnt obtain RPC server binding. exiting.\n");
135      exit(1);
136    }
137
138
139  /*
140   * Do the RPC call
141   */
142
143  printf ("calling server\n");
144  DCETHREAD_TRY
145    {
146      ntstatus = samrt_Connect(samr_server, NULL, 0, &handle);
147    }
148  DCETHREAD_CATCH_ALL(THIS_CATCH)
149    {
150      printf ("Exception caught from samrt_Connect\n");
151    }
152  DCETHREAD_ENDTRY
153
154
155
156  /*
157   * Print the results
158   */
159
160  if (ntstatus == 0)
161    {
162      printf ("got response from server. results: \n");
163      printf("\tntstatus = %u\n", (unsigned int)(ntstatus));
164      printf("\n===================================\n");
165
166    }
167
168  if (ntstatus != 0)
169      chk_dce_err(ntstatus, "samrt_Connet()", "main()", 1);
170
171  mech_ctx = NULL;
172  rpc_binding_inq_security_context(samr_server, &authn_protocol, &mech_ctx,
173				   &status);
174
175  /*
176   * Done. Now gracefully teardown the RPC binding to the server
177   */
178
179  rpc_binding_free(&samr_server, &status);
180  exit(0);
181
182}
183
184/*==========================================================================
185 *
186 * get_client_rpc_binding()
187 *
188 *==========================================================================
189 *
190 * Gets a binding handle to an RPC interface.
191 *
192 * parameters:
193 *
194 *    [in/out]  binding_handle
195 *    [in]      hostname       <- Internet hostname where server lives
196 *    [in]      interface_uuid <- DCE Interface UUID for service
197 *    [in]      protocol       <- "udp", "tcp" or "any"
198 *
199 *==========================================================================*/
200
201static int
202get_client_rpc_binding(
203     rpc_binding_handle_t * binding_handle,
204     const char * hostname,
205     rpc_if_handle_t interface_spec,
206     const char * protocol,
207     const char * mech,
208     const char * level)
209{
210  char * resolved_binding;
211  char * printable_uuid ATTRIBUTE_UNUSED;
212  const char * protocol_family;
213  char partial_string_binding[128];
214  char server_principal[128];
215  rpc_if_id_t nonkeyword_interface ATTRIBUTE_UNUSED;
216  idl_uuid_t ifc_uuid ATTRIBUTE_UNUSED;
217  error_status_t status;
218  unsigned32 authn_protocol = rpc_c_authn_gss_negotiate;
219  unsigned32 authn_level = rpc_c_authn_level_connect;
220
221  /*
222   * create a string binding given the command line parameters and
223   * resolve it into a full binding handle using the endpoint mapper.
224   *  The binding handle resolution is handled by the runtime library
225   */
226
227
228  if (strcmp(protocol, "udp")==0)
229    protocol_family = "ncadg_ip_udp";
230  else
231    protocol_family = "ncacn_ip_tcp";
232
233
234  sprintf(partial_string_binding, "%s:%s[]",
235	  protocol_family,
236	  hostname);
237
238  rpc_binding_from_string_binding((unsigned char *)partial_string_binding,
239				  binding_handle,
240				  &status);
241      chk_dce_err(status, "string2binding()", "get_client_rpc_binding", 1);
242
243  /*
244   * Resolve the partial binding handle using the endpoint mapper
245   */
246
247  rpc_ep_resolve_binding(*binding_handle,
248			 interface_spec,
249			 &status);
250  chk_dce_err(status, "rpc_ep_resolve_binding()", "get_client_rpc_binding", 1);
251
252/*TODO*/  sprintf(server_principal, "host/%s",
253	  hostname);
254
255  if (strcmp(mech, "spnego") == 0)
256      authn_protocol = rpc_c_authn_gss_negotiate;
257  else if (strcmp(mech, "krb5") == 0)
258      authn_protocol = rpc_c_authn_gss_mskrb;
259  else {
260	printf("invalid mech[%s]\n", mech);
261	exit(1);
262  }
263
264  if (strcmp(level, "connect") == 0)
265      authn_level = rpc_c_authn_level_connect;
266  else if (strcmp(level, "sign") == 0)
267      authn_level = rpc_c_protect_level_pkt_integ;
268  else if (strcmp(level, "seal") == 0)
269      authn_level = rpc_c_protect_level_pkt_privacy;
270  else {
271	printf("invalid level[%s]\n", level);
272	exit(1);
273  }
274
275  rpc_binding_set_auth_info(*binding_handle,
276			    (unsigned_char_p_t)server_principal,
277			    authn_level,
278			    authn_protocol,
279			    NULL,
280			    rpc_c_authz_name,
281			    &status);
282  chk_dce_err(status, "rpc_binding_set_auth_info()", "get_client_rpc_binding", 1);
283
284/*
285 * Get a printable rendition of the binding handle and echo to
286 * the user.
287 */
288
289  rpc_binding_to_string_binding(*binding_handle,
290				(unsigned char **)&resolved_binding,
291				&status);
292        chk_dce_err(status, "binding2string()", "get_client_rpc_binding", 1);
293
294  printf("fully resolving binding for server is: %s (mech[%s],level[%s])\n",
295	resolved_binding, mech, level);
296
297
298  return 1;
299}
300