5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2002 Pekka Riikonen
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; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
23 #include "net-nonblock.h"
24 #include "net-sendbuffer.h"
34 #include "channels-setup.h"
36 #include "silc-servers.h"
37 #include "silc-channels.h"
38 #include "silc-queries.h"
39 #include "silc-nicklist.h"
40 #include "window-item-def.h"
42 #include "fe-common/core/printtext.h"
43 #include "fe-common/core/keyboard.h"
47 /* Lists supported ciphers */
49 void silc_client_list_ciphers()
51 char *ciphers = silc_cipher_get_supported();
52 fprintf(stdout, "%s\n", ciphers);
56 /* Lists supported hash functions */
58 void silc_client_list_hash_funcs()
60 char *hash = silc_hash_get_supported();
61 fprintf(stdout, "%s\n", hash);
65 /* Lists supported hash functions */
67 void silc_client_list_hmacs()
69 char *hash = silc_hmac_get_supported();
70 fprintf(stdout, "%s\n", hash);
74 /* Lists supported PKCS algorithms */
76 void silc_client_list_pkcs()
78 char *pkcs = silc_pkcs_get_supported();
79 fprintf(stdout, "%s\n", pkcs);
83 /* Returns identifier string for public key generation. */
85 char *silc_client_create_identifier()
87 char *username = NULL, *realname = NULL;
88 char *hostname, email[256];
92 realname = silc_get_real_name();
95 hostname = silc_net_localhost();
99 /* Get username (mandatory) */
100 username = silc_get_username();
104 /* Create default email address, whether it is right or not */
105 snprintf(email, sizeof(email), "%s@%s", username, hostname);
107 ident = silc_pkcs_encode_identifier(username, hostname, realname, email,
117 /* Creates new public key and private key pair. This is used only
118 when user wants to create new key pair from command line. */
120 int silc_client_create_key_pair(char *pkcs_name, int bits,
121 char *public_key, char *private_key,
123 SilcPublicKey *ret_pub_key,
124 SilcPrivateKey *ret_prv_key)
127 SilcPublicKey pub_key;
128 SilcPrivateKey prv_key;
133 char *pkfile = NULL, *prvfile = NULL;
135 if (!pkcs_name || !public_key || !private_key)
137 New pair of keys will be created. Please, answer to following questions.\n\
142 pkcs_name = silc_get_input("PKCS name (l to list names) [rsa]: ", FALSE);
144 pkcs_name = strdup("rsa");
146 if (*pkcs_name == 'l' || *pkcs_name == 'L') {
147 silc_client_list_pkcs();
148 silc_free(pkcs_name);
153 if (!silc_pkcs_is_supported(pkcs_name)) {
154 fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
160 length = silc_get_input("Key length in bits [2048]: ", FALSE);
168 char *def = silc_client_create_identifier();
170 memset(line, 0, sizeof(line));
172 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
174 snprintf(line, sizeof(line),
175 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
176 "RN=Jon Johnson, E=jon@dummy.com): ");
178 while (!identifier) {
179 identifier = silc_get_input(line, FALSE);
180 if (!identifier && def)
181 identifier = strdup(def);
188 rng = silc_rng_alloc();
190 silc_rng_global_init(rng);
193 memset(line, 0, sizeof(line));
194 snprintf(line, sizeof(line), "Public key filename [%s] ",
195 SILC_CLIENT_PUBLIC_KEY_NAME);
196 pkfile = silc_get_input(line, FALSE);
198 pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
204 memset(line, 0, sizeof(line));
205 snprintf(line, sizeof(line), "Public key filename [%s] ",
206 SILC_CLIENT_PRIVATE_KEY_NAME);
207 prvfile = silc_get_input(line, FALSE);
209 prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
211 prvfile = private_key;
215 silc_pkcs_alloc(pkcs_name, &pkcs);
216 silc_pkcs_generate_key(pkcs, bits, rng);
218 /* Save public key into file */
219 key = silc_pkcs_get_public_key(pkcs, &key_len);
220 pub_key = silc_pkcs_public_key_alloc(silc_pkcs_get_name(pkcs), identifier,
222 silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
224 *ret_pub_key = pub_key;
226 memset(key, 0, key_len);
229 /* Save private key into file */
230 key = silc_pkcs_get_private_key(pkcs, &key_len);
231 prv_key = silc_pkcs_private_key_alloc(silc_pkcs_get_name(pkcs),
233 silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
235 *ret_prv_key = prv_key;
237 printf("Public key has been saved into `%s'.\n", pkfile);
238 printf("Private key has been saved into `%s'.\n", prvfile);
239 printf("Press <Enter> to continue...\n");
242 memset(key, 0, key_len);
246 silc_pkcs_free(pkcs);
251 /* This checks stats for various SILC files and directories. First it
252 checks if ~/.silc directory exist and is owned by the correct user. If
253 it doesn't exist, it will create the directory. After that it checks if
254 user's Public and Private key files exists and that they aren't expired.
255 If they doesn't exist or they are expired, they will be (re)created
258 int silc_client_check_silc_dir()
260 char filename[256], file_public_key[256], file_private_key[256];
261 char servfilename[256], clientfilename[256];
265 int firstime = FALSE;
266 time_t curtime, modtime;
268 SILC_LOG_DEBUG(("Checking ~./silc directory"));
270 memset(filename, 0, sizeof(filename));
271 memset(file_public_key, 0, sizeof(file_public_key));
272 memset(file_private_key, 0, sizeof(file_private_key));
274 identifier = silc_client_create_identifier();
276 pw = getpwuid(getuid());
278 fprintf(stderr, "silc: %s\n", strerror(errno));
280 silc_free(identifier);
284 /* We'll take home path from /etc/passwd file to be sure. */
285 snprintf(filename, sizeof(filename) - 1, "%s/", get_irssi_dir());
286 snprintf(servfilename, sizeof(servfilename) - 1, "%s/serverkeys",
288 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/clientkeys",
292 * Check ~/.silc directory
294 if ((stat(filename, &st)) == -1) {
295 /* If dir doesn't exist */
296 if (errno == ENOENT) {
297 if (pw->pw_uid == geteuid()) {
298 if ((mkdir(filename, 0755)) == -1) {
299 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
303 /* Directory was created. First time running SILC */
306 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
311 fprintf(stderr, "%s\n", strerror(errno));
316 /* Check the owner of the dir */
317 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
318 fprintf(stderr, "You don't seem to own `%s' directory\n",
324 /* Check the permissions of the dir */
325 if ((st.st_mode & 0777) != 0755) {
326 if ((chmod(filename, 0755)) == -1) {
327 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
336 * Check ~./silc/serverkeys directory
338 if ((stat(servfilename, &st)) == -1) {
339 /* If dir doesn't exist */
340 if (errno == ENOENT) {
341 if (pw->pw_uid == geteuid()) {
342 if ((mkdir(servfilename, 0755)) == -1) {
343 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
347 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
352 fprintf(stderr, "%s\n", strerror(errno));
358 * Check ~./silc/clientkeys directory
360 if ((stat(clientfilename, &st)) == -1) {
361 /* If dir doesn't exist */
362 if (errno == ENOENT) {
363 if (pw->pw_uid == geteuid()) {
364 if ((mkdir(clientfilename, 0755)) == -1) {
365 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
369 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
374 fprintf(stderr, "%s\n", strerror(errno));
380 * Check Public and Private keys
382 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
383 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
384 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
385 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
387 /* If running SILC first time */
389 fprintf(stdout, "Running SILC for the first time\n");
390 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
391 SILC_CLIENT_DEF_PKCS_LEN,
392 file_public_key, file_private_key,
393 identifier, NULL, NULL);
397 if ((stat(file_public_key, &st)) == -1) {
398 /* If file doesn't exist */
399 if (errno == ENOENT) {
400 fprintf(stdout, "Your public key doesn't exist\n");
401 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
402 SILC_CLIENT_DEF_PKCS_LEN,
404 file_private_key, identifier, NULL, NULL);
406 fprintf(stderr, "%s\n", strerror(errno));
411 /* Check the owner of the public key */
412 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
413 fprintf(stderr, "You don't seem to own your public key!?\n");
417 if ((stat(file_private_key, &st)) == -1) {
418 /* If file doesn't exist */
419 if (errno == ENOENT) {
420 fprintf(stdout, "Your private key doesn't exist\n");
421 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
422 SILC_CLIENT_DEF_PKCS_LEN,
424 file_private_key, identifier, NULL, NULL);
426 fprintf(stderr, "%s\n", strerror(errno));
431 /* Check the owner of the private key */
432 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
433 fprintf(stderr, "You don't seem to own your private key!?\n");
437 /* Check the permissions for the private key */
438 if ((st.st_mode & 0777) != 0600) {
439 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
440 "Trying to change them ... ", file_private_key);
441 if ((chmod(file_private_key, 0600)) == -1) {
443 "Failed to change permissions for private key file!\n"
444 "Permissions for your private key file must be 0600.\n");
447 fprintf(stderr, "Done.\n\n");
450 /* See if the key has expired. */
451 modtime = st.st_mtime; /* last modified */
452 curtime = time(0) - modtime;
454 /* 86400 is seconds in a day. */
455 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
459 "----------------------------------------------------\n"
460 "Your private key has expired and needs to be\n"
461 "recreated. Would you like to create a new key pair\n"
462 "now? If you answer Yes, the new key will expire in\n"
463 "%d days from today. If you answer No, the old key\n"
464 "will expire again in %d days from today.\n"
465 "----------------------------------------------------\n",
466 SILC_CLIENT_KEY_EXPIRES, SILC_CLIENT_KEY_EXPIRES);
468 answer = silc_get_input("Would you like to create a new key pair "
469 "([y]/n)?: ", FALSE);
470 if (!answer || answer[0] == 'Y' || answer[0] == 'y') {
471 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
472 SILC_CLIENT_DEF_PKCS_LEN,
474 file_private_key, identifier, NULL, NULL);
478 utim.actime = time(NULL);
479 utim.modtime = time(NULL);
480 utime(file_private_key, &utim);
487 silc_free(identifier);
492 /* Loads public and private key from files. */
494 int silc_client_load_keys(SilcClient client)
499 SILC_LOG_DEBUG(("Loading public and private keys"));
501 pw = getpwuid(getuid());
505 memset(filename, 0, sizeof(filename));
506 snprintf(filename, sizeof(filename) - 1, "%s/%s",
507 get_irssi_dir(), SILC_CLIENT_PRIVATE_KEY_NAME);
509 if (silc_pkcs_load_private_key(filename, &client->private_key,
510 SILC_PKCS_FILE_BIN) == FALSE)
511 if (silc_pkcs_load_private_key(filename, &client->private_key,
512 SILC_PKCS_FILE_PEM) == FALSE)
515 memset(filename, 0, sizeof(filename));
516 snprintf(filename, sizeof(filename) - 1, "%s/%s",
517 get_irssi_dir(), SILC_CLIENT_PUBLIC_KEY_NAME);
519 if (silc_pkcs_load_public_key(filename, &client->public_key,
520 SILC_PKCS_FILE_PEM) == FALSE)
521 if (silc_pkcs_load_public_key(filename, &client->public_key,
522 SILC_PKCS_FILE_BIN) == FALSE)
525 silc_pkcs_alloc(client->public_key->name, &client->pkcs);
526 silc_pkcs_public_key_set(client->pkcs, client->public_key);
527 silc_pkcs_private_key_set(client->pkcs, client->private_key);
532 /* Dumps the public key on screen. Used from the command line option. */
534 int silc_client_show_key(char *keyfile)
536 SilcPublicKey public_key;
537 SilcPublicKeyIdentifier ident;
538 char *fingerprint, *babbleprint;
544 if (silc_pkcs_load_public_key(keyfile, &public_key,
545 SILC_PKCS_FILE_PEM) == FALSE)
546 if (silc_pkcs_load_public_key(keyfile, &public_key,
547 SILC_PKCS_FILE_BIN) == FALSE) {
548 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
552 ident = silc_pkcs_decode_identifier(public_key->identifier);
554 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
555 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
556 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
558 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
559 key_len = silc_pkcs_public_key_set(pkcs, public_key);
560 silc_pkcs_free(pkcs);
563 printf("Public key file : %s\n", keyfile);
564 printf("Algorithm : %s\n", public_key->name);
566 printf("Key length (bits) : %d\n", key_len);
568 printf("Real name : %s\n", ident->realname);
570 printf("Username : %s\n", ident->username);
572 printf("Hostname : %s\n", ident->host);
574 printf("Email : %s\n", ident->email);
576 printf("Organization : %s\n", ident->org);
578 printf("Country : %s\n", ident->country);
579 printf("Fingerprint (SHA1) : %s\n", fingerprint);
580 printf("Babbleprint (SHA1) : %s\n", babbleprint);
584 silc_free(fingerprint);
585 silc_free(babbleprint);
587 silc_pkcs_public_key_free(public_key);
588 silc_pkcs_free_identifier(ident);