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 pw = getpwuid(getuid());
308 fprintf(stderr, "silc: %s\n", strerror(errno));
312 identifier = silc_client_create_identifier();
314 /* We'll take home path from /etc/passwd file to be sure. */
315 snprintf(filename, sizeof(filename) - 1, "%s/.silc/", pw->pw_dir);
316 snprintf(servfilename, sizeof(servfilename) - 1, "%s/.silc/serverkeys",
318 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/.silc/clientkeys",
322 * Check ~/.silc directory
324 if ((stat(filename, &st)) == -1) {
325 /* If dir doesn't exist */
326 if (errno == ENOENT) {
327 if (pw->pw_uid == geteuid()) {
328 if ((mkdir(filename, 0755)) == -1) {
329 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
333 /* Directory was created. First time running SILC */
336 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
341 fprintf(stderr, "%s\n", strerror(errno));
346 /* Check the owner of the dir */
347 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
348 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",
366 * Check ~./silc/serverkeys directory
368 if ((stat(servfilename, &st)) == -1) {
369 /* If dir doesn't exist */
370 if (errno == ENOENT) {
371 if (pw->pw_uid == geteuid()) {
372 if ((mkdir(servfilename, 0755)) == -1) {
373 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
377 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
382 fprintf(stderr, "%s\n", strerror(errno));
388 * Check ~./silc/clientkeys directory
390 if ((stat(clientfilename, &st)) == -1) {
391 /* If dir doesn't exist */
392 if (errno == ENOENT) {
393 if (pw->pw_uid == geteuid()) {
394 if ((mkdir(clientfilename, 0755)) == -1) {
395 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
399 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
404 fprintf(stderr, "%s\n", strerror(errno));
410 * Check Public and Private keys
412 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
413 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
414 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
415 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
417 /* If running SILC first time */
419 fprintf(stdout, "Running SILC for the first time\n");
420 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
421 SILC_CLIENT_DEF_PKCS_LEN,
422 file_public_key, file_private_key,
423 identifier, NULL, NULL);
427 if ((stat(file_public_key, &st)) == -1) {
428 /* If file doesn't exist */
429 if (errno == ENOENT) {
430 fprintf(stdout, "Your public key doesn't exist\n");
431 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
432 SILC_CLIENT_DEF_PKCS_LEN,
434 file_private_key, identifier, NULL, NULL);
436 fprintf(stderr, "%s\n", strerror(errno));
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 public key */
456 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
457 fprintf(stderr, "You don't seem to own your public key!?\n");
461 /* Check the owner of the private key */
462 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
463 fprintf(stderr, "You don't seem to own your private key!?\n");
467 /* Check the permissions for the private key */
468 if ((st.st_mode & 0777) != 0600) {
469 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
470 "Trying to change them ... ", file_private_key);
471 if ((chmod(file_private_key, 0600)) == -1) {
473 "Failed to change permissions for private key file!\n"
474 "Permissions for your private key file must be 0600.\n");
477 fprintf(stderr, "Done.\n\n");
480 /* See if the key has expired. */
481 modtime = st.st_mtime; /* last modified */
482 curtime = time(0) - modtime;
484 /* 86400 is seconds in a day. */
485 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
487 "--------------------------------------------------\n"
488 "Your private key has expired and needs to be\n"
489 "recreated. This will be done automatically now.\n"
490 "Your new key will expire in %d days from today.\n"
491 "--------------------------------------------------\n",
492 SILC_CLIENT_KEY_EXPIRES);
494 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
495 SILC_CLIENT_DEF_PKCS_LEN,
497 file_private_key, identifier, NULL, NULL);
501 silc_free(identifier);
506 /* Loads public and private key from files. */
508 int silc_client_load_keys(SilcClient client)
513 SILC_LOG_DEBUG(("Loading public and private keys"));
515 pw = getpwuid(getuid());
519 memset(filename, 0, sizeof(filename));
520 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
521 pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
523 if (silc_pkcs_load_private_key(filename, &client->private_key,
524 SILC_PKCS_FILE_BIN) == FALSE)
525 if (silc_pkcs_load_private_key(filename, &client->private_key,
526 SILC_PKCS_FILE_PEM) == FALSE)
529 memset(filename, 0, sizeof(filename));
530 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
531 pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
533 if (silc_pkcs_load_public_key(filename, &client->public_key,
534 SILC_PKCS_FILE_PEM) == FALSE)
535 if (silc_pkcs_load_public_key(filename, &client->public_key,
536 SILC_PKCS_FILE_BIN) == FALSE)
539 silc_pkcs_alloc(client->public_key->name, &client->pkcs);
540 silc_pkcs_public_key_set(client->pkcs, client->public_key);
541 silc_pkcs_private_key_set(client->pkcs, client->private_key);
546 /* Dumps the public key on screen. Used from the command line option. */
548 int silc_client_show_key(char *keyfile)
550 SilcPublicKey public_key;
551 SilcPublicKeyIdentifier ident;
552 char *fingerprint, *babbleprint;
558 if (silc_pkcs_load_public_key(keyfile, &public_key,
559 SILC_PKCS_FILE_PEM) == FALSE)
560 if (silc_pkcs_load_public_key(keyfile, &public_key,
561 SILC_PKCS_FILE_BIN) == FALSE) {
562 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
566 ident = silc_pkcs_decode_identifier(public_key->identifier);
568 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
569 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
570 babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
572 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
573 key_len = silc_pkcs_public_key_set(pkcs, public_key);
574 silc_pkcs_free(pkcs);
577 printf("Public key file : %s\n", keyfile);
578 printf("Algorithm : %s\n", public_key->name);
580 printf("Key length (bits) : %d\n", key_len);
582 printf("Real name : %s\n", ident->realname);
584 printf("Username : %s\n", ident->username);
586 printf("Hostname : %s\n", ident->host);
588 printf("Email : %s\n", ident->email);
590 printf("Organization : %s\n", ident->org);
592 printf("Country : %s\n", ident->country);
593 printf("Fingerprint (SHA1) : %s\n", fingerprint);
594 printf("Babbleprint (SHA1) : %s\n", babbleprint);
598 silc_free(fingerprint);
599 silc_free(babbleprint);
601 silc_pkcs_public_key_free(public_key);
602 silc_pkcs_free_identifier(ident);