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"
36 #include "servers-setup.h"
38 #include "silc-servers.h"
39 #include "silc-channels.h"
40 #include "silc-queries.h"
41 #include "window-item-def.h"
43 #include "fe-common/core/printtext.h"
45 /* Asks yes/no from user on the input line. Returns TRUE on "yes" and
48 int silc_client_ask_yes_no(SilcClient client, char *prompt)
56 // silc_screen_input_print_prompt(app->screen, prompt);
59 memset(answer, 0, sizeof(answer));
61 getnstr(answer, sizeof(answer));
62 if (!strncasecmp(answer, "yes", strlen(answer)) ||
63 !strncasecmp(answer, "y", strlen(answer))) {
65 } else if (!strncasecmp(answer, "no", strlen(answer)) ||
66 !strncasecmp(answer, "n", strlen(answer))) {
69 printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Type yes or no");
74 // silc_screen_input_reset(app->screen);
79 /* Lists supported (builtin) ciphers */
81 void silc_client_list_ciphers()
83 char *ciphers = silc_cipher_get_supported();
84 fprintf(stdout, "%s\n", ciphers);
88 /* Lists supported (builtin) hash functions */
90 void silc_client_list_hash_funcs()
92 char *hash = silc_hash_get_supported();
93 fprintf(stdout, "%s\n", hash);
97 /* Lists supported PKCS algorithms */
99 void silc_client_list_pkcs()
101 char *pkcs = silc_pkcs_get_supported();
102 fprintf(stdout, "%s\n", pkcs);
106 /* Displays input prompt on command line and takes input data from user */
108 char *silc_client_get_input(const char *prompt)
114 fd = open("/dev/tty", O_RDONLY);
116 fprintf(stderr, "silc: %s\n", strerror(errno));
120 memset(input, 0, sizeof(input));
122 printf("%s", prompt);
125 if ((read(fd, input, sizeof(input))) < 0) {
126 fprintf(stderr, "silc: %s\n", strerror(errno));
130 if (strlen(input) <= 1)
133 if (strchr(input, '\n'))
134 *strchr(input, '\n') = '\0';
135 return strdup(input);
140 /* Returns identifier string for public key generation. */
142 char *silc_client_create_identifier()
144 char *username = NULL, *realname = NULL;
145 char hostname[256], email[256];
148 realname = silc_get_real_name();
151 memset(hostname, 0, sizeof(hostname));
152 gethostname(hostname, sizeof(hostname));
154 /* Get username (mandatory) */
155 username = silc_get_username();
159 /* Create default email address, whether it is right or not */
160 snprintf(email, sizeof(email), "%s@%s", username, hostname);
162 return silc_pkcs_encode_identifier(username, hostname, realname, email,
166 /* Creates new public key and private key pair. This is used only
167 when user wants to create new key pair from command line. */
169 int silc_client_create_key_pair(char *pkcs_name, int bits,
170 char *public_key, char *private_key,
172 SilcPublicKey *ret_pub_key,
173 SilcPrivateKey *ret_prv_key)
176 SilcPublicKey pub_key;
177 SilcPrivateKey prv_key;
182 char *pkfile = NULL, *prvfile = NULL;
184 if (!pkcs_name || !public_key || !private_key)
186 New pair of keys will be created. Please, answer to following questions.\n\
192 silc_client_get_input("PKCS name (l to list names) [rsa]: ");
194 pkcs_name = strdup("rsa");
196 if (*pkcs_name == 'l' || *pkcs_name == 'L') {
197 silc_client_list_pkcs();
198 silc_free(pkcs_name);
203 if (!silc_pkcs_is_supported(pkcs_name)) {
204 fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
211 silc_client_get_input("Key length in bits [1024]: ");
219 char *def = silc_client_create_identifier();
221 memset(line, 0, sizeof(line));
223 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
225 snprintf(line, sizeof(line),
226 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
227 "RN=Jon Johnson, E=jon@dummy.com): ");
229 while (!identifier) {
230 identifier = silc_client_get_input(line);
231 if (!identifier && def)
232 identifier = strdup(def);
239 rng = silc_rng_alloc();
241 silc_rng_global_init(rng);
244 memset(line, 0, sizeof(line));
245 snprintf(line, sizeof(line), "Public key filename [%s] ",
246 SILC_CLIENT_PUBLIC_KEY_NAME);
247 pkfile = silc_client_get_input(line);
249 pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
255 memset(line, 0, sizeof(line));
256 snprintf(line, sizeof(line), "Public key filename [%s] ",
257 SILC_CLIENT_PRIVATE_KEY_NAME);
258 prvfile = silc_client_get_input(line);
260 prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
262 prvfile = private_key;
266 silc_pkcs_alloc(pkcs_name, &pkcs);
267 pkcs->pkcs->init(pkcs->context, bits, rng);
269 /* Save public key into file */
270 key = silc_pkcs_get_public_key(pkcs, &key_len);
271 pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
273 silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
275 *ret_pub_key = pub_key;
277 memset(key, 0, sizeof(key_len));
280 /* Save private key into file */
281 key = silc_pkcs_get_private_key(pkcs, &key_len);
282 prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
284 silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
286 *ret_prv_key = prv_key;
288 printf("Public key has been saved into `%s'.\n", pkfile);
289 printf("Private key has been saved into `%s'.\n", prvfile);
290 printf("Press <Enter> to continue...\n");
293 memset(key, 0, sizeof(key_len));
297 silc_pkcs_free(pkcs);
302 /* This checks stats for various SILC files and directories. First it
303 checks if ~/.silc directory exist and is owned by the correct user. If
304 it doesn't exist, it will create the directory. After that it checks if
305 user's Public and Private key files exists and that they aren't expired.
306 If they doesn't exist or they are expired, they will be (re)created
309 int silc_client_check_silc_dir()
311 char filename[256], file_public_key[256], file_private_key[256];
312 char servfilename[256], clientfilename[256];
316 int firstime = FALSE;
317 time_t curtime, modtime;
319 SILC_LOG_DEBUG(("Checking ~./silc directory"));
321 memset(filename, 0, sizeof(filename));
322 memset(file_public_key, 0, sizeof(file_public_key));
323 memset(file_private_key, 0, sizeof(file_private_key));
325 pw = getpwuid(getuid());
327 fprintf(stderr, "silc: %s\n", strerror(errno));
331 identifier = silc_client_create_identifier();
333 /* We'll take home path from /etc/passwd file to be sure. */
334 snprintf(filename, sizeof(filename) - 1, "%s/.silc/", pw->pw_dir);
335 snprintf(servfilename, sizeof(servfilename) - 1, "%s/.silc/serverkeys",
337 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/.silc/clientkeys",
341 * Check ~/.silc directory
343 if ((stat(filename, &st)) == -1) {
344 /* If dir doesn't exist */
345 if (errno == ENOENT) {
346 if (pw->pw_uid == geteuid()) {
347 if ((mkdir(filename, 0755)) == -1) {
348 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
352 /* Directory was created. First time running SILC */
355 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
360 fprintf(stderr, "%s\n", strerror(errno));
365 /* Check the owner of the dir */
366 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
367 fprintf(stderr, "You don't seem to own `%s' directory\n",
372 /* Check the permissions of the dir */
373 if ((st.st_mode & 0777) != 0755) {
374 if ((chmod(filename, 0755)) == -1) {
375 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
383 * Check ~./silc/serverkeys directory
385 if ((stat(servfilename, &st)) == -1) {
386 /* If dir doesn't exist */
387 if (errno == ENOENT) {
388 if (pw->pw_uid == geteuid()) {
389 if ((mkdir(servfilename, 0755)) == -1) {
390 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
394 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
399 fprintf(stderr, "%s\n", strerror(errno));
405 * Check ~./silc/clientkeys directory
407 if ((stat(clientfilename, &st)) == -1) {
408 /* If dir doesn't exist */
409 if (errno == ENOENT) {
410 if (pw->pw_uid == geteuid()) {
411 if ((mkdir(clientfilename, 0755)) == -1) {
412 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
416 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
421 fprintf(stderr, "%s\n", strerror(errno));
427 * Check Public and Private keys
429 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
430 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
431 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
432 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
434 /* If running SILC first time */
436 fprintf(stdout, "Running SILC for the first time\n");
437 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
438 SILC_CLIENT_DEF_PKCS_LEN,
439 file_public_key, file_private_key,
440 identifier, NULL, NULL);
444 if ((stat(file_public_key, &st)) == -1) {
445 /* If file doesn't exist */
446 if (errno == ENOENT) {
447 fprintf(stdout, "Your public key doesn't exist\n");
448 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
449 SILC_CLIENT_DEF_PKCS_LEN,
451 file_private_key, identifier, NULL, NULL);
453 fprintf(stderr, "%s\n", strerror(errno));
458 if ((stat(file_private_key, &st)) == -1) {
459 /* If file doesn't exist */
460 if (errno == ENOENT) {
461 fprintf(stdout, "Your private key doesn't exist\n");
462 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
463 SILC_CLIENT_DEF_PKCS_LEN,
465 file_private_key, identifier, NULL, NULL);
467 fprintf(stderr, "%s\n", strerror(errno));
472 /* Check the owner of the public key */
473 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
474 fprintf(stderr, "You don't seem to own your public key!?\n");
478 /* Check the owner of the private key */
479 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
480 fprintf(stderr, "You don't seem to own your private key!?\n");
484 /* Check the permissions for the private key */
485 if ((st.st_mode & 0777) != 0600) {
486 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
487 "Trying to change them ... ", file_private_key);
488 if ((chmod(file_private_key, 0600)) == -1) {
490 "Failed to change permissions for private key file!\n"
491 "Permissions for your private key file must be 0600.\n");
494 fprintf(stderr, "Done.\n\n");
497 /* See if the key has expired. */
498 modtime = st.st_mtime; /* last modified */
499 curtime = time(0) - modtime;
501 /* 86400 is seconds in a day. */
502 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
504 "--------------------------------------------------\n"
505 "Your private key has expired and needs to be\n"
506 "recreated. This will be done automatically now.\n"
507 "Your new key will expire in %d days from today.\n"
508 "--------------------------------------------------\n",
509 SILC_CLIENT_KEY_EXPIRES);
511 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
512 SILC_CLIENT_DEF_PKCS_LEN,
514 file_private_key, identifier, NULL, NULL);
518 silc_free(identifier);
523 /* Loads public and private key from files. */
525 int silc_client_load_keys(SilcClient client)
530 SILC_LOG_DEBUG(("Loading public and private keys"));
532 pw = getpwuid(getuid());
536 memset(filename, 0, sizeof(filename));
537 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
538 pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
540 if (silc_pkcs_load_private_key(filename, &client->private_key,
541 SILC_PKCS_FILE_BIN) == FALSE)
542 if (silc_pkcs_load_private_key(filename, &client->private_key,
543 SILC_PKCS_FILE_PEM) == FALSE)
546 memset(filename, 0, sizeof(filename));
547 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
548 pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
550 if (silc_pkcs_load_public_key(filename, &client->public_key,
551 SILC_PKCS_FILE_PEM) == FALSE)
552 if (silc_pkcs_load_public_key(filename, &client->public_key,
553 SILC_PKCS_FILE_BIN) == FALSE)
559 /* Dumps the public key on screen. Used from the command line option. */
561 int silc_client_show_key(char *keyfile)
563 SilcPublicKey public_key;
564 SilcPublicKeyIdentifier ident;
571 if (silc_pkcs_load_public_key(keyfile, &public_key,
572 SILC_PKCS_FILE_PEM) == FALSE)
573 if (silc_pkcs_load_public_key(keyfile, &public_key,
574 SILC_PKCS_FILE_BIN) == FALSE) {
575 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
579 ident = silc_pkcs_decode_identifier(public_key->identifier);
581 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
582 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
584 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
585 key_len = silc_pkcs_public_key_set(pkcs, public_key);
586 silc_pkcs_free(pkcs);
589 printf("Public key file : %s\n", keyfile);
590 printf("Algorithm : %s\n", public_key->name);
592 printf("Key length (bits) : %d\n", key_len);
594 printf("Real name : %s\n", ident->realname);
596 printf("Username : %s\n", ident->username);
598 printf("Hostname : %s\n", ident->host);
600 printf("Email : %s\n", ident->email);
602 printf("Organization : %s\n", ident->org);
604 printf("Country : %s\n", ident->country);
605 printf("Fingerprint (SHA1) : %s\n", fingerprint);
609 silc_free(fingerprint);
611 silc_pkcs_public_key_free(public_key);
612 silc_pkcs_free_identifier(ident);