Use cast instead of talloc_get_type_abort for stack-allocated data
[trust_router.git] / tid / example / tidc_main.c
1 /*
2  * Copyright (c) 2012, JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <talloc.h>
38 #include <argp.h>
39
40 #include <gsscon.h>
41 #include <tr_debug.h>
42 #include <tid_internal.h>
43 #include <trust_router/tr_dh.h>
44 #include <trust_router/tid.h>
45 #include <tr_inet_util.h>
46
47 struct tidc_resp_cookie {
48   int succeeded;
49 };
50
51 static void tidc_resp_handler (TIDC_INSTANCE * tidc, 
52                         TID_REQ *req,
53                         TID_RESP *resp, 
54                         void *cookie) 
55 {
56   int c_keylen = 0;
57   unsigned char *c_keybuf = NULL;
58   int i;
59   struct timeval tv;
60   struct tidc_resp_cookie *data = (struct tidc_resp_cookie *) cookie;
61
62   printf ("Response received! Realm = %s, Community = %s.\n", resp->realm->buf, resp->comm->buf);
63
64   data->succeeded = 0;
65
66   /* Generate the client key -- TBD, handle more than one server */
67   if (TID_SUCCESS != resp->result) {
68     fprintf(stderr, "tidc_resp_handler: Response is an error.\n");
69     return;
70   }
71
72   if (!resp->servers) {
73     fprintf(stderr, "tidc_resp_handler: Response does not contain server info.\n");
74     return;
75   }
76   if (tid_srvr_get_key_expiration(tid_resp_get_server(resp, 0), &tv))
77     printf("Error reading key expiration\n");
78   else
79     printf("Key expiration: %s", ctime(&tv.tv_sec));
80
81
82   if (0 > (c_keylen = tr_compute_dh_key(&c_keybuf, 
83                                       resp->servers->aaa_server_dh->pub_key, 
84                                       req->tidc_dh))) {
85     
86     printf("tidc_resp_handler: Error computing client key.\n");
87     return;
88   }
89   
90   /* Print out the client key. */
91   printf("Client Key Generated (len = %d):\n", c_keylen);
92   for (i = 0; i < c_keylen; i++) {
93     printf("%.2x", c_keybuf[i]); 
94   }
95   printf("\n");
96
97   data->succeeded = 1;
98   return;
99 }
100
101
102 static void print_version_info(void)
103 {
104   printf("Moonshot TID Client %s\n\n", PACKAGE_VERSION);
105 }
106
107 /* command-line option setup */
108
109 /* argp global parameters */
110 const char *argp_program_bug_address=PACKAGE_BUGREPORT; /* bug reporting address */
111
112 /* doc strings */
113 static const char doc[]=PACKAGE_NAME " - Moonshot TID Client " PACKAGE_VERSION;
114 static const char arg_doc[]="<server> <RP-realm> <target-realm> <community> [<port>]"; /* string describing arguments, if any */
115
116 /* define the options here. Fields are:
117  * { long-name, short-name, variable name, options, help description } */
118 static const struct argp_option cmdline_options[] = {
119     { "version", 'v', NULL, 0, "Print version information and exit"},
120     { NULL }
121 };
122
123 /* structure for communicating with option parser */
124 struct cmdline_args {
125   char *server;
126   char *rp_realm;
127   char *target_realm;
128   char *community;
129   int port; /* optional */
130 };
131
132 /* parser for individual options - fills in a struct cmdline_args */
133 static error_t parse_option(int key, char *arg, struct argp_state *state)
134 {
135   /* get a shorthand to the command line argument structure, part of state */
136   struct cmdline_args *arguments=state->input;
137
138   switch (key) {
139   case ARGP_KEY_ARG: /* handle argument (not option) */
140     switch (state->arg_num) {
141     case 0:
142       arguments->server=arg;
143       break;
144
145     case 1:
146       arguments->rp_realm=arg;
147       break;
148
149     case 2:
150       arguments->target_realm=arg;
151       break;
152
153     case 3:
154       arguments->community=arg;
155       break;
156
157     case 4:
158       arguments->port=tr_parse_port(arg); /* optional */
159       if (arguments->port < 0) {
160         switch(-(arguments->port)) {
161           case ERANGE:
162             printf("\nError parsing port (%s): port must be an integer in the range 1 - 65535\n\n", arg);
163             break;
164
165           default:
166             printf("\nError parsing port (%s): %s\n\n", arg, strerror(-arguments->port));
167             break;
168         }
169         argp_usage(state);
170       }
171       break;
172
173     default:
174       /* too many arguments */
175       argp_usage(state);
176     }
177     break;
178
179   case ARGP_KEY_END: /* no more arguments */
180     if (state->arg_num < 4) {
181       /* not enough arguments encountered */
182       argp_usage(state);
183     }
184     break;
185
186   case 'v':
187     print_version_info();
188     exit(0);
189
190   default:
191     return ARGP_ERR_UNKNOWN;
192   }
193
194   return 0; /* success */
195 }
196
197 /* Exit values */
198 #define EXIT_OK 0
199 #define EXIT_REQ_FAILED 2
200 #define EXIT_ERROR 1
201
202 /* assemble the argp parser */
203 static struct argp argp = {cmdline_options, parse_option, arg_doc, doc};
204
205 int main (int argc, 
206           char *argv[]) 
207 {
208   TIDC_INSTANCE *tidc;
209   int conn = 0;
210   int rc;
211   gss_ctx_id_t gssctx;
212   struct cmdline_args opts;
213   struct tidc_resp_cookie cookie = {0};
214
215   /* parse the command line*/
216   /* set defaults */
217   opts.server=NULL;
218   opts.rp_realm=NULL;
219   opts.target_realm=NULL;
220   opts.community=NULL;
221   opts.port=TID_PORT;
222
223   argp_parse(&argp, argc, argv, 0, 0, &opts);
224   /* TBD -- validity checking, dealing with quotes, etc. */
225
226   print_version_info();
227
228   /* Use standalone logging */
229   tr_log_open();
230
231   /* set logging levels */
232   talloc_set_log_stderr();
233   tr_log_threshold(LOG_CRIT);
234   tr_console_threshold(LOG_DEBUG);
235
236   printf("TIDC Client:\nServer = %s, rp_realm = %s, target_realm = %s, community = %s, port = %i\n", opts.server, opts.rp_realm, opts.target_realm, opts.community, opts.port);
237  
238   /* Create a TID client instance & the client DH */
239   tidc = tidc_create();
240   tidc_set_dh(tidc, tr_create_dh_params(NULL, 0));
241   if (tidc_get_dh(tidc) == NULL) {
242     printf("Error creating client DH params.\n");
243     return EXIT_ERROR;
244   }
245
246   /* Set-up TID connection */
247   if (-1 == (conn = tidc_open_connection(tidc, opts.server, opts.port, &gssctx))) {
248     /* Handle error */
249     printf("Error in tidc_open_connection.\n");
250     return EXIT_ERROR;
251   };
252
253   /* Send a TID request */
254   if (0 > (rc = tidc_send_request(tidc, conn, gssctx, opts.rp_realm, opts.target_realm, opts.community, 
255                                   &tidc_resp_handler, &cookie))) {
256     /* Handle error */
257     printf("Error in tidc_send_request, rc = %d.\n", rc);
258     return EXIT_ERROR;
259   }
260     
261   /* Clean-up the TID client instance, and exit */
262   tidc_destroy(tidc);
263
264   if (cookie.succeeded)
265     return EXIT_OK;
266   else
267     return EXIT_REQ_FAILED;
268 }
269