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 void silc_client_ask_yes_no(char *prompt, SIGNAL_FUNC func)
50 keyboard_entry_redirect(func, prompt, 0, NULL);
53 /* Lists supported (builtin) ciphers */
55 void silc_client_list_ciphers()
57 char *ciphers = silc_cipher_get_supported();
58 fprintf(stdout, "%s\n", ciphers);
62 /* Lists supported (builtin) hash functions */
64 void silc_client_list_hash_funcs()
66 char *hash = silc_hash_get_supported();
67 fprintf(stdout, "%s\n", hash);
71 /* Lists supported PKCS algorithms */
73 void silc_client_list_pkcs()
75 char *pkcs = silc_pkcs_get_supported();
76 fprintf(stdout, "%s\n", pkcs);
80 /* Displays input prompt on command line and takes input data from user */
82 void silc_client_get_input(char *prompt, SIGNAL_FUNC func)
84 keyboard_entry_redirect(func, prompt, 0, NULL);
87 /* Returns identifier string for public key generation. */
89 char *silc_client_create_identifier()
91 char *username = NULL, *realname = NULL;
92 char hostname[256], email[256];
95 realname = silc_get_real_name();
98 memset(hostname, 0, sizeof(hostname));
99 gethostname(hostname, sizeof(hostname));
101 /* Get username (mandatory) */
102 username = silc_get_username();
106 /* Create default email address, whether it is right or not */
107 snprintf(email, sizeof(email), "%s@%s", username, hostname);
109 return silc_pkcs_encode_identifier(username, hostname, realname, email,
113 /* Creates new public key and private key pair. This is used only
114 when user wants to create new key pair from command line. */
116 int silc_client_create_key_pair(char *pkcs_name, int bits,
117 char *public_key, char *private_key,
119 SilcPublicKey *ret_pub_key,
120 SilcPrivateKey *ret_prv_key)
123 SilcPublicKey pub_key;
124 SilcPrivateKey prv_key;
129 char *pkfile = NULL, *prvfile = NULL;
131 if (!pkcs_name || !public_key || !private_key)
133 New pair of keys will be created. Please, answer to following questions.\n\
139 silc_client_get_input("PKCS name (l to list names) [rsa]: ");
141 pkcs_name = strdup("rsa");
143 if (*pkcs_name == 'l' || *pkcs_name == 'L') {
144 silc_client_list_pkcs();
145 silc_free(pkcs_name);
150 if (!silc_pkcs_is_supported(pkcs_name)) {
151 fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
158 silc_client_get_input("Key length in bits [1024]: ");
166 char *def = silc_client_create_identifier();
168 memset(line, 0, sizeof(line));
170 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
172 snprintf(line, sizeof(line),
173 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
174 "RN=Jon Johnson, E=jon@dummy.com): ");
176 while (!identifier) {
177 identifier = silc_client_get_input(line);
178 if (!identifier && def)
179 identifier = strdup(def);
186 rng = silc_rng_alloc();
188 silc_rng_global_init(rng);
191 memset(line, 0, sizeof(line));
192 snprintf(line, sizeof(line), "Public key filename [%s] ",
193 SILC_CLIENT_PUBLIC_KEY_NAME);
194 pkfile = silc_client_get_input(line);
196 pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
202 memset(line, 0, sizeof(line));
203 snprintf(line, sizeof(line), "Public key filename [%s] ",
204 SILC_CLIENT_PRIVATE_KEY_NAME);
205 prvfile = silc_client_get_input(line);
207 prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
209 prvfile = private_key;
213 silc_pkcs_alloc(pkcs_name, &pkcs);
214 pkcs->pkcs->init(pkcs->context, bits, rng);
216 /* Save public key into file */
217 key = silc_pkcs_get_public_key(pkcs, &key_len);
218 pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
220 silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
222 *ret_pub_key = pub_key;
224 memset(key, 0, sizeof(key_len));
227 /* Save private key into file */
228 key = silc_pkcs_get_private_key(pkcs, &key_len);
229 prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
231 silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
233 *ret_prv_key = prv_key;
235 printf("Public key has been saved into `%s'.\n", pkfile);
236 printf("Private key has been saved into `%s'.\n", prvfile);
237 printf("Press <Enter> to continue...\n");
240 memset(key, 0, sizeof(key_len));
244 silc_pkcs_free(pkcs);
249 /* This checks stats for various SILC files and directories. First it
250 checks if ~/.silc directory exist and is owned by the correct user. If
251 it doesn't exist, it will create the directory. After that it checks if
252 user's Public and Private key files exists and that they aren't expired.
253 If they doesn't exist or they are expired, they will be (re)created
256 int silc_client_check_silc_dir()
258 char filename[256], file_public_key[256], file_private_key[256];
259 char servfilename[256], clientfilename[256];
263 int firstime = FALSE;
264 time_t curtime, modtime;
266 SILC_LOG_DEBUG(("Checking ~./silc directory"));
268 memset(filename, 0, sizeof(filename));
269 memset(file_public_key, 0, sizeof(file_public_key));
270 memset(file_private_key, 0, sizeof(file_private_key));
272 pw = getpwuid(getuid());
274 fprintf(stderr, "silc: %s\n", strerror(errno));
278 identifier = silc_client_create_identifier();
280 /* We'll take home path from /etc/passwd file to be sure. */
281 snprintf(filename, sizeof(filename) - 1, "%s/.silc/", pw->pw_dir);
282 snprintf(servfilename, sizeof(servfilename) - 1, "%s/.silc/serverkeys",
284 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/.silc/clientkeys",
288 * Check ~/.silc directory
290 if ((stat(filename, &st)) == -1) {
291 /* If dir doesn't exist */
292 if (errno == ENOENT) {
293 if (pw->pw_uid == geteuid()) {
294 if ((mkdir(filename, 0755)) == -1) {
295 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
299 /* Directory was created. First time running SILC */
302 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
307 fprintf(stderr, "%s\n", strerror(errno));
312 /* Check the owner of the dir */
313 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
314 fprintf(stderr, "You don't seem to own `%s' directory\n",
319 /* Check the permissions of the dir */
320 if ((st.st_mode & 0777) != 0755) {
321 if ((chmod(filename, 0755)) == -1) {
322 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
330 * Check ~./silc/serverkeys directory
332 if ((stat(servfilename, &st)) == -1) {
333 /* If dir doesn't exist */
334 if (errno == ENOENT) {
335 if (pw->pw_uid == geteuid()) {
336 if ((mkdir(servfilename, 0755)) == -1) {
337 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
341 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
346 fprintf(stderr, "%s\n", strerror(errno));
352 * Check ~./silc/clientkeys directory
354 if ((stat(clientfilename, &st)) == -1) {
355 /* If dir doesn't exist */
356 if (errno == ENOENT) {
357 if (pw->pw_uid == geteuid()) {
358 if ((mkdir(clientfilename, 0755)) == -1) {
359 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
363 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
368 fprintf(stderr, "%s\n", strerror(errno));
374 * Check Public and Private keys
376 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
377 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
378 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
379 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
381 /* If running SILC first time */
383 fprintf(stdout, "Running SILC for the first time\n");
384 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
385 SILC_CLIENT_DEF_PKCS_LEN,
386 file_public_key, file_private_key,
387 identifier, NULL, NULL);
391 if ((stat(file_public_key, &st)) == -1) {
392 /* If file doesn't exist */
393 if (errno == ENOENT) {
394 fprintf(stdout, "Your public key doesn't exist\n");
395 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
396 SILC_CLIENT_DEF_PKCS_LEN,
398 file_private_key, identifier, NULL, NULL);
400 fprintf(stderr, "%s\n", strerror(errno));
405 if ((stat(file_private_key, &st)) == -1) {
406 /* If file doesn't exist */
407 if (errno == ENOENT) {
408 fprintf(stdout, "Your private key doesn't exist\n");
409 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
410 SILC_CLIENT_DEF_PKCS_LEN,
412 file_private_key, identifier, NULL, NULL);
414 fprintf(stderr, "%s\n", strerror(errno));
419 /* Check the owner of the public key */
420 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
421 fprintf(stderr, "You don't seem to own your public key!?\n");
425 /* Check the owner of the private key */
426 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
427 fprintf(stderr, "You don't seem to own your private key!?\n");
431 /* Check the permissions for the private key */
432 if ((st.st_mode & 0777) != 0600) {
433 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
434 "Trying to change them ... ", file_private_key);
435 if ((chmod(file_private_key, 0600)) == -1) {
437 "Failed to change permissions for private key file!\n"
438 "Permissions for your private key file must be 0600.\n");
441 fprintf(stderr, "Done.\n\n");
444 /* See if the key has expired. */
445 modtime = st.st_mtime; /* last modified */
446 curtime = time(0) - modtime;
448 /* 86400 is seconds in a day. */
449 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
451 "--------------------------------------------------\n"
452 "Your private key has expired and needs to be\n"
453 "recreated. This will be done automatically now.\n"
454 "Your new key will expire in %d days from today.\n"
455 "--------------------------------------------------\n",
456 SILC_CLIENT_KEY_EXPIRES);
458 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
459 SILC_CLIENT_DEF_PKCS_LEN,
461 file_private_key, identifier, NULL, NULL);
465 silc_free(identifier);
470 /* Loads public and private key from files. */
472 int silc_client_load_keys(SilcClient client)
477 SILC_LOG_DEBUG(("Loading public and private keys"));
479 pw = getpwuid(getuid());
483 memset(filename, 0, sizeof(filename));
484 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
485 pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
487 if (silc_pkcs_load_private_key(filename, &client->private_key,
488 SILC_PKCS_FILE_BIN) == FALSE)
489 if (silc_pkcs_load_private_key(filename, &client->private_key,
490 SILC_PKCS_FILE_PEM) == FALSE)
493 memset(filename, 0, sizeof(filename));
494 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
495 pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
497 if (silc_pkcs_load_public_key(filename, &client->public_key,
498 SILC_PKCS_FILE_PEM) == FALSE)
499 if (silc_pkcs_load_public_key(filename, &client->public_key,
500 SILC_PKCS_FILE_BIN) == FALSE)
506 /* Dumps the public key on screen. Used from the command line option. */
508 int silc_client_show_key(char *keyfile)
510 SilcPublicKey public_key;
511 SilcPublicKeyIdentifier ident;
518 if (silc_pkcs_load_public_key(keyfile, &public_key,
519 SILC_PKCS_FILE_PEM) == FALSE)
520 if (silc_pkcs_load_public_key(keyfile, &public_key,
521 SILC_PKCS_FILE_BIN) == FALSE) {
522 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
526 ident = silc_pkcs_decode_identifier(public_key->identifier);
528 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
529 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
531 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
532 key_len = silc_pkcs_public_key_set(pkcs, public_key);
533 silc_pkcs_free(pkcs);
536 printf("Public key file : %s\n", keyfile);
537 printf("Algorithm : %s\n", public_key->name);
539 printf("Key length (bits) : %d\n", key_len);
541 printf("Real name : %s\n", ident->realname);
543 printf("Username : %s\n", ident->username);
545 printf("Hostname : %s\n", ident->host);
547 printf("Email : %s\n", ident->email);
549 printf("Organization : %s\n", ident->org);
551 printf("Country : %s\n", ident->country);
552 printf("Fingerprint (SHA1) : %s\n", fingerprint);
556 silc_free(fingerprint);
558 silc_pkcs_public_key_free(public_key);
559 silc_pkcs_free_identifier(ident);