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], friendsfilename[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",
290 snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s/friends",
294 * Check ~/.silc directory
296 if ((stat(filename, &st)) == -1) {
297 /* If dir doesn't exist */
298 if (errno == ENOENT) {
299 if (pw->pw_uid == geteuid()) {
300 if ((mkdir(filename, 0755)) == -1) {
301 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
305 /* Directory was created. First time running SILC */
308 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
313 fprintf(stderr, "%s\n", strerror(errno));
318 /* Check the owner of the dir */
319 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
320 fprintf(stderr, "You don't seem to own `%s' directory\n",
326 /* Check the permissions of the dir */
327 if ((st.st_mode & 0777) != 0755) {
328 if ((chmod(filename, 0755)) == -1) {
329 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
338 * Check ~./silc/serverkeys directory
340 if ((stat(servfilename, &st)) == -1) {
341 /* If dir doesn't exist */
342 if (errno == ENOENT) {
343 if (pw->pw_uid == geteuid()) {
344 if ((mkdir(servfilename, 0755)) == -1) {
345 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
349 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
354 fprintf(stderr, "%s\n", strerror(errno));
360 * Check ~./silc/clientkeys directory
362 if ((stat(clientfilename, &st)) == -1) {
363 /* If dir doesn't exist */
364 if (errno == ENOENT) {
365 if (pw->pw_uid == geteuid()) {
366 if ((mkdir(clientfilename, 0755)) == -1) {
367 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
371 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
376 fprintf(stderr, "%s\n", strerror(errno));
382 * Check ~./silc/friends directory
384 if ((stat(friendsfilename, &st)) == -1) {
385 /* If dir doesn't exist */
386 if (errno == ENOENT) {
387 if (pw->pw_uid == geteuid()) {
388 if ((mkdir(friendsfilename, 0755)) == -1) {
389 fprintf(stderr, "Couldn't create `%s' directory\n", friendsfilename);
393 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
398 fprintf(stderr, "%s\n", strerror(errno));
404 * Check Public and Private keys
406 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
407 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
408 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
409 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
411 /* If running SILC first time */
413 fprintf(stdout, "Running SILC for the first time\n");
414 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
415 SILC_CLIENT_DEF_PKCS_LEN,
416 file_public_key, file_private_key,
417 identifier, NULL, NULL);
421 if ((stat(file_public_key, &st)) == -1) {
422 /* If file doesn't exist */
423 if (errno == ENOENT) {
424 fprintf(stdout, "Your public key doesn't exist\n");
425 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
426 SILC_CLIENT_DEF_PKCS_LEN,
428 file_private_key, identifier, NULL, NULL);
430 fprintf(stderr, "%s\n", strerror(errno));
435 /* Check the owner of the public key */
436 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
437 fprintf(stderr, "You don't seem to own your public key!?\n");
441 if ((stat(file_private_key, &st)) == -1) {
442 /* If file doesn't exist */
443 if (errno == ENOENT) {
444 fprintf(stdout, "Your private key doesn't exist\n");
445 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
446 SILC_CLIENT_DEF_PKCS_LEN,
448 file_private_key, identifier, NULL, NULL);
450 fprintf(stderr, "%s\n", strerror(errno));
455 /* Check the owner of the private key */
456 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
457 fprintf(stderr, "You don't seem to own your private key!?\n");
461 /* Check the permissions for the private key */
462 if ((st.st_mode & 0777) != 0600) {
463 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
464 "Trying to change them ... ", file_private_key);
465 if ((chmod(file_private_key, 0600)) == -1) {
467 "Failed to change permissions for private key file!\n"
468 "Permissions for your private key file must be 0600.\n");
471 fprintf(stderr, "Done.\n\n");
474 /* See if the key has expired. */
475 modtime = st.st_mtime; /* last modified */
476 curtime = time(0) - modtime;
478 /* 86400 is seconds in a day. */
479 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
483 "----------------------------------------------------\n"
484 "Your private key has expired and needs to be\n"
485 "recreated. Would you like to create a new key pair\n"
486 "now? If you answer Yes, the new key will expire in\n"
487 "%d days from today. If you answer No, the old key\n"
488 "will expire again in %d days from today.\n"
489 "----------------------------------------------------\n",
490 SILC_CLIENT_KEY_EXPIRES, SILC_CLIENT_KEY_EXPIRES);
492 answer = silc_get_input("Would you like to create a new key pair "
493 "([y]/n)?: ", FALSE);
494 if (!answer || answer[0] == 'Y' || answer[0] == 'y') {
495 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
496 SILC_CLIENT_DEF_PKCS_LEN,
498 file_private_key, identifier, NULL, NULL);
502 utim.actime = time(NULL);
503 utim.modtime = time(NULL);
504 utime(file_private_key, &utim);
511 silc_free(identifier);
516 /* Loads public and private key from files. */
518 int silc_client_load_keys(SilcClient client)
523 SILC_LOG_DEBUG(("Loading public and private keys"));
525 pw = getpwuid(getuid());
529 memset(filename, 0, sizeof(filename));
530 snprintf(filename, sizeof(filename) - 1, "%s/%s",
531 get_irssi_dir(), SILC_CLIENT_PRIVATE_KEY_NAME);
533 if (silc_pkcs_load_private_key(filename, &client->private_key,
534 SILC_PKCS_FILE_BIN) == FALSE)
535 if (silc_pkcs_load_private_key(filename, &client->private_key,
536 SILC_PKCS_FILE_PEM) == FALSE)
539 memset(filename, 0, sizeof(filename));
540 snprintf(filename, sizeof(filename) - 1, "%s/%s",
541 get_irssi_dir(), SILC_CLIENT_PUBLIC_KEY_NAME);
543 if (silc_pkcs_load_public_key(filename, &client->public_key,
544 SILC_PKCS_FILE_PEM) == FALSE)
545 if (silc_pkcs_load_public_key(filename, &client->public_key,
546 SILC_PKCS_FILE_BIN) == FALSE)
549 silc_pkcs_alloc(client->public_key->name, &client->pkcs);
550 silc_pkcs_public_key_set(client->pkcs, client->public_key);
551 silc_pkcs_private_key_set(client->pkcs, client->private_key);
556 /* Dumps the public key on screen. Used from the command line option. */
558 int silc_client_show_key(char *keyfile)
560 SilcPublicKey public_key;
561 SilcPublicKeyIdentifier ident;
562 char *fingerprint, *babbleprint;
568 if (silc_pkcs_load_public_key(keyfile, &public_key,
569 SILC_PKCS_FILE_PEM) == FALSE)
570 if (silc_pkcs_load_public_key(keyfile, &public_key,
571 SILC_PKCS_FILE_BIN) == FALSE) {
572 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
576 ident = silc_pkcs_decode_identifier(public_key->identifier);
578 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
579 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
580 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
582 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
583 key_len = silc_pkcs_public_key_set(pkcs, public_key);
584 silc_pkcs_free(pkcs);
587 printf("Public key file : %s\n", keyfile);
588 printf("Algorithm : %s\n", public_key->name);
590 printf("Key length (bits) : %d\n", key_len);
592 printf("Real name : %s\n", ident->realname);
594 printf("Username : %s\n", ident->username);
596 printf("Hostname : %s\n", ident->host);
598 printf("Email : %s\n", ident->email);
600 printf("Organization : %s\n", ident->org);
602 printf("Country : %s\n", ident->country);
603 printf("Fingerprint (SHA1) : %s\n", fingerprint);
604 printf("Babbleprint (SHA1) : %s\n", babbleprint);
608 silc_free(fingerprint);
609 silc_free(babbleprint);
611 silc_pkcs_public_key_free(public_key);
612 silc_pkcs_free_identifier(ident);