Added user public key, user signature and server signature
[silc.git] / apps / irssi / src / silc / core / silc-queries.c
1 /*
2
3   silc-queries.c 
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 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
20 #include "module.h"
21 #include "signals.h"
22 #include "misc.h"
23 #include "silc-queries.h"
24 #include "settings.h"
25 #include "levels.h"
26 #include "modules.h"
27 #include "commands.h"
28 #include "misc.h"
29
30 #include "fe-common/core/printtext.h"
31 #include "fe-common/core/fe-channels.h"
32 #include "fe-common/core/keyboard.h"
33 #include "fe-common/silc/module-formats.h"
34
35 static void silc_query_attributes_print_final(bool success, void *context);
36
37 QUERY_REC *silc_query_create(const char *server_tag,
38                              const char *nick, int automatic)
39 {
40   QUERY_REC *rec;
41
42   g_return_val_if_fail(nick != NULL, NULL);
43
44   rec = g_new0(QUERY_REC, 1);
45   rec->chat_type = SILC_PROTOCOL;
46   rec->name = g_strdup(nick);
47   rec->server_tag = g_strdup(server_tag);
48   query_init(rec, automatic);
49   return rec;
50 }
51
52 void silc_queries_init(void)
53 {
54 }
55
56 void silc_queries_deinit(void)
57 {
58 }
59
60 /* ATTR command */
61
62 void command_attr(const char *data, SILC_SERVER_REC *server,
63                   WI_ITEM_REC *item)
64 {
65   char *tmp;
66   unsigned char **argv;
67   SilcUInt32 argc;
68   SilcUInt32 *argv_lens, *argv_types;
69   const char *sv;
70   bool allowed;
71
72   /* Now parse all arguments */
73   tmp = g_strconcat("ATTR", " ", data, NULL);
74   silc_parse_command_line(tmp, &argv, &argv_lens, &argv_types, &argc, 3);
75   g_free(tmp);
76
77   if (argc == 1) {
78     /* Show all attributes */
79     printformat_module("fe-common/silc", server, NULL,
80                        MSGLEVEL_CRAP, SILCTXT_ATTR_HEADER);
81
82     allowed = settings_get_bool("attr_allow");
83     printformat_module("fe-common/silc", server, NULL,
84                        MSGLEVEL_CRAP, SILCTXT_ATTR_ALLOW,
85                        allowed ? "Yes" : "No");
86
87     sv = settings_get_str("attr_vcard");
88     if (sv && *sv)
89       printformat_module("fe-common/silc", server, NULL,
90                          MSGLEVEL_CRAP, SILCTXT_ATTR_VCARD_FILE, sv);
91
92     sv = settings_get_str("attr_services");
93     if (sv && *sv)
94       printformat_module("fe-common/silc", server, NULL,
95                          MSGLEVEL_CRAP, SILCTXT_ATTR_SERVICES, sv);
96
97     sv = settings_get_str("attr_status_mood");
98     if (sv && *sv)
99       printformat_module("fe-common/silc", server, NULL,
100                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MOOD, sv);
101
102     sv = settings_get_str("attr_status_text");
103     if (sv && *sv)
104       printformat_module("fe-common/silc", server, NULL,
105                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_TEXT, sv);
106
107     sv = settings_get_str("attr_status_message");
108     if (sv && *sv)
109       printformat_module("fe-common/silc", server, NULL,
110                          MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MESSAGE_FILE,
111                          sv);
112
113     sv = settings_get_str("attr_preferred_language");
114     if (sv && *sv)
115       printformat_module("fe-common/silc", server, NULL,
116                          MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_LANGUAGE,
117                          sv);
118
119     sv = settings_get_str("attr_preferred_contact");
120     if (sv && *sv)
121       printformat_module("fe-common/silc", server, NULL,
122                          MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_CONTACT,
123                          sv);
124
125     sv = settings_get_str("attr_geolocation");
126     if (sv && *sv)
127       printformat_module("fe-common/silc", server, NULL,
128                          MSGLEVEL_CRAP, SILCTXT_ATTR_GEOLOCATION,
129                          sv);
130
131     sv = settings_get_str("attr_device_info");
132     if (sv && *sv)
133       printformat_module("fe-common/silc", server, NULL,
134                          MSGLEVEL_CRAP, SILCTXT_ATTR_DEVICE_INFO,
135                          sv);
136
137     sv = settings_get_str("attr_public_keys");
138     if (sv && *sv)
139       printformat_module("fe-common/silc", server, NULL,
140                          MSGLEVEL_CRAP, SILCTXT_ATTR_PUBLIC_KEYS,
141                          sv);
142
143     allowed = settings_get_bool("attr_timezone");
144     printformat_module("fe-common/silc", server, NULL,
145                        MSGLEVEL_CRAP, SILCTXT_ATTR_TIMEZONE_ALLOW,
146                        allowed ? "Yes" : "No");
147
148     printformat_module("fe-common/silc", server, NULL,
149                        MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER);
150     return;
151   }
152
153   if (argc < 3)
154     cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
155
156   if (!strcasecmp(argv[1], "-del")) {
157     /* Delete attribute */
158     if (!strcasecmp(argv[1], "vcard")) {
159       silc_client_attribute_del(silc_client, server->conn,
160                                 SILC_ATTRIBUTE_USER_INFO, NULL);
161       settings_set_str("attr_vcard", "");
162     } else if (!strcasecmp(argv[1], "services")) {
163       silc_client_attribute_del(silc_client, server->conn,
164                                 SILC_ATTRIBUTE_SERVICE, NULL);
165       settings_set_str("attr_services", argv[2]);
166     } else if (!strcasecmp(argv[1], "status_mood")) {
167       silc_client_attribute_del(silc_client, server->conn,
168                                 SILC_ATTRIBUTE_STATUS_MOOD, NULL);
169       settings_set_str("attr_status_mood", "");
170     } else if (!strcasecmp(argv[1], "status_text")) {
171       silc_client_attribute_del(silc_client, server->conn,
172                                 SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
173       settings_set_str("attr_status_text", "");
174     } else if (!strcasecmp(argv[1], "status_message")) {
175       silc_client_attribute_del(silc_client, server->conn,
176                                 SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
177       settings_set_str("attr_status_message", "");
178     } else if (!strcasecmp(argv[1], "preferred_langauge")) {
179       silc_client_attribute_del(silc_client, server->conn,
180                                 SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
181       settings_set_str("attr_preferred_language", "");
182     } else if (!strcasecmp(argv[1], "preferred_contact")) {
183       silc_client_attribute_del(silc_client, server->conn,
184                                 SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
185       settings_set_str("attr_preferred_contact", "");
186     } else if (!strcasecmp(argv[1], "timezone")) {
187       return;
188     } else if (!strcasecmp(argv[1], "geolocation")) {
189       silc_client_attribute_del(silc_client, server->conn,
190                                 SILC_ATTRIBUTE_GEOLOCATION, NULL);
191       settings_set_str("attr_geolocation", "");
192     } else if (!strcasecmp(argv[1], "device_info")) {
193       silc_client_attribute_del(silc_client, server->conn,
194                                 SILC_ATTRIBUTE_DEVICE_INFO, NULL);
195       settings_set_str("attr_device_info", "");
196     } else if (!strcasecmp(argv[1], "public_keys")) {
197       silc_client_attribute_del(silc_client, server->conn,
198                                 SILC_ATTRIBUTE_USER_PUBLIC_KEY, NULL);
199       settings_set_str("attr_public_keys", "");
200     } else {
201       cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
202     }
203     return;
204   }
205
206   /* Add new attribute */
207   if (!strcasecmp(argv[1], "allow")) {
208     allowed = !strcasecmp(argv[2], "ON") || !strcasecmp(argv[2], "YES");
209     settings_set_bool("attr_allow", allowed);
210   } else if (!strcasecmp(argv[1], "vcard")) {
211     settings_set_str("attr_vcard", argv[2]);
212   } else if (!strcasecmp(argv[1], "services")) {
213     settings_set_str("attr_services", argv[2]);
214   } else if (!strcasecmp(argv[1], "status_mood")) {
215     settings_set_str("attr_status_mood", argv[2]);
216   } else if (!strcasecmp(argv[1], "status_text")) {
217     settings_set_str("attr_status_text", argv[2]);
218   } else if (!strcasecmp(argv[1], "status_message")) {
219     settings_set_str("attr_status_message", argv[2]);
220   } else if (!strcasecmp(argv[1], "preferred_langauge")) {
221     settings_set_str("attr_preferred_language", argv[2]);
222   } else if (!strcasecmp(argv[1], "preferred_contact")) {
223     settings_set_str("attr_preferred_contact", argv[2]);
224   } else if (!strcasecmp(argv[1], "timezone")) {
225     allowed = !strcasecmp(argv[2], "ON") || !strcasecmp(argv[2], "YES");
226     settings_set_bool("attr_timezone", allowed);
227   } else if (!strcasecmp(argv[1], "geolocation")) {
228     settings_set_str("attr_geolocation", argv[2]);
229   } else if (!strcasecmp(argv[1], "device_info")) {
230     settings_set_str("attr_device_info", argv[2]);
231   } else if (!strcasecmp(argv[1], "public_keys")) {
232     settings_set_str("attr_public_keys", argv[2]);
233   } else {
234     cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
235   }
236
237   silc_query_attributes_default(silc_client, server->conn);
238 }
239
240 /* Put default attributes to client library */
241
242 void silc_query_attributes_default(SilcClient client,
243                                    SilcClientConnection conn)
244 {
245   char *tmp, **list, **entry;
246   const char *sv;
247   SilcUInt32 tmp_len, mask;
248   SilcAttributeObjService service;
249   SilcAttributeObjMime mime;
250   SilcAttributeObjGeo geo;
251   SilcAttributeObjDevice dev;
252   SilcAttributeObjPk pk;
253   SilcVCardStruct vcard;
254   bool allowed;
255
256   memset(&service, 0, sizeof(service));
257   memset(&mime, 0, sizeof(mime));
258   memset(&geo, 0, sizeof(geo));
259   memset(&dev, 0, sizeof(dev));
260   memset(&pk, 0, sizeof(pk));
261   memset(&vcard, 0, sizeof(vcard));
262
263   sv = settings_get_str("attr_vcard");
264   if (sv && *sv) {
265     /* Put USER_INFO */
266     silc_client_attribute_del(silc_client, conn,
267                               SILC_ATTRIBUTE_USER_INFO, NULL);
268     tmp = silc_file_readfile(sv, &tmp_len);
269     if (tmp && silc_vcard_decode(tmp, tmp_len, &vcard))
270       silc_client_attribute_add(silc_client, conn,
271                                 SILC_ATTRIBUTE_USER_INFO, (void *)&vcard,
272                                 sizeof(vcard));
273     silc_vcard_free(&vcard);
274     silc_free(tmp);
275   }
276
277   sv = settings_get_str("attr_services");
278   if (sv && *sv) {
279     /* Put SERVICE */
280     silc_client_attribute_del(silc_client, conn,
281                               SILC_ATTRIBUTE_SERVICE, NULL);
282     list = g_strsplit(sv, " ", -1);
283     for (entry = list; *entry != NULL; entry++) {
284       if (!strchr(*entry, ':'))
285         continue;
286       tmp = strchr(*entry, ':') + 1;
287       if (!tmp || !(*tmp))
288         continue;
289       service.port = atoi(tmp);
290       *strchr(*entry, ':') = '\0';
291       silc_strncat(service.address, sizeof(service.address), *entry,
292                    strlen(*entry));
293       service.status = TRUE;
294       silc_client_attribute_add(silc_client, conn,
295                                 SILC_ATTRIBUTE_SERVICE, &service,
296                                 sizeof(service));
297     }
298     g_strfreev(list);
299   }
300
301   sv = settings_get_str("attr_status_mood");
302   if (sv && *sv) {
303     /* Put STATUS_MOOD */
304     silc_client_attribute_del(silc_client, conn,
305                               SILC_ATTRIBUTE_STATUS_MOOD, NULL);
306     mask = 0;
307     list = g_strsplit(sv, " ", -1);
308     for (entry = list; *entry != NULL; entry++) {
309       if (!strcasecmp(*entry, "NORMAL"))
310         mask |= SILC_ATTRIBUTE_MOOD_NORMAL;
311       if (!strcasecmp(*entry, "HAPPY"))
312         mask |= SILC_ATTRIBUTE_MOOD_HAPPY;
313       if (!strcasecmp(*entry, "SAD"))
314         mask |= SILC_ATTRIBUTE_MOOD_SAD;
315       if (!strcasecmp(*entry, "ANGRY"))
316         mask |= SILC_ATTRIBUTE_MOOD_ANGRY;
317       if (!strcasecmp(*entry, "JEALOUS"))
318         mask |= SILC_ATTRIBUTE_MOOD_JEALOUS;
319       if (!strcasecmp(*entry, "ASHAMED"))
320         mask |= SILC_ATTRIBUTE_MOOD_ASHAMED;
321       if (!strcasecmp(*entry, "INVINCIBLE"))
322         mask |= SILC_ATTRIBUTE_MOOD_INVINCIBLE;
323       if (!strcasecmp(*entry, "INLOVE"))
324         mask |= SILC_ATTRIBUTE_MOOD_INLOVE;
325       if (!strcasecmp(*entry, "SLEEPY"))
326         mask |= SILC_ATTRIBUTE_MOOD_SLEEPY;
327       if (!strcasecmp(*entry, "BORED"))
328         mask |= SILC_ATTRIBUTE_MOOD_BORED;
329       if (!strcasecmp(*entry, "EXCITED"))
330         mask |= SILC_ATTRIBUTE_MOOD_EXCITED;
331       if (!strcasecmp(*entry, "ANXIOUS"))
332         mask |= SILC_ATTRIBUTE_MOOD_ANXIOUS;
333       silc_client_attribute_add(silc_client, conn,
334                                 SILC_ATTRIBUTE_STATUS_MOOD, (void *)mask,
335                                 sizeof(SilcUInt32));
336     }
337     g_strfreev(list);
338   }
339
340   sv = settings_get_str("attr_status_text");
341   if (sv && *sv) {
342     /* Put STATUS_TEXT */
343     silc_client_attribute_del(silc_client, conn,
344                               SILC_ATTRIBUTE_STATUS_FREETEXT, NULL);
345     silc_client_attribute_add(silc_client, conn,
346                               SILC_ATTRIBUTE_STATUS_FREETEXT, (void *)sv,
347                               strlen(sv));
348   }
349
350   sv = settings_get_str("attr_status_message");
351   if (sv && *sv) {
352     /* Put STATUS_MESSAGE */
353     silc_client_attribute_del(silc_client, conn,
354                               SILC_ATTRIBUTE_STATUS_MESSAGE, NULL);
355     tmp = silc_file_readfile(sv, &tmp_len);
356     if (tmp) {
357       mime.mime = (const unsigned char *)tmp;
358       mime.mime_len = tmp_len;
359       silc_client_attribute_add(silc_client, conn,
360                                 SILC_ATTRIBUTE_STATUS_MESSAGE, &mime,
361                                 sizeof(mime));
362     }
363     silc_free(tmp);
364   }
365
366   sv = settings_get_str("attr_preferred_language");
367   if (sv && *sv) {
368     /* Put PREFERRED_LANGUAGE */
369     silc_client_attribute_del(silc_client, conn,
370                               SILC_ATTRIBUTE_PREFERRED_LANGUAGE, NULL);
371     list = g_strsplit(sv, " ", -1);
372     for (entry = list; *entry != NULL; entry++) {
373       silc_client_attribute_add(silc_client, conn,
374                                 SILC_ATTRIBUTE_PREFERRED_LANGUAGE, *entry,
375                                 strlen(*entry));
376     }
377     g_strfreev(list);
378   }
379
380   sv = settings_get_str("attr_preferred_contact");
381   if (sv && *sv) {
382     /* Put PREFERRED_CONTACT */
383     silc_client_attribute_del(silc_client, conn,
384                               SILC_ATTRIBUTE_PREFERRED_CONTACT, NULL);
385     mask = 0;
386     list = g_strsplit(sv, " ", -1);
387     for (entry = list; *entry != NULL; entry++) {
388       if (!strcasecmp(*entry, "NONE"))
389         mask = 0;
390       if (!strcasecmp(*entry, "EMAIL"))
391         mask |= SILC_ATTRIBUTE_CONTACT_EMAIL;
392       if (!strcasecmp(*entry, "CALL"))
393         mask |= SILC_ATTRIBUTE_CONTACT_CALL;
394       if (!strcasecmp(*entry, "PAGE"))
395         mask |= SILC_ATTRIBUTE_CONTACT_PAGE;
396       if (!strcasecmp(*entry, "SMS"))
397         mask |= SILC_ATTRIBUTE_CONTACT_SMS;
398       if (!strcasecmp(*entry, "MMS"))
399         mask |= SILC_ATTRIBUTE_CONTACT_MMS;
400       if (!strcasecmp(*entry, "CHAT"))
401         mask |= SILC_ATTRIBUTE_CONTACT_CHAT;
402       silc_client_attribute_add(silc_client, conn,
403                                 SILC_ATTRIBUTE_PREFERRED_CONTACT, (void *)mask,
404                                 sizeof(SilcUInt32));
405     }
406     g_strfreev(list);
407   }
408
409   /* Put TIMEZONE */
410   allowed = settings_get_bool("attr_timezone");
411   silc_client_attribute_del(silc_client, conn,
412                             SILC_ATTRIBUTE_TIMEZONE, NULL);
413   if (allowed)
414     silc_client_attribute_add(silc_client, conn,
415                               SILC_ATTRIBUTE_TIMEZONE, "foo", 3);
416
417   sv = settings_get_str("attr_geolocation");
418   if (sv && *sv) {
419     /* Put GEOLOCATION */
420     silc_client_attribute_del(silc_client, conn,
421                               SILC_ATTRIBUTE_GEOLOCATION, NULL);
422     list = g_strsplit(sv, ":", -1);
423     for (entry = list; *entry != NULL; entry++) {
424       if (!geo.longitude) {
425         geo.longitude = *entry;
426         continue;
427       }
428       if (!geo.latitude) {
429         geo.latitude = *entry;
430         continue;
431       }
432       if (!geo.altitude) {
433         geo.altitude = *entry;
434         continue;
435       }
436       if (!geo.accuracy) {
437         geo.accuracy = *entry;
438         continue;
439       }
440     }
441     silc_client_attribute_add(silc_client, conn,
442                               SILC_ATTRIBUTE_GEOLOCATION, &geo,
443                               sizeof(geo));
444     g_strfreev(list);
445   }
446
447   sv = settings_get_str("attr_device_info");
448   if (sv && *sv) {
449     /* Put DEVICE_INFO */
450     silc_client_attribute_del(silc_client, conn,
451                               SILC_ATTRIBUTE_DEVICE_INFO, NULL);
452     allowed = FALSE;
453     list = g_strsplit(sv, ":", -1);
454     for (entry = list; *entry != NULL; entry++) {
455       if (!allowed) {
456         allowed = TRUE;
457         if (!strcasecmp(*entry, "COMPUTER"))
458           dev.type = SILC_ATTRIBUTE_DEVICE_COMPUTER;
459         if (!strcasecmp(*entry, "MOBILE_PHONE"))
460           dev.type = SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE;
461         if (!strcasecmp(sv, "PDA"))
462           dev.type = SILC_ATTRIBUTE_DEVICE_PDA;
463         if (!strcasecmp(sv, "TERMINAL"))
464           dev.type = SILC_ATTRIBUTE_DEVICE_TERMINAL;
465         continue;
466       }
467       if (!dev.manufacturer) {
468         dev.manufacturer = *entry;
469         continue;
470       }
471       if (!dev.version) {
472         dev.version = *entry;
473         continue;
474       }
475       if (!dev.model) {
476         dev.model = *entry;
477         continue;
478       }
479       if (!dev.language) {
480         dev.language = *entry;
481         continue;
482       }
483     }
484     silc_client_attribute_add(silc_client, conn,
485                               SILC_ATTRIBUTE_DEVICE_INFO, &dev,
486                               sizeof(dev));
487     g_strfreev(list);
488   }
489
490   sv = settings_get_str("attr_public_keys");
491   if (sv && *sv) {
492     /* Put USER_PUBLIC_KEY */
493     silc_client_attribute_del(silc_client, conn,
494                               SILC_ATTRIBUTE_USER_PUBLIC_KEY, NULL);
495     list = g_strsplit(sv, " ", -1);
496     for (entry = list; *entry != NULL; entry++) {
497       if (!strncasecmp(*entry, "silc-rsa:", 8)) {
498         tmp = silc_file_readfile((*entry) + 8, &tmp_len);
499         if (tmp) {
500           pk.type = "silc-rsa";
501           pk.data = tmp;
502           pk.data_len = tmp_len;
503           silc_client_attribute_add(silc_client, conn,
504                                     SILC_ATTRIBUTE_USER_PUBLIC_KEY, &pk,
505                                     sizeof(pk));
506         }
507         silc_free(tmp);
508       } else {
509         silc_say_error("Unsupported public key type '%s'", *entry);
510       }
511     }
512     g_strfreev(list);
513   }
514 }
515
516 typedef struct {
517   SILC_SERVER_REC *server;
518   char *name;
519   SilcAttributeObjPk userpk;
520   SilcVCardStruct vcard;
521   SilcAttributeObjMime message;
522   SilcAttributeObjMime extension;
523 } *AttrVerify;
524
525 void silc_query_attributes_print(SILC_SERVER_REC *server,
526                                  SilcClient client,
527                                  SilcClientConnection conn,
528                                  SilcDList attrs,
529                                  SilcClientEntry client_entry)
530 {
531   SilcAttributePayload attr;
532   SilcAttribute attribute;
533   char tmp[512];
534   SilcAttributeObjPk serverpk, usersign, serversign;
535   AttrVerify verify;
536
537   printformat_module("fe-common/silc", server, NULL,
538                      MSGLEVEL_CRAP, SILCTXT_ATTR_HEADER);
539
540   memset(&serverpk, 0, sizeof(serverpk));
541   memset(&usersign, 0, sizeof(usersign));
542   memset(&serversign, 0, sizeof(serversign));
543
544   verify = silc_calloc(1, sizeof(*verify));
545   if (!verify)
546     return;
547   verify->server = server;
548   verify->name = strdup(client_entry->nickname);
549
550   silc_dlist_start(attrs);
551   while ((attr = silc_dlist_get(attrs)) != SILC_LIST_END) {
552     attribute = silc_attribute_get_attribute(attr);
553     memset(tmp, 0, sizeof(tmp));
554
555     switch (attribute) {
556
557     case SILC_ATTRIBUTE_USER_INFO:
558       {
559         if (!silc_attribute_get_object(attr, (void *)&verify->vcard,
560                                        sizeof(verify->vcard)))
561           continue;
562         printformat_module("fe-common/silc", server, NULL,
563                            MSGLEVEL_CRAP, SILCTXT_ATTR_VCARD_FILE,
564                            "present");
565       }
566       break;
567
568     case SILC_ATTRIBUTE_SERVICE:
569       {
570         SilcAttributeObjService service;
571         if (!silc_attribute_get_object(attr, (void *)&service,
572                                        sizeof(service)))
573           continue;
574         snprintf(tmp, sizeof(tmp) - 1, "%s:%d (logged %s)",
575                  service.address, (unsigned int)service.port,
576                  service.status ? "in" : "out");
577         printformat_module("fe-common/silc", server, NULL,
578                            MSGLEVEL_CRAP, SILCTXT_ATTR_SERVICES, tmp);
579       }
580       break;
581
582     case SILC_ATTRIBUTE_STATUS_MOOD:
583       {
584         SilcUInt32 mask;
585         if (!silc_attribute_get_object(attr, (void *)&mask, sizeof(mask)))
586           continue;
587         if (!mask)
588           silc_strncat(tmp, sizeof(tmp), "NORMAL ", strlen(" NORMAL"));
589         if (mask & SILC_ATTRIBUTE_MOOD_HAPPY)
590           silc_strncat(tmp, sizeof(tmp), "HAPPY ", strlen(" HAPPY"));
591         if (mask & SILC_ATTRIBUTE_MOOD_SAD)
592           silc_strncat(tmp, sizeof(tmp), "SAD ", strlen(" SAD"));
593         if (mask & SILC_ATTRIBUTE_MOOD_ANGRY)
594           silc_strncat(tmp, sizeof(tmp), "ANGRY ", strlen(" ANGRY"));
595         if (mask & SILC_ATTRIBUTE_MOOD_JEALOUS)
596           silc_strncat(tmp, sizeof(tmp), "JEALOUS ", strlen(" JEALOUS"));
597         if (mask & SILC_ATTRIBUTE_MOOD_ASHAMED)
598           silc_strncat(tmp, sizeof(tmp), "ASHAMED ", strlen(" ASHAMED"));
599         if (mask & SILC_ATTRIBUTE_MOOD_INVINCIBLE)
600           silc_strncat(tmp, sizeof(tmp), "INVINCIBLE ", strlen(" INVINCIBLE"));
601         if (mask & SILC_ATTRIBUTE_MOOD_INLOVE)
602           silc_strncat(tmp, sizeof(tmp), "INLOVE ", strlen(" INLOVE"));
603         if (mask & SILC_ATTRIBUTE_MOOD_SLEEPY)
604           silc_strncat(tmp, sizeof(tmp), "SLEEPY ", strlen(" SLEEPY"));
605         if (mask & SILC_ATTRIBUTE_MOOD_BORED)
606           silc_strncat(tmp, sizeof(tmp), "BORED ", strlen(" BORED"));
607         if (mask & SILC_ATTRIBUTE_MOOD_EXCITED)
608           silc_strncat(tmp, sizeof(tmp), "EXCITED ", strlen(" EXCITED"));
609         if (mask & SILC_ATTRIBUTE_MOOD_ANXIOUS)
610           silc_strncat(tmp, sizeof(tmp), "ANXIOUS ", strlen(" ANXIOUS"));
611         printformat_module("fe-common/silc", server, NULL,
612                            MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MOOD, tmp);
613       }
614       break;
615
616     case SILC_ATTRIBUTE_STATUS_FREETEXT:
617       {
618         if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
619           continue;
620         printformat_module("fe-common/silc", server, NULL,
621                            MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_TEXT, tmp);
622       }
623       break;
624
625     case SILC_ATTRIBUTE_STATUS_MESSAGE:
626       {
627         if (!silc_attribute_get_object(attr, (void *)&verify->message,
628                                        sizeof(verify->message)))
629           continue;
630         printformat_module("fe-common/silc", server, NULL,
631                            MSGLEVEL_CRAP, SILCTXT_ATTR_STATUS_MESSAGE,
632                            "present");
633       }
634       break;
635
636     case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
637       {
638         if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
639           continue;
640         printformat_module("fe-common/silc", server, NULL,
641                            MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_LANGUAGE,
642                            tmp);
643       }
644       break;
645
646     case SILC_ATTRIBUTE_PREFERRED_CONTACT:
647       {
648         SilcUInt32 mask;
649         if (!silc_attribute_get_object(attr, (void *)&mask, sizeof(mask)))
650           continue;
651         if (!mask)
652           silc_strncat(tmp, sizeof(tmp), "NONE ", strlen(" NONE"));
653         if (mask & SILC_ATTRIBUTE_CONTACT_CHAT)
654           silc_strncat(tmp, sizeof(tmp), "CHAT ", strlen(" CHAT"));
655         if (mask & SILC_ATTRIBUTE_CONTACT_EMAIL)
656           silc_strncat(tmp, sizeof(tmp), "EMAIL ", strlen(" EMAIL"));
657         if (mask & SILC_ATTRIBUTE_CONTACT_CALL)
658           silc_strncat(tmp, sizeof(tmp), "CALL ", strlen(" CALL"));
659         if (mask & SILC_ATTRIBUTE_CONTACT_PAGE)
660           silc_strncat(tmp, sizeof(tmp), "PAGE ", strlen(" PAGE"));
661         if (mask & SILC_ATTRIBUTE_CONTACT_SMS)
662           silc_strncat(tmp, sizeof(tmp), "SMS ", strlen(" SMS"));
663         if (mask & SILC_ATTRIBUTE_CONTACT_MMS)
664           silc_strncat(tmp, sizeof(tmp), "MMS ", strlen(" MMS"));
665         printformat_module("fe-common/silc", server, NULL,
666                            MSGLEVEL_CRAP, SILCTXT_ATTR_PREFERRED_CONTACT, tmp);
667       }
668       break;
669
670     case SILC_ATTRIBUTE_TIMEZONE:
671       {
672         if (!silc_attribute_get_object(attr, (void *)&tmp, sizeof(tmp) - 1))
673           continue;
674         printformat_module("fe-common/silc", server, NULL,
675                            MSGLEVEL_CRAP, SILCTXT_ATTR_TIMEZONE, tmp);
676       }
677       break;
678
679     case SILC_ATTRIBUTE_EXTENSION:
680       {
681         if (!silc_attribute_get_object(attr, (void *)&verify->extension,
682                                        sizeof(verify->extension)))
683           continue;
684         printformat_module("fe-common/silc", server, NULL,
685                            MSGLEVEL_CRAP, SILCTXT_ATTR_EXTENSION,
686                            "present");
687       }
688       break;
689
690     case SILC_ATTRIBUTE_GEOLOCATION:
691       {
692         SilcAttributeObjGeo geo;
693         memset(&geo, 0, sizeof(geo));
694         if (!silc_attribute_get_object(attr, (void *)&geo, sizeof(geo)))
695           continue;
696         snprintf(tmp, sizeof(tmp) - 1, "%s:%s:%s:%s",
697                  geo.longitude ? geo.longitude : "",
698                  geo.latitude ? geo.latitude : "",
699                  geo.altitude ? geo.altitude : "",
700                  geo.accuracy ? geo.accuracy : "");
701         printformat_module("fe-common/silc", server, NULL,
702                            MSGLEVEL_CRAP, SILCTXT_ATTR_GEOLOCATION, tmp);
703       }
704       break;
705
706     case SILC_ATTRIBUTE_DEVICE_INFO:
707       {
708         SilcAttributeObjDevice dev;
709         memset(&dev, 0, sizeof(dev));
710         if (!silc_attribute_get_object(attr, (void *)&dev, sizeof(dev)))
711           continue;
712         snprintf(tmp, sizeof(tmp) - 1, "%s:%s:%s:%s:%s",
713                  (dev.type == SILC_ATTRIBUTE_DEVICE_COMPUTER ? "COMPUTER" :
714                   dev.type == SILC_ATTRIBUTE_DEVICE_PDA ? "PDA" :
715                   dev.type == SILC_ATTRIBUTE_DEVICE_MOBILE_PHONE ?
716                   "MOBILE PHONE" :
717                   dev.type == SILC_ATTRIBUTE_DEVICE_TERMINAL ? "TERMINAL" :
718                   ""),
719                  dev.manufacturer ? dev.manufacturer : "",
720                  dev.version ? dev.version : "",
721                  dev.model ? dev.model: "",
722                  dev.language ? dev.language : "");
723         printformat_module("fe-common/silc", server, NULL,
724                            MSGLEVEL_CRAP, SILCTXT_ATTR_DEVICE_INFO, tmp);
725       }
726       break;
727
728     case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
729       {
730         if (verify->userpk.type)
731           continue;
732         if (!silc_attribute_get_object(attr, (void *)&verify->userpk,
733                                        sizeof(verify->userpk)))
734           continue;
735       }
736       break;
737
738     case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
739       {
740         if (serverpk.type)
741           continue;
742         if (!silc_attribute_get_object(attr, (void *)&serverpk,
743                                        sizeof(serverpk)))
744           continue;
745       }
746       break;
747
748     case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
749       {
750         if (usersign.data)
751           continue;
752         if (!silc_attribute_get_object(attr, (void *)&usersign,
753                                        sizeof(usersign)))
754           continue;
755       }
756       break;
757
758     case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
759       {
760         if (serversign.data)
761           continue;
762         if (!silc_attribute_get_object(attr, (void *)&serversign,
763                                        sizeof(serversign)))
764           continue;
765       }
766       break;
767
768     default:
769       break;
770     }
771   }
772
773   /* Handle the signature verifications and public key verifying here */
774
775   if (usersign.data && !strcmp(verify->userpk.type, "silc-rsa")) {
776     /* Verify the signature now */
777     SilcPublicKey public_key;
778     SilcPKCS pkcs;
779     unsigned char *verifyd;
780     SilcUInt32 verify_len;
781
782     if (silc_pkcs_public_key_decode(verify->userpk.data,
783                                     verify->userpk.data_len,
784                                     &public_key)) {
785       silc_pkcs_alloc("rsa", &pkcs);
786       verifyd = silc_attribute_get_verify_data(attrs, FALSE, &verify_len);
787       if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)){
788         if (silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
789                                        usersign.data,
790                                        usersign.data_len,
791                                        verifyd, verify_len)) {
792           printformat_module("fe-common/silc", server, NULL,
793                              MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_VERIFIED);
794         } else {
795           printformat_module("fe-common/silc", server, NULL,
796                              MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_FAILED);
797         }
798       }
799
800       silc_pkcs_public_key_free(public_key);
801       silc_free(verifyd);
802     }
803   } else {
804     printformat_module("fe-common/silc", server, NULL,
805                        MSGLEVEL_CRAP, SILCTXT_ATTR_USER_SIGN_NOT_PRESENT);
806   }
807
808   if (serversign.data && !strcmp(serverpk.type, "silc-rsa")) {
809     /* Verify the signature now */
810     SilcPublicKey public_key;
811     SilcPKCS pkcs;
812     unsigned char *verifyd;
813     SilcUInt32 verify_len;
814
815     if (silc_pkcs_public_key_decode(serverpk.data, serverpk.data_len,
816                                     &public_key)) {
817       silc_pkcs_alloc("rsa", &pkcs);
818       verifyd = silc_attribute_get_verify_data(attrs, TRUE, &verify_len);
819       if (verifyd && silc_pkcs_public_key_set(pkcs, public_key)) {
820         if (silc_pkcs_verify_with_hash(pkcs, client->sha1hash,
821                                        serversign.data,
822                                        serversign.data_len,
823                                        verifyd, verify_len)) {
824           printformat_module("fe-common/silc", server, NULL,
825                              MSGLEVEL_CRAP, SILCTXT_ATTR_SERVER_SIGN_VERIFIED);
826         } else {
827           printformat_module("fe-common/silc", server, NULL,
828                              MSGLEVEL_CRAP, SILCTXT_ATTR_SERVER_SIGN_FAILED);
829         }
830       }
831
832       silc_pkcs_public_key_free(public_key);
833       silc_free(verifyd);
834     }
835   }
836
837   if (!verify->userpk.type || !usersign.data)
838     printformat_module("fe-common/silc", server, NULL,
839                        MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER);
840
841   silc_verify_public_key(client, conn, SILC_SOCKET_TYPE_CLIENT,
842                          verify->userpk.data, verify->userpk.data_len, 
843                          SILC_SKE_PK_TYPE_SILC,
844                          silc_query_attributes_print_final, verify);
845 }
846
847 static void silc_query_attributes_print_final(bool success, void *context)
848 {
849   AttrVerify verify = context;
850   SILC_SERVER_REC *server = verify->server;
851
852   if (success) {
853     printformat_module("fe-common/silc", NULL, NULL,
854                        MSGLEVEL_CRAP, SILCTXT_GETKEY_VERIFIED, "user",
855                        verify->name);
856   } else {
857     printformat_module("fe-common/silc", NULL, NULL,
858                        MSGLEVEL_CRAP, SILCTXT_GETKEY_DISCARD, "user",
859                        verify->name);
860   }
861
862   printformat_module("fe-common/silc", server, NULL,
863                      MSGLEVEL_CRAP, SILCTXT_ATTR_FOOTER);
864
865   silc_free(verify->name);
866   silc_vcard_free(&verify->vcard);
867   silc_free(verify);
868 }