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 /* Displays input prompt on command line and takes input data from user */
85 char *silc_client_get_input(const char *prompt)
90 fd = open("/dev/tty", O_RDONLY);
92 fprintf(stderr, "silc: %s\n", strerror(errno));
96 memset(input, 0, sizeof(input));
101 if ((read(fd, input, sizeof(input))) < 0) {
102 fprintf(stderr, "silc: %s\n", strerror(errno));
106 if (strlen(input) <= 1)
109 if (strchr(input, '\n'))
110 *strchr(input, '\n') = '\0';
112 return strdup(input);
115 /* Returns identifier string for public key generation. */
117 char *silc_client_create_identifier()
119 char *username = NULL, *realname = NULL;
120 char *hostname, email[256];
124 realname = silc_get_real_name();
127 hostname = silc_net_localhost();
131 /* Get username (mandatory) */
132 username = silc_get_username();
136 /* Create default email address, whether it is right or not */
137 snprintf(email, sizeof(email), "%s@%s", username, hostname);
139 ident = silc_pkcs_encode_identifier(username, hostname, realname, email,
149 /* Creates new public key and private key pair. This is used only
150 when user wants to create new key pair from command line. */
152 int silc_client_create_key_pair(char *pkcs_name, int bits,
153 char *public_key, char *private_key,
155 SilcPublicKey *ret_pub_key,
156 SilcPrivateKey *ret_prv_key)
159 SilcPublicKey pub_key;
160 SilcPrivateKey prv_key;
165 char *pkfile = NULL, *prvfile = NULL;
167 if (!pkcs_name || !public_key || !private_key)
169 New pair of keys will be created. Please, answer to following questions.\n\
175 silc_client_get_input("PKCS name (l to list names) [rsa]: ");
177 pkcs_name = strdup("rsa");
179 if (*pkcs_name == 'l' || *pkcs_name == 'L') {
180 silc_client_list_pkcs();
181 silc_free(pkcs_name);
186 if (!silc_pkcs_is_supported(pkcs_name)) {
187 fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
194 silc_client_get_input("Key length in bits [1024]: ");
202 char *def = silc_client_create_identifier();
204 memset(line, 0, sizeof(line));
206 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
208 snprintf(line, sizeof(line),
209 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
210 "RN=Jon Johnson, E=jon@dummy.com): ");
212 while (!identifier) {
213 identifier = silc_client_get_input(line);
214 if (!identifier && def)
215 identifier = strdup(def);
222 rng = silc_rng_alloc();
224 silc_rng_global_init(rng);
227 memset(line, 0, sizeof(line));
228 snprintf(line, sizeof(line), "Public key filename [%s] ",
229 SILC_CLIENT_PUBLIC_KEY_NAME);
230 pkfile = silc_client_get_input(line);
232 pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
238 memset(line, 0, sizeof(line));
239 snprintf(line, sizeof(line), "Public key filename [%s] ",
240 SILC_CLIENT_PRIVATE_KEY_NAME);
241 prvfile = silc_client_get_input(line);
243 prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
245 prvfile = private_key;
249 silc_pkcs_alloc(pkcs_name, &pkcs);
250 silc_pkcs_generate_key(pkcs, bits, rng);
252 /* Save public key into file */
253 key = silc_pkcs_get_public_key(pkcs, &key_len);
254 pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
256 silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
258 *ret_pub_key = pub_key;
260 memset(key, 0, sizeof(key_len));
263 /* Save private key into file */
264 key = silc_pkcs_get_private_key(pkcs, &key_len);
265 prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
267 silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
269 *ret_prv_key = prv_key;
271 printf("Public key has been saved into `%s'.\n", pkfile);
272 printf("Private key has been saved into `%s'.\n", prvfile);
273 printf("Press <Enter> to continue...\n");
276 memset(key, 0, sizeof(key_len));
280 silc_pkcs_free(pkcs);
285 /* This checks stats for various SILC files and directories. First it
286 checks if ~/.silc directory exist and is owned by the correct user. If
287 it doesn't exist, it will create the directory. After that it checks if
288 user's Public and Private key files exists and that they aren't expired.
289 If they doesn't exist or they are expired, they will be (re)created
292 int silc_client_check_silc_dir()
294 char filename[256], file_public_key[256], file_private_key[256];
295 char servfilename[256], clientfilename[256];
299 int firstime = FALSE;
300 time_t curtime, modtime;
302 SILC_LOG_DEBUG(("Checking ~./silc directory"));
304 memset(filename, 0, sizeof(filename));
305 memset(file_public_key, 0, sizeof(file_public_key));
306 memset(file_private_key, 0, sizeof(file_private_key));
308 identifier = silc_client_create_identifier();
310 pw = getpwuid(getuid());
312 fprintf(stderr, "silc: %s\n", strerror(errno));
314 silc_free(identifier);
318 /* We'll take home path from /etc/passwd file to be sure. */
319 snprintf(filename, sizeof(filename) - 1, "%s/", get_irssi_dir());
320 snprintf(servfilename, sizeof(servfilename) - 1, "%s/serverkeys",
322 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/clientkeys",
326 * Check ~/.silc directory
328 if ((stat(filename, &st)) == -1) {
329 /* If dir doesn't exist */
330 if (errno == ENOENT) {
331 if (pw->pw_uid == geteuid()) {
332 if ((mkdir(filename, 0755)) == -1) {
333 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
337 /* Directory was created. First time running SILC */
340 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
345 fprintf(stderr, "%s\n", strerror(errno));
350 /* Check the owner of the dir */
351 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
352 fprintf(stderr, "You don't seem to own `%s' directory\n",
358 /* Check the permissions of the dir */
359 if ((st.st_mode & 0777) != 0755) {
360 if ((chmod(filename, 0755)) == -1) {
361 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
370 * Check ~./silc/serverkeys directory
372 if ((stat(servfilename, &st)) == -1) {
373 /* If dir doesn't exist */
374 if (errno == ENOENT) {
375 if (pw->pw_uid == geteuid()) {
376 if ((mkdir(servfilename, 0755)) == -1) {
377 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
381 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
386 fprintf(stderr, "%s\n", strerror(errno));
392 * Check ~./silc/clientkeys directory
394 if ((stat(clientfilename, &st)) == -1) {
395 /* If dir doesn't exist */
396 if (errno == ENOENT) {
397 if (pw->pw_uid == geteuid()) {
398 if ((mkdir(clientfilename, 0755)) == -1) {
399 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
403 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
408 fprintf(stderr, "%s\n", strerror(errno));
414 * Check Public and Private keys
416 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
417 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
418 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
419 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
421 /* If running SILC first time */
423 fprintf(stdout, "Running SILC for the first time\n");
424 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
425 SILC_CLIENT_DEF_PKCS_LEN,
426 file_public_key, file_private_key,
427 identifier, NULL, NULL);
431 if ((stat(file_public_key, &st)) == -1) {
432 /* If file doesn't exist */
433 if (errno == ENOENT) {
434 fprintf(stdout, "Your public key doesn't exist\n");
435 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
436 SILC_CLIENT_DEF_PKCS_LEN,
438 file_private_key, identifier, NULL, NULL);
440 fprintf(stderr, "%s\n", strerror(errno));
445 if ((stat(file_private_key, &st)) == -1) {
446 /* If file doesn't exist */
447 if (errno == ENOENT) {
448 fprintf(stdout, "Your private key doesn't exist\n");
449 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
450 SILC_CLIENT_DEF_PKCS_LEN,
452 file_private_key, identifier, NULL, NULL);
454 fprintf(stderr, "%s\n", strerror(errno));
459 /* Check the owner of the public key */
460 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
461 fprintf(stderr, "You don't seem to own your public key!?\n");
465 /* Check the owner of the private key */
466 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
467 fprintf(stderr, "You don't seem to own your private key!?\n");
471 /* Check the permissions for the private key */
472 if ((st.st_mode & 0777) != 0600) {
473 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
474 "Trying to change them ... ", file_private_key);
475 if ((chmod(file_private_key, 0600)) == -1) {
477 "Failed to change permissions for private key file!\n"
478 "Permissions for your private key file must be 0600.\n");
481 fprintf(stderr, "Done.\n\n");
484 /* See if the key has expired. */
485 modtime = st.st_mtime; /* last modified */
486 curtime = time(0) - modtime;
488 /* 86400 is seconds in a day. */
489 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
491 "--------------------------------------------------\n"
492 "Your private key has expired and needs to be\n"
493 "recreated. This will be done automatically now.\n"
494 "Your new key will expire in %d days from today.\n"
495 "--------------------------------------------------\n",
496 SILC_CLIENT_KEY_EXPIRES);
498 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
499 SILC_CLIENT_DEF_PKCS_LEN,
501 file_private_key, identifier, NULL, NULL);
505 silc_free(identifier);
510 /* Loads public and private key from files. */
512 int silc_client_load_keys(SilcClient client)
517 SILC_LOG_DEBUG(("Loading public and private keys"));
519 pw = getpwuid(getuid());
523 memset(filename, 0, sizeof(filename));
524 snprintf(filename, sizeof(filename) - 1, "%s/%s",
525 get_irssi_dir(), SILC_CLIENT_PRIVATE_KEY_NAME);
527 if (silc_pkcs_load_private_key(filename, &client->private_key,
528 SILC_PKCS_FILE_BIN) == FALSE)
529 if (silc_pkcs_load_private_key(filename, &client->private_key,
530 SILC_PKCS_FILE_PEM) == FALSE)
533 memset(filename, 0, sizeof(filename));
534 snprintf(filename, sizeof(filename) - 1, "%s/%s",
535 get_irssi_dir(), SILC_CLIENT_PUBLIC_KEY_NAME);
537 if (silc_pkcs_load_public_key(filename, &client->public_key,
538 SILC_PKCS_FILE_PEM) == FALSE)
539 if (silc_pkcs_load_public_key(filename, &client->public_key,
540 SILC_PKCS_FILE_BIN) == FALSE)
543 silc_pkcs_alloc(client->public_key->name, &client->pkcs);
544 silc_pkcs_public_key_set(client->pkcs, client->public_key);
545 silc_pkcs_private_key_set(client->pkcs, client->private_key);
550 /* Dumps the public key on screen. Used from the command line option. */
552 int silc_client_show_key(char *keyfile)
554 SilcPublicKey public_key;
555 SilcPublicKeyIdentifier ident;
556 char *fingerprint, *babbleprint;
562 if (silc_pkcs_load_public_key(keyfile, &public_key,
563 SILC_PKCS_FILE_PEM) == FALSE)
564 if (silc_pkcs_load_public_key(keyfile, &public_key,
565 SILC_PKCS_FILE_BIN) == FALSE) {
566 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
570 ident = silc_pkcs_decode_identifier(public_key->identifier);
572 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
573 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
574 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
576 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
577 key_len = silc_pkcs_public_key_set(pkcs, public_key);
578 silc_pkcs_free(pkcs);
581 printf("Public key file : %s\n", keyfile);
582 printf("Algorithm : %s\n", public_key->name);
584 printf("Key length (bits) : %d\n", key_len);
586 printf("Real name : %s\n", ident->realname);
588 printf("Username : %s\n", ident->username);
590 printf("Hostname : %s\n", ident->host);
592 printf("Email : %s\n", ident->email);
594 printf("Organization : %s\n", ident->org);
596 printf("Country : %s\n", ident->country);
597 printf("Fingerprint (SHA1) : %s\n", fingerprint);
598 printf("Babbleprint (SHA1) : %s\n", babbleprint);
602 silc_free(fingerprint);
603 silc_free(babbleprint);
605 silc_pkcs_public_key_free(public_key);
606 silc_pkcs_free_identifier(ident);