5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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; either version 2 of the License, or
12 (at your option) any later version.
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.
24 #include "net-nonblock.h"
25 #include "net-sendbuffer.h"
35 #include "channels-setup.h"
37 #include "silc-servers.h"
38 #include "silc-channels.h"
39 #include "silc-queries.h"
40 #include "silc-nicklist.h"
41 #include "window-item-def.h"
43 #include "fe-common/core/printtext.h"
44 #include "fe-common/core/keyboard.h"
46 /* Lists supported ciphers */
48 void silc_client_list_ciphers()
50 char *ciphers = silc_cipher_get_supported();
51 fprintf(stdout, "%s\n", ciphers);
55 /* Lists supported hash functions */
57 void silc_client_list_hash_funcs()
59 char *hash = silc_hash_get_supported();
60 fprintf(stdout, "%s\n", hash);
64 /* Lists supported hash functions */
66 void silc_client_list_hmacs()
68 char *hash = silc_hmac_get_supported();
69 fprintf(stdout, "%s\n", hash);
73 /* Lists supported PKCS algorithms */
75 void silc_client_list_pkcs()
77 char *pkcs = silc_pkcs_get_supported();
78 fprintf(stdout, "%s\n", pkcs);
82 /* Displays input prompt on command line and takes input data from user */
84 char *silc_client_get_input(const char *prompt)
89 fd = open("/dev/tty", O_RDONLY);
91 fprintf(stderr, "silc: %s\n", strerror(errno));
95 memset(input, 0, sizeof(input));
100 if ((read(fd, input, sizeof(input))) < 0) {
101 fprintf(stderr, "silc: %s\n", strerror(errno));
105 if (strlen(input) <= 1)
108 if (strchr(input, '\n'))
109 *strchr(input, '\n') = '\0';
111 return strdup(input);
114 /* Returns identifier string for public key generation. */
116 char *silc_client_create_identifier()
118 char *username = NULL, *realname = NULL;
119 char *hostname, email[256];
123 realname = silc_get_real_name();
126 hostname = silc_net_localhost();
130 /* Get username (mandatory) */
131 username = silc_get_username();
135 /* Create default email address, whether it is right or not */
136 snprintf(email, sizeof(email), "%s@%s", username, hostname);
138 ident = silc_pkcs_encode_identifier(username, hostname, realname, email,
148 /* Creates new public key and private key pair. This is used only
149 when user wants to create new key pair from command line. */
151 int silc_client_create_key_pair(char *pkcs_name, int bits,
152 char *public_key, char *private_key,
154 SilcPublicKey *ret_pub_key,
155 SilcPrivateKey *ret_prv_key)
158 SilcPublicKey pub_key;
159 SilcPrivateKey prv_key;
164 char *pkfile = NULL, *prvfile = NULL;
166 if (!pkcs_name || !public_key || !private_key)
168 New pair of keys will be created. Please, answer to following questions.\n\
174 silc_client_get_input("PKCS name (l to list names) [rsa]: ");
176 pkcs_name = strdup("rsa");
178 if (*pkcs_name == 'l' || *pkcs_name == 'L') {
179 silc_client_list_pkcs();
180 silc_free(pkcs_name);
185 if (!silc_pkcs_is_supported(pkcs_name)) {
186 fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
193 silc_client_get_input("Key length in bits [1024]: ");
201 char *def = silc_client_create_identifier();
203 memset(line, 0, sizeof(line));
205 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
207 snprintf(line, sizeof(line),
208 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
209 "RN=Jon Johnson, E=jon@dummy.com): ");
211 while (!identifier) {
212 identifier = silc_client_get_input(line);
213 if (!identifier && def)
214 identifier = strdup(def);
221 rng = silc_rng_alloc();
223 silc_rng_global_init(rng);
226 memset(line, 0, sizeof(line));
227 snprintf(line, sizeof(line), "Public key filename [%s] ",
228 SILC_CLIENT_PUBLIC_KEY_NAME);
229 pkfile = silc_client_get_input(line);
231 pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
237 memset(line, 0, sizeof(line));
238 snprintf(line, sizeof(line), "Public key filename [%s] ",
239 SILC_CLIENT_PRIVATE_KEY_NAME);
240 prvfile = silc_client_get_input(line);
242 prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
244 prvfile = private_key;
248 silc_pkcs_alloc(pkcs_name, &pkcs);
249 pkcs->pkcs->init(pkcs->context, bits, rng);
251 /* Save public key into file */
252 key = silc_pkcs_get_public_key(pkcs, &key_len);
253 pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
255 silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
257 *ret_pub_key = pub_key;
259 memset(key, 0, sizeof(key_len));
262 /* Save private key into file */
263 key = silc_pkcs_get_private_key(pkcs, &key_len);
264 prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
266 silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
268 *ret_prv_key = prv_key;
270 printf("Public key has been saved into `%s'.\n", pkfile);
271 printf("Private key has been saved into `%s'.\n", prvfile);
272 printf("Press <Enter> to continue...\n");
275 memset(key, 0, sizeof(key_len));
279 silc_pkcs_free(pkcs);
284 /* This checks stats for various SILC files and directories. First it
285 checks if ~/.silc directory exist and is owned by the correct user. If
286 it doesn't exist, it will create the directory. After that it checks if
287 user's Public and Private key files exists and that they aren't expired.
288 If they doesn't exist or they are expired, they will be (re)created
291 int silc_client_check_silc_dir()
293 char filename[256], file_public_key[256], file_private_key[256];
294 char servfilename[256], clientfilename[256];
298 int firstime = FALSE;
299 time_t curtime, modtime;
301 SILC_LOG_DEBUG(("Checking ~./silc directory"));
303 memset(filename, 0, sizeof(filename));
304 memset(file_public_key, 0, sizeof(file_public_key));
305 memset(file_private_key, 0, sizeof(file_private_key));
307 pw = getpwuid(getuid());
309 fprintf(stderr, "silc: %s\n", strerror(errno));
313 identifier = silc_client_create_identifier();
315 /* We'll take home path from /etc/passwd file to be sure. */
316 snprintf(filename, sizeof(filename) - 1, "%s/.silc/", pw->pw_dir);
317 snprintf(servfilename, sizeof(servfilename) - 1, "%s/.silc/serverkeys",
319 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/.silc/clientkeys",
323 * Check ~/.silc directory
325 if ((stat(filename, &st)) == -1) {
326 /* If dir doesn't exist */
327 if (errno == ENOENT) {
328 if (pw->pw_uid == geteuid()) {
329 if ((mkdir(filename, 0755)) == -1) {
330 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
334 /* Directory was created. First time running SILC */
337 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
342 fprintf(stderr, "%s\n", strerror(errno));
347 /* Check the owner of the dir */
348 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
349 fprintf(stderr, "You don't seem to own `%s' directory\n",
355 /* Check the permissions of the dir */
356 if ((st.st_mode & 0777) != 0755) {
357 if ((chmod(filename, 0755)) == -1) {
358 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
367 * Check ~./silc/serverkeys directory
369 if ((stat(servfilename, &st)) == -1) {
370 /* If dir doesn't exist */
371 if (errno == ENOENT) {
372 if (pw->pw_uid == geteuid()) {
373 if ((mkdir(servfilename, 0755)) == -1) {
374 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
378 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
383 fprintf(stderr, "%s\n", strerror(errno));
389 * Check ~./silc/clientkeys directory
391 if ((stat(clientfilename, &st)) == -1) {
392 /* If dir doesn't exist */
393 if (errno == ENOENT) {
394 if (pw->pw_uid == geteuid()) {
395 if ((mkdir(clientfilename, 0755)) == -1) {
396 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
400 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
405 fprintf(stderr, "%s\n", strerror(errno));
411 * Check Public and Private keys
413 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
414 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
415 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
416 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
418 /* If running SILC first time */
420 fprintf(stdout, "Running SILC for the first time\n");
421 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
422 SILC_CLIENT_DEF_PKCS_LEN,
423 file_public_key, file_private_key,
424 identifier, NULL, NULL);
428 if ((stat(file_public_key, &st)) == -1) {
429 /* If file doesn't exist */
430 if (errno == ENOENT) {
431 fprintf(stdout, "Your public key doesn't exist\n");
432 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
433 SILC_CLIENT_DEF_PKCS_LEN,
435 file_private_key, identifier, NULL, NULL);
437 fprintf(stderr, "%s\n", strerror(errno));
442 if ((stat(file_private_key, &st)) == -1) {
443 /* If file doesn't exist */
444 if (errno == ENOENT) {
445 fprintf(stdout, "Your private key doesn't exist\n");
446 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
447 SILC_CLIENT_DEF_PKCS_LEN,
449 file_private_key, identifier, NULL, NULL);
451 fprintf(stderr, "%s\n", strerror(errno));
456 /* Check the owner of the public key */
457 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
458 fprintf(stderr, "You don't seem to own your public key!?\n");
462 /* Check the owner of the private key */
463 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
464 fprintf(stderr, "You don't seem to own your private key!?\n");
468 /* Check the permissions for the private key */
469 if ((st.st_mode & 0777) != 0600) {
470 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
471 "Trying to change them ... ", file_private_key);
472 if ((chmod(file_private_key, 0600)) == -1) {
474 "Failed to change permissions for private key file!\n"
475 "Permissions for your private key file must be 0600.\n");
478 fprintf(stderr, "Done.\n\n");
481 /* See if the key has expired. */
482 modtime = st.st_mtime; /* last modified */
483 curtime = time(0) - modtime;
485 /* 86400 is seconds in a day. */
486 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
488 "--------------------------------------------------\n"
489 "Your private key has expired and needs to be\n"
490 "recreated. This will be done automatically now.\n"
491 "Your new key will expire in %d days from today.\n"
492 "--------------------------------------------------\n",
493 SILC_CLIENT_KEY_EXPIRES);
495 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
496 SILC_CLIENT_DEF_PKCS_LEN,
498 file_private_key, identifier, NULL, NULL);
502 silc_free(identifier);
507 /* Loads public and private key from files. */
509 int silc_client_load_keys(SilcClient client)
514 SILC_LOG_DEBUG(("Loading public and private keys"));
516 pw = getpwuid(getuid());
520 memset(filename, 0, sizeof(filename));
521 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
522 pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
524 if (silc_pkcs_load_private_key(filename, &client->private_key,
525 SILC_PKCS_FILE_BIN) == FALSE)
526 if (silc_pkcs_load_private_key(filename, &client->private_key,
527 SILC_PKCS_FILE_PEM) == FALSE)
530 memset(filename, 0, sizeof(filename));
531 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
532 pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
534 if (silc_pkcs_load_public_key(filename, &client->public_key,
535 SILC_PKCS_FILE_PEM) == FALSE)
536 if (silc_pkcs_load_public_key(filename, &client->public_key,
537 SILC_PKCS_FILE_BIN) == FALSE)
543 /* Dumps the public key on screen. Used from the command line option. */
545 int silc_client_show_key(char *keyfile)
547 SilcPublicKey public_key;
548 SilcPublicKeyIdentifier ident;
555 if (silc_pkcs_load_public_key(keyfile, &public_key,
556 SILC_PKCS_FILE_PEM) == FALSE)
557 if (silc_pkcs_load_public_key(keyfile, &public_key,
558 SILC_PKCS_FILE_BIN) == FALSE) {
559 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
563 ident = silc_pkcs_decode_identifier(public_key->identifier);
565 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
566 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
568 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
569 key_len = silc_pkcs_public_key_set(pkcs, public_key);
570 silc_pkcs_free(pkcs);
573 printf("Public key file : %s\n", keyfile);
574 printf("Algorithm : %s\n", public_key->name);
576 printf("Key length (bits) : %d\n", key_len);
578 printf("Real name : %s\n", ident->realname);
580 printf("Username : %s\n", ident->username);
582 printf("Hostname : %s\n", ident->host);
584 printf("Email : %s\n", ident->email);
586 printf("Organization : %s\n", ident->org);
588 printf("Country : %s\n", ident->country);
589 printf("Fingerprint (SHA1) : %s\n", fingerprint);
593 silc_free(fingerprint);
595 silc_pkcs_public_key_free(public_key);
596 silc_pkcs_free_identifier(ident);