06a2831a0446ce71e3a3a7304ffaf122da7a2375
[trust_router.git] / tid / example / tids_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 <stdio.h>
36 #include <string.h>
37 #include <stdlib.h>
38 #include <sqlite3.h>
39
40 #include <trust_router/tid.h>
41 #include <trust_router/tr_dh.h>
42 #include <openssl/rand.h>
43
44 static sqlite3 *db = NULL;
45 static sqlite3_stmt *insert_stmt = NULL;
46
47 static int  create_key_id(char *out_id, size_t len)
48 {
49   unsigned char rand_buf[32];
50   size_t bin_len;
51   if (len <8)
52     return -1;
53   strncpy(out_id, "key-", len);
54   len -= 4;
55   out_id += 4;
56   if (sizeof(rand_buf)*2+1 < len)
57     len = sizeof(rand_buf)*2 + 1;
58   bin_len = (len-1)/2;
59   if (-1 == RAND_pseudo_bytes(rand_buf, bin_len))
60       return -1;
61   tr_bin_to_hex(rand_buf, bin_len, out_id, len);
62   out_id[bin_len*2] = '\0';
63   return 0;
64 }
65   
66 static int tids_req_handler (TIDS_INSTANCE * tids,
67                       TID_REQ *req, 
68                       TID_RESP **resp,
69                       void *cookie)
70 {
71   unsigned char *s_keybuf = NULL;
72   int s_keylen = 0;
73   int i = 0;
74   char key_id[12];
75   
76
77   printf("Request received! target_realm = %s, community = %s\n", req->realm->buf, req->comm->buf);
78   if (tids)
79     tids->req_count++;
80
81   if (!(resp) || !(*resp)) {
82     printf("tids_req_handler: No response structure.\n");
83     return -1;
84   }
85
86   /* Allocate a new server block */
87   if (NULL == ((*resp)->servers = malloc(sizeof(TID_SRVR_BLK)))){
88     printf("tids_req_handler(): malloc failed.\n");
89     return -1;
90   }
91   memset((*resp)->servers, 0, sizeof(TID_SRVR_BLK));
92
93   /* TBD -- Set up the server IP Address */
94
95   if (!(req) || !(req->tidc_dh)) {
96     printf("tids_req_handler(): No client DH info.\n");
97     return -1;
98   }
99
100   if ((!req->tidc_dh->p) || (!req->tidc_dh->g)) {
101     printf("tids_req_handler(): NULL dh values.\n");
102     return -1;
103   }
104
105   /* Generate the server DH block based on the client DH block */
106   printf("Generating the server DH block.\n");
107   printf("...from client DH block, dh_g = %s, dh_p = %s.\n", BN_bn2hex(req->tidc_dh->g), BN_bn2hex(req->tidc_dh->p));
108
109   if (NULL == ((*resp)->servers->aaa_server_dh = tr_create_matching_dh(NULL, 0, req->tidc_dh))) {
110     printf("tids_req_handler(): Can't create server DH params.\n");
111     return -1;
112   }
113
114   if (0 == inet_aton(tids->ipaddr, &((*resp)->servers->aaa_server_addr))) {
115     printf("tids_req_handler(): inet_aton() failed.\n");
116     return -1;
117   }
118
119   /* Set the key name */
120   if (-1 == create_key_id(key_id, sizeof(key_id)))
121     return -1;
122   (*resp)->servers->key_name = tr_new_name(key_id);
123
124   /* Generate the server key */
125   printf("Generating the server key.\n");
126
127   if (0 > (s_keylen = tr_compute_dh_key(&s_keybuf, 
128                                         req->tidc_dh->pub_key, 
129                                         (*resp)->servers->aaa_server_dh))) {
130     printf("tids_req_handler(): Key computation failed.");
131     return -1;
132   }
133       if (NULL != insert_stmt) {
134         int sqlite3_result;
135         sqlite3_bind_text(insert_stmt, 1, key_id, -1, SQLITE_TRANSIENT);
136         sqlite3_bind_blob(insert_stmt, 2, s_keybuf, s_keylen, SQLITE_TRANSIENT);
137         sqlite3_result = sqlite3_step(insert_stmt);
138         if (SQLITE_DONE != sqlite3_result)
139           printf("sqlite3: failed to write to database\n");
140         sqlite3_reset(insert_stmt);
141       }
142       
143   /* Print out the key.  If this were a AAA server, we'd store the key. */
144   printf("tids_req_handler(): Server Key Generated (len = %d):\n", s_keylen);
145   for (i = 0; i < s_keylen; i++) {
146     printf("%x", s_keybuf[i]); 
147   }
148   printf("\n");
149   return s_keylen;
150 }
151
152 int main (int argc, 
153           const char *argv[]) 
154 {
155   TIDS_INSTANCE *tids;
156   int rc = 0;
157   char *ipaddr = NULL;
158
159   /* Parse command-line arguments */ 
160   if (argc > 3)
161     printf("Usage: %s [<ip-address> [<database-name>]]\n", argv[0]);
162
163   if (argc >= 2) {
164     ipaddr = (char *)argv[1];
165   } else {
166     ipaddr = "127.0.0.1";
167   }
168
169   /* TBD -- check that input is a valid IP address? */
170
171   /*If we have a database, open and prepare*/
172   if (argc == 3) {
173     if (SQLITE_OK != sqlite3_open(argv[2], &db)) {
174       printf("Error opening database %s\n", argv[2]);
175       exit(1);
176     }
177     sqlite3_prepare_v2(db, "insert into psk_keys (keyid, key) values(?, ?)",
178                        -1, &insert_stmt, NULL);
179   }
180
181   /* Create a TID server instance */
182   if (NULL == (tids = tids_create())) {
183     printf("Unable to create TIDS instance,exiting.\n");
184     return 1;
185   }
186
187   tids->ipaddr = ipaddr;
188
189   /* Start-up the server, won't return unless there is an error. */
190   rc = tids_start(tids, &tids_req_handler , NULL);
191   
192   printf("Error in tids_start(), rc = %d. Exiting.\n", rc);
193
194   /* Clean-up the TID server instance */
195   tids_destroy(tids);
196
197   return 1;
198 }
199