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",
354 /* Check the permissions of the dir */
355 if ((st.st_mode & 0777) != 0755) {
356 if ((chmod(filename, 0755)) == -1) {
357 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
365 * Check ~./silc/serverkeys directory
367 if ((stat(servfilename, &st)) == -1) {
368 /* If dir doesn't exist */
369 if (errno == ENOENT) {
370 if (pw->pw_uid == geteuid()) {
371 if ((mkdir(servfilename, 0755)) == -1) {
372 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
376 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
381 fprintf(stderr, "%s\n", strerror(errno));
387 * Check ~./silc/clientkeys directory
389 if ((stat(clientfilename, &st)) == -1) {
390 /* If dir doesn't exist */
391 if (errno == ENOENT) {
392 if (pw->pw_uid == geteuid()) {
393 if ((mkdir(clientfilename, 0755)) == -1) {
394 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
398 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
403 fprintf(stderr, "%s\n", strerror(errno));
409 * Check Public and Private keys
411 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
412 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
413 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
414 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
416 /* If running SILC first time */
418 fprintf(stdout, "Running SILC for the first time\n");
419 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
420 SILC_CLIENT_DEF_PKCS_LEN,
421 file_public_key, file_private_key,
422 identifier, NULL, NULL);
426 if ((stat(file_public_key, &st)) == -1) {
427 /* If file doesn't exist */
428 if (errno == ENOENT) {
429 fprintf(stdout, "Your public key doesn't exist\n");
430 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
431 SILC_CLIENT_DEF_PKCS_LEN,
433 file_private_key, identifier, NULL, NULL);
435 fprintf(stderr, "%s\n", strerror(errno));
440 if ((stat(file_private_key, &st)) == -1) {
441 /* If file doesn't exist */
442 if (errno == ENOENT) {
443 fprintf(stdout, "Your private key doesn't exist\n");
444 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
445 SILC_CLIENT_DEF_PKCS_LEN,
447 file_private_key, identifier, NULL, NULL);
449 fprintf(stderr, "%s\n", strerror(errno));
454 /* Check the owner of the public key */
455 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
456 fprintf(stderr, "You don't seem to own your public key!?\n");
460 /* Check the owner of the private key */
461 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
462 fprintf(stderr, "You don't seem to own your private key!?\n");
466 /* Check the permissions for the private key */
467 if ((st.st_mode & 0777) != 0600) {
468 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
469 "Trying to change them ... ", file_private_key);
470 if ((chmod(file_private_key, 0600)) == -1) {
472 "Failed to change permissions for private key file!\n"
473 "Permissions for your private key file must be 0600.\n");
476 fprintf(stderr, "Done.\n\n");
479 /* See if the key has expired. */
480 modtime = st.st_mtime; /* last modified */
481 curtime = time(0) - modtime;
483 /* 86400 is seconds in a day. */
484 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
486 "--------------------------------------------------\n"
487 "Your private key has expired and needs to be\n"
488 "recreated. This will be done automatically now.\n"
489 "Your new key will expire in %d days from today.\n"
490 "--------------------------------------------------\n",
491 SILC_CLIENT_KEY_EXPIRES);
493 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
494 SILC_CLIENT_DEF_PKCS_LEN,
496 file_private_key, identifier, NULL, NULL);
500 silc_free(identifier);
505 /* Loads public and private key from files. */
507 int silc_client_load_keys(SilcClient client)
512 SILC_LOG_DEBUG(("Loading public and private keys"));
514 pw = getpwuid(getuid());
518 memset(filename, 0, sizeof(filename));
519 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
520 pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
522 if (silc_pkcs_load_private_key(filename, &client->private_key,
523 SILC_PKCS_FILE_BIN) == FALSE)
524 if (silc_pkcs_load_private_key(filename, &client->private_key,
525 SILC_PKCS_FILE_PEM) == FALSE)
528 memset(filename, 0, sizeof(filename));
529 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
530 pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
532 if (silc_pkcs_load_public_key(filename, &client->public_key,
533 SILC_PKCS_FILE_PEM) == FALSE)
534 if (silc_pkcs_load_public_key(filename, &client->public_key,
535 SILC_PKCS_FILE_BIN) == FALSE)
541 /* Dumps the public key on screen. Used from the command line option. */
543 int silc_client_show_key(char *keyfile)
545 SilcPublicKey public_key;
546 SilcPublicKeyIdentifier ident;
553 if (silc_pkcs_load_public_key(keyfile, &public_key,
554 SILC_PKCS_FILE_PEM) == FALSE)
555 if (silc_pkcs_load_public_key(keyfile, &public_key,
556 SILC_PKCS_FILE_BIN) == FALSE) {
557 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
561 ident = silc_pkcs_decode_identifier(public_key->identifier);
563 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
564 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
566 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
567 key_len = silc_pkcs_public_key_set(pkcs, public_key);
568 silc_pkcs_free(pkcs);
571 printf("Public key file : %s\n", keyfile);
572 printf("Algorithm : %s\n", public_key->name);
574 printf("Key length (bits) : %d\n", key_len);
576 printf("Real name : %s\n", ident->realname);
578 printf("Username : %s\n", ident->username);
580 printf("Hostname : %s\n", ident->host);
582 printf("Email : %s\n", ident->email);
584 printf("Organization : %s\n", ident->org);
586 printf("Country : %s\n", ident->country);
587 printf("Fingerprint (SHA1) : %s\n", fingerprint);
591 silc_free(fingerprint);
593 silc_pkcs_public_key_free(public_key);
594 silc_pkcs_free_identifier(ident);