5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
21 #include "clientincludes.h"
23 /* Prints a message with three star (*) sign before the actual message
24 on the current output window. This is used to print command outputs
25 and error messages. */
27 void silc_say(SilcClient client, SilcClientConnection conn,
32 SilcClientInternal app = (SilcClientInternal)client->application;
34 memset(message, 0, sizeof(message));
35 strncat(message, "\n*** ", 5);
38 vsprintf(message + 5, msg, vp);
41 /* Print the message */
42 silc_print_to_window(app->screen->output_win[0], message);
45 /* Message for a channel. The `sender' is the nickname of the sender
46 received in the packet. The `channel_name' is the name of the channel. */
48 void silc_channel_message(SilcClient client, SilcClientConnection conn,
49 SilcClientEntry sender, SilcChannelEntry channel
52 /* Message from client */
53 if (conn && !strcmp(conn->current_channel->channel_name,
54 channel->channel_name))
55 silc_print(client, "<%s> %s", sender ? sender->nickname : "[<unknown>]",
58 silc_print(client, "<%s:%s> %s", sender ? sender->nickname : "[<unknown>]",
59 channel->channel_name, msg);
62 /* Private message to the client. The `sender' is the nickname of the
63 sender received in the packet. */
65 void silc_private_message(SilcClient client, SilcClientConnection conn,
66 SilcClientEntry sender, char *msg)
68 silc_print(client, "*%s* %s", sender->nickname, msg);
72 /* Notify message to the client. The notify arguments are sent in the
73 same order as servers sends them. The arguments are same as received
74 from the server except for ID's. If ID is received application receives
75 the corresponding entry to the ID. For example, if Client ID is received
76 application receives SilcClientEntry. Also, if the notify type is
77 for channel the channel entry is sent to application (even if server
80 void silc_notify(SilcClient client, SilcClientConnection conn,
81 SilcNotifyType type, ...)
83 SilcClientInternal app = (SilcClientInternal)client->application;
86 SilcClientEntry client_entry, client_entry2;
87 SilcChannelEntry channel_entry;
93 memset(message, 0, sizeof(message));
95 /* Get arguments (defined by protocol in silc-pp-01 -draft) */
97 case SILC_NOTIFY_TYPE_NONE:
98 tmp = va_arg(vp, char *);
101 strcpy(message, tmp);
104 case SILC_NOTIFY_TYPE_INVITE:
105 client_entry = va_arg(vp, SilcClientEntry);
106 channel_entry = va_arg(vp, SilcChannelEntry);
107 snprintf(message, sizeof(message), "%s invites you to channel %s",
108 client_entry->nickname, channel_entry->channel_name);
111 case SILC_NOTIFY_TYPE_JOIN:
112 client_entry = va_arg(vp, SilcClientEntry);
113 channel_entry = va_arg(vp, SilcChannelEntry);
114 snprintf(message, sizeof(message), "%s (%s) has joined channel %s",
115 client_entry->nickname, client_entry->username,
116 channel_entry->channel_name);
117 if (client_entry == conn->local_entry) {
120 silc_list_start(channel_entry->clients);
121 while ((chu = silc_list_get(channel_entry->clients)) != SILC_LIST_END) {
122 if (chu->client == client_entry) {
123 if (app->screen->bottom_line->mode)
124 silc_free(app->screen->bottom_line->mode);
125 app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode);
126 silc_screen_print_bottom_line(app->screen, 0);
133 case SILC_NOTIFY_TYPE_LEAVE:
134 client_entry = va_arg(vp, SilcClientEntry);
135 channel_entry = va_arg(vp, SilcChannelEntry);
136 if (client_entry->server)
137 snprintf(message, sizeof(message), "%s@%s has left channel %s",
138 client_entry->nickname, client_entry->server,
139 channel_entry->channel_name);
141 snprintf(message, sizeof(message), "%s has left channel %s",
142 client_entry->nickname, channel_entry->channel_name);
145 case SILC_NOTIFY_TYPE_SIGNOFF:
146 client_entry = va_arg(vp, SilcClientEntry);
147 tmp = va_arg(vp, char *);
148 if (client_entry->server)
149 snprintf(message, sizeof(message), "Signoff: %s@%s %s%s%s",
150 client_entry->nickname, client_entry->server,
151 tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
153 snprintf(message, sizeof(message), "Signoff: %s %s%s%s",
154 client_entry->nickname,
155 tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
158 case SILC_NOTIFY_TYPE_TOPIC_SET:
159 client_entry = va_arg(vp, SilcClientEntry);
160 tmp = va_arg(vp, char *);
161 channel_entry = va_arg(vp, SilcChannelEntry);
162 if (client_entry->server)
163 snprintf(message, sizeof(message), "%s@%s set topic on %s: %s",
164 client_entry->nickname, client_entry->server,
165 channel_entry->channel_name, tmp);
167 snprintf(message, sizeof(message), "%s set topic on %s: %s",
168 client_entry->nickname, channel_entry->channel_name, tmp);
171 case SILC_NOTIFY_TYPE_NICK_CHANGE:
172 client_entry = va_arg(vp, SilcClientEntry);
173 client_entry2 = va_arg(vp, SilcClientEntry);
174 if (client_entry->server && client_entry2->server)
175 snprintf(message, sizeof(message), "%s@%s is known as %s@%s",
176 client_entry->nickname, client_entry->server,
177 client_entry2->nickname, client_entry2->server);
179 snprintf(message, sizeof(message), "%s is known as %s",
180 client_entry->nickname, client_entry2->nickname);
183 case SILC_NOTIFY_TYPE_CMODE_CHANGE:
184 client_entry = va_arg(vp, SilcClientEntry);
185 tmp = silc_client_chmode(va_arg(vp, unsigned int));
186 channel_entry = va_arg(vp, SilcChannelEntry);
188 snprintf(message, sizeof(message), "%s changed channel mode to +%s",
189 client_entry->nickname, tmp);
191 snprintf(message, sizeof(message), "%s removed all channel modes",
192 client_entry->nickname);
193 if (app->screen->bottom_line->channel_mode)
194 silc_free(app->screen->bottom_line->channel_mode);
195 app->screen->bottom_line->channel_mode = tmp;
196 silc_screen_print_bottom_line(app->screen, 0);
199 case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
200 client_entry = va_arg(vp, SilcClientEntry);
201 tmp_int = va_arg(vp, unsigned int);
202 tmp = silc_client_chumode(tmp_int);
203 client_entry2 = va_arg(vp, SilcClientEntry);
204 channel_entry = va_arg(vp, SilcChannelEntry);
206 snprintf(message, sizeof(message), "%s changed %s's mode to +%s",
207 client_entry->nickname, client_entry2->nickname, tmp);
209 snprintf(message, sizeof(message), "%s removed %s's modes",
210 client_entry->nickname, client_entry2->nickname);
211 if (client_entry2 == conn->local_entry) {
212 if (app->screen->bottom_line->mode)
213 silc_free(app->screen->bottom_line->mode);
214 app->screen->bottom_line->mode = silc_client_chumode_char(tmp_int);
215 silc_screen_print_bottom_line(app->screen, 0);
220 case SILC_NOTIFY_TYPE_MOTD:
224 tmp = va_arg(vp, unsigned char *);
228 if (tmp[i++] == '\n') {
229 memset(line, 0, sizeof(line));
230 strncat(line, tmp, i - 1);
233 silc_say(client, conn, "%s", line);
243 case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
246 case SILC_NOTIFY_TYPE_KICKED:
247 client_entry = va_arg(vp, SilcClientEntry);
248 tmp = va_arg(vp, char *);
249 channel_entry = va_arg(vp, SilcChannelEntry);
251 if (client_entry == conn->local_entry) {
252 snprintf(message, sizeof(message),
253 "You have been kicked off channel %s %s%s%s",
254 conn->current_channel->channel_name,
255 tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
257 snprintf(message, sizeof(message),
258 "%s%s%s has been kicked off channel %s %s%s%s",
259 client_entry->nickname,
260 client_entry->server ? "@" : "",
261 client_entry->server ? client_entry->server : "",
262 conn->current_channel->channel_name,
263 tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
267 case SILC_NOTIFY_TYPE_KILLED:
268 client_entry = va_arg(vp, SilcClientEntry);
269 tmp = va_arg(vp, char *);
270 channel_entry = va_arg(vp, SilcChannelEntry);
272 if (client_entry == conn->local_entry) {
273 snprintf(message, sizeof(message),
274 "You have been killed from the SILC Network %s%s%s",
275 tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
277 snprintf(message, sizeof(message),
278 "%s%s%s has been killed from the SILC Network %s%s%s",
279 client_entry->nickname,
280 client_entry->server ? "@" : "",
281 client_entry->server ? client_entry->server : "",
282 tmp ? "(" : "", tmp ? tmp : "", tmp ? ")" : "");
290 silc_print(client, "*** %s", message);
293 /* Command handler. This function is called always in the command function.
294 If error occurs it will be called as well. `conn' is the associated
295 client connection. `cmd_context' is the command context that was
296 originally sent to the command. `success' is FALSE if error occured
297 during command. `command' is the command being processed. It must be
298 noted that this is not reply from server. This is merely called just
299 after application has called the command. Just to tell application
300 that the command really was processed. */
302 void silc_command(SilcClient client, SilcClientConnection conn,
303 SilcClientCommandContext cmd_context, int success,
306 SilcClientInternal app = (SilcClientInternal)client->application;
314 case SILC_COMMAND_QUIT:
315 app->screen->bottom_line->channel = NULL;
316 silc_screen_print_bottom_line(app->screen, 0);
319 case SILC_COMMAND_LEAVE:
321 if (!strncmp(conn->current_channel->channel_name, name, strlen(name))) {
322 app->screen->bottom_line->channel = NULL;
323 silc_screen_print_bottom_line(app->screen, 0);
331 /* We've resolved all clients we don't know about, now just print the
332 users from the channel on the screen. */
334 void silc_client_show_users(SilcClient client,
335 SilcClientConnection conn,
336 SilcClientEntry *clients,
337 unsigned int clients_count,
340 SilcChannelEntry channel = (SilcChannelEntry)context;
342 int k = 0, len1 = 0, len2 = 0;
343 char *name_list = NULL;
348 silc_list_start(channel->clients);
349 while ((chu = silc_list_get(channel->clients)) != SILC_LIST_END) {
350 char *m, *n = chu->client->nickname;
357 name_list = silc_realloc(name_list, sizeof(*name_list) * (len1 + 3));
359 m = silc_client_chumode_char(chu->mode);
361 memcpy(name_list + (len1 - len2), m, strlen(m));
366 memcpy(name_list + (len1 - len2), n, len2);
369 if (k == silc_list_count(channel->clients) - 1)
371 memcpy(name_list + len1, " ", 1);
376 client->ops->say(client, conn, "Users on %s: %s", channel->channel_name,
378 silc_free(name_list);
381 /* Command reply handler. This function is called always in the command reply
382 function. If error occurs it will be called as well. Normal scenario
383 is that it will be called after the received command data has been parsed
384 and processed. The function is used to pass the received command data to
387 `conn' is the associated client connection. `cmd_payload' is the command
388 payload data received from server and it can be ignored. It is provided
389 if the application would like to re-parse the received command data,
390 however, it must be noted that the data is parsed already by the library
391 thus the payload can be ignored. `success' is FALSE if error occured.
392 In this case arguments are not sent to the application. `command' is the
393 command reply being processed. The function has variable argument list
394 and each command defines the number and type of arguments it passes to the
395 application (on error they are not sent). */
397 void silc_command_reply(SilcClient client, SilcClientConnection conn,
398 SilcCommandPayload cmd_payload, int success,
399 SilcCommand command, SilcCommandStatus status, ...)
401 SilcClientInternal app = (SilcClientInternal)client->application;
405 va_start(vp, status);
409 case SILC_COMMAND_WHOIS:
411 char buf[1024], *nickname, *username, *realname;
413 unsigned int idle, mode;
416 if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
417 status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
419 tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
422 client->ops->say(client, conn, "%s: %s", tmp,
423 silc_client_command_status_message(status));
425 client->ops->say(client, conn, "%s",
426 silc_client_command_status_message(status));
433 (void)va_arg(vp, SilcClientEntry);
434 nickname = va_arg(vp, char *);
435 username = va_arg(vp, char *);
436 realname = va_arg(vp, char *);
437 channels = va_arg(vp, SilcBuffer);
438 mode = va_arg(vp, unsigned int);
439 idle = va_arg(vp, unsigned int);
441 memset(buf, 0, sizeof(buf));
444 len = strlen(nickname);
445 strncat(buf, nickname, len);
446 strncat(buf, " is ", 4);
450 strncat(buf, username, strlen(username));
454 strncat(buf, " (", 2);
455 strncat(buf, realname, strlen(realname));
456 strncat(buf, ")", 1);
459 client->ops->say(client, conn, "%s", buf);
462 SilcDList list = silc_channel_payload_parse_list(channels);
464 SilcChannelPayload entry;
466 memset(buf, 0, sizeof(buf));
467 strcat(buf, "on channels: ");
469 silc_dlist_start(list);
470 while ((entry = silc_dlist_get(list)) != SILC_LIST_END) {
471 char *m = silc_client_chumode_char(silc_channel_get_mode(entry));
472 unsigned int name_len;
473 char *name = silc_channel_get_name(entry, &name_len);
476 strncat(buf, m, strlen(m));
477 strncat(buf, name, name_len);
478 strncat(buf, " ", 1);
482 client->ops->say(client, conn, "%s", buf);
483 silc_channel_payload_list_free(list);
488 client->ops->say(client, conn, "%s is %s", nickname,
489 (mode & SILC_UMODE_SERVER_OPERATOR) ?
491 (mode & SILC_UMODE_ROUTER_OPERATOR) ?
492 "SILC Operator" : "[Unknown mode]");
494 if (idle && nickname)
495 client->ops->say(client, conn, "%s has been idle %d %s",
497 idle > 60 ? (idle / 60) : idle,
498 idle > 60 ? "minutes" : "seconds");
502 case SILC_COMMAND_WHOWAS:
504 char buf[1024], *nickname, *username, *realname;
507 if (status == SILC_STATUS_ERR_NO_SUCH_NICK ||
508 status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) {
510 tmp = silc_argument_get_arg_type(silc_command_get_args(cmd_payload),
513 client->ops->say(client, conn, "%s: %s", tmp,
514 silc_client_command_status_message(status));
516 client->ops->say(client, conn, "%s",
517 silc_client_command_status_message(status));
524 (void)va_arg(vp, SilcClientEntry);
525 nickname = va_arg(vp, char *);
526 username = va_arg(vp, char *);
527 realname = va_arg(vp, char *);
529 memset(buf, 0, sizeof(buf));
532 len = strlen(nickname);
533 strncat(buf, nickname, len);
534 strncat(buf, " was ", 5);
538 strncat(buf, username, strlen(nickname));
542 strncat(buf, " (", 2);
543 strncat(buf, realname, strlen(realname));
544 strncat(buf, ")", 1);
547 client->ops->say(client, conn, "%s", buf);
551 case SILC_COMMAND_JOIN:
555 SilcBuffer client_id_list;
556 unsigned int list_count;
557 SilcChannelEntry channel;
562 app->screen->bottom_line->channel = va_arg(vp, char *);
563 channel = va_arg(vp, SilcChannelEntry);
564 mode = va_arg(vp, unsigned int);
565 (void)va_arg(vp, unsigned int);
566 (void)va_arg(vp, unsigned char *);
567 (void)va_arg(vp, unsigned char *);
568 (void)va_arg(vp, unsigned char *);
569 topic = va_arg(vp, char *);
570 (void)va_arg(vp, unsigned char *);
571 list_count = va_arg(vp, unsigned int);
572 client_id_list = va_arg(vp, SilcBuffer);
575 client->ops->say(client, conn, "Topic for %s: %s",
576 app->screen->bottom_line->channel, topic);
578 app->screen->bottom_line->channel_mode = silc_client_chmode(mode);
579 silc_screen_print_bottom_line(app->screen, 0);
581 /* Resolve the client information */
582 silc_client_get_clients_by_list(client, conn, list_count,
584 silc_client_show_users, channel);
588 case SILC_COMMAND_NICK:
590 SilcClientEntry entry;
595 entry = va_arg(vp, SilcClientEntry);
596 silc_say(client, conn, "Your current nickname is %s", entry->nickname);
597 app->screen->bottom_line->nickname = entry->nickname;
598 silc_screen_print_bottom_line(app->screen, 0);
602 case SILC_COMMAND_LIST:
605 unsigned int usercount;
606 unsigned char buf[256], tmp[16];
612 (void)va_arg(vp, SilcChannelEntry);
613 name = va_arg(vp, char *);
614 topic = va_arg(vp, char *);
615 usercount = va_arg(vp, unsigned int);
617 if (status == SILC_STATUS_LIST_START ||
618 status == SILC_STATUS_OK)
619 silc_say(client, conn,
620 " Channel Users Topic");
622 memset(buf, 0, sizeof(buf));
623 strncat(buf, " ", 2);
625 strncat(buf, name, len > 40 ? 40 : len);
627 for (i = 0; i < 40 - len; i++)
631 memset(tmp, 0, sizeof(tmp));
633 snprintf(tmp, sizeof(tmp), "%d", usercount);
638 for (i = 0; i < 10 - len; i++)
644 strncat(buf, topic, len);
647 silc_say(client, conn, "%s", buf);
651 case SILC_COMMAND_UMODE:
658 mode = va_arg(vp, unsigned int);
660 if (!mode && app->screen->bottom_line->umode) {
661 silc_free(app->screen->bottom_line->umode);
662 app->screen->bottom_line->umode = NULL;
665 if (mode & SILC_UMODE_SERVER_OPERATOR) {
666 if (app->screen->bottom_line->umode)
667 silc_free(app->screen->bottom_line->umode);
668 app->screen->bottom_line->umode = strdup("Server Operator");;
671 if (mode & SILC_UMODE_ROUTER_OPERATOR) {
672 if (app->screen->bottom_line->umode)
673 silc_free(app->screen->bottom_line->umode);
674 app->screen->bottom_line->umode = strdup("SILC Operator");;
677 silc_screen_print_bottom_line(app->screen, 0);
681 case SILC_COMMAND_OPER:
682 if (status == SILC_STATUS_OK) {
683 conn->local_entry->mode |= SILC_UMODE_SERVER_OPERATOR;
684 if (app->screen->bottom_line->umode)
685 silc_free(app->screen->bottom_line->umode);
686 app->screen->bottom_line->umode = strdup("Server Operator");;
687 silc_screen_print_bottom_line(app->screen, 0);
691 case SILC_COMMAND_SILCOPER:
692 if (status == SILC_STATUS_OK) {
693 conn->local_entry->mode |= SILC_UMODE_ROUTER_OPERATOR;
694 if (app->screen->bottom_line->umode)
695 silc_free(app->screen->bottom_line->umode);
696 app->screen->bottom_line->umode = strdup("SILC Operator");;
697 silc_screen_print_bottom_line(app->screen, 0);
701 case SILC_COMMAND_USERS:
705 silc_list_start(conn->current_channel->clients);
706 while ((chu = silc_list_get(conn->current_channel->clients))
708 if (chu->client == conn->local_entry) {
709 if (app->screen->bottom_line->mode)
710 silc_free(app->screen->bottom_line->mode);
711 app->screen->bottom_line->mode = silc_client_chumode_char(chu->mode);
712 silc_screen_print_bottom_line(app->screen, 0);
718 case SILC_COMMAND_BAN:
720 SilcChannelEntry channel;
726 channel = va_arg(vp, SilcChannelEntry);
727 ban_list = va_arg(vp, char *);
730 silc_say(client, conn, "%s ban list: %s", channel->channel_name,
733 silc_say(client, conn, "%s ban list not set", channel->channel_name);
742 /* Called to indicate that connection was either successfully established
743 or connecting failed. This is also the first time application receives
744 the SilcClientConnection objecet which it should save somewhere. */
746 void silc_connect(SilcClient client, SilcClientConnection conn, int success)
748 SilcClientInternal app = (SilcClientInternal)client->application;
751 app->screen->bottom_line->connection = conn->remote_host;
752 silc_screen_print_bottom_line(app->screen, 0);
757 /* Called to indicate that connection was disconnected to the server. */
759 void silc_disconnect(SilcClient client, SilcClientConnection conn)
761 SilcClientInternal app = (SilcClientInternal)client->application;
763 app->screen->bottom_line->connection = NULL;
764 silc_screen_print_bottom_line(app->screen, 0);
768 /* Asks passphrase from user on the input line. */
770 unsigned char *silc_ask_passphrase(SilcClient client,
771 SilcClientConnection conn)
773 SilcClientInternal app = (SilcClientInternal)conn->client->application;
774 char pass1[256], pass2[256];
781 wattroff(app->screen->input_win, A_INVIS);
782 silc_screen_input_print_prompt(app->screen, "Passphrase: ");
783 wattron(app->screen->input_win, A_INVIS);
786 memset(pass1, 0, sizeof(pass1));
787 wgetnstr(app->screen->input_win, pass1, sizeof(pass1));
789 /* Print retype prompt */
790 wattroff(app->screen->input_win, A_INVIS);
791 silc_screen_input_print_prompt(app->screen, "Retype passphrase: ");
792 wattron(app->screen->input_win, A_INVIS);
795 memset(pass2, 0, sizeof(pass2));
796 wgetnstr(app->screen->input_win, pass2, sizeof(pass2));
798 if (!strncmp(pass1, pass2, strlen(pass2)))
804 ret = silc_calloc(strlen(pass1), sizeof(char));
805 memcpy(ret, pass1, strlen(pass1));
807 memset(pass1, 0, sizeof(pass1));
808 memset(pass2, 0, sizeof(pass2));
810 wattroff(app->screen->input_win, A_INVIS);
811 silc_screen_input_reset(app->screen);
816 /* Verifies received public key. If user decides to trust the key it is
817 saved as trusted server key for later use. If user does not trust the
818 key this returns FALSE. */
820 int silc_verify_server_key(SilcClient client,
821 SilcClientConnection conn,
822 unsigned char *pk, unsigned int pk_len,
823 SilcSKEPKType pk_type)
825 SilcSocketConnection sock = conn->sock;
828 char *hostname, *fingerprint;
832 hostname = sock->hostname ? sock->hostname : sock->ip;
834 if (pk_type != SILC_SKE_PK_TYPE_SILC) {
835 silc_say(client, conn, "We don't support server %s key type", hostname);
839 pw = getpwuid(getuid());
843 memset(filename, 0, sizeof(filename));
844 memset(file, 0, sizeof(file));
845 snprintf(file, sizeof(file) - 1, "serverkey_%s_%d.pub", hostname,
847 snprintf(filename, sizeof(filename) - 1, "%s/.silc/serverkeys/%s",
850 /* Check wheter this key already exists */
851 if (stat(filename, &st) < 0) {
853 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
854 silc_say(client, conn, "Received server %s public key", hostname);
855 silc_say(client, conn, "Fingerprint for the server %s key is", hostname);
856 silc_say(client, conn, "%s", fingerprint);
857 silc_free(fingerprint);
859 /* Ask user to verify the key and save it */
860 if (silc_client_ask_yes_no(client,
861 "Would you like to accept the key (y/n)? "))
863 /* Save the key for future checking */
864 silc_pkcs_save_public_key_data(filename, pk, pk_len,
869 /* The key already exists, verify it. */
870 SilcPublicKey public_key;
871 unsigned char *encpk;
872 unsigned int encpk_len;
874 /* Load the key file */
875 if (!silc_pkcs_load_public_key(filename, &public_key,
877 if (!silc_pkcs_load_public_key(filename, &public_key,
878 SILC_PKCS_FILE_BIN)) {
879 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
880 silc_say(client, conn, "Received server %s public key", hostname);
881 silc_say(client, conn, "Fingerprint for the server %s key is", hostname);
882 silc_say(client, conn, "%s", fingerprint);
883 silc_free(fingerprint);
884 silc_say(client, conn, "Could not load your local copy of the server %s key",
886 if (silc_client_ask_yes_no(client,
887 "Would you like to accept the key anyway (y/n)? "))
889 /* Save the key for future checking */
891 silc_pkcs_save_public_key_data(filename, pk, pk_len,
899 /* Encode the key data */
900 encpk = silc_pkcs_public_key_encode(public_key, &encpk_len);
902 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
903 silc_say(client, conn, "Received server %s public key", hostname);
904 silc_say(client, conn, "Fingerprint for the server %s key is", hostname);
905 silc_say(client, conn, "%s", fingerprint);
906 silc_free(fingerprint);
907 silc_say(client, conn, "Your local copy of the server %s key is malformed",
909 if (silc_client_ask_yes_no(client,
910 "Would you like to accept the key anyway (y/n)? "))
912 /* Save the key for future checking */
914 silc_pkcs_save_public_key_data(filename, pk, pk_len,
922 if (memcmp(encpk, pk, encpk_len)) {
923 fingerprint = silc_hash_fingerprint(NULL, pk, pk_len);
924 silc_say(client, conn, "Received server %s public key", hostname);
925 silc_say(client, conn, "Fingerprint for the server %s key is", hostname);
926 silc_say(client, conn, "%s", fingerprint);
927 silc_free(fingerprint);
928 silc_say(client, conn, "Server %s key does not match with your local copy",
930 silc_say(client, conn, "It is possible that the key has expired or changed");
931 silc_say(client, conn, "It is also possible that some one is performing "
932 "man-in-the-middle attack");
934 /* Ask user to verify the key and save it */
935 if (silc_client_ask_yes_no(client,
936 "Would you like to accept the key anyway (y/n)? "))
938 /* Save the key for future checking */
940 silc_pkcs_save_public_key_data(filename, pk, pk_len,
945 silc_say(client, conn, "Will not accept server %s key", hostname);
949 /* Local copy matched */
953 silc_say(client, conn, "Will not accept server %s key", hostname);
957 /* Find authentication method and authentication data by hostname and
958 port. The hostname may be IP address as well. The found authentication
959 method and authentication data is returned to `auth_meth', `auth_data'
960 and `auth_data_len'. The function returns TRUE if authentication method
961 is found and FALSE if not. `conn' may be NULL. */
963 int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
964 char *hostname, unsigned short port,
965 SilcProtocolAuthMeth *auth_meth,
966 unsigned char **auth_data,
967 unsigned int *auth_data_len)
969 SilcClientInternal app = (SilcClientInternal)client->application;
971 if (app->config->conns) {
972 SilcClientConfigSectionConnection *conn = NULL;
974 /* Check if we find a match from user configured connections */
975 conn = silc_client_config_find_connection(app->config,
979 /* Match found. Use the configured authentication method */
980 *auth_meth = conn->auth_meth;
982 if (conn->auth_data) {
983 *auth_data = strdup(conn->auth_data);
984 *auth_data_len = strlen(conn->auth_data);
994 /* Notifies application that failure packet was received. This is called
995 if there is some protocol active in the client. The `protocol' is the
996 protocol context. The `failure' is opaque pointer to the failure
997 indication. Note, that the `failure' is protocol dependant and application
998 must explicitly cast it to correct type. Usually `failure' is 32 bit
999 failure type (see protocol specs for all protocol failure types). */
1001 void silc_failure(SilcClient client, SilcClientConnection conn,
1002 SilcProtocol protocol, void *failure)
1007 /* Asks whether the user would like to perform the key agreement protocol.
1008 This is called after we have received an key agreement packet or an
1009 reply to our key agreement packet. This returns TRUE if the user wants
1010 the library to perform the key agreement protocol and FALSE if it is not
1011 desired (application may start it later by calling the function
1012 silc_client_perform_key_agreement). */
1014 int silc_key_agreement(SilcClient client, SilcClientConnection conn,
1015 SilcClientEntry client_entry, char *hostname,
1017 SilcKeyAgreementCallback *completion,
1024 /* SILC client operations */
1025 SilcClientOperations ops = {
1027 channel_message: silc_channel_message,
1028 private_message: silc_private_message,
1029 notify: silc_notify,
1030 command: silc_command,
1031 command_reply: silc_command_reply,
1032 connect: silc_connect,
1033 disconnect: silc_disconnect,
1034 get_auth_method: silc_get_auth_method,
1035 verify_server_key: silc_verify_server_key,
1036 ask_passphrase: silc_ask_passphrase,
1037 failure: silc_failure,
1038 key_agreement: silc_key_agreement,