1/* ex: set shiftwidth=4 softtabstop=4 expandtab: */
2/*
3 * access_client  : demo DCE RPC application
4 *
5 * Jim Doyle, jrd@bu.edu, 09-05-1998
6 *
7 *
8 */
9#if HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#define getopt getopt_system
14
15#include <stdio.h>
16#include <string.h>
17#include <stdlib.h>
18#include <compat/dcerpc.h>
19#include "access.h"
20#include <misc.h>
21
22#undef getopt
23
24#ifdef HAVE_GETOPT_H
25#include <getopt.h>
26#endif
27
28#ifdef _WIN32
29#define EOF_STRING "^Z"
30#else
31#define EOF_STRING "^D"
32#endif
33
34/*
35 * Forward declarations
36 */
37
38static int
39get_client_rpc_binding(
40    rpc_binding_handle_t * binding_handle,
41    rpc_if_handle_t interface_spec,
42    char * hostname,
43    char * protocol,
44    char * endpoint,
45    const char* mech
46    );
47
48/*
49 * usage()
50 */
51
52static void usage()
53{
54    printf("usage: access_client [-h hostname] [-e endpoint] [-n] [-u] [-t]\n");
55    printf("         -h:  specify host of RPC server (default is localhost)\n");
56    printf("         -e:  specify endpoint for protocol\n");
57    printf("         -n:  use named pipe protocol\n");
58    printf("         -u:  use UDP protocol\n");
59    printf("         -t:  use TCP protocol (default)\n");
60    printf("         -g:  instead of prompting, generate a data string of the specified length\n");
61    printf("         -d:  turn on debugging\n");
62    printf("\n");
63    exit(1);
64}
65
66int
67main(
68    int argc,
69    char *argv[]
70    )
71{
72
73    /*
74     * command line processing and options stuff
75     */
76
77    extern char *optarg;
78    extern int optind, opterr, optopt;
79    int c;
80
81    char * rpc_host = "localhost";
82    char * protocol = PROTOCOL_TCP;
83    char * endpoint = NULL;
84    char * mech = NULL;
85
86    /*
87     * stuff needed to make RPC calls
88     */
89
90    unsigned32 status;
91    rpc_binding_handle_t access_server;
92    int ok;
93    unsigned32 i;
94    int generate_length = -1;
95    char * nl;
96    string_t me = NULL;
97
98    /*
99     * Process the cmd line args
100     */
101
102    while ((c = getopt(argc, argv, "lh:e:nutdg:m:")) != EOF)
103    {
104        switch (c)
105        {
106        case 'h':
107            rpc_host = optarg;
108            break;
109        case 'e':
110            endpoint = optarg;
111            break;
112        case 'n':
113            protocol = PROTOCOL_NP;
114            break;
115        case 'u':
116            protocol = PROTOCOL_UDP;
117            break;
118        case 't':
119            protocol = PROTOCOL_TCP;
120            break;
121        case 'l':
122            protocol = PROTOCOL_LRPC;
123            break;
124        case 'd':
125#ifdef _WIN32
126	    printf("This option is only supported on Linux.\n");
127#else
128            rpc__dbg_set_switches("0-19.10", &status);
129            //Skip 20, which is memory allocs and frees
130            rpc__dbg_set_switches("21-43.10", &status);
131#endif
132            break;
133        case 'g':
134            generate_length = strtol(optarg, NULL, 10);
135            break;
136        case 'm':
137            mech = optarg;
138            break;
139        default:
140            usage();
141        }
142    }
143
144    /*
145     * Get a binding handle to the server using the following params:
146     *
147     *  1. the hostname where the server lives
148     *  2. the interface description structure of the IDL interface
149     *  3. the desired transport protocol (UDP or TCP)
150     */
151
152    if (get_client_rpc_binding(&access_server,
153                               access_v1_0_c_ifspec,
154                               rpc_host,
155                               protocol,
156                               endpoint,
157                               mech) == 0)
158    {
159        printf ("Couldnt obtain RPC server binding. exiting.\n");
160        exit(1);
161    }
162
163
164    WhoAmI(access_server, &me);
165
166    /*
167     * Print the results
168     */
169
170    printf ("%s\n", me);
171
172    /*
173     * Done. Now gracefully teardown the RPC binding to the server
174     */
175
176    rpc_binding_free(&access_server, &status);
177    exit(0);
178}
179
180/*==========================================================================
181 *
182 * get_client_rpc_binding()
183 *
184 *==========================================================================
185 *
186 * Gets a binding handle to an RPC interface.
187 *
188 * parameters:
189 *
190 *    [out]     binding_handle
191 *    [in]      interface_spec <- DCE Interface handle for service
192 *    [in]      hostname       <- Internet hostname where server lives
193 *    [in]      protocol       <- "ncacn_ip_tcp", etc.
194 *    [in]      endpoint       <- optional
195 *
196 *==========================================================================*/
197
198static int
199get_client_rpc_binding(
200    rpc_binding_handle_t * binding_handle,
201    rpc_if_handle_t interface_spec,
202    char * hostname,
203    char * protocol,
204    char * endpoint,
205    const char* mech
206    )
207{
208    char * string_binding = NULL;
209    error_status_t status;
210    unsigned32 authn_protocol = rpc_c_authn_gss_negotiate;
211    unsigned32 authn_level = rpc_c_authn_level_connect;
212    char server_principal[512];
213
214    /*
215     * create a string binding given the command line parameters and
216     * resolve it into a full binding handle using the endpoint mapper.
217     *  The binding handle resolution is handled by the runtime library
218     */
219
220    rpc_string_binding_compose(NULL,
221			       protocol,
222			       hostname,
223			       endpoint,
224			       NULL,
225			       &string_binding,
226			       &status);
227    chk_dce_err(status, "rpc_string_binding_compose()", "get_client_rpc_binding", 1);
228
229
230    rpc_binding_from_string_binding((unsigned char *)string_binding,
231                                    binding_handle,
232                                    &status);
233    chk_dce_err(status, "rpc_binding_from_string_binding()", "get_client_rpc_binding", 1);
234
235    if (!endpoint)
236    {
237        /*
238         * Resolve the partial binding handle using the endpoint mapper
239         */
240
241        rpc_ep_resolve_binding(*binding_handle,
242                               interface_spec,
243                               &status);
244        chk_dce_err(status, "rpc_ep_resolve_binding()", "get_client_rpc_binding", 1);
245    }
246
247    if (mech)
248    {
249        if (!strcmp(mech, "spnego"))
250        {
251            authn_protocol = rpc_c_authn_gss_negotiate;
252        }
253
254        sprintf(server_principal, "host/%s", hostname);
255
256        rpc_binding_set_auth_info(*binding_handle,
257                                  server_principal,
258                                  authn_level,
259                                  authn_protocol,
260                                  NULL,
261                                  rpc_c_authz_name,
262                                  &status);
263        chk_dce_err(status, "rpc_binding_set_auth_info()", "get_client_rpc_binding", 1);
264    }
265
266    rpc_string_free(&string_binding, &status);
267    chk_dce_err(status, "rpc_string_free()", "get_client_rpc_binding", 1);
268
269    /*
270     * Get a printable rendition of the binding handle and echo to
271     * the user.
272     */
273
274    rpc_binding_to_string_binding(*binding_handle,
275                                  (unsigned char **)&string_binding,
276                                  &status);
277    chk_dce_err(status, "rpc_binding_to_string_binding()", "get_client_rpc_binding", 1);
278
279    printf("fully resolving binding for server is: %s\n", string_binding);
280
281    rpc_string_free(&string_binding, &status);
282    chk_dce_err(status, "rpc_string_free()", "get_client_rpc_binding", 1);
283
284    return 1;
285}
286