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 (builtin) ciphers */
48 void silc_client_list_ciphers()
50 char *ciphers = silc_cipher_get_supported();
51 fprintf(stdout, "%s\n", ciphers);
55 /* Lists supported (builtin) 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 PKCS algorithms */
66 void silc_client_list_pkcs()
68 char *pkcs = silc_pkcs_get_supported();
69 fprintf(stdout, "%s\n", pkcs);
73 /* Displays input prompt on command line and takes input data from user */
75 char *silc_client_get_input(const char *prompt)
80 fd = open("/dev/tty", O_RDONLY);
82 fprintf(stderr, "silc: %s\n", strerror(errno));
86 memset(input, 0, sizeof(input));
91 if ((read(fd, input, sizeof(input))) < 0) {
92 fprintf(stderr, "silc: %s\n", strerror(errno));
96 if (strlen(input) <= 1)
99 if (strchr(input, '\n'))
100 *strchr(input, '\n') = '\0';
102 return strdup(input);
105 /* Returns identifier string for public key generation. */
107 char *silc_client_create_identifier()
109 char *username = NULL, *realname = NULL;
110 char hostname[256], email[256];
113 realname = silc_get_real_name();
116 memset(hostname, 0, sizeof(hostname));
117 gethostname(hostname, sizeof(hostname));
119 /* Get username (mandatory) */
120 username = silc_get_username();
124 /* Create default email address, whether it is right or not */
125 snprintf(email, sizeof(email), "%s@%s", username, hostname);
127 return silc_pkcs_encode_identifier(username, hostname, realname, email,
131 /* Creates new public key and private key pair. This is used only
132 when user wants to create new key pair from command line. */
134 int silc_client_create_key_pair(char *pkcs_name, int bits,
135 char *public_key, char *private_key,
137 SilcPublicKey *ret_pub_key,
138 SilcPrivateKey *ret_prv_key)
141 SilcPublicKey pub_key;
142 SilcPrivateKey prv_key;
147 char *pkfile = NULL, *prvfile = NULL;
149 if (!pkcs_name || !public_key || !private_key)
151 New pair of keys will be created. Please, answer to following questions.\n\
157 silc_client_get_input("PKCS name (l to list names) [rsa]: ");
159 pkcs_name = strdup("rsa");
161 if (*pkcs_name == 'l' || *pkcs_name == 'L') {
162 silc_client_list_pkcs();
163 silc_free(pkcs_name);
168 if (!silc_pkcs_is_supported(pkcs_name)) {
169 fprintf(stderr, "Unknown PKCS `%s'", pkcs_name);
176 silc_client_get_input("Key length in bits [1024]: ");
184 char *def = silc_client_create_identifier();
186 memset(line, 0, sizeof(line));
188 snprintf(line, sizeof(line), "Identifier [%s]: ", def);
190 snprintf(line, sizeof(line),
191 "Identifier (eg. UN=jon, HN=jon.dummy.com, "
192 "RN=Jon Johnson, E=jon@dummy.com): ");
194 while (!identifier) {
195 identifier = silc_client_get_input(line);
196 if (!identifier && def)
197 identifier = strdup(def);
204 rng = silc_rng_alloc();
206 silc_rng_global_init(rng);
209 memset(line, 0, sizeof(line));
210 snprintf(line, sizeof(line), "Public key filename [%s] ",
211 SILC_CLIENT_PUBLIC_KEY_NAME);
212 pkfile = silc_client_get_input(line);
214 pkfile = SILC_CLIENT_PUBLIC_KEY_NAME;
220 memset(line, 0, sizeof(line));
221 snprintf(line, sizeof(line), "Public key filename [%s] ",
222 SILC_CLIENT_PRIVATE_KEY_NAME);
223 prvfile = silc_client_get_input(line);
225 prvfile = SILC_CLIENT_PRIVATE_KEY_NAME;
227 prvfile = private_key;
231 silc_pkcs_alloc(pkcs_name, &pkcs);
232 pkcs->pkcs->init(pkcs->context, bits, rng);
234 /* Save public key into file */
235 key = silc_pkcs_get_public_key(pkcs, &key_len);
236 pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
238 silc_pkcs_save_public_key(pkfile, pub_key, SILC_PKCS_FILE_PEM);
240 *ret_pub_key = pub_key;
242 memset(key, 0, sizeof(key_len));
245 /* Save private key into file */
246 key = silc_pkcs_get_private_key(pkcs, &key_len);
247 prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
249 silc_pkcs_save_private_key(prvfile, prv_key, NULL, SILC_PKCS_FILE_BIN);
251 *ret_prv_key = prv_key;
253 printf("Public key has been saved into `%s'.\n", pkfile);
254 printf("Private key has been saved into `%s'.\n", prvfile);
255 printf("Press <Enter> to continue...\n");
258 memset(key, 0, sizeof(key_len));
262 silc_pkcs_free(pkcs);
267 /* This checks stats for various SILC files and directories. First it
268 checks if ~/.silc directory exist and is owned by the correct user. If
269 it doesn't exist, it will create the directory. After that it checks if
270 user's Public and Private key files exists and that they aren't expired.
271 If they doesn't exist or they are expired, they will be (re)created
274 int silc_client_check_silc_dir()
276 char filename[256], file_public_key[256], file_private_key[256];
277 char servfilename[256], clientfilename[256];
281 int firstime = FALSE;
282 time_t curtime, modtime;
284 SILC_LOG_DEBUG(("Checking ~./silc directory"));
286 memset(filename, 0, sizeof(filename));
287 memset(file_public_key, 0, sizeof(file_public_key));
288 memset(file_private_key, 0, sizeof(file_private_key));
290 pw = getpwuid(getuid());
292 fprintf(stderr, "silc: %s\n", strerror(errno));
296 identifier = silc_client_create_identifier();
298 /* We'll take home path from /etc/passwd file to be sure. */
299 snprintf(filename, sizeof(filename) - 1, "%s/.silc/", pw->pw_dir);
300 snprintf(servfilename, sizeof(servfilename) - 1, "%s/.silc/serverkeys",
302 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/.silc/clientkeys",
306 * Check ~/.silc directory
308 if ((stat(filename, &st)) == -1) {
309 /* If dir doesn't exist */
310 if (errno == ENOENT) {
311 if (pw->pw_uid == geteuid()) {
312 if ((mkdir(filename, 0755)) == -1) {
313 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
317 /* Directory was created. First time running SILC */
320 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
325 fprintf(stderr, "%s\n", strerror(errno));
330 /* Check the owner of the dir */
331 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
332 fprintf(stderr, "You don't seem to own `%s' directory\n",
337 /* Check the permissions of the dir */
338 if ((st.st_mode & 0777) != 0755) {
339 if ((chmod(filename, 0755)) == -1) {
340 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
348 * Check ~./silc/serverkeys directory
350 if ((stat(servfilename, &st)) == -1) {
351 /* If dir doesn't exist */
352 if (errno == ENOENT) {
353 if (pw->pw_uid == geteuid()) {
354 if ((mkdir(servfilename, 0755)) == -1) {
355 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
359 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
364 fprintf(stderr, "%s\n", strerror(errno));
370 * Check ~./silc/clientkeys directory
372 if ((stat(clientfilename, &st)) == -1) {
373 /* If dir doesn't exist */
374 if (errno == ENOENT) {
375 if (pw->pw_uid == geteuid()) {
376 if ((mkdir(clientfilename, 0755)) == -1) {
377 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
381 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
386 fprintf(stderr, "%s\n", strerror(errno));
392 * Check Public and Private keys
394 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
395 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
396 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
397 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
399 /* If running SILC first time */
401 fprintf(stdout, "Running SILC for the first time\n");
402 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
403 SILC_CLIENT_DEF_PKCS_LEN,
404 file_public_key, file_private_key,
405 identifier, NULL, NULL);
409 if ((stat(file_public_key, &st)) == -1) {
410 /* If file doesn't exist */
411 if (errno == ENOENT) {
412 fprintf(stdout, "Your public key doesn't exist\n");
413 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
414 SILC_CLIENT_DEF_PKCS_LEN,
416 file_private_key, identifier, NULL, NULL);
418 fprintf(stderr, "%s\n", strerror(errno));
423 if ((stat(file_private_key, &st)) == -1) {
424 /* If file doesn't exist */
425 if (errno == ENOENT) {
426 fprintf(stdout, "Your private key doesn't exist\n");
427 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
428 SILC_CLIENT_DEF_PKCS_LEN,
430 file_private_key, identifier, NULL, NULL);
432 fprintf(stderr, "%s\n", strerror(errno));
437 /* Check the owner of the public key */
438 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
439 fprintf(stderr, "You don't seem to own your public key!?\n");
443 /* Check the owner of the private key */
444 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
445 fprintf(stderr, "You don't seem to own your private key!?\n");
449 /* Check the permissions for the private key */
450 if ((st.st_mode & 0777) != 0600) {
451 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
452 "Trying to change them ... ", file_private_key);
453 if ((chmod(file_private_key, 0600)) == -1) {
455 "Failed to change permissions for private key file!\n"
456 "Permissions for your private key file must be 0600.\n");
459 fprintf(stderr, "Done.\n\n");
462 /* See if the key has expired. */
463 modtime = st.st_mtime; /* last modified */
464 curtime = time(0) - modtime;
466 /* 86400 is seconds in a day. */
467 if (curtime >= (86400 * SILC_CLIENT_KEY_EXPIRES)) {
469 "--------------------------------------------------\n"
470 "Your private key has expired and needs to be\n"
471 "recreated. This will be done automatically now.\n"
472 "Your new key will expire in %d days from today.\n"
473 "--------------------------------------------------\n",
474 SILC_CLIENT_KEY_EXPIRES);
476 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
477 SILC_CLIENT_DEF_PKCS_LEN,
479 file_private_key, identifier, NULL, NULL);
483 silc_free(identifier);
488 /* Loads public and private key from files. */
490 int silc_client_load_keys(SilcClient client)
495 SILC_LOG_DEBUG(("Loading public and private keys"));
497 pw = getpwuid(getuid());
501 memset(filename, 0, sizeof(filename));
502 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
503 pw->pw_dir, SILC_CLIENT_PRIVATE_KEY_NAME);
505 if (silc_pkcs_load_private_key(filename, &client->private_key,
506 SILC_PKCS_FILE_BIN) == FALSE)
507 if (silc_pkcs_load_private_key(filename, &client->private_key,
508 SILC_PKCS_FILE_PEM) == FALSE)
511 memset(filename, 0, sizeof(filename));
512 snprintf(filename, sizeof(filename) - 1, "%s/.silc/%s",
513 pw->pw_dir, SILC_CLIENT_PUBLIC_KEY_NAME);
515 if (silc_pkcs_load_public_key(filename, &client->public_key,
516 SILC_PKCS_FILE_PEM) == FALSE)
517 if (silc_pkcs_load_public_key(filename, &client->public_key,
518 SILC_PKCS_FILE_BIN) == FALSE)
524 /* Dumps the public key on screen. Used from the command line option. */
526 int silc_client_show_key(char *keyfile)
528 SilcPublicKey public_key;
529 SilcPublicKeyIdentifier ident;
536 if (silc_pkcs_load_public_key(keyfile, &public_key,
537 SILC_PKCS_FILE_PEM) == FALSE)
538 if (silc_pkcs_load_public_key(keyfile, &public_key,
539 SILC_PKCS_FILE_BIN) == FALSE) {
540 fprintf(stderr, "Could not load public key file `%s'\n", keyfile);
544 ident = silc_pkcs_decode_identifier(public_key->identifier);
546 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
547 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
549 if (silc_pkcs_alloc(public_key->name, &pkcs)) {
550 key_len = silc_pkcs_public_key_set(pkcs, public_key);
551 silc_pkcs_free(pkcs);
554 printf("Public key file : %s\n", keyfile);
555 printf("Algorithm : %s\n", public_key->name);
557 printf("Key length (bits) : %d\n", key_len);
559 printf("Real name : %s\n", ident->realname);
561 printf("Username : %s\n", ident->username);
563 printf("Hostname : %s\n", ident->host);
565 printf("Email : %s\n", ident->email);
567 printf("Organization : %s\n", ident->org);
569 printf("Country : %s\n", ident->country);
570 printf("Fingerprint (SHA1) : %s\n", fingerprint);
574 silc_free(fingerprint);
576 silc_pkcs_public_key_free(public_key);
577 silc_pkcs_free_identifier(ident);