Merged silc_1_0_branch to trunk.
[silc.git] / apps / irssi / src / silc / core / clientutil.c
1 /*
2
3   client.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
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.
12   
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.
17
18 */
19 /* $Id$ */
20
21 #include "module.h"
22
23 #include "net-nonblock.h"
24 #include "net-sendbuffer.h"
25 #include "signals.h"
26 #include "servers.h"
27 #include "commands.h"
28 #include "levels.h"
29 #include "modules.h"
30 #include "rawlog.h"
31 #include "misc.h"
32 #include "settings.h"
33
34 #include "channels-setup.h"
35
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"
41
42 #include "fe-common/core/printtext.h"
43 #include "fe-common/core/keyboard.h"
44
45 #include "core.h"
46
47 /* Lists supported ciphers */
48
49 void silc_client_list_ciphers()
50 {
51   char *ciphers = silc_cipher_get_supported();
52   fprintf(stdout, "%s\n", ciphers);
53   silc_free(ciphers);
54 }
55
56 /* Lists supported hash functions */
57
58 void silc_client_list_hash_funcs()
59 {
60   char *hash = silc_hash_get_supported();
61   fprintf(stdout, "%s\n", hash);
62   silc_free(hash);
63 }
64
65 /* Lists supported hash functions */
66
67 void silc_client_list_hmacs()
68 {
69   char *hash = silc_hmac_get_supported();
70   fprintf(stdout, "%s\n", hash);
71   silc_free(hash);
72 }
73
74 /* Lists supported PKCS algorithms */
75
76 void silc_client_list_pkcs()
77 {
78   char *pkcs = silc_pkcs_get_supported();
79   fprintf(stdout, "%s\n", pkcs);
80   silc_free(pkcs);
81 }
82
83 /* This checks stats for various SILC files and directories. First it 
84    checks if ~/.silc directory exist and is owned by the correct user. If 
85    it doesn't exist, it will create the directory. After that it checks if
86    user's Public and Private key files exists. If they doesn't exist they 
87    will be created after return. */
88
89 int silc_client_check_silc_dir()
90 {
91   char filename[256], file_public_key[256], file_private_key[256];
92   char servfilename[256], clientfilename[256], friendsfilename[256];
93   struct stat st;
94   struct passwd *pw;
95
96   SILC_LOG_DEBUG(("Checking ~./silc directory"));
97
98   memset(filename, 0, sizeof(filename));
99   memset(file_public_key, 0, sizeof(file_public_key));
100   memset(file_private_key, 0, sizeof(file_private_key));
101
102   pw = getpwuid(getuid());
103   if (!pw) {
104     fprintf(stderr, "silc: %s\n", strerror(errno));
105     return FALSE;
106   }
107
108   /* We'll take home path from /etc/passwd file to be sure. */
109   snprintf(filename, sizeof(filename) - 1, "%s/", get_irssi_dir());
110   snprintf(servfilename, sizeof(servfilename) - 1, "%s/serverkeys", 
111            get_irssi_dir());
112   snprintf(clientfilename, sizeof(clientfilename) - 1, "%s/clientkeys", 
113            get_irssi_dir());
114   snprintf(friendsfilename, sizeof(friendsfilename) - 1, "%s/friends", 
115            get_irssi_dir());
116
117   /*
118    * Check ~/.silc directory
119    */
120   if ((stat(filename, &st)) == -1) {
121     /* If dir doesn't exist */
122     if (errno == ENOENT) {
123       if (pw->pw_uid == geteuid()) {
124         if ((mkdir(filename, 0755)) == -1) {
125           fprintf(stderr, "Couldn't create `%s' directory\n", filename);
126           return FALSE;
127         }
128       } else {
129         fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
130                 filename);
131         return FALSE;
132       }
133     } else {
134       fprintf(stderr, "%s\n", strerror(errno));
135       return FALSE;
136     }
137   } else {
138     
139     /* Check the owner of the dir */
140     if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { 
141       fprintf(stderr, "You don't seem to own `%s' directory\n",
142               filename);
143       return FALSE;
144     }
145     
146 #if 0
147     /* Check the permissions of the dir */
148     if ((st.st_mode & 0777) != 0755) {
149       if ((chmod(filename, 0755)) == -1) {
150         fprintf(stderr, "Permissions for `%s' directory must be 0755\n", 
151                 filename);
152         return FALSE;
153       }
154     }
155 #endif
156   }
157
158   /*
159    * Check ~./silc/serverkeys directory
160    */
161   if ((stat(servfilename, &st)) == -1) {
162     /* If dir doesn't exist */
163     if (errno == ENOENT) {
164       if (pw->pw_uid == geteuid()) {
165         if ((mkdir(servfilename, 0755)) == -1) {
166           fprintf(stderr, "Couldn't create `%s' directory\n", servfilename);
167           return FALSE;
168         }
169       } else {
170         fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
171                 servfilename);
172         return FALSE;
173       }
174     } else {
175       fprintf(stderr, "%s\n", strerror(errno));
176       return FALSE;
177     }
178   }
179   
180   /*
181    * Check ~./silc/clientkeys directory
182    */
183   if ((stat(clientfilename, &st)) == -1) {
184     /* If dir doesn't exist */
185     if (errno == ENOENT) {
186       if (pw->pw_uid == geteuid()) {
187         if ((mkdir(clientfilename, 0755)) == -1) {
188           fprintf(stderr, "Couldn't create `%s' directory\n", clientfilename);
189           return FALSE;
190         }
191       } else {
192         fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
193                 clientfilename);
194         return FALSE;
195       }
196     } else {
197       fprintf(stderr, "%s\n", strerror(errno));
198       return FALSE;
199     }
200   }
201   
202   /*
203    * Check ~./silc/friends directory
204    */
205   if ((stat(friendsfilename, &st)) == -1) {
206     /* If dir doesn't exist */
207     if (errno == ENOENT) {
208       if (pw->pw_uid == geteuid()) {
209         if ((mkdir(friendsfilename, 0755)) == -1) {
210           fprintf(stderr, "Couldn't create `%s' directory\n", friendsfilename);
211           return FALSE;
212         }
213       } else {
214         fprintf(stderr, "Couldn't create `%s' directory due to a wrong uid!\n",
215                 friendsfilename);
216         return FALSE;
217       }
218     } else {
219       fprintf(stderr, "%s\n", strerror(errno));
220       return FALSE;
221     }
222   }
223   
224   /*
225    * Check Public and Private keys
226    */
227   snprintf(file_public_key, sizeof(file_public_key) - 1, "%s%s", 
228            filename, SILC_CLIENT_PUBLIC_KEY_NAME);
229   snprintf(file_private_key, sizeof(file_private_key) - 1, "%s%s", 
230            filename, SILC_CLIENT_PRIVATE_KEY_NAME);
231   
232   if ((stat(file_public_key, &st)) == -1) {
233     /* If file doesn't exist */
234     if (errno == ENOENT) {
235       fprintf(stdout, "Running SILC for the first time\n");
236       silc_create_key_pair(SILC_CLIENT_DEF_PKCS,
237                            SILC_CLIENT_DEF_PKCS_LEN,
238                            file_public_key, file_private_key, NULL,
239                            NULL, NULL, NULL, NULL, FALSE);
240       printf("Press <Enter> to continue...\n");
241       getchar();
242     } else {
243       fprintf(stderr, "%s\n", strerror(errno));
244       return FALSE;
245     }
246   }
247   
248   /* Check the owner of the public key */
249   if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { 
250     fprintf(stderr, "You don't seem to own your public key!?\n");
251     return FALSE;
252   }
253   
254   if ((stat(file_private_key, &st)) == -1) {
255     /* If file doesn't exist */
256     if (errno == ENOENT) {
257       fprintf(stdout, "Your private key doesn't exist\n");
258       silc_create_key_pair(SILC_CLIENT_DEF_PKCS,
259                            SILC_CLIENT_DEF_PKCS_LEN,
260                            file_public_key, file_private_key, NULL,
261                            NULL, NULL, NULL, NULL, FALSE);
262       printf("Press <Enter> to continue...\n");
263       getchar();
264     } else {
265       fprintf(stderr, "%s\n", strerror(errno));
266       return FALSE;
267     }
268   }
269     
270   /* Check the owner of the private key */
271   if (st.st_uid != 0 && st.st_uid != pw->pw_uid) { 
272     fprintf(stderr, "You don't seem to own your private key!?\n");
273     return FALSE;
274   }
275     
276   /* Check the permissions for the private key */
277   if ((st.st_mode & 0777) != 0600) {
278     fprintf(stderr, "Wrong permissions in your private key file `%s'!\n"
279             "Trying to change them ... ", file_private_key);
280     if ((chmod(file_private_key, 0600)) == -1) {
281       fprintf(stderr,
282               "Failed to change permissions for private key file!\n" 
283               "Permissions for your private key file must be 0600.\n");
284       return FALSE;
285     }
286     fprintf(stderr, "Done.\n\n");
287   }
288
289   return TRUE;
290 }
291
292 /* Loads public and private key from files. */
293
294 int silc_client_load_keys(SilcClient client)
295 {
296   char pub[256], prv[256];
297   struct passwd *pw;
298   bool ret;
299
300   SILC_LOG_DEBUG(("Loading public and private keys"));
301
302   pw = getpwuid(getuid());
303   if (!pw)
304     return FALSE;
305
306   memset(prv, 0, sizeof(prv));
307   snprintf(prv, sizeof(prv) - 1, "%s/%s",
308            get_irssi_dir(), SILC_CLIENT_PRIVATE_KEY_NAME);
309
310   memset(pub, 0, sizeof(pub));
311   snprintf(pub, sizeof(pub) - 1, "%s/%s",
312            get_irssi_dir(), SILC_CLIENT_PUBLIC_KEY_NAME);
313   
314   /* Try loading first with "" passphrase, for those that didn't set
315      passphrase for private key, and only if that fails let it prompt
316      for passphrase. */
317   ret = silc_load_key_pair(pub, prv, "", &client->pkcs, &client->public_key,
318                            &client->private_key);
319   if (!ret)
320     ret = silc_load_key_pair(pub, prv, NULL, &client->pkcs,
321                              &client->public_key, &client->private_key);
322   return ret;
323 }