5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2006 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"
44 #include "fe-common/silc/module-formats.h"
49 void silc_client_print_list(char *list)
54 items = g_strsplit(list, ",", -1);
56 while (items[i] != NULL)
57 printformat_module("fe-common/silc", NULL, NULL,
58 MSGLEVEL_CRAP, SILCTXT_CONFIG_LIST,
65 /* Lists supported ciphers */
67 void silc_client_list_ciphers()
69 char *ciphers = silc_cipher_get_supported();
71 printformat_module("fe-common/silc", NULL, NULL,
72 MSGLEVEL_CRAP, SILCTXT_CONFIG_ALGOS,
74 silc_client_print_list(ciphers);
76 fprintf(stdout, "%s\n", ciphers);
81 /* Lists supported hash functions */
83 void silc_client_list_hash_funcs()
85 char *hash = silc_hash_get_supported();
87 printformat_module("fe-common/silc", NULL, NULL,
88 MSGLEVEL_CRAP, SILCTXT_CONFIG_ALGOS,
90 silc_client_print_list(hash);
92 fprintf(stdout, "%s\n", hash);
97 /* Lists supported hash functions */
99 void silc_client_list_hmacs()
101 char *hash = silc_hmac_get_supported();
103 printformat_module("fe-common/silc", NULL, NULL,
104 MSGLEVEL_CRAP, SILCTXT_CONFIG_ALGOS,
106 silc_client_print_list(hash);
108 fprintf(stdout, "%s\n", hash);
113 /* Lists supported PKCS algorithms */
115 void silc_client_list_pkcs()
117 char *pkcs = silc_pkcs_get_supported();
119 printformat_module("fe-common/silc", NULL, NULL,
120 MSGLEVEL_CRAP, SILCTXT_CONFIG_ALGOS,
122 silc_client_print_list(pkcs);
124 fprintf(stdout, "%s\n", pkcs);
129 /* This checks stats for various SILC files and directories. First it
130 checks if ~/.silc directory exist and is owned by the correct user. If
131 it doesn't exist, it will create the directory. After that it checks if
132 user's Public and Private key files exists. If they doesn't exist they
133 will be created after return. */
135 int silc_client_check_silc_dir()
137 char filename[256], file_public_key[256], file_private_key[256];
138 char servfilename[256], clientfilename[256], friendsfilename[256];
142 SILC_LOG_DEBUG(("Checking ~./silc directory"));
144 memset(filename, 0, sizeof(filename));
145 memset(file_public_key, 0, sizeof(file_public_key));
146 memset(file_private_key, 0, sizeof(file_private_key));
148 pw = getpwuid(getuid());
150 fprintf(stderr, "silc: %s\n", strerror(errno));
154 /* We'll take home path from /etc/passwd file to be sure. */
155 snprintf(filename, sizeof(filename) - 1, "%s/", get_irssi_dir());
156 snprintf(servfilename, sizeof(servfilename) - 1, "%s/serverkeys",
158 snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/clientkeys",
160 snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s/friends",
164 * Check ~/.silc directory
166 if ((stat(filename, &st)) == -1) {
167 /* If dir doesn't exist */
168 if (errno == ENOENT) {
169 if (pw->pw_uid == geteuid()) {
170 if ((mkdir(filename, 0755)) == -1) {
171 fprintf(stderr, "Couldn't create `%s' directory\n", filename);
175 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
180 fprintf(stderr, "%s\n", strerror(errno));
185 /* Check the owner of the dir */
186 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
187 fprintf(stderr, "You don't seem to own `%s' directory\n",
193 /* Check the permissions of the dir */
194 if ((st.st_mode & 0777) != 0755) {
195 if ((chmod(filename, 0755)) == -1) {
196 fprintf(stderr, "Permissions for `%s' directory must be 0755\n",
205 * Check ~./silc/serverkeys directory
207 if ((stat(servfilename, &st)) == -1) {
208 /* If dir doesn't exist */
209 if (errno == ENOENT) {
210 if (pw->pw_uid == geteuid()) {
211 if ((mkdir(servfilename, 0755)) == -1) {
212 fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
216 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
221 fprintf(stderr, "%s\n", strerror(errno));
227 * Check ~./silc/clientkeys directory
229 if ((stat(clientfilename, &st)) == -1) {
230 /* If dir doesn't exist */
231 if (errno == ENOENT) {
232 if (pw->pw_uid == geteuid()) {
233 if ((mkdir(clientfilename, 0755)) == -1) {
234 fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
238 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
243 fprintf(stderr, "%s\n", strerror(errno));
249 * Check ~./silc/friends directory
251 if ((stat(friendsfilename, &st)) == -1) {
252 /* If dir doesn't exist */
253 if (errno == ENOENT) {
254 if (pw->pw_uid == geteuid()) {
255 if ((mkdir(friendsfilename, 0755)) == -1) {
256 fprintf(stderr, "Couldn't create `%s' directory\n", friendsfilename);
260 fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
265 fprintf(stderr, "%s\n", strerror(errno));
271 * Check Public and Private keys
273 snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s",
274 filename, SILC_CLIENT_PUBLIC_KEY_NAME);
275 snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s",
276 filename, SILC_CLIENT_PRIVATE_KEY_NAME);
278 if ((stat(file_public_key, &st)) == -1) {
279 /* If file doesn't exist */
280 if (errno == ENOENT) {
281 fprintf(stdout, "Running SILC for the first time\n");
282 silc_create_key_pair(SILC_CLIENT_DEF_PKCS,
283 SILC_CLIENT_DEF_PKCS_LEN,
284 file_public_key, file_private_key,
285 NULL, NULL, NULL, NULL, FALSE);
286 printf("Press <Enter> to continue...\n");
289 fprintf(stderr, "%s\n", strerror(errno));
294 /* Check the owner of the public key */
295 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
296 fprintf(stderr, "You don't seem to own your public key!?\n");
300 if ((stat(file_private_key, &st)) == -1) {
301 /* If file doesn't exist */
302 if (errno == ENOENT) {
303 fprintf(stdout, "Your private key doesn't exist\n");
304 silc_create_key_pair(SILC_CLIENT_DEF_PKCS,
305 SILC_CLIENT_DEF_PKCS_LEN,
306 file_public_key, file_private_key,
307 NULL, NULL, NULL, NULL, FALSE);
308 printf("Press <Enter> to continue...\n");
311 fprintf(stderr, "%s\n", strerror(errno));
316 /* Check the owner of the private key */
317 if (st.st_uid != 0 && st.st_uid != pw->pw_uid) {
318 fprintf(stderr, "You don't seem to own your private key!?\n");
322 /* Check the permissions for the private key */
323 if ((st.st_mode & 0777) != 0600) {
324 fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
325 "Trying to change them ... ", file_private_key);
326 if ((chmod(file_private_key, 0600)) == -1) {
328 "Failed to change permissions for private key file!\n"
329 "Permissions for your private key file must be 0600.\n");
332 fprintf(stderr, "Done.\n\n");
338 /* Loads public and private key from files. */
340 int silc_client_load_keys(SilcClient client)
342 char pub[256], prv[256];
346 SILC_LOG_DEBUG(("Loading public and private keys"));
348 pw = getpwuid(getuid());
352 memset(prv, 0, sizeof(prv));
353 snprintf(prv, sizeof(prv) - 1, "%s/%s",
354 get_irssi_dir(), SILC_CLIENT_PRIVATE_KEY_NAME);
356 memset(pub, 0, sizeof(pub));
357 snprintf(pub, sizeof(pub) - 1, "%s/%s",
358 get_irssi_dir(), SILC_CLIENT_PUBLIC_KEY_NAME);
360 /* Try loading first with "" passphrase, for those that didn't set
361 passphrase for private key, and only if that fails let it prompt
363 ret = silc_load_key_pair(pub, prv, "", &irssi_pubkey, &irssi_privkey);
365 ret = silc_load_key_pair(pub, prv, NULL, &irssi_pubkey, &irssi_privkey);
368 SILC_LOG_ERROR(("Could not load key pair"));
374 void create_key_passphrase(const char *answer, CREATE_KEY_REC *rec)
376 char priv_key_file[128], pub_key_file[128];
380 if ((rec->passphrase == NULL) && (answer) && (*answer != '\0')) {
381 rec->passphrase = g_strdup(answer);
382 keyboard_entry_redirect((SIGNAL_FUNC) create_key_passphrase,
383 format_get_text("fe-common/silc", NULL, NULL,
384 NULL, SILCTXT_CONFIG_PASS_ASK2),
385 ENTRY_REDIRECT_FLAG_HIDDEN, rec);
389 if ((answer) && (*answer != '\0') && (rec->passphrase != NULL)) {
390 if (strcmp(answer, rec->passphrase)) {
391 printformat_module("fe-common/silc", NULL, NULL,
392 MSGLEVEL_CRAP, SILCTXT_CONFIG_PASSMISMATCH);
394 g_free(rec->passphrase);
400 memset(priv_key_file, 0, sizeof(priv_key_file));
401 memset(pub_key_file, 0, sizeof(pub_key_file));
402 snprintf(priv_key_file, sizeof(priv_key_file) - 1, "%s/%s",
403 get_irssi_dir(), SILC_CLIENT_PRIVATE_KEY_NAME);
404 snprintf(pub_key_file, sizeof(pub_key_file) - 1, "%s/%s",
405 get_irssi_dir(), SILC_CLIENT_PUBLIC_KEY_NAME);
407 if (silc_create_key_pair(rec->pkcs, rec->bits, pub_key_file, priv_key_file,
408 NULL, (rec->passphrase == NULL ? "" : rec->passphrase),
409 NULL, NULL, FALSE) == TRUE)
410 printformat_module("fe-common/silc", NULL, NULL,
411 MSGLEVEL_CRAP, SILCTXT_CONFIG_CREATE);
413 printformat_module("fe-common/silc", NULL, NULL,
414 MSGLEVEL_CRAP, SILCTXT_CONFIG_CREATE_FAIL);
416 g_free(rec->passphrase);
421 void change_private_key_passphrase(const char *answer, CREATE_KEY_REC *rec)
425 if (rec->old == NULL) {
426 rec->old = g_strdup((answer == NULL ? "" : answer));
427 keyboard_entry_redirect((SIGNAL_FUNC) change_private_key_passphrase,
428 format_get_text("fe-common/silc", NULL, NULL,
429 NULL, SILCTXT_CONFIG_PASS_ASK2),
430 ENTRY_REDIRECT_FLAG_HIDDEN, rec);
434 if ((rec->passphrase == NULL) && (answer) && (*answer != '\0')) {
435 rec->passphrase = g_strdup(answer);
436 keyboard_entry_redirect((SIGNAL_FUNC) change_private_key_passphrase,
437 format_get_text("fe-common/silc", NULL, NULL,
438 NULL, SILCTXT_CONFIG_PASS_ASK3),
439 ENTRY_REDIRECT_FLAG_HIDDEN, rec);
443 if ((answer) && (*answer != '\0') && (rec->passphrase != NULL)) {
444 if (strcmp(answer, rec->passphrase)) {
445 printformat_module("fe-common/silc", NULL, NULL,
446 MSGLEVEL_CRAP, SILCTXT_CONFIG_PASSMISMATCH);
450 g_free(rec->passphrase);
456 if (silc_change_private_key_passphrase(rec->file, rec->old,
457 (rec->passphrase == NULL ?
458 "" : rec->passphrase)) == TRUE)
459 printformat_module("fe-common/silc", NULL, NULL,
460 MSGLEVEL_CRAP, SILCTXT_CONFIG_PASSCHANGE);
462 printformat_module("fe-common/silc", NULL, NULL,
463 MSGLEVEL_CRAP, SILCTXT_CONFIG_PASSCHANGE_FAIL);
466 g_free(rec->passphrase);