Added ~./silc directory checking, autoloading of keys and
[silc.git] / apps / silc / silc.c
1 /*
2
3   silc.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /*
21  * $Id$
22  * $Log$
23  * Revision 1.3  2000/07/05 06:11:00  priikone
24  *      Added ~./silc directory checking, autoloading of keys and
25  *      tweaked the key pair generation function.
26  *
27  * Revision 1.2  2000/06/30 10:49:48  priikone
28  *      Added SOCKS4 and SOCKS5 support for SILC client.
29  *
30  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
31  *      Imported from internal CVS/Added Log headers.
32  *
33  *
34  */
35
36 #include "clientincludes.h"
37 #include "version.h"
38
39 /* Long command line options */
40 static struct option long_opts[] = 
41 {
42   /* Generic options */
43   { "server", 1, NULL, 's' },
44   { "port", 1, NULL, 'p' },
45   { "nickname", 1, NULL, 'n' },
46   { "channel", 1, NULL, 'c' },
47   { "cipher", 1, NULL, 'r' },
48   { "public-key", 1, NULL, 'b' },
49   { "private-key", 1, NULL, 'k' },
50   { "config-file", 1, NULL, 'f' },
51   { "no-silcrc", 0, NULL, 'q' },
52   { "help", 0, NULL, 'h' },
53   { "version", 0, NULL, 'V' },
54   { "list-ciphers", 0, NULL, 1 },
55   { "list-hash-funcs", 0, NULL, 2 },
56   { "list-pkcs", 0, NULL, 3 },
57
58   /* Key management options */
59   { "create-key-pair", 0, NULL, 'C' },
60   { "pkcs", 1, NULL, 10 },
61   { "bits", 1, NULL, 11 },
62
63   { NULL, 0, NULL, 0 }
64 };
65
66 /* Command line option variables */
67 static char *opt_server = NULL;
68 static int opt_port = 0;
69 static char *opt_nickname = NULL;
70 static char *opt_channel = NULL;
71 static char *opt_cipher = NULL;
72 static char *opt_public_key = NULL;
73 static char *opt_private_key = NULL;
74 static char *opt_config_file = NULL;
75 static int opt_no_silcrc = FALSE;
76
77 static int opt_create_keypair = FALSE;
78 static char *opt_pkcs = NULL;
79 static int opt_bits = 0;
80
81 /* Prints out the usage of silc client */
82
83 void usage()
84 {
85   printf("\
86 Usage: silc [options]\n\
87 \n\
88   Generic Options:\n\
89   -s, --server=HOST            Open connection to server HOST\n\
90   -p, --port=PORT              Set PORT as default port to connect\n\
91   -n, --nickname=STRING        Set default nickname on startup\n\
92   -c, --channel=STRING         Join channel on startup\n\
93   -r, --cipher=CIPHER          Use CIPHER as default cipher in SILC\n\
94   -b, --public-key=FILE        Public key used in SILC\n\
95   -k, --private-key=FILE       Private key used in SILC\n\
96   -f, --config-file=FILE       Alternate configuration file\n\
97   -q, --no-silcrc              Don't load ~/.silcrc on startup\n\
98   -h, --help                   Display this help message\n\
99   -V, --version                Display version\n\
100       --list-ciphers           List supported ciphers\n\
101       --list-hash-funcs        List supported hash functions\n\
102       --list-pkcs              List supported PKCS's\n\
103 \n\
104   Key Management Options:\n\
105   -C, --create-key-pair        Create new public key pair\n\
106       --pkcs=PKCS              Set the PKCS of the public key pair\n\
107       --bits=VALUE             Set length of the public key pair\n\
108 \n");
109 }
110
111 int main(int argc, char **argv)
112 {
113   int opt, option_index = 1;
114   int ret;
115   SilcClient silc = NULL;
116   SilcClientConfig config = NULL;
117   
118   if (argc > 1) 
119     {
120       while ((opt = 
121               getopt_long(argc, argv,
122                           "s:p:n:c:b:k:f:qhVC",
123                           long_opts, &option_index)) != EOF)
124         {
125           switch(opt) 
126             {
127               /* 
128                * Generic options
129                */
130             case 's':
131               if (optarg)
132                 opt_server = strdup(optarg);
133               break;
134             case 'p':
135               if (optarg)
136                 opt_port = atoi(optarg);
137               break;
138             case 'n':
139               if (optarg)
140                 opt_nickname = strdup(optarg);
141               break;
142             case 'c':
143               if (optarg)
144                 opt_channel = strdup(optarg);
145               break;
146             case 'r':
147               if (optarg)
148                 opt_cipher = strdup(optarg);
149               break;
150             case 'b':
151               if (optarg)
152                 opt_public_key = strdup(optarg);
153               break;
154             case 'k':
155               if (optarg)
156                 opt_private_key = strdup(optarg);
157               break;
158             case 'f':
159               if (optarg)
160                 opt_config_file = strdup(optarg);
161               break;
162             case 'q':
163               opt_no_silcrc = TRUE;
164               break;
165             case 'h':
166               usage();
167               exit(0);
168               break;
169             case 'V':
170               printf("\
171 SILC Secure Internet Live Conferencing, version %s\n", 
172                      silc_version);
173               printf("\
174 (c) 1997 - 2000 Pekka Riikonen <priikone@poseidon.pspt.fi>\n");
175               exit(0);
176               break;
177             case 1:
178               silc_client_list_ciphers();
179               exit(0);
180               break;
181             case 2:
182               silc_client_list_hash_funcs();
183               exit(0);
184               break;
185             case 3:
186               silc_client_list_pkcs();
187               exit(0);
188               break;
189
190               /*
191                * Key management options
192                */
193             case 'C':
194               opt_create_keypair = TRUE;
195               break;
196             case 10:
197               if (optarg)
198                 opt_pkcs = strdup(optarg);
199               break;
200             case 11:
201               if (optarg)
202                 opt_bits = atoi(optarg);
203               break;
204
205             default:
206               exit(0);
207               break;
208             }
209         }
210     }
211
212   /* Init signals */
213   signal(SIGHUP, SIG_DFL);
214   signal(SIGTERM, SIG_DFL);
215   signal(SIGPIPE, SIG_IGN);
216   signal(SIGCHLD, SIG_DFL);
217   signal(SIGALRM, SIG_IGN);
218   signal(SIGQUIT, SIG_IGN);
219   signal(SIGSEGV, SIG_DFL);
220   signal(SIGBUS, SIG_DFL);
221   signal(SIGFPE, SIG_DFL);
222   //  signal(SIGINT, SIG_IGN);
223   
224   /* Default configuration file */
225   if (!opt_config_file)
226     opt_config_file = strdup(SILC_CLIENT_CONFIG_FILE);
227
228   /* Read global configuration file. */
229   config = silc_client_config_alloc(opt_config_file);
230   if (config == NULL)
231     goto fail;
232
233   if (opt_create_keypair == TRUE) {
234     /* Create new key pair and exit */
235     silc_client_create_key_pair(opt_pkcs, opt_bits, 
236                                 NULL, NULL, NULL, NULL, NULL);
237     exit(0);
238   }
239
240   /* Read local configuration file */
241
242   /* Check ~/.silc directory and public and private keys */
243   if (silc_client_check_silc_dir() == FALSE)
244     goto fail;
245
246 #ifdef SOCKS
247   /* Init SOCKS */
248   SOCKSinit(argv[0]);
249 #endif
250
251   /* Allocate new client */
252   ret = silc_client_alloc(&silc);
253   if (ret == FALSE)
254     goto fail;
255
256   /* Initialize the client */
257   silc->config = config;
258   ret = silc_client_init(silc);
259   if (ret == FALSE)
260     goto fail;
261
262   /* Run the client */
263   silc_client_run(silc);
264
265   /* Stop the client. This probably has been done already but it
266      doesn't hurt to do it here again. */
267   silc_client_stop(silc);
268   silc_client_free(silc);
269   
270   exit(0);
271
272  fail:
273   if (opt_config_file)
274     silc_free(opt_config_file);
275   if (config)
276     silc_client_config_free(config);
277   if (silc)
278     silc_client_free(silc);
279   exit(1);
280 }