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"
45 /* Lists supported ciphers */
47 void silc_client_list_ciphers()
49 char *ciphers = silc_cipher_get_supported();
50 fprintf(stdout, "%s\n", ciphers);
54 /* Lists supported hash functions */
56 void silc_client_list_hash_funcs()
58 char *hash = silc_hash_get_supported();
59 fprintf(stdout, "%s\n", hash);
63 /* Lists supported hash functions */
65 void silc_client_list_hmacs()
67 char *hash = silc_hmac_get_supported();
68 fprintf(stdout, "%s\n", hash);
72 /* Lists supported PKCS algorithms */
74 void silc_client_list_pkcs()
76 char *pkcs = silc_pkcs_get_supported();
77 fprintf(stdout, "%s\n", pkcs);
81 /* Displays input prompt on command line and takes input data from user */
83 char *silc_client_get_input(const char *prompt)
88 fd = open("/dev/tty", O_RDONLY);
90 fprintf(stderr, "silc: %s\n", strerror(errno));
94 memset(input, 0, sizeof(input));
99 if ((read(fd, input, sizeof(input))) < 0) {
100 fprintf(stderr, "silc: %s\n", strerror(errno));
104 if (strlen(input) <= 1)
107 if (strchr(input, '\n'))
108 *strchr(input, '\n') = '\0';
110 return strdup(input);
113 /* Returns identifier string for public key generation. */
115 char *silc_client_create_identifier()
117 char *username = NULL, *realname = NULL;
118 char *hostname, email[256];
122 realname = silc_get_real_name();
125 hostname = silc_net_localhost();
129 /* Get username (mandatory) */
130 username = silc_get_username();
134 /* Create default email address, whether it is right or not */
135 snprintf(email, sizeof(email), "%s@%s", username, hostname);
137 ident = silc_pkcs_encode_identifier(username, hostname, realname, email,
147 /* Creates new public key and private key pair. This is used only
148 when user wants to create new key pair from command line. */
150 int silc_client_create_key_pair(char *pkcs_name, int bits,
151 char *public_key, char *private_key,
153 SilcPublicKey *ret_pub_key,
154 SilcPrivateKey *ret_prv_key)
157 SilcPublicKey pub_key;
158 SilcPrivateKey prv_key;
163 char *pkfile = NULL, *prvfile = NULL;
165 if (!pkcs_name || !public_key || !private_key)
167 New pair of keys will be created. Please, answer to following questions.\n\
173 silc_client_get_input("PKCS name (l to list names) [rsa]: ");
175 pkcs_name = strdup("rsa");
177 if (*pkcs_name == 'l' || *pkcs_name == 'L') {
178 silc_client_list_pkcs();
179 silc_free(pkcs_name);
184 if (!silc_pkcs_is_supported(pkcs_name)) {
185 fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
192 silc_client_get_input("Key length in bits [1024]: ");
200 char *def = silc_client_create_identifier();
202 memset(line, 0, sizeof(line));
204 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
206 snprintf(line, sizeof(line),
207 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
208 "RN=Jon Johnson, E=jon@dummy.com): ");
210 while (!identifier) {
211 identifier = silc_client_get_input(line);
212 if (!identifier && def)
213 identifier = strdup(def);
220 rng = silc_rng_alloc();
222 silc_rng_global_init(rng);
225 memset(line, 0, sizeof(line));
226 snprintf(line, sizeof(line), "Public key filename [%s] ",
227 SILC_CLIENT_PUBLIC_KEY_NAME);
228 pkfile = silc_client_get_input(line);
230 pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
236 memset(line, 0, sizeof(line));
237 snprintf(line, sizeof(line), "Public key filename [%s] ",
238 SILC_CLIENT_PRIVATE_KEY_NAME);
239 prvfile = silc_client_get_input(line);
241 prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
243 prvfile = private_key;
247 silc_pkcs_alloc(pkcs_name, &pkcs);
248 pkcs->pkcs->init(pkcs->context, bits, rng);
250 /* Save public key into file */
251 key = silc_pkcs_get_public_key(pkcs, &key_len);
252 pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
254 silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
256 *ret_pub_key = pub_key;
258 memset(key, 0, sizeof(key_len));
261 /* Save private key into file */
262 key = silc_pkcs_get_private_key(pkcs, &key_len);
263 prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
265 silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
267 *ret_prv_key = prv_key;
269 printf("Public key has been saved into `%s'.\n", pkfile);
270 printf("Private key has been saved into `%s'.\n", prvfile);
271 printf("Press <Enter> to continue...\n");
274 memset(key, 0, sizeof(key_len));
278 silc_pkcs_free(pkcs);
283 /* This checks stats for various SILC files and directories. First it
284 checks if ~/.silc directory exist and is owned by the correct user. If
285 it doesn't exist, it will create the directory. After that it checks if
286 user's Public and Private key files exists and that they aren't expired.
287 If they doesn't exist or they are expired, they will be (re)created
290 int silc_client_check_silc_dir()
292 char filename[256], file_public_key[256], file_private_key[256];
293 char servfilename[256], clientfilename[256];
297 int firstime = FALSE;
298 time_t curtime, modtime;
300 SILC_LOG_DEBUG(("Checking ~./silc directory"));
302 memset(filename, 0, sizeof(filename));
303 memset(file_public_key, 0, sizeof(file_public_key));
304 memset(file_private_key, 0, sizeof(file_private_key));
306 identifier = silc_client_create_identifier();
308 pw = getpwuid(getuid());
310 fprintf(stderr, "silc: %s\n", strerror(errno));
312 silc_free(identifier);
316 /* We'll take home path from /etc/passwd file to be sure. */
317 snprintf(filename, sizeof(filename) - 1, "%s/.silc/", pw->pw_dir);
318 snprintf(servfilename, sizeof(servfilename) - 1, "%s/.silc/serverkeys",
320 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/.silc/clientkeys",
324 * Check ~/.silc directory
326 if ((stat(filename, &st)) == -1) {
327 /* If dir doesn't exist */
328 if (errno == ENOENT) {
329 if (pw->pw_uid == geteuid()) {
330 if ((mkdir(filename, 0755)) == -1) {
331 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
335 /* Directory was created. First time running SILC */
338 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
343 fprintf(stderr, "%s\n", strerror(errno));
348 /* Check the owner of the dir */
349 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
350 fprintf(stderr, "You don't seem to own `%s' directory\n",
356 /* Check the permissions of the dir */
357 if ((st.st_mode & 0777) != 0755) {
358 if ((chmod(filename, 0755)) == -1) {
359 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
368 * Check ~./silc/serverkeys directory
370 if ((stat(servfilename, &st)) == -1) {
371 /* If dir doesn't exist */
372 if (errno == ENOENT) {
373 if (pw->pw_uid == geteuid()) {
374 if ((mkdir(servfilename, 0755)) == -1) {
375 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
379 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
384 fprintf(stderr, "%s\n", strerror(errno));
390 * Check ~./silc/clientkeys directory
392 if ((stat(clientfilename, &st)) == -1) {
393 /* If dir doesn't exist */
394 if (errno == ENOENT) {
395 if (pw->pw_uid == geteuid()) {
396 if ((mkdir(clientfilename, 0755)) == -1) {
397 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
401 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
406 fprintf(stderr, "%s\n", strerror(errno));
412 * Check Public and Private keys
414 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
415 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
416 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
417 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
419 /* If running SILC first time */
421 fprintf(stdout, "Running SILC for the first time\n");
422 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
423 SILC_CLIENT_DEF_PKCS_LEN,
424 file_public_key, file_private_key,
425 identifier, NULL, NULL);
429 if ((stat(file_public_key, &st)) == -1) {
430 /* If file doesn't exist */
431 if (errno == ENOENT) {
432 fprintf(stdout, "Your public key doesn't exist\n");
433 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
434 SILC_CLIENT_DEF_PKCS_LEN,
436 file_private_key, identifier, NULL, NULL);
438 fprintf(stderr, "%s\n", strerror(errno));
443 if ((stat(file_private_key, &st)) == -1) {
444 /* If file doesn't exist */
445 if (errno == ENOENT) {
446 fprintf(stdout, "Your private key doesn't exist\n");
447 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
448 SILC_CLIENT_DEF_PKCS_LEN,
450 file_private_key, identifier, NULL, NULL);
452 fprintf(stderr, "%s\n", strerror(errno));
457 /* Check the owner of the public key */
458 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
459 fprintf(stderr, "You don't seem to own your public key!?\n");
463 /* Check the owner of the private key */
464 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
465 fprintf(stderr, "You don't seem to own your private key!?\n");
469 /* Check the permissions for the private key */
470 if ((st.st_mode & 0777) != 0600) {
471 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
472 "Trying to change them ... ", file_private_key);
473 if ((chmod(file_private_key, 0600)) == -1) {
475 "Failed to change permissions for private key file!\n"
476 "Permissions for your private key file must be 0600.\n");
479 fprintf(stderr, "Done.\n\n");
482 /* See if the key has expired. */
483 modtime = st.st_mtime; /* last modified */
484 curtime = time(0) - modtime;
486 /* 86400 is seconds in a day. */
487 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
489 "--------------------------------------------------\n"
490 "Your private key has expired and needs to be\n"
491 "recreated. This will be done automatically now.\n"
492 "Your new key will expire in %d days from today.\n"
493 "--------------------------------------------------\n",
494 SILC_CLIENT_KEY_EXPIRES);
496 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
497 SILC_CLIENT_DEF_PKCS_LEN,
499 file_private_key, identifier, NULL, NULL);
503 silc_free(identifier);
508 /* Loads public and private key from files. */
510 int silc_client_load_keys(SilcClient client)
515 SILC_LOG_DEBUG(("Loading public and private keys"));
517 pw = getpwuid(getuid());
521 memset(filename, 0, sizeof(filename));
522 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
523 pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
525 if (silc_pkcs_load_private_key(filename, &client->private_key,
526 SILC_PKCS_FILE_BIN) == FALSE)
527 if (silc_pkcs_load_private_key(filename, &client->private_key,
528 SILC_PKCS_FILE_PEM) == FALSE)
531 memset(filename, 0, sizeof(filename));
532 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
533 pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
535 if (silc_pkcs_load_public_key(filename, &client->public_key,
536 SILC_PKCS_FILE_PEM) == FALSE)
537 if (silc_pkcs_load_public_key(filename, &client->public_key,
538 SILC_PKCS_FILE_BIN) == FALSE)
541 silc_pkcs_alloc(client->public_key->name, &client->pkcs);
542 silc_pkcs_public_key_set(client->pkcs, client->public_key);
543 silc_pkcs_private_key_set(client->pkcs, client->private_key);
548 /* Dumps the public key on screen. Used from the command line option. */
550 int silc_client_show_key(char *keyfile)
552 SilcPublicKey public_key;
553 SilcPublicKeyIdentifier ident;
554 char *fingerprint, *babbleprint;
560 if (silc_pkcs_load_public_key(keyfile, &public_key,
561 SILC_PKCS_FILE_PEM) == FALSE)
562 if (silc_pkcs_load_public_key(keyfile, &public_key,
563 SILC_PKCS_FILE_BIN) == FALSE) {
564 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
568 ident = silc_pkcs_decode_identifier(public_key->identifier);
570 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
571 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
572 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
574 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
575 key_len = silc_pkcs_public_key_set(pkcs, public_key);
576 silc_pkcs_free(pkcs);
579 printf("Public key file : %s\n", keyfile);
580 printf("Algorithm : %s\n", public_key->name);
582 printf("Key length (bits) : %d\n", key_len);
584 printf("Real name : %s\n", ident->realname);
586 printf("Username : %s\n", ident->username);
588 printf("Hostname : %s\n", ident->host);
590 printf("Email : %s\n", ident->email);
592 printf("Organization : %s\n", ident->org);
594 printf("Country : %s\n", ident->country);
595 printf("Fingerprint (SHA1) : %s\n", fingerprint);
596 printf("Babbleprint (SHA1) : %s\n", babbleprint);
600 silc_free(fingerprint);
601 silc_free(babbleprint);
603 silc_pkcs_public_key_free(public_key);
604 silc_pkcs_free_identifier(ident);