Mercurial > pidgin
comparison libpurple/protocols/silc/buddy.c @ 18080:bb2e5f6ff2b4
propagate from branch 'im.pidgin.pidgin' (head 5fdf4fa0a7dcefa78c9ec2e7c25b151f1e3acf18)
to branch 'im.pidgin.pidgin.2.1.0' (head 1d53de833ec35c1899f24b60e7d79db753917c15)
author | Stu Tomlinson <stu@nosnilmot.com> |
---|---|
date | Sun, 10 Jun 2007 01:46:31 +0000 |
parents | 980a104267da |
children | 9a96d8711303 |
comparison
equal
deleted
inserted
replaced
18079:c885a9ccd301 | 18080:bb2e5f6ff2b4 |
---|---|
2 | 2 |
3 silcpurple_buddy.c | 3 silcpurple_buddy.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 #include "wb.h" | 23 #include "wb.h" |
24 | 24 |
25 /***************************** Key Agreement *********************************/ | 25 /***************************** Key Agreement *********************************/ |
27 static void | 27 static void |
28 silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data); | 28 silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data); |
29 | 29 |
30 static void | 30 static void |
31 silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, | 31 silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, |
32 gboolean force_local); | 32 gboolean force_local); |
33 | 33 |
34 typedef struct { | 34 typedef struct { |
35 char *nick; | 35 char *nick; |
36 PurpleConnection *gc; | 36 PurpleConnection *gc; |
37 } *SilcPurpleResolve; | 37 } *SilcPurpleResolve; |
38 | 38 |
39 static void | 39 static void |
40 silcpurple_buddy_keyagr_resolved(SilcClient client, | 40 silcpurple_buddy_keyagr_resolved(SilcClient client, |
41 SilcClientConnection conn, | 41 SilcClientConnection conn, |
42 SilcClientEntry *clients, | 42 SilcStatus status, |
43 SilcUInt32 clients_count, | 43 SilcDList clients, |
44 void *context) | 44 void *context) |
45 { | 45 { |
46 PurpleConnection *gc = client->application; | 46 PurpleConnection *gc = client->application; |
47 SilcPurpleResolve r = context; | 47 SilcPurpleResolve r = context; |
48 char tmp[256]; | 48 char tmp[256]; |
49 | 49 |
60 silcpurple_buddy_keyagr_do(gc, r->nick, FALSE); | 60 silcpurple_buddy_keyagr_do(gc, r->nick, FALSE); |
61 silc_free(r->nick); | 61 silc_free(r->nick); |
62 silc_free(r); | 62 silc_free(r); |
63 } | 63 } |
64 | 64 |
65 typedef struct { | |
66 gboolean responder; | |
67 } *SilcPurpleKeyAgr; | |
68 | |
69 static void | 65 static void |
70 silcpurple_buddy_keyagr_cb(SilcClient client, | 66 silcpurple_buddy_keyagr_cb(SilcClient client, |
71 SilcClientConnection conn, | 67 SilcClientConnection conn, |
72 SilcClientEntry client_entry, | 68 SilcClientEntry client_entry, |
73 SilcKeyAgreementStatus status, | 69 SilcKeyAgreementStatus status, |
74 SilcSKEKeyMaterial *key, | 70 SilcSKEKeyMaterial key, |
75 void *context) | 71 void *context) |
76 { | 72 { |
77 PurpleConnection *gc = client->application; | 73 PurpleConnection *gc = client->application; |
78 SilcPurple sg = gc->proto_data; | 74 SilcPurple sg = gc->proto_data; |
79 SilcPurpleKeyAgr a = context; | |
80 | 75 |
81 if (!sg->conn) | 76 if (!sg->conn) |
82 return; | 77 return; |
83 | 78 |
84 switch (status) { | 79 switch (status) { |
88 char tmp[128]; | 83 char tmp[128]; |
89 | 84 |
90 /* Set the private key for this client */ | 85 /* Set the private key for this client */ |
91 silc_client_del_private_message_key(client, conn, client_entry); | 86 silc_client_del_private_message_key(client, conn, client_entry); |
92 silc_client_add_private_message_key_ske(client, conn, client_entry, | 87 silc_client_add_private_message_key_ske(client, conn, client_entry, |
93 NULL, NULL, key, a->responder); | 88 NULL, NULL, key); |
94 silc_ske_free_key_material(key); | 89 silc_ske_free_key_material(key); |
95 | 90 |
96 | 91 |
97 /* Open IM window */ | 92 /* Open IM window */ |
98 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, | 93 convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, |
99 client_entry->nickname, sg->account); | 94 client_entry->nickname, sg->account); |
100 if (convo) { | 95 if (convo) { |
101 /* we don't have windows in the core anymore...but we may want to | 96 /* we don't have windows in the core anymore...but we may want to |
102 * provide some method for asking the UI to show the window | 97 * provide some method for asking the UI to show the window |
103 purple_conv_window_show(purple_conversation_get_window(convo)); | 98 purple_conv_window_show(purple_conversation_get_window(convo)); |
104 */ | 99 */ |
105 } else { | 100 } else { |
106 convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account, | 101 convo = purple_conversation_new(PURPLE_CONV_TYPE_IM, sg->account, |
107 client_entry->nickname); | 102 client_entry->nickname); |
108 } | 103 } |
109 g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname); | 104 g_snprintf(tmp, sizeof(tmp), "%s [private key]", client_entry->nickname); |
110 purple_conversation_set_title(convo, tmp); | 105 purple_conversation_set_title(convo, tmp); |
111 } | 106 } |
112 break; | 107 break; |
113 | 108 |
114 case SILC_KEY_AGREEMENT_ERROR: | 109 case SILC_KEY_AGREEMENT_ERROR: |
115 purple_notify_error(gc, _("Key Agreement"), | 110 purple_notify_error(gc, _("Key Agreement"), |
116 _("Error occurred during key agreement"), NULL); | 111 _("Error occurred during key agreement"), NULL); |
117 break; | 112 break; |
118 | 113 |
119 case SILC_KEY_AGREEMENT_FAILURE: | 114 case SILC_KEY_AGREEMENT_FAILURE: |
120 purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL); | 115 purple_notify_error(gc, _("Key Agreement"), _("Key Agreement failed"), NULL); |
121 break; | 116 break; |
122 | 117 |
123 case SILC_KEY_AGREEMENT_TIMEOUT: | 118 case SILC_KEY_AGREEMENT_TIMEOUT: |
124 purple_notify_error(gc, _("Key Agreement"), | 119 purple_notify_error(gc, _("Key Agreement"), |
125 _("Timeout during key agreement"), NULL); | 120 _("Timeout during key agreement"), NULL); |
126 break; | 121 break; |
127 | 122 |
128 case SILC_KEY_AGREEMENT_ABORTED: | 123 case SILC_KEY_AGREEMENT_ABORTED: |
129 purple_notify_error(gc, _("Key Agreement"), | 124 purple_notify_error(gc, _("Key Agreement"), |
130 _("Key agreement was aborted"), NULL); | 125 _("Key agreement was aborted"), NULL); |
131 break; | 126 break; |
132 | 127 |
133 case SILC_KEY_AGREEMENT_ALREADY_STARTED: | 128 case SILC_KEY_AGREEMENT_ALREADY_STARTED: |
134 purple_notify_error(gc, _("Key Agreement"), | 129 purple_notify_error(gc, _("Key Agreement"), |
135 _("Key agreement is already started"), NULL); | 130 _("Key agreement is already started"), NULL); |
136 break; | 131 break; |
137 | 132 |
138 case SILC_KEY_AGREEMENT_SELF_DENIED: | 133 case SILC_KEY_AGREEMENT_SELF_DENIED: |
139 purple_notify_error(gc, _("Key Agreement"), | 134 purple_notify_error(gc, _("Key Agreement"), |
140 _("Key agreement cannot be started with yourself"), | 135 _("Key agreement cannot be started with yourself"), |
141 NULL); | 136 NULL); |
142 break; | 137 break; |
143 | 138 |
144 default: | 139 default: |
145 break; | 140 break; |
146 } | 141 } |
147 | |
148 silc_free(a); | |
149 } | 142 } |
150 | 143 |
151 static void | 144 static void |
152 silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, | 145 silcpurple_buddy_keyagr_do(PurpleConnection *gc, const char *name, |
153 gboolean force_local) | 146 gboolean force_local) |
154 { | 147 { |
155 SilcPurple sg = gc->proto_data; | 148 SilcPurple sg = gc->proto_data; |
156 SilcClientEntry *clients; | 149 SilcDList clients; |
157 SilcUInt32 clients_count; | 150 SilcClientEntry client_entry; |
151 SilcClientConnectionParams params; | |
158 char *local_ip = NULL, *remote_ip = NULL; | 152 char *local_ip = NULL, *remote_ip = NULL; |
159 gboolean local = TRUE; | 153 gboolean local = TRUE; |
160 char *nickname; | 154 SilcSocket sock; |
161 SilcPurpleKeyAgr a; | |
162 | 155 |
163 if (!sg->conn || !name) | 156 if (!sg->conn || !name) |
164 return; | 157 return; |
165 | 158 |
166 if (!silc_parse_userfqdn(name, &nickname, NULL)) | |
167 return; | |
168 | |
169 /* Find client entry */ | 159 /* Find client entry */ |
170 clients = silc_client_get_clients_local(sg->client, sg->conn, nickname, name, | 160 clients = silc_client_get_clients_local(sg->client, sg->conn, name, |
171 &clients_count); | 161 FALSE); |
172 if (!clients) { | 162 if (!clients) { |
173 /* Resolve unknown user */ | 163 /* Resolve unknown user */ |
174 SilcPurpleResolve r = silc_calloc(1, sizeof(*r)); | 164 SilcPurpleResolve r = silc_calloc(1, sizeof(*r)); |
175 if (!r) | 165 if (!r) |
176 return; | 166 return; |
177 r->nick = g_strdup(name); | 167 r->nick = g_strdup(name); |
178 r->gc = gc; | 168 r->gc = gc; |
179 silc_client_get_clients(sg->client, sg->conn, nickname, NULL, | 169 silc_client_get_clients(sg->client, sg->conn, name, NULL, |
180 silcpurple_buddy_keyagr_resolved, r); | 170 silcpurple_buddy_keyagr_resolved, r); |
181 silc_free(nickname); | 171 return; |
182 return; | 172 } |
183 } | 173 |
174 silc_socket_stream_get_info(silc_packet_stream_get_stream(sg->conn->stream), | |
175 &sock, NULL, NULL, NULL); | |
184 | 176 |
185 /* Resolve the local IP from the outgoing socket connection. We resolve | 177 /* Resolve the local IP from the outgoing socket connection. We resolve |
186 it to check whether we have a private range IP address or public IP | 178 it to check whether we have a private range IP address or public IP |
187 address. If we have public then we will assume that we are not behind | 179 address. If we have public then we will assume that we are not behind |
188 NAT and will provide automatically the point of connection to the | 180 NAT and will provide automatically the point of connection to the |
194 assume that we are chatting in LAN and will provide the point of | 186 assume that we are chatting in LAN and will provide the point of |
195 connection. | 187 connection. |
196 | 188 |
197 Naturally this algorithm does not always get things right. */ | 189 Naturally this algorithm does not always get things right. */ |
198 | 190 |
199 if (silc_net_check_local_by_sock(sg->conn->sock->sock, NULL, &local_ip)) { | 191 if (silc_net_check_local_by_sock(sock, NULL, &local_ip)) { |
200 /* Check if the IP is private */ | 192 /* Check if the IP is private */ |
201 if (!force_local && silcpurple_ip_is_private(local_ip)) { | 193 if (!force_local && silcpurple_ip_is_private(local_ip)) { |
202 local = FALSE; | 194 local = FALSE; |
203 | 195 |
204 /* Local IP is private, resolve the remote server IP to see whether | 196 /* Local IP is private, resolve the remote server IP to see whether |
205 we are talking to Internet or just on LAN. */ | 197 we are talking to Internet or just on LAN. */ |
206 if (silc_net_check_host_by_sock(sg->conn->sock->sock, NULL, | 198 if (silc_net_check_host_by_sock(sock, NULL, |
207 &remote_ip)) | 199 &remote_ip)) |
208 if (silcpurple_ip_is_private(remote_ip)) | 200 if (silcpurple_ip_is_private(remote_ip)) |
209 /* We assume we are in LAN. Let's provide | 201 /* We assume we are in LAN. Let's provide |
210 the connection point. */ | 202 the connection point. */ |
211 local = TRUE; | 203 local = TRUE; |
216 local = TRUE; | 208 local = TRUE; |
217 | 209 |
218 if (local && !local_ip) | 210 if (local && !local_ip) |
219 local_ip = silc_net_localip(); | 211 local_ip = silc_net_localip(); |
220 | 212 |
221 a = silc_calloc(1, sizeof(*a)); | 213 silc_dlist_start(clients); |
222 if (!a) | 214 client_entry = silc_dlist_get(clients); |
223 return; | 215 |
224 a->responder = local; | 216 memset(¶ms, 0, sizeof(params)); |
217 params.timeout_secs = 60; | |
218 if (local) | |
219 /* Provide connection point */ | |
220 params.local_ip = local_ip; | |
225 | 221 |
226 /* Send the key agreement request */ | 222 /* Send the key agreement request */ |
227 silc_client_send_key_agreement(sg->client, sg->conn, clients[0], | 223 silc_client_send_key_agreement(sg->client, sg->conn, client_entry, |
228 local ? local_ip : NULL, NULL, 0, 60, | 224 ¶ms, sg->public_key, |
229 silcpurple_buddy_keyagr_cb, a); | 225 sg->private_key, |
226 silcpurple_buddy_keyagr_cb, NULL); | |
230 | 227 |
231 silc_free(local_ip); | 228 silc_free(local_ip); |
232 silc_free(remote_ip); | 229 silc_free(remote_ip); |
233 silc_free(clients); | 230 silc_client_list_free(sg->client, sg->conn, clients); |
234 } | 231 } |
235 | 232 |
236 typedef struct { | 233 typedef struct { |
237 SilcClient client; | 234 SilcClient client; |
238 SilcClientConnection conn; | 235 SilcClientConnection conn; |
242 } *SilcPurpleKeyAgrAsk; | 239 } *SilcPurpleKeyAgrAsk; |
243 | 240 |
244 static void | 241 static void |
245 silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id) | 242 silcpurple_buddy_keyagr_request_cb(SilcPurpleKeyAgrAsk a, gint id) |
246 { | 243 { |
247 SilcPurpleKeyAgr ai; | |
248 SilcClientEntry client_entry; | 244 SilcClientEntry client_entry; |
245 SilcClientConnectionParams params; | |
249 | 246 |
250 if (id != 1) | 247 if (id != 1) |
251 goto out; | 248 goto out; |
252 | 249 |
253 /* Get the client entry. */ | 250 /* Get the client entry. */ |
254 client_entry = silc_client_get_client_by_id(a->client, a->conn, | 251 client_entry = silc_client_get_client_by_id(a->client, a->conn, |
255 &a->client_id); | 252 &a->client_id); |
256 if (!client_entry) { | 253 if (!client_entry) { |
257 purple_notify_error(a->client->application, _("Key Agreement"), | 254 purple_notify_error(a->client->application, _("Key Agreement"), |
258 _("The remote user is not present in the network any more"), | 255 _("The remote user is not present in the network any more"), |
259 NULL); | 256 NULL); |
260 goto out; | 257 goto out; |
261 } | 258 } |
262 | 259 |
263 /* If the hostname was provided by the requestor perform the key agreement | 260 /* If the hostname was provided by the requestor perform the key agreement |
264 now. Otherwise, we will send him a request to connect to us. */ | 261 now. Otherwise, we will send him a request to connect to us. */ |
265 if (a->hostname) { | 262 if (a->hostname) { |
266 ai = silc_calloc(1, sizeof(*ai)); | 263 memset(¶ms, 0, sizeof(params)); |
267 if (!ai) | 264 params.timeout_secs = 60; |
268 goto out; | 265 silc_client_perform_key_agreement(a->client, a->conn, |
269 ai->responder = FALSE; | 266 client_entry, ¶ms, |
270 silc_client_perform_key_agreement(a->client, a->conn, client_entry, | 267 a->conn->public_key, |
268 a->conn->private_key, | |
271 a->hostname, a->port, | 269 a->hostname, a->port, |
272 silcpurple_buddy_keyagr_cb, ai); | 270 silcpurple_buddy_keyagr_cb, NULL); |
273 } else { | 271 } else { |
274 /* Send request. Force us as the point of connection since requestor | 272 /* Send request. Force us as the point of connection since requestor |
275 did not provide the point of connection. */ | 273 did not provide the point of connection. */ |
276 silcpurple_buddy_keyagr_do(a->client->application, | 274 silcpurple_buddy_keyagr_do(a->client->application, |
277 client_entry->nickname, TRUE); | 275 client_entry->nickname, TRUE); |
278 } | 276 } |
279 | 277 |
280 out: | 278 out: |
281 silc_free(a->hostname); | 279 silc_free(a->hostname); |
282 silc_free(a); | 280 silc_free(a); |
283 } | 281 } |
284 | 282 |
285 void silcpurple_buddy_keyagr_request(SilcClient client, | 283 void silcpurple_buddy_keyagr_request(SilcClient client, |
286 SilcClientConnection conn, | 284 SilcClientConnection conn, |
287 SilcClientEntry client_entry, | 285 SilcClientEntry client_entry, |
288 const char *hostname, SilcUInt16 port) | 286 const char *hostname, SilcUInt16 port, |
287 SilcUInt16 protocol) | |
289 { | 288 { |
290 char tmp[128], tmp2[128]; | 289 char tmp[128], tmp2[128]; |
291 SilcPurpleKeyAgrAsk a; | 290 SilcPurpleKeyAgrAsk a; |
292 PurpleConnection *gc = client->application; | 291 PurpleConnection *gc = client->application; |
292 | |
293 /* For now Pidgin don't support UDP key agreement */ | |
294 if (protocol == 1) | |
295 return; | |
293 | 296 |
294 g_snprintf(tmp, sizeof(tmp), | 297 g_snprintf(tmp, sizeof(tmp), |
295 _("Key agreement request received from %s. Would you like to " | 298 _("Key agreement request received from %s. Would you like to " |
296 "perform the key agreement?"), client_entry->nickname); | 299 "perform the key agreement?"), client_entry->nickname); |
297 if (hostname) | 300 if (hostname) |
302 a = silc_calloc(1, sizeof(*a)); | 305 a = silc_calloc(1, sizeof(*a)); |
303 if (!a) | 306 if (!a) |
304 return; | 307 return; |
305 a->client = client; | 308 a->client = client; |
306 a->conn = conn; | 309 a->conn = conn; |
307 a->client_id = *client_entry->id; | 310 a->client_id = client_entry->id; |
308 if (hostname) | 311 if (hostname) |
309 a->hostname = strdup(hostname); | 312 a->hostname = strdup(hostname); |
310 a->port = port; | 313 a->port = port; |
311 | 314 |
312 purple_request_action(client->application, _("Key Agreement Request"), tmp, | 315 purple_request_action(client->application, _("Key Agreement Request"), tmp, |
313 hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, | 316 hostname ? tmp2 : NULL, 1, gc->account, client_entry->nickname, |
314 NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), | 317 NULL, a, 2, _("Yes"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb), |
315 _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); | 318 _("No"), G_CALLBACK(silcpurple_buddy_keyagr_request_cb)); |
316 } | 319 } |
317 | 320 |
318 static void | 321 static void |
319 silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data) | 322 silcpurple_buddy_keyagr(PurpleBlistNode *node, gpointer data) |
320 { | 323 { |
331 silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data) | 334 silcpurple_buddy_resetkey(PurpleBlistNode *node, gpointer data) |
332 { | 335 { |
333 PurpleBuddy *b; | 336 PurpleBuddy *b; |
334 PurpleConnection *gc; | 337 PurpleConnection *gc; |
335 SilcPurple sg; | 338 SilcPurple sg; |
336 char *nickname; | 339 SilcDList clients; |
337 SilcClientEntry *clients; | |
338 SilcUInt32 clients_count; | |
339 | 340 |
340 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); | 341 g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node)); |
341 | 342 |
342 b = (PurpleBuddy *) node; | 343 b = (PurpleBuddy *) node; |
343 gc = purple_account_get_connection(b->account); | 344 gc = purple_account_get_connection(b->account); |
344 sg = gc->proto_data; | 345 sg = gc->proto_data; |
345 | 346 |
346 if (!silc_parse_userfqdn(b->name, &nickname, NULL)) | |
347 return; | |
348 | |
349 /* Find client entry */ | 347 /* Find client entry */ |
350 clients = silc_client_get_clients_local(sg->client, sg->conn, | 348 clients = silc_client_get_clients_local(sg->client, sg->conn, |
351 nickname, b->name, | 349 b->name, FALSE); |
352 &clients_count); | 350 if (!clients) |
353 if (!clients) { | 351 return; |
354 silc_free(nickname); | 352 |
355 return; | 353 silc_dlist_start(clients); |
356 } | |
357 | |
358 clients[0]->prv_resp = FALSE; | |
359 silc_client_del_private_message_key(sg->client, sg->conn, | 354 silc_client_del_private_message_key(sg->client, sg->conn, |
360 clients[0]); | 355 silc_dlist_get(clients)); |
361 silc_free(clients); | 356 silc_client_list_free(sg->client, sg->conn, clients); |
362 silc_free(nickname); | |
363 } | 357 } |
364 | 358 |
365 typedef struct { | 359 typedef struct { |
366 SilcClient client; | 360 SilcClient client; |
367 SilcClientConnection conn; | 361 SilcClientConnection conn; |
384 /* Get the client entry. */ | 378 /* Get the client entry. */ |
385 client_entry = silc_client_get_client_by_id(p->client, p->conn, | 379 client_entry = silc_client_get_client_by_id(p->client, p->conn, |
386 &p->client_id); | 380 &p->client_id); |
387 if (!client_entry) { | 381 if (!client_entry) { |
388 purple_notify_error(p->client->application, _("IM With Password"), | 382 purple_notify_error(p->client->application, _("IM With Password"), |
389 _("The remote user is not present in the network any more"), | 383 _("The remote user is not present in the network any more"), |
390 NULL); | 384 NULL); |
391 silc_free(p); | 385 silc_free(p); |
392 return; | 386 return; |
393 } | 387 } |
394 | 388 |
395 /* Set the private message key */ | 389 /* Set the private message key */ |
396 silc_client_del_private_message_key(p->client, p->conn, | 390 silc_client_del_private_message_key(p->client, p->conn, |
397 client_entry); | 391 client_entry); |
398 silc_client_add_private_message_key(p->client, p->conn, | 392 silc_client_add_private_message_key(p->client, p->conn, |
399 client_entry, NULL, NULL, | 393 client_entry, NULL, NULL, |
400 (unsigned char *)passphrase, | 394 (unsigned char *)passphrase, |
401 strlen(passphrase), FALSE, | 395 strlen(passphrase)); |
402 client_entry->prv_resp); | |
403 if (!client_entry->prv_resp) | |
404 silc_client_send_private_message_key_request(p->client, | |
405 p->conn, | |
406 client_entry); | |
407 silc_free(p); | 396 silc_free(p); |
408 } | 397 } |
409 | 398 |
410 static void | 399 static void |
411 silcpurple_buddy_privkey_resolved(SilcClient client, | 400 silcpurple_buddy_privkey_resolved(SilcClient client, |
412 SilcClientConnection conn, | 401 SilcClientConnection conn, |
413 SilcClientEntry *clients, | 402 SilcStatus status, |
414 SilcUInt32 clients_count, | 403 SilcDList clients, |
415 void *context) | 404 void *context) |
416 { | 405 { |
417 char tmp[256]; | 406 char tmp[256]; |
418 | 407 |
419 if (!clients) { | 408 if (!clients) { |
420 g_snprintf(tmp, sizeof(tmp), | 409 g_snprintf(tmp, sizeof(tmp), |
432 | 421 |
433 static void | 422 static void |
434 silcpurple_buddy_privkey(PurpleConnection *gc, const char *name) | 423 silcpurple_buddy_privkey(PurpleConnection *gc, const char *name) |
435 { | 424 { |
436 SilcPurple sg = gc->proto_data; | 425 SilcPurple sg = gc->proto_data; |
437 char *nickname; | |
438 SilcPurplePrivkey p; | 426 SilcPurplePrivkey p; |
439 SilcClientEntry *clients; | 427 SilcDList clients; |
440 SilcUInt32 clients_count; | 428 SilcClientEntry client_entry; |
441 | 429 |
442 if (!name) | 430 if (!name) |
443 return; | |
444 if (!silc_parse_userfqdn(name, &nickname, NULL)) | |
445 return; | 431 return; |
446 | 432 |
447 /* Find client entry */ | 433 /* Find client entry */ |
448 clients = silc_client_get_clients_local(sg->client, sg->conn, | 434 clients = silc_client_get_clients_local(sg->client, sg->conn, |
449 nickname, name, | 435 name, FALSE); |
450 &clients_count); | |
451 if (!clients) { | 436 if (!clients) { |
452 silc_client_get_clients(sg->client, sg->conn, nickname, NULL, | 437 silc_client_get_clients(sg->client, sg->conn, name, NULL, |
453 silcpurple_buddy_privkey_resolved, | 438 silcpurple_buddy_privkey_resolved, |
454 g_strdup(name)); | 439 g_strdup(name)); |
455 silc_free(nickname); | 440 return; |
456 return; | 441 } |
457 } | 442 |
443 silc_dlist_start(clients); | |
444 client_entry = silc_dlist_get(clients); | |
458 | 445 |
459 p = silc_calloc(1, sizeof(*p)); | 446 p = silc_calloc(1, sizeof(*p)); |
460 if (!p) | 447 if (!p) |
461 return; | 448 return; |
462 p->client = sg->client; | 449 p->client = sg->client; |
463 p->conn = sg->conn; | 450 p->conn = sg->conn; |
464 p->client_id = *clients[0]->id; | 451 p->client_id = client_entry->id; |
465 purple_request_input(gc, _("IM With Password"), NULL, | 452 purple_request_input(gc, _("IM With Password"), NULL, |
466 _("Set IM Password"), NULL, FALSE, TRUE, NULL, | 453 _("Set IM Password"), NULL, FALSE, TRUE, NULL, |
467 _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), | 454 _("OK"), G_CALLBACK(silcpurple_buddy_privkey_cb), |
468 _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), | 455 _("Cancel"), G_CALLBACK(silcpurple_buddy_privkey_cb), |
469 gc->account, NULL, NULL, p); | 456 gc->account, NULL, NULL, p); |
470 | 457 |
471 silc_free(clients); | 458 silc_client_list_free(sg->client, sg->conn, clients); |
472 silc_free(nickname); | |
473 } | 459 } |
474 | 460 |
475 static void | 461 static void |
476 silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data) | 462 silcpurple_buddy_privkey_menu(PurpleBlistNode *node, gpointer data) |
477 { | 463 { |
496 } *SilcPurpleBuddyGetkey; | 482 } *SilcPurpleBuddyGetkey; |
497 | 483 |
498 static void | 484 static void |
499 silcpurple_buddy_getkey(PurpleConnection *gc, const char *name); | 485 silcpurple_buddy_getkey(PurpleConnection *gc, const char *name); |
500 | 486 |
501 static void | 487 static SilcBool |
502 silcpurple_buddy_getkey_cb(SilcPurpleBuddyGetkey g, | 488 silcpurple_buddy_getkey_cb(SilcClient client, SilcClientConnection conn, |
503 SilcClientCommandReplyContext cmd) | 489 SilcCommand command, SilcStatus status, |
490 SilcStatus error, void *context, va_list ap) | |
504 { | 491 { |
505 SilcClientEntry client_entry; | 492 SilcClientEntry client_entry; |
506 unsigned char *pk; | 493 SilcPurpleBuddyGetkey g = context; |
507 SilcUInt32 pk_len; | 494 |
495 if (status != SILC_STATUS_OK) { | |
496 purple_notify_error(g->client->application, _("Get Public Key"), | |
497 _("The remote user is not present in the network any more"), | |
498 NULL); | |
499 silc_free(g); | |
500 return FALSE; | |
501 } | |
508 | 502 |
509 /* Get the client entry. */ | 503 /* Get the client entry. */ |
510 client_entry = silc_client_get_client_by_id(g->client, g->conn, | 504 client_entry = silc_client_get_client_by_id(g->client, g->conn, |
511 &g->client_id); | 505 &g->client_id); |
512 if (!client_entry) { | 506 if (!client_entry) { |
513 purple_notify_error(g->client->application, _("Get Public Key"), | 507 purple_notify_error(g->client->application, _("Get Public Key"), |
514 _("The remote user is not present in the network any more"), | 508 _("The remote user is not present in the network any more"), |
515 NULL); | 509 NULL); |
516 silc_free(g); | 510 silc_free(g); |
517 return; | 511 return FALSE; |
518 } | 512 } |
519 | 513 |
520 if (!client_entry->public_key) { | 514 if (!client_entry->public_key) { |
521 silc_free(g); | 515 silc_free(g); |
522 return; | 516 return FALSE; |
523 } | 517 } |
524 | 518 |
525 /* Now verify the public key */ | 519 /* Now verify the public key */ |
526 pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); | |
527 silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, | 520 silcpurple_verify_public_key(g->client, g->conn, client_entry->nickname, |
528 SILC_SOCKET_TYPE_CLIENT, | 521 SILC_CONN_CLIENT, client_entry->public_key, |
529 pk, pk_len, SILC_SKE_PK_TYPE_SILC, | 522 NULL, NULL); |
530 NULL, NULL); | |
531 silc_free(pk); | |
532 silc_free(g); | 523 silc_free(g); |
524 return TRUE; | |
533 } | 525 } |
534 | 526 |
535 static void | 527 static void |
536 silcpurple_buddy_getkey_resolved(SilcClient client, | 528 silcpurple_buddy_getkey_resolved(SilcClient client, |
537 SilcClientConnection conn, | 529 SilcClientConnection conn, |
538 SilcClientEntry *clients, | 530 SilcStatus status, |
539 SilcUInt32 clients_count, | 531 SilcDList clients, |
540 void *context) | 532 void *context) |
541 { | 533 { |
542 char tmp[256]; | 534 char tmp[256]; |
543 | 535 |
544 if (!clients) { | 536 if (!clients) { |
545 g_snprintf(tmp, sizeof(tmp), | 537 g_snprintf(tmp, sizeof(tmp), |
546 _("User %s is not present in the network"), | 538 _("User %s is not present in the network"), |
547 (const char *)context); | 539 (const char *)context); |
548 purple_notify_error(client->application, _("Get Public Key"), | 540 purple_notify_error(client->application, _("Get Public Key"), |
549 _("Cannot fetch the public key"), tmp); | 541 _("Cannot fetch the public key"), tmp); |
550 g_free(context); | 542 g_free(context); |
551 return; | 543 return; |
552 } | 544 } |
553 | 545 |
554 silcpurple_buddy_getkey(client->application, context); | 546 silcpurple_buddy_getkey(client->application, context); |
559 silcpurple_buddy_getkey(PurpleConnection *gc, const char *name) | 551 silcpurple_buddy_getkey(PurpleConnection *gc, const char *name) |
560 { | 552 { |
561 SilcPurple sg = gc->proto_data; | 553 SilcPurple sg = gc->proto_data; |
562 SilcClient client = sg->client; | 554 SilcClient client = sg->client; |
563 SilcClientConnection conn = sg->conn; | 555 SilcClientConnection conn = sg->conn; |
564 SilcClientEntry *clients; | 556 SilcClientEntry client_entry; |
565 SilcUInt32 clients_count; | 557 SilcDList clients; |
566 SilcPurpleBuddyGetkey g; | 558 SilcPurpleBuddyGetkey g; |
567 char *nickname; | 559 SilcUInt16 cmd_ident; |
568 | 560 |
569 if (!name) | 561 if (!name) |
570 return; | 562 return; |
571 | 563 |
572 if (!silc_parse_userfqdn(name, &nickname, NULL)) | |
573 return; | |
574 | |
575 /* Find client entry */ | 564 /* Find client entry */ |
576 clients = silc_client_get_clients_local(client, conn, nickname, name, | 565 clients = silc_client_get_clients_local(client, conn, name, FALSE); |
577 &clients_count); | |
578 if (!clients) { | 566 if (!clients) { |
579 silc_client_get_clients(client, conn, nickname, NULL, | 567 silc_client_get_clients(client, conn, name, NULL, |
580 silcpurple_buddy_getkey_resolved, | 568 silcpurple_buddy_getkey_resolved, |
581 g_strdup(name)); | 569 g_strdup(name)); |
582 silc_free(nickname); | 570 return; |
583 return; | 571 } |
584 } | 572 |
573 silc_dlist_start(clients); | |
574 client_entry = silc_dlist_get(clients); | |
585 | 575 |
586 /* Call GETKEY */ | 576 /* Call GETKEY */ |
587 g = silc_calloc(1, sizeof(*g)); | 577 g = silc_calloc(1, sizeof(*g)); |
588 if (!g) | 578 if (!g) |
589 return; | 579 return; |
590 g->client = client; | 580 g->client = client; |
591 g->conn = conn; | 581 g->conn = conn; |
592 g->client_id = *clients[0]->id; | 582 g->client_id = client_entry->id; |
593 silc_client_command_call(client, conn, NULL, "GETKEY", | 583 cmd_ident = silc_client_command_call(client, conn, NULL, "GETKEY", |
594 clients[0]->nickname, NULL); | 584 client_entry->nickname, NULL); |
595 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, | 585 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, cmd_ident, |
596 conn->cmd_ident, | 586 silcpurple_buddy_getkey_cb, g); |
597 (SilcCommandCb)silcpurple_buddy_getkey_cb, g); | 587 silc_client_list_free(client, conn, clients); |
598 silc_free(clients); | |
599 silc_free(nickname); | |
600 } | 588 } |
601 | 589 |
602 static void | 590 static void |
603 silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data) | 591 silcpurple_buddy_getkey_menu(PurpleBlistNode *node, gpointer data) |
604 { | 592 { |
627 b = (PurpleBuddy *) node; | 615 b = (PurpleBuddy *) node; |
628 gc = purple_account_get_connection(b->account); | 616 gc = purple_account_get_connection(b->account); |
629 sg = gc->proto_data; | 617 sg = gc->proto_data; |
630 | 618 |
631 pkfile = purple_blist_node_get_string(node, "public-key"); | 619 pkfile = purple_blist_node_get_string(node, "public-key"); |
632 if (!silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_PEM) && | 620 if (!silc_pkcs_load_public_key(pkfile, &public_key)) { |
633 !silc_pkcs_load_public_key(pkfile, &public_key, SILC_PKCS_FILE_BIN)) { | |
634 purple_notify_error(gc, | 621 purple_notify_error(gc, |
635 _("Show Public Key"), | 622 _("Show Public Key"), |
636 _("Could not load public key"), NULL); | 623 _("Could not load public key"), NULL); |
637 return; | 624 return; |
638 } | 625 } |
659 SilcClientConnection conn; | 646 SilcClientConnection conn; |
660 SilcClientID client_id; | 647 SilcClientID client_id; |
661 PurpleBuddy *b; | 648 PurpleBuddy *b; |
662 unsigned char *offline_pk; | 649 unsigned char *offline_pk; |
663 SilcUInt32 offline_pk_len; | 650 SilcUInt32 offline_pk_len; |
651 SilcPublicKey public_key; | |
664 unsigned int offline : 1; | 652 unsigned int offline : 1; |
665 unsigned int pubkey_search : 1; | 653 unsigned int pubkey_search : 1; |
666 unsigned int init : 1; | 654 unsigned int init : 1; |
667 } *SilcPurpleBuddyRes; | 655 } *SilcPurpleBuddyRes; |
668 | 656 |
669 static void | 657 static void |
670 silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id); | 658 silcpurple_add_buddy_ask_pk_cb(SilcPurpleBuddyRes r, gint id); |
671 static void | 659 static void |
672 silcpurple_add_buddy_resolved(SilcClient client, | 660 silcpurple_add_buddy_resolved(SilcClient client, |
673 SilcClientConnection conn, | 661 SilcClientConnection conn, |
674 SilcClientEntry *clients, | 662 SilcStatus status, |
675 SilcUInt32 clients_count, | 663 SilcDList clients, |
676 void *context); | 664 void *context); |
677 | 665 |
678 void silcpurple_get_info(PurpleConnection *gc, const char *who) | 666 void silcpurple_get_info(PurpleConnection *gc, const char *who) |
679 { | 667 { |
680 SilcPurple sg = gc->proto_data; | 668 SilcPurple sg = gc->proto_data; |
681 SilcClient client = sg->client; | 669 SilcClient client = sg->client; |
733 { | 721 { |
734 char tmp[512]; | 722 char tmp[512]; |
735 g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"), | 723 g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not trusted"), |
736 r->b->name); | 724 r->b->name); |
737 purple_notify_error(r->client->application, _("Add Buddy"), tmp, | 725 purple_notify_error(r->client->application, _("Add Buddy"), tmp, |
738 _("You cannot receive buddy notifications until you " | 726 _("You cannot receive buddy notifications until you " |
739 "import his/her public key. You can use the Get Public Key " | 727 "import his/her public key. You can use the Get Public Key " |
740 "command to get the public key.")); | 728 "command to get the public key.")); |
741 purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); | 729 purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); |
742 } | 730 } |
743 | 731 |
744 static void | 732 static void |
745 silcpurple_add_buddy_save(bool success, void *context) | 733 silcpurple_add_buddy_save(SilcBool success, void *context) |
746 { | 734 { |
747 SilcPurpleBuddyRes r = context; | 735 SilcPurpleBuddyRes r = context; |
748 PurpleBuddy *b = r->b; | 736 PurpleBuddy *b = r->b; |
749 SilcClient client = r->client; | |
750 SilcClientEntry client_entry; | 737 SilcClientEntry client_entry; |
751 SilcAttributePayload attr; | 738 SilcAttributePayload attr; |
752 SilcAttribute attribute; | 739 SilcAttribute attribute; |
753 SilcVCardStruct vcard; | 740 SilcVCardStruct vcard; |
754 SilcAttributeObjMime message, extension; | 741 SilcMime message = NULL, extension = NULL; |
755 #ifdef SILC_ATTRIBUTE_USER_ICON | 742 #ifdef SILC_ATTRIBUTE_USER_ICON |
756 SilcAttributeObjMime usericon; | 743 SilcMime usericon = NULL; |
757 #endif | 744 #endif |
758 SilcAttributeObjPk serverpk, usersign, serversign; | 745 SilcAttributeObjPk serverpk, usersign, serversign; |
759 gboolean usign_success = TRUE, ssign_success = TRUE; | 746 gboolean usign_success = TRUE, ssign_success = TRUE; |
760 char filename[512], filename2[512], *fingerprint = NULL, *tmp; | 747 char filename[512], filename2[512], *fingerprint = NULL, *tmp; |
761 SilcUInt32 len; | 748 SilcUInt32 len; |
749 SilcHash hash; | |
762 int i; | 750 int i; |
763 | 751 |
764 if (!success) { | 752 if (!success) { |
765 /* The user did not trust the public key. */ | 753 /* The user did not trust the public key. */ |
766 silcpurple_add_buddy_pk_no(r); | 754 silcpurple_add_buddy_pk_no(r); |
755 silc_free(r->offline_pk); | |
756 if (r->public_key) | |
757 silc_pkcs_public_key_free(r->public_key); | |
767 silc_free(r); | 758 silc_free(r); |
768 return; | 759 return; |
769 } | 760 } |
770 | 761 |
771 if (r->offline) { | 762 if (r->offline) { |
781 silcpurple_silcdir(), fingerprint); | 772 silcpurple_silcdir(), fingerprint); |
782 purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); | 773 purple_blist_node_set_string((PurpleBlistNode *)b, "public-key", filename); |
783 purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); | 774 purple_prpl_got_user_status(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), SILCPURPLE_STATUS_ID_OFFLINE, NULL); |
784 silc_free(fingerprint); | 775 silc_free(fingerprint); |
785 silc_free(r->offline_pk); | 776 silc_free(r->offline_pk); |
777 if (r->public_key) | |
778 silc_pkcs_public_key_free(r->public_key); | |
786 silc_free(r); | 779 silc_free(r); |
787 return; | 780 return; |
788 } | 781 } |
789 | 782 |
790 /* Get the client entry. */ | 783 /* Get the client entry. */ |
791 client_entry = silc_client_get_client_by_id(r->client, r->conn, | 784 client_entry = silc_client_get_client_by_id(r->client, r->conn, |
792 &r->client_id); | 785 &r->client_id); |
793 if (!client_entry) { | 786 if (!client_entry) { |
787 silc_free(r->offline_pk); | |
788 silc_pkcs_public_key_free(r->public_key); | |
789 if (r->public_key) | |
790 silc_pkcs_public_key_free(r->public_key); | |
794 silc_free(r); | 791 silc_free(r); |
795 return; | 792 return; |
796 } | 793 } |
797 | 794 |
798 memset(&vcard, 0, sizeof(vcard)); | 795 memset(&vcard, 0, sizeof(vcard)); |
799 memset(&message, 0, sizeof(message)); | |
800 memset(&extension, 0, sizeof(extension)); | |
801 #ifdef SILC_ATTRIBUTE_USER_ICON | |
802 memset(&usericon, 0, sizeof(usericon)); | |
803 #endif | |
804 memset(&serverpk, 0, sizeof(serverpk)); | 796 memset(&serverpk, 0, sizeof(serverpk)); |
805 memset(&usersign, 0, sizeof(usersign)); | 797 memset(&usersign, 0, sizeof(usersign)); |
806 memset(&serversign, 0, sizeof(serversign)); | 798 memset(&serversign, 0, sizeof(serversign)); |
807 | 799 |
808 /* Now that we have the public key and we trust it now we | 800 /* Now that we have the public key and we trust it now we |
820 sizeof(vcard))) | 812 sizeof(vcard))) |
821 continue; | 813 continue; |
822 break; | 814 break; |
823 | 815 |
824 case SILC_ATTRIBUTE_STATUS_MESSAGE: | 816 case SILC_ATTRIBUTE_STATUS_MESSAGE: |
825 if (!silc_attribute_get_object(attr, (void *)&message, | 817 message = silc_mime_alloc(); |
826 sizeof(message))) | 818 if (!silc_attribute_get_object(attr, (void *)message, |
819 sizeof(*message))) | |
827 continue; | 820 continue; |
828 break; | 821 break; |
829 | 822 |
830 case SILC_ATTRIBUTE_EXTENSION: | 823 case SILC_ATTRIBUTE_EXTENSION: |
831 if (!silc_attribute_get_object(attr, (void *)&extension, | 824 extension = silc_mime_alloc(); |
832 sizeof(extension))) | 825 if (!silc_attribute_get_object(attr, (void *)extension, |
826 sizeof(*extension))) | |
833 continue; | 827 continue; |
834 break; | 828 break; |
835 | 829 |
836 #ifdef SILC_ATTRIBUTE_USER_ICON | 830 #ifdef SILC_ATTRIBUTE_USER_ICON |
837 case SILC_ATTRIBUTE_USER_ICON: | 831 case SILC_ATTRIBUTE_USER_ICON: |
838 if (!silc_attribute_get_object(attr, (void *)&usericon, | 832 usericon = silc_mime_alloc(); |
839 sizeof(usericon))) | 833 if (!silc_attribute_get_object(attr, (void *)usericon, |
834 sizeof(*usericon))) | |
840 continue; | 835 continue; |
841 break; | 836 break; |
842 #endif | 837 #endif |
843 | 838 |
844 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: | 839 case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY: |
870 } | 865 } |
871 } | 866 } |
872 } | 867 } |
873 | 868 |
874 /* Verify the attribute signatures */ | 869 /* Verify the attribute signatures */ |
870 silc_hash_alloc((const unsigned char *)"sha1", &hash); | |
875 | 871 |
876 if (usersign.data) { | 872 if (usersign.data) { |
877 SilcPKCS pkcs; | |
878 unsigned char *verifyd; | 873 unsigned char *verifyd; |
879 SilcUInt32 verify_len; | 874 SilcUInt32 verify_len; |
880 | 875 |
881 silc_pkcs_alloc((unsigned char*)"rsa", &pkcs); | |
882 verifyd = silc_attribute_get_verify_data(client_entry->attrs, | 876 verifyd = silc_attribute_get_verify_data(client_entry->attrs, |
883 FALSE, &verify_len); | 877 FALSE, &verify_len); |
884 if (verifyd && silc_pkcs_public_key_set(pkcs, client_entry->public_key)){ | 878 if (verifyd && !silc_pkcs_verify(client_entry->public_key, |
885 if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, | 879 usersign.data, |
886 usersign.data, | 880 usersign.data_len, |
887 usersign.data_len, | 881 verifyd, verify_len, hash)) |
888 verifyd, verify_len)) | 882 usign_success = FALSE; |
889 usign_success = FALSE; | |
890 } | |
891 silc_free(verifyd); | 883 silc_free(verifyd); |
892 } | 884 } |
893 | 885 |
894 if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) { | 886 if (serversign.data) { |
895 SilcPublicKey public_key; | 887 SilcPublicKey public_key; |
896 SilcPKCS pkcs; | 888 SilcPKCSType type = 0; |
897 unsigned char *verifyd; | 889 unsigned char *verifyd; |
898 SilcUInt32 verify_len; | 890 SilcUInt32 verify_len; |
899 | 891 |
900 if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len, | 892 if (!strcmp(serverpk.type, "silc-rsa")) |
901 &public_key)) { | 893 type = SILC_PKCS_SILC; |
902 silc_pkcs_alloc((unsigned char *)"rsa", &pkcs); | 894 else if (!strcmp(serverpk.type, "ssh-rsa")) |
895 type = SILC_PKCS_SSH2; | |
896 else if (!strcmp(serverpk.type, "x509v3-sign-rsa")) | |
897 type = SILC_PKCS_X509V3; | |
898 else if (!strcmp(serverpk.type, "pgp-sign-rsa")) | |
899 type = SILC_PKCS_OPENPGP; | |
900 | |
901 if (silc_pkcs_public_key_alloc(type, serverpk.data, | |
902 serverpk.data_len, | |
903 &public_key)) { | |
903 verifyd = silc_attribute_get_verify_data(client_entry->attrs, | 904 verifyd = silc_attribute_get_verify_data(client_entry->attrs, |
904 TRUE, &verify_len); | 905 TRUE, &verify_len); |
905 if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) { | 906 if (verifyd && !silc_pkcs_verify(public_key, |
906 if (!silc_pkcs_verify_with_hash(pkcs, client->sha1hash, | 907 serversign.data, |
907 serversign.data, | 908 serversign.data_len, |
908 serversign.data_len, | 909 verifyd, verify_len, |
909 verifyd, verify_len)) | 910 hash)) |
910 ssign_success = FALSE; | 911 ssign_success = FALSE; |
911 } | |
912 silc_pkcs_public_key_free(public_key); | 912 silc_pkcs_public_key_free(public_key); |
913 silc_free(verifyd); | 913 silc_free(verifyd); |
914 } | 914 } |
915 } | 915 } |
916 | 916 |
917 fingerprint = silc_fingerprint(client_entry->fingerprint, | 917 fingerprint = silc_fingerprint(client_entry->fingerprint, 20); |
918 client_entry->fingerprint_len); | |
919 for (i = 0; i < strlen(fingerprint); i++) | 918 for (i = 0; i < strlen(fingerprint); i++) |
920 if (fingerprint[i] == ' ') | 919 if (fingerprint[i] == ' ') |
921 fingerprint[i] = '_'; | 920 fingerprint[i] = '_'; |
922 | 921 |
923 if (usign_success || ssign_success) { | 922 if (usign_success || ssign_success) { |
952 silc_file_writefile(filename2, tmp, len); | 951 silc_file_writefile(filename2, tmp, len); |
953 silc_free(tmp); | 952 silc_free(tmp); |
954 } | 953 } |
955 | 954 |
956 /* Save status message */ | 955 /* Save status message */ |
957 if (message.mime) { | 956 if (message) { |
958 memset(filename2, 0, sizeof(filename2)); | 957 memset(filename2, 0, sizeof(filename2)); |
959 g_snprintf(filename2, sizeof(filename2) - 1, | 958 g_snprintf(filename2, sizeof(filename2) - 1, |
960 "%s" G_DIR_SEPARATOR_S "status_message.mime", | 959 "%s" G_DIR_SEPARATOR_S "status_message.mime", |
961 filename); | 960 filename); |
962 silc_file_writefile(filename2, (char *)message.mime, | 961 tmp = (char *)silc_mime_get_data(message, &len); |
963 message.mime_len); | 962 silc_file_writefile(filename2, tmp, len); |
963 silc_mime_free(message); | |
964 } | 964 } |
965 | 965 |
966 /* Save extension data */ | 966 /* Save extension data */ |
967 if (extension.mime) { | 967 if (extension) { |
968 memset(filename2, 0, sizeof(filename2)); | 968 memset(filename2, 0, sizeof(filename2)); |
969 g_snprintf(filename2, sizeof(filename2) - 1, | 969 g_snprintf(filename2, sizeof(filename2) - 1, |
970 "%s" G_DIR_SEPARATOR_S "extension.mime", | 970 "%s" G_DIR_SEPARATOR_S "extension.mime", |
971 filename); | 971 filename); |
972 silc_file_writefile(filename2, (char *)extension.mime, | 972 tmp = (char *)silc_mime_get_data(extension, &len); |
973 extension.mime_len); | 973 silc_file_writefile(filename2, tmp, len); |
974 silc_mime_free(extension); | |
974 } | 975 } |
975 | 976 |
976 #ifdef SILC_ATTRIBUTE_USER_ICON | 977 #ifdef SILC_ATTRIBUTE_USER_ICON |
977 /* Save user icon */ | 978 /* Save user icon */ |
978 if (usericon.mime) { | 979 if (usericon) { |
979 SilcMime m = silc_mime_decode(usericon.mime, | 980 const char *type = silc_mime_get_field(usericon, "Content-Type"); |
980 usericon.mime_len); | 981 if (type && |
981 if (m) { | 982 (!strcmp(type, "image/jpeg") || |
982 const char *type = silc_mime_get_field(m, "Content-Type"); | 983 !strcmp(type, "image/gif") || |
983 if (!strcmp(type, "image/jpeg") || | 984 !strcmp(type, "image/bmp") || |
984 !strcmp(type, "image/gif") || | 985 !strcmp(type, "image/png"))) { |
985 !strcmp(type, "image/bmp") || | 986 const unsigned char *data; |
986 !strcmp(type, "image/png")) { | 987 SilcUInt32 data_len; |
987 const unsigned char *data; | 988 data = silc_mime_get_data(usericon, &data_len); |
988 SilcUInt32 data_len; | 989 if (data) { |
989 data = silc_mime_get_data(m, &data_len); | 990 /* TODO: Check if SILC gives us something to use as the checksum instead */ |
990 if (data) { | 991 purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL); |
991 /* TODO: Check if SILC gives us something to use as the checksum instead */ | |
992 purple_buddy_icons_set_for_user(purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), g_memdup(data, data_len), data_len, NULL); | |
993 } | |
994 } | 992 } |
995 silc_mime_free(m); | |
996 } | 993 } |
994 silc_mime_free(usericon); | |
997 } | 995 } |
998 #endif | 996 #endif |
999 } | 997 } |
1000 | 998 |
1001 /* Save the public key path to buddy properties, as it is used | 999 /* Save the public key path to buddy properties, as it is used |
1013 changes from the server */ | 1011 changes from the server */ |
1014 g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename); | 1012 g_snprintf(filename2, sizeof(filename2) - 1, "+%s", filename); |
1015 silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey", | 1013 silc_client_command_call(r->client, r->conn, NULL, "WATCH", "-pubkey", |
1016 filename2, NULL); | 1014 filename2, NULL); |
1017 | 1015 |
1016 silc_hash_free(hash); | |
1018 silc_free(fingerprint); | 1017 silc_free(fingerprint); |
1018 silc_free(r->offline_pk); | |
1019 if (r->public_key) | |
1020 silc_pkcs_public_key_free(r->public_key); | |
1019 silc_free(r); | 1021 silc_free(r); |
1020 } | 1022 } |
1021 | 1023 |
1022 static void | 1024 static void |
1023 silcpurple_add_buddy_ask_import(void *user_data, const char *name) | 1025 silcpurple_add_buddy_ask_import(void *user_data, const char *name) |
1024 { | 1026 { |
1025 SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; | 1027 SilcPurpleBuddyRes r = (SilcPurpleBuddyRes)user_data; |
1026 SilcPublicKey public_key; | |
1027 | 1028 |
1028 /* Load the public key */ | 1029 /* Load the public key */ |
1029 if (!silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_PEM) && | 1030 if (!silc_pkcs_load_public_key(name, &r->public_key)) { |
1030 !silc_pkcs_load_public_key(name, &public_key, SILC_PKCS_FILE_BIN)) { | |
1031 silcpurple_add_buddy_ask_pk_cb(r, 0); | 1031 silcpurple_add_buddy_ask_pk_cb(r, 0); |
1032 purple_notify_error(r->client->application, | 1032 purple_notify_error(r->client->application, |
1033 _("Add Buddy"), _("Could not load public key"), NULL); | 1033 _("Add Buddy"), _("Could not load public key"), NULL); |
1034 return; | 1034 return; |
1035 } | 1035 } |
1036 | 1036 |
1037 /* Now verify the public key */ | 1037 /* Now verify the public key */ |
1038 r->offline_pk = silc_pkcs_public_key_encode(public_key, &r->offline_pk_len); | 1038 r->offline_pk = silc_pkcs_public_key_encode(r->public_key, &r->offline_pk_len); |
1039 silcpurple_verify_public_key(r->client, r->conn, r->b->name, | 1039 silcpurple_verify_public_key(r->client, r->conn, r->b->name, |
1040 SILC_SOCKET_TYPE_CLIENT, | 1040 SILC_CONN_CLIENT, r->public_key, |
1041 r->offline_pk, r->offline_pk_len, | 1041 silcpurple_add_buddy_save, r); |
1042 SILC_SKE_PK_TYPE_SILC, | |
1043 silcpurple_add_buddy_save, r); | |
1044 } | 1042 } |
1045 | 1043 |
1046 static void | 1044 static void |
1047 silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name) | 1045 silcpurple_add_buddy_ask_pk_cancel(void *user_data, const char *name) |
1048 { | 1046 { |
1063 return; | 1061 return; |
1064 } | 1062 } |
1065 | 1063 |
1066 /* Open file selector to select the public key. */ | 1064 /* Open file selector to select the public key. */ |
1067 purple_request_file(r->client->application, _("Open..."), NULL, FALSE, | 1065 purple_request_file(r->client->application, _("Open..."), NULL, FALSE, |
1068 G_CALLBACK(silcpurple_add_buddy_ask_import), | 1066 G_CALLBACK(silcpurple_add_buddy_ask_import), |
1069 G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), | 1067 G_CALLBACK(silcpurple_add_buddy_ask_pk_cancel), |
1070 purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); | 1068 purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); |
1071 | 1069 |
1072 } | 1070 } |
1073 | 1071 |
1074 static void | 1072 static void |
1075 silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r) | 1073 silcpurple_add_buddy_ask_pk(SilcPurpleBuddyRes r) |
1076 { | 1074 { |
1077 char tmp[512]; | 1075 char tmp[512]; |
1078 g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), | 1076 g_snprintf(tmp, sizeof(tmp), _("The %s buddy is not present in the network"), |
1079 r->b->name); | 1077 r->b->name); |
1080 purple_request_action(r->client->application, _("Add Buddy"), tmp, | 1078 purple_request_action(r->client->application, _("Add Buddy"), tmp, |
1081 _("To add the buddy you must import his/her public key. " | 1079 _("To add the buddy you must import his/her public key. " |
1082 "Press Import to import a public key."), 0, | 1080 "Press Import to import a public key."), 0, |
1083 purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, | 1081 purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r, 2, |
1084 _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), | 1082 _("Cancel"), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb), |
1085 _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); | 1083 _("_Import..."), G_CALLBACK(silcpurple_add_buddy_ask_pk_cb)); |
1086 } | 1084 } |
1087 | 1085 |
1088 static void | 1086 static SilcBool |
1089 silcpurple_add_buddy_getkey_cb(SilcPurpleBuddyRes r, | 1087 silcpurple_add_buddy_getkey_cb(SilcClient client, SilcClientConnection conn, |
1090 SilcClientCommandReplyContext cmd) | 1088 SilcCommand command, SilcStatus status, |
1091 { | 1089 SilcStatus error, void *context, va_list ap) |
1090 { | |
1091 SilcPurpleBuddyRes r = context; | |
1092 SilcClientEntry client_entry; | 1092 SilcClientEntry client_entry; |
1093 unsigned char *pk; | 1093 |
1094 SilcUInt32 pk_len; | 1094 if (status != SILC_STATUS_OK) { |
1095 /* The buddy is offline/nonexistent. We will require user | |
1096 to associate a public key with the buddy or the buddy | |
1097 cannot be added. */ | |
1098 r->offline = TRUE; | |
1099 silcpurple_add_buddy_ask_pk(r); | |
1100 return FALSE; | |
1101 } | |
1095 | 1102 |
1096 /* Get the client entry. */ | 1103 /* Get the client entry. */ |
1097 client_entry = silc_client_get_client_by_id(r->client, r->conn, | 1104 client_entry = silc_client_get_client_by_id(r->client, r->conn, |
1098 &r->client_id); | 1105 &r->client_id); |
1099 if (!client_entry || !client_entry->public_key) { | 1106 if (!client_entry || !client_entry->public_key) { |
1100 /* The buddy is offline/nonexistent. We will require user | 1107 /* The buddy is offline/nonexistent. We will require user |
1101 to associate a public key with the buddy or the buddy | 1108 to associate a public key with the buddy or the buddy |
1102 cannot be added. */ | 1109 cannot be added. */ |
1103 r->offline = TRUE; | 1110 r->offline = TRUE; |
1104 silcpurple_add_buddy_ask_pk(r); | 1111 silcpurple_add_buddy_ask_pk(r); |
1105 return; | 1112 return FALSE; |
1106 } | 1113 } |
1107 | 1114 |
1108 /* Now verify the public key */ | 1115 /* Now verify the public key */ |
1109 pk = silc_pkcs_public_key_encode(client_entry->public_key, &pk_len); | |
1110 silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname, | 1116 silcpurple_verify_public_key(r->client, r->conn, client_entry->nickname, |
1111 SILC_SOCKET_TYPE_CLIENT, | 1117 SILC_CONN_CLIENT, client_entry->public_key, |
1112 pk, pk_len, SILC_SKE_PK_TYPE_SILC, | 1118 silcpurple_add_buddy_save, r); |
1113 silcpurple_add_buddy_save, r); | 1119 return TRUE; |
1114 silc_free(pk); | |
1115 } | 1120 } |
1116 | 1121 |
1117 static void | 1122 static void |
1118 silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields) | 1123 silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields) |
1119 { | 1124 { |
1120 PurpleRequestField *f; | 1125 PurpleRequestField *f; |
1121 const GList *list; | 1126 const GList *list; |
1122 SilcClientEntry client_entry; | 1127 SilcClientEntry client_entry; |
1128 SilcDList clients; | |
1123 | 1129 |
1124 f = purple_request_fields_get_field(fields, "list"); | 1130 f = purple_request_fields_get_field(fields, "list"); |
1125 list = purple_request_field_list_get_selected(f); | 1131 list = purple_request_field_list_get_selected(f); |
1126 if (!list) { | 1132 if (!list) { |
1127 /* The user did not select any user. */ | 1133 /* The user did not select any user. */ |
1129 silc_free(r); | 1135 silc_free(r); |
1130 return; | 1136 return; |
1131 } | 1137 } |
1132 | 1138 |
1133 client_entry = purple_request_field_list_get_data(f, list->data); | 1139 client_entry = purple_request_field_list_get_data(f, list->data); |
1134 silcpurple_add_buddy_resolved(r->client, r->conn, &client_entry, 1, r); | 1140 clients = silc_dlist_init(); |
1141 silc_dlist_add(clients, client_entry); | |
1142 silcpurple_add_buddy_resolved(r->client, r->conn, SILC_STATUS_OK, | |
1143 clients, r); | |
1144 silc_dlist_uninit(clients); | |
1135 } | 1145 } |
1136 | 1146 |
1137 static void | 1147 static void |
1138 silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields) | 1148 silcpurple_add_buddy_select_cancel(SilcPurpleBuddyRes r, PurpleRequestFields *fields) |
1139 { | 1149 { |
1141 silcpurple_add_buddy_pk_no(r); | 1151 silcpurple_add_buddy_pk_no(r); |
1142 silc_free(r); | 1152 silc_free(r); |
1143 } | 1153 } |
1144 | 1154 |
1145 static void | 1155 static void |
1146 silcpurple_add_buddy_select(SilcPurpleBuddyRes r, | 1156 silcpurple_add_buddy_select(SilcPurpleBuddyRes r, SilcDList clients) |
1147 SilcClientEntry *clients, | |
1148 SilcUInt32 clients_count) | |
1149 { | 1157 { |
1150 PurpleRequestFields *fields; | 1158 PurpleRequestFields *fields; |
1151 PurpleRequestFieldGroup *g; | 1159 PurpleRequestFieldGroup *g; |
1152 PurpleRequestField *f; | 1160 PurpleRequestField *f; |
1153 char tmp[512], tmp2[128]; | 1161 char tmp[512], tmp2[128]; |
1154 int i; | |
1155 char *fingerprint; | 1162 char *fingerprint; |
1163 SilcClientEntry client_entry; | |
1156 | 1164 |
1157 fields = purple_request_fields_new(); | 1165 fields = purple_request_fields_new(); |
1158 g = purple_request_field_group_new(NULL); | 1166 g = purple_request_field_group_new(NULL); |
1159 f = purple_request_field_list_new("list", NULL); | 1167 f = purple_request_field_list_new("list", NULL); |
1160 purple_request_field_group_add_field(g, f); | 1168 purple_request_field_group_add_field(g, f); |
1161 purple_request_field_list_set_multi_select(f, FALSE); | 1169 purple_request_field_list_set_multi_select(f, FALSE); |
1162 purple_request_fields_add_group(fields, g); | 1170 purple_request_fields_add_group(fields, g); |
1163 | 1171 |
1164 for (i = 0; i < clients_count; i++) { | 1172 silc_dlist_start(clients); |
1173 while ((client_entry = silc_dlist_get(clients))) { | |
1165 fingerprint = NULL; | 1174 fingerprint = NULL; |
1166 if (clients[i]->fingerprint) { | 1175 if (*client_entry->fingerprint) { |
1167 fingerprint = silc_fingerprint(clients[i]->fingerprint, | 1176 fingerprint = silc_fingerprint(client_entry->fingerprint, 20); |
1168 clients[i]->fingerprint_len); | |
1169 g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint); | 1177 g_snprintf(tmp2, sizeof(tmp2), "\n%s", fingerprint); |
1170 } | 1178 } |
1171 g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s", | 1179 g_snprintf(tmp, sizeof(tmp), "%s - %s (%s@%s)%s", |
1172 clients[i]->realname, clients[i]->nickname, | 1180 client_entry->realname, client_entry->nickname, |
1173 clients[i]->username, clients[i]->hostname ? | 1181 client_entry->username, *client_entry->hostname ? |
1174 clients[i]->hostname : "", | 1182 client_entry->hostname : "", |
1175 fingerprint ? tmp2 : ""); | 1183 fingerprint ? tmp2 : ""); |
1176 purple_request_field_list_add(f, tmp, clients[i]); | 1184 purple_request_field_list_add(f, tmp, client_entry); |
1177 silc_free(fingerprint); | 1185 silc_free(fingerprint); |
1178 } | 1186 } |
1179 | 1187 |
1180 purple_request_fields(r->client->application, _("Add Buddy"), | 1188 purple_request_fields(r->client->application, _("Add Buddy"), |
1181 _("Select correct user"), | 1189 _("Select correct user"), |
1182 r->pubkey_search | 1190 r->pubkey_search |
1183 ? _("More than one user was found with the same public key. Select " | 1191 ? _("More than one user was found with the same public key. Select " |
1184 "the correct user from the list to add to the buddy list.") | 1192 "the correct user from the list to add to the buddy list.") |
1185 : _("More than one user was found with the same name. Select " | 1193 : _("More than one user was found with the same name. Select " |
1186 "the correct user from the list to add to the buddy list."), | 1194 "the correct user from the list to add to the buddy list."), |
1187 fields, | 1195 fields, |
1188 _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), | 1196 _("OK"), G_CALLBACK(silcpurple_add_buddy_select_cb), |
1189 _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), | 1197 _("Cancel"), G_CALLBACK(silcpurple_add_buddy_select_cancel), |
1190 purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); | 1198 purple_buddy_get_account(r->b), purple_buddy_get_name(r->b), NULL, r); |
1191 } | 1199 } |
1192 | 1200 |
1193 static void | 1201 static void |
1194 silcpurple_add_buddy_resolved(SilcClient client, | 1202 silcpurple_add_buddy_resolved(SilcClient client, |
1195 SilcClientConnection conn, | 1203 SilcClientConnection conn, |
1196 SilcClientEntry *clients, | 1204 SilcStatus status, |
1197 SilcUInt32 clients_count, | 1205 SilcDList clients, |
1198 void *context) | 1206 void *context) |
1199 { | 1207 { |
1200 SilcPurpleBuddyRes r = context; | 1208 SilcPurpleBuddyRes r = context; |
1201 PurpleBuddy *b = r->b; | 1209 PurpleBuddy *b = r->b; |
1202 SilcAttributePayload pub; | 1210 SilcAttributePayload pub; |
1203 SilcAttributeObjPk userpk; | 1211 SilcAttributeObjPk userpk; |
1204 unsigned char *pk; | |
1205 SilcUInt32 pk_len; | |
1206 const char *filename; | 1212 const char *filename; |
1213 SilcClientEntry client_entry = NULL; | |
1214 SilcUInt16 cmd_ident; | |
1207 | 1215 |
1208 filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); | 1216 filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); |
1209 | 1217 |
1210 /* If the buddy is offline/nonexistent, we will require user | 1218 /* If the buddy is offline/nonexistent, we will require user |
1211 to associate a public key with the buddy or the buddy | 1219 to associate a public key with the buddy or the buddy |
1212 cannot be added. */ | 1220 cannot be added. */ |
1213 if (!clients_count) { | 1221 if (!clients) { |
1214 if (r->init) { | 1222 if (r->init) { |
1215 silc_free(r); | 1223 silc_free(r); |
1216 return; | 1224 return; |
1217 } | 1225 } |
1218 | 1226 |
1226 return; | 1234 return; |
1227 } | 1235 } |
1228 | 1236 |
1229 /* If more than one client was found with nickname, we need to verify | 1237 /* If more than one client was found with nickname, we need to verify |
1230 from user which one is the correct. */ | 1238 from user which one is the correct. */ |
1231 if (clients_count > 1 && !r->pubkey_search) { | 1239 if (silc_dlist_count(clients) > 1 && !r->pubkey_search) { |
1232 if (r->init) { | 1240 if (r->init) { |
1233 silc_free(r); | 1241 silc_free(r); |
1234 return; | 1242 return; |
1235 } | 1243 } |
1236 | 1244 |
1237 silcpurple_add_buddy_select(r, clients, clients_count); | 1245 silcpurple_add_buddy_select(r, clients); |
1238 return; | 1246 return; |
1239 } | 1247 } |
1248 | |
1249 silc_dlist_start(clients); | |
1250 client_entry = silc_dlist_get(clients); | |
1240 | 1251 |
1241 /* If we searched using public keys and more than one entry was found | 1252 /* If we searched using public keys and more than one entry was found |
1242 the same person is logged on multiple times. */ | 1253 the same person is logged on multiple times. */ |
1243 if (clients_count > 1 && r->pubkey_search && b->name) { | 1254 if (silc_dlist_count(clients) > 1 && r->pubkey_search && b->name) { |
1244 if (r->init) { | 1255 if (r->init) { |
1245 /* Find the entry that closest matches to the | 1256 /* Find the entry that closest matches to the |
1246 buddy nickname. */ | 1257 buddy nickname. */ |
1247 int i; | 1258 SilcClientEntry entry; |
1248 for (i = 0; i < clients_count; i++) { | 1259 silc_dlist_start(clients); |
1249 if (!strncasecmp(b->name, clients[i]->nickname, | 1260 while ((entry = silc_dlist_get(clients))) { |
1261 if (!strncasecmp(b->name, entry->nickname, | |
1250 strlen(b->name))) { | 1262 strlen(b->name))) { |
1251 clients[0] = clients[i]; | 1263 client_entry = entry; |
1252 break; | 1264 break; |
1253 } | 1265 } |
1254 } | 1266 } |
1255 } else { | 1267 } else { |
1256 /* Verify from user which one is correct */ | 1268 /* Verify from user which one is correct */ |
1257 silcpurple_add_buddy_select(r, clients, clients_count); | 1269 silcpurple_add_buddy_select(r, clients); |
1258 return; | 1270 return; |
1259 } | 1271 } |
1260 } | 1272 } |
1261 | 1273 |
1262 /* The client was found. Now get its public key and verify | 1274 /* The client was found. Now get its public key and verify |
1263 that before adding the buddy. */ | 1275 that before adding the buddy. */ |
1264 memset(&userpk, 0, sizeof(userpk)); | 1276 memset(&userpk, 0, sizeof(userpk)); |
1265 b->proto_data = silc_memdup(clients[0]->id, sizeof(*clients[0]->id)); | 1277 b->proto_data = silc_memdup(&client_entry->id, sizeof(client_entry->id)); |
1266 r->client_id = *clients[0]->id; | 1278 r->client_id = client_entry->id; |
1267 | 1279 |
1268 /* Get the public key from attributes, if not present then | 1280 /* Get the public key from attributes, if not present then |
1269 resolve it with GETKEY unless we have it cached already. */ | 1281 resolve it with GETKEY unless we have it cached already. */ |
1270 if (clients[0]->attrs && !clients[0]->public_key) { | 1282 if (client_entry->attrs && !client_entry->public_key) { |
1271 pub = silcpurple_get_attr(clients[0]->attrs, | 1283 pub = silcpurple_get_attr(client_entry->attrs, |
1272 SILC_ATTRIBUTE_USER_PUBLIC_KEY); | 1284 SILC_ATTRIBUTE_USER_PUBLIC_KEY); |
1273 if (!pub || !silc_attribute_get_object(pub, (void *)&userpk, | 1285 if (!pub || !silc_attribute_get_object(pub, (void *)&userpk, |
1274 sizeof(userpk))) { | 1286 sizeof(userpk))) { |
1275 /* Get public key with GETKEY */ | 1287 /* Get public key with GETKEY */ |
1276 silc_client_command_call(client, conn, NULL, | 1288 cmd_ident = |
1277 "GETKEY", clients[0]->nickname, NULL); | 1289 silc_client_command_call(client, conn, NULL, |
1290 "GETKEY", client_entry->nickname, NULL); | |
1278 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, | 1291 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, |
1279 conn->cmd_ident, | 1292 cmd_ident, |
1280 (SilcCommandCb)silcpurple_add_buddy_getkey_cb, | 1293 silcpurple_add_buddy_getkey_cb, |
1281 r); | 1294 r); |
1282 return; | 1295 return; |
1283 } | 1296 } |
1284 if (!silc_pkcs_public_key_decode(userpk.data, userpk.data_len, | 1297 if (!silc_pkcs_public_key_alloc(SILC_PKCS_SILC, |
1285 &clients[0]->public_key)) | 1298 userpk.data, userpk.data_len, |
1299 &client_entry->public_key)) | |
1286 return; | 1300 return; |
1287 silc_free(userpk.data); | 1301 silc_free(userpk.data); |
1288 } else if (filename && !clients[0]->public_key) { | 1302 } else if (filename && !client_entry->public_key) { |
1289 if (!silc_pkcs_load_public_key(filename, &clients[0]->public_key, | 1303 if (!silc_pkcs_load_public_key(filename, &client_entry->public_key)) { |
1290 SILC_PKCS_FILE_PEM) && | |
1291 !silc_pkcs_load_public_key(filename, &clients[0]->public_key, | |
1292 SILC_PKCS_FILE_BIN)) { | |
1293 /* Get public key with GETKEY */ | 1304 /* Get public key with GETKEY */ |
1294 silc_client_command_call(client, conn, NULL, | 1305 cmd_ident = |
1295 "GETKEY", clients[0]->nickname, NULL); | 1306 silc_client_command_call(client, conn, NULL, |
1307 "GETKEY", client_entry->nickname, NULL); | |
1296 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, | 1308 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, |
1297 conn->cmd_ident, | 1309 cmd_ident, |
1298 (SilcCommandCb)silcpurple_add_buddy_getkey_cb, | 1310 silcpurple_add_buddy_getkey_cb, |
1299 r); | 1311 r); |
1300 return; | 1312 return; |
1301 } | 1313 } |
1302 } else if (!clients[0]->public_key) { | 1314 } else if (!client_entry->public_key) { |
1303 /* Get public key with GETKEY */ | 1315 /* Get public key with GETKEY */ |
1304 silc_client_command_call(client, conn, NULL, | 1316 cmd_ident = |
1305 "GETKEY", clients[0]->nickname, NULL); | 1317 silc_client_command_call(client, conn, NULL, |
1318 "GETKEY", client_entry->nickname, NULL); | |
1306 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, | 1319 silc_client_command_pending(conn, SILC_COMMAND_GETKEY, |
1307 conn->cmd_ident, | 1320 cmd_ident, |
1308 (SilcCommandCb)silcpurple_add_buddy_getkey_cb, | 1321 silcpurple_add_buddy_getkey_cb, |
1309 r); | 1322 r); |
1310 return; | 1323 return; |
1311 } | 1324 } |
1312 | 1325 |
1313 /* We have the public key, verify it. */ | 1326 /* We have the public key, verify it. */ |
1314 pk = silc_pkcs_public_key_encode(clients[0]->public_key, &pk_len); | 1327 silcpurple_verify_public_key(client, conn, client_entry->nickname, |
1315 silcpurple_verify_public_key(client, conn, clients[0]->nickname, | 1328 SILC_CONN_CLIENT, |
1316 SILC_SOCKET_TYPE_CLIENT, | 1329 client_entry->public_key, |
1317 pk, pk_len, SILC_SKE_PK_TYPE_SILC, | 1330 silcpurple_add_buddy_save, r); |
1318 silcpurple_add_buddy_save, r); | |
1319 silc_free(pk); | |
1320 } | 1331 } |
1321 | 1332 |
1322 static void | 1333 static void |
1323 silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) | 1334 silcpurple_add_buddy_i(PurpleConnection *gc, PurpleBuddy *b, gboolean init) |
1324 { | 1335 { |
1342 filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); | 1353 filename = purple_blist_node_get_string((PurpleBlistNode *)b, "public-key"); |
1343 if (filename) { | 1354 if (filename) { |
1344 SilcPublicKey public_key; | 1355 SilcPublicKey public_key; |
1345 SilcAttributeObjPk userpk; | 1356 SilcAttributeObjPk userpk; |
1346 | 1357 |
1347 if (!silc_pkcs_load_public_key(filename, &public_key, | 1358 if (!silc_pkcs_load_public_key(filename, &public_key)) |
1348 SILC_PKCS_FILE_PEM) && | |
1349 !silc_pkcs_load_public_key(filename, &public_key, | |
1350 SILC_PKCS_FILE_BIN)) | |
1351 return; | 1359 return; |
1352 | 1360 |
1353 /* Get all attributes, and use the public key to search user */ | 1361 /* Get all attributes, and use the public key to search user */ |
1354 name = NULL; | 1362 name = NULL; |
1355 attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO, | 1363 attrs = silc_client_attributes_request(SILC_ATTRIBUTE_USER_INFO, |
1630 pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key"); | 1638 pkfile = purple_blist_node_get_string((PurpleBlistNode *) buddy, "public-key"); |
1631 client_entry = silc_client_get_client_by_id(sg->client, | 1639 client_entry = silc_client_get_client_by_id(sg->client, |
1632 sg->conn, | 1640 sg->conn, |
1633 buddy->proto_data); | 1641 buddy->proto_data); |
1634 | 1642 |
1635 if (client_entry && client_entry->send_key) { | 1643 if (client_entry && |
1644 silc_client_private_message_key_is_set(sg->client, | |
1645 sg->conn, client_entry)) { | |
1636 act = purple_menu_action_new(_("Reset IM Key"), | 1646 act = purple_menu_action_new(_("Reset IM Key"), |
1637 PURPLE_CALLBACK(silcpurple_buddy_resetkey), | 1647 PURPLE_CALLBACK(silcpurple_buddy_resetkey), |
1638 NULL, NULL); | 1648 NULL, NULL); |
1639 m = g_list_append(m, act); | 1649 m = g_list_append(m, act); |
1640 | |
1641 } else { | 1650 } else { |
1642 act = purple_menu_action_new(_("IM with Key Exchange"), | 1651 act = purple_menu_action_new(_("IM with Key Exchange"), |
1643 PURPLE_CALLBACK(silcpurple_buddy_keyagr), | 1652 PURPLE_CALLBACK(silcpurple_buddy_keyagr), |
1644 NULL, NULL); | 1653 NULL, NULL); |
1645 m = g_list_append(m, act); | 1654 m = g_list_append(m, act); |
1688 SilcPurple sg = gc->proto_data; | 1697 SilcPurple sg = gc->proto_data; |
1689 SilcClient client = sg->client; | 1698 SilcClient client = sg->client; |
1690 SilcClientConnection conn = sg->conn; | 1699 SilcClientConnection conn = sg->conn; |
1691 SilcMime mime; | 1700 SilcMime mime; |
1692 char type[32]; | 1701 char type[32]; |
1693 unsigned char *icon; | |
1694 const char *t; | 1702 const char *t; |
1695 SilcAttributeObjMime obj; | |
1696 | 1703 |
1697 /* Remove */ | 1704 /* Remove */ |
1698 if (!img) { | 1705 if (!img) { |
1699 silc_client_attribute_del(client, conn, | 1706 silc_client_attribute_del(client, conn, |
1700 SILC_ATTRIBUTE_USER_ICON, NULL); | 1707 SILC_ATTRIBUTE_USER_ICON, NULL); |
1715 t = "jpeg"; | 1722 t = "jpeg"; |
1716 g_snprintf(type, sizeof(type), "image/%s", t); | 1723 g_snprintf(type, sizeof(type), "image/%s", t); |
1717 silc_mime_add_field(mime, "Content-Type", type); | 1724 silc_mime_add_field(mime, "Content-Type", type); |
1718 silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); | 1725 silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img)); |
1719 | 1726 |
1720 obj.mime = icon = silc_mime_encode(mime, &obj.mime_len); | 1727 silc_client_attribute_add(client, conn, |
1721 if (obj.mime) | 1728 SILC_ATTRIBUTE_USER_ICON, mime, sizeof(*mime)); |
1722 silc_client_attribute_add(client, conn, | 1729 |
1723 SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj)); | |
1724 | |
1725 silc_free(icon); | |
1726 silc_mime_free(mime); | 1730 silc_mime_free(mime); |
1727 } | 1731 } |
1728 #endif | 1732 #endif |