comparison libpurple/protocols/silc/pk.c @ 17568:980a104267da

Patch from Pekka Riikonen to update the SILC protocol plugin to work with SILC Toolkit 1.1 I added the fallback to SILC Toolkit 1.0 support (silc10 protocol directory) and configure.ac adjustments, any problems with this are 100% my fault.
author Stu Tomlinson <stu@nosnilmot.com>
date Sat, 09 Jun 2007 17:31:28 +0000
parents a5176db228b7
children 285bb637a2b7 6b02dba5bf41
comparison
equal deleted inserted replaced
17567:ba1b50f114f6 17568:980a104267da
2 2
3 silcpurple_pk.c 3 silcpurple_pk.c
4 4
5 Author: Pekka Riikonen <priikone@silcnet.org> 5 Author: Pekka Riikonen <priikone@silcnet.org>
6 6
7 Copyright (C) 2004 Pekka Riikonen 7 Copyright (C) 2004 - 2007 Pekka Riikonen
8 8
9 This program is free software; you can redistribute it and/or modify 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 10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License. 11 the Free Software Foundation; version 2 of the License.
12 12
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details. 16 GNU General Public License for more details.
17 17
18 */ 18 */
19 19
20 #include "silcincludes.h" 20 #include "silc.h"
21 #include "silcclient.h" 21 #include "silcclient.h"
22 #include "silcpurple.h" 22 #include "silcpurple.h"
23 23
24 /************************* Public Key Verification ***************************/ 24 /************************* Public Key Verification ***************************/
25 25
29 char *filename; 29 char *filename;
30 char *entity; 30 char *entity;
31 char *entity_name; 31 char *entity_name;
32 char *fingerprint; 32 char *fingerprint;
33 char *babbleprint; 33 char *babbleprint;
34 unsigned char *pk; 34 SilcPublicKey public_key;
35 SilcUInt32 pk_len;
36 SilcSKEPKType pk_type;
37 SilcVerifyPublicKey completion; 35 SilcVerifyPublicKey completion;
38 void *context; 36 void *context;
39 gboolean changed; 37 gboolean changed;
40 } *PublicKeyVerify; 38 } *PublicKeyVerify;
41 39
42 static void silcpurple_verify_ask(const char *entity, 40 static void silcpurple_verify_ask(const char *entity,
43 const char *fingerprint, 41 const char *fingerprint,
44 const char *babbleprint, 42 const char *babbleprint,
45 PublicKeyVerify verify); 43 PublicKeyVerify verify);
46 44
47 static void silcpurple_verify_cb(PublicKeyVerify verify, gint id) 45 static void silcpurple_verify_cb(PublicKeyVerify verify, gint id)
48 { 46 {
49 if (id != 2) { 47 if (id != 2) {
50 if (verify->completion) 48 if (verify->completion)
52 } else { 50 } else {
53 if (verify->completion) 51 if (verify->completion)
54 verify->completion(TRUE, verify->context); 52 verify->completion(TRUE, verify->context);
55 53
56 /* Save the key for future checking */ 54 /* Save the key for future checking */
57 silc_pkcs_save_public_key_data(verify->filename, verify->pk, 55 silc_pkcs_save_public_key(verify->filename, verify->public_key,
58 verify->pk_len, SILC_PKCS_FILE_PEM); 56 SILC_PKCS_FILE_BASE64);
59 } 57 }
60 58
61 silc_free(verify->filename); 59 silc_free(verify->filename);
62 silc_free(verify->entity); 60 silc_free(verify->entity);
63 silc_free(verify->entity_name); 61 silc_free(verify->entity_name);
64 silc_free(verify->fingerprint); 62 silc_free(verify->fingerprint);
65 silc_free(verify->babbleprint); 63 silc_free(verify->babbleprint);
66 silc_free(verify->pk); 64 silc_pkcs_public_key_free(verify->public_key);
67 silc_free(verify); 65 silc_free(verify);
68 } 66 }
69 67
70 static void silcpurple_verify_details_cb(PublicKeyVerify verify) 68 static void silcpurple_verify_details_cb(PublicKeyVerify verify)
71 { 69 {
72 /* What a hack. We have to display the accept dialog _again_ 70 /* What a hack. We have to display the accept dialog _again_
73 because Purple closes the dialog after you press the button. Purple 71 because Purple closes the dialog after you press the button. Purple
74 should have option for the dialogs whether the buttons close them 72 should have option for the dialogs whether the buttons close them
75 or not. */ 73 or not. */
76 silcpurple_verify_ask(verify->entity, verify->fingerprint, 74 silcpurple_verify_ask(verify->entity, verify->fingerprint,
77 verify->babbleprint, verify); 75 verify->babbleprint, verify);
78 } 76 }
79 77
80 static void silcpurple_verify_details(PublicKeyVerify verify, gint id) 78 static void silcpurple_verify_details(PublicKeyVerify verify, gint id)
81 { 79 {
82 SilcPublicKey public_key;
83 PurpleConnection *gc = verify->client->application; 80 PurpleConnection *gc = verify->client->application;
84 SilcPurple sg = gc->proto_data; 81 SilcPurple sg = gc->proto_data;
85 82
86 silc_pkcs_public_key_decode(verify->pk, verify->pk_len, 83 silcpurple_show_public_key(sg, verify->entity_name, verify->public_key,
87 &public_key); 84 G_CALLBACK(silcpurple_verify_details_cb),
88 silcpurple_show_public_key(sg, verify->entity_name, public_key, 85 verify);
89 G_CALLBACK(silcpurple_verify_details_cb),
90 verify);
91 silc_pkcs_public_key_free(public_key);
92 } 86 }
93 87
94 static void silcpurple_verify_ask(const char *entity, 88 static void silcpurple_verify_ask(const char *entity,
95 const char *fingerprint, 89 const char *fingerprint,
96 const char *babbleprint, 90 const char *babbleprint,
97 PublicKeyVerify verify) 91 PublicKeyVerify verify)
98 { 92 {
99 PurpleConnection *gc = verify->client->application; 93 PurpleConnection *gc = verify->client->application;
100 char tmp[256], tmp2[256]; 94 char tmp[256], tmp2[256];
101 95
102 if (verify->changed) { 96 if (verify->changed) {
112 g_snprintf(tmp2, sizeof(tmp2), 106 g_snprintf(tmp2, sizeof(tmp2),
113 _("Fingerprint and babbleprint for the %s key are:\n\n" 107 _("Fingerprint and babbleprint for the %s key are:\n\n"
114 "%s\n%s\n"), entity, fingerprint, babbleprint); 108 "%s\n%s\n"), entity, fingerprint, babbleprint);
115 109
116 purple_request_action(gc, _("Verify Public Key"), tmp, tmp2, 110 purple_request_action(gc, _("Verify Public Key"), tmp, tmp2,
117 PURPLE_DEFAULT_ACTION_NONE, 111 PURPLE_DEFAULT_ACTION_NONE,
118 purple_connection_get_account(gc), entity, NULL, verify, 3, 112 purple_connection_get_account(gc), entity, NULL, verify, 3,
119 _("Yes"), G_CALLBACK(silcpurple_verify_cb), 113 _("Yes"), G_CALLBACK(silcpurple_verify_cb),
120 _("No"), G_CALLBACK(silcpurple_verify_cb), 114 _("No"), G_CALLBACK(silcpurple_verify_cb),
121 _("_View..."), G_CALLBACK(silcpurple_verify_details)); 115 _("_View..."), G_CALLBACK(silcpurple_verify_details));
122 } 116 }
123 117
124 void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn, 118 void silcpurple_verify_public_key(SilcClient client, SilcClientConnection conn,
125 const char *name, SilcSocketType conn_type, 119 const char *name, SilcConnectionType conn_type,
126 unsigned char *pk, SilcUInt32 pk_len, 120 SilcPublicKey public_key,
127 SilcSKEPKType pk_type, 121 SilcVerifyPublicKey completion, void *context)
128 SilcVerifyPublicKey completion, void *context)
129 { 122 {
130 PurpleConnection *gc = client->application; 123 PurpleConnection *gc = client->application;
131 int i; 124 int i;
132 char file[256], filename[256], filename2[256], *ipf, *hostf = NULL; 125 char file[256], filename[256], filename2[256], *ipf, *hostf = NULL;
133 char *fingerprint, *babbleprint; 126 char *fingerprint, *babbleprint;
134 struct passwd *pw; 127 struct passwd *pw;
135 struct stat st; 128 struct stat st;
136 char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER || 129 char *entity = ((conn_type == SILC_CONN_SERVER ||
137 conn_type == SILC_SOCKET_TYPE_ROUTER) ? 130 conn_type == SILC_CONN_ROUTER) ?
138 "server" : "client"); 131 "server" : "client");
139 PublicKeyVerify verify; 132 PublicKeyVerify verify;
140 133 const char *ip, *hostname;
141 if (pk_type != SILC_SKE_PK_TYPE_SILC) { 134 SilcUInt16 port;
135 unsigned char *pk;
136 SilcUInt32 pk_len;
137
138 if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) {
142 purple_notify_error(gc, _("Verify Public Key"), 139 purple_notify_error(gc, _("Verify Public Key"),
143 _("Unsupported public key type"), NULL); 140 _("Unsupported public key type"), NULL);
144 if (completion) 141 if (completion)
145 completion(FALSE, context); 142 completion(FALSE, context);
146 return; 143 return;
147 } 144 }
148 145
155 152
156 memset(filename, 0, sizeof(filename)); 153 memset(filename, 0, sizeof(filename));
157 memset(filename2, 0, sizeof(filename2)); 154 memset(filename2, 0, sizeof(filename2));
158 memset(file, 0, sizeof(file)); 155 memset(file, 0, sizeof(file));
159 156
160 if (conn_type == SILC_SOCKET_TYPE_SERVER || 157 silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream),
161 conn_type == SILC_SOCKET_TYPE_ROUTER) { 158 NULL, &hostname, &ip, &port);
159
160 pk = silc_pkcs_public_key_encode(public_key, &pk_len);
161
162 if (conn_type == SILC_CONN_SERVER ||
163 conn_type == SILC_CONN_ROUTER) {
162 if (!name) { 164 if (!name) {
163 g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, 165 g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
164 conn->sock->ip, conn->sock->port); 166 ip, port);
165 g_snprintf(filename, sizeof(filename) - 1, 167 g_snprintf(filename, sizeof(filename) - 1,
166 "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", 168 "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
167 silcpurple_silcdir(), entity, file); 169 silcpurple_silcdir(), entity, file);
168 170
169 g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, 171 g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
170 conn->sock->hostname, conn->sock->port); 172 hostname, port);
171 g_snprintf(filename2, sizeof(filename2) - 1, 173 g_snprintf(filename2, sizeof(filename2) - 1,
172 "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", 174 "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
173 silcpurple_silcdir(), entity, file); 175 silcpurple_silcdir(), entity, file);
174 176
175 ipf = filename; 177 ipf = filename;
176 hostf = filename2; 178 hostf = filename2;
177 } else { 179 } else {
178 g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, 180 g_snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity,
179 name, conn->sock->port); 181 name, port);
180 g_snprintf(filename, sizeof(filename) - 1, 182 g_snprintf(filename, sizeof(filename) - 1,
181 "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s", 183 "%s" G_DIR_SEPARATOR_S "%skeys" G_DIR_SEPARATOR_S "%s",
182 silcpurple_silcdir(), entity, file); 184 silcpurple_silcdir(), entity, file);
183 185
184 ipf = filename; 186 ipf = filename;
204 return; 206 return;
205 verify->client = client; 207 verify->client = client;
206 verify->conn = conn; 208 verify->conn = conn;
207 verify->filename = strdup(ipf); 209 verify->filename = strdup(ipf);
208 verify->entity = strdup(entity); 210 verify->entity = strdup(entity);
209 verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ? 211 verify->entity_name = (conn_type != SILC_CONN_CLIENT ?
210 (name ? strdup(name) : strdup(conn->sock->hostname)) 212 (name ? strdup(name) : strdup(hostname))
211 : NULL); 213 : NULL);
212 verify->pk = silc_memdup(pk, pk_len); 214 verify->public_key = silc_pkcs_public_key_copy(public_key);
213 verify->pk_len = pk_len;
214 verify->pk_type = pk_type;
215 verify->completion = completion; 215 verify->completion = completion;
216 verify->context = context; 216 verify->context = context;
217 fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); 217 fingerprint = verify->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
218 babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); 218 babbleprint = verify->babbleprint = silc_hash_babbleprint(NULL, pk, pk_len);
219 219
220 /* Check whether this key already exists */ 220 /* Check whether this key already exists */
221 if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) { 221 if (g_stat(ipf, &st) < 0 && (!hostf || g_stat(hostf, &st) < 0)) {
222 /* Key does not exist, ask user to verify the key and save it */ 222 /* Key does not exist, ask user to verify the key and save it */
223 silcpurple_verify_ask(name ? name : entity, 223 silcpurple_verify_ask(name ? name : entity,
224 fingerprint, babbleprint, verify); 224 fingerprint, babbleprint, verify);
225 return; 225 return;
226 } else { 226 } else {
227 /* The key already exists, verify it. */ 227 /* The key already exists, verify it. */
228 SilcPublicKey public_key; 228 SilcPublicKey public_key;
229 unsigned char *encpk; 229 unsigned char *encpk;
230 SilcUInt32 encpk_len; 230 SilcUInt32 encpk_len;
231 231
232 /* Load the key file, try for both IP filename and hostname filename */ 232 /* Load the key file, try for both IP filename and hostname filename */
233 if (!silc_pkcs_load_public_key(ipf, &public_key, 233 if (!silc_pkcs_load_public_key(ipf, &public_key) &&
234 SILC_PKCS_FILE_PEM) && 234 (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key)))) {
235 !silc_pkcs_load_public_key(ipf, &public_key,
236 SILC_PKCS_FILE_BIN) &&
237 (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key,
238 SILC_PKCS_FILE_PEM) &&
239 !silc_pkcs_load_public_key(hostf, &public_key,
240 SILC_PKCS_FILE_BIN)))) {
241 silcpurple_verify_ask(name ? name : entity, 235 silcpurple_verify_ask(name ? name : entity,
242 fingerprint, babbleprint, verify); 236 fingerprint, babbleprint, verify);
243 return; 237 return;
244 } 238 }
245 239
264 if (completion) 258 if (completion)
265 completion(TRUE, context); 259 completion(TRUE, context);
266 silc_free(verify->filename); 260 silc_free(verify->filename);
267 silc_free(verify->entity); 261 silc_free(verify->entity);
268 silc_free(verify->entity_name); 262 silc_free(verify->entity_name);
269 silc_free(verify->pk);
270 silc_free(verify->fingerprint); 263 silc_free(verify->fingerprint);
271 silc_free(verify->babbleprint); 264 silc_free(verify->babbleprint);
265 silc_pkcs_public_key_free(verify->public_key);
272 silc_free(verify); 266 silc_free(verify);
273 } 267 }
274 } 268 }