2 #include "chat-protocols.h"
5 #include "servers-setup.h"
6 #include "channels-setup.h"
7 #include "silc-servers.h"
8 #include "silc-channels.h"
9 #include "silc-queries.h"
10 #include "silc-nicklist.h"
11 #include "version_internal.h"
16 #include "fe-common/core/printtext.h"
17 #include "fe-common/core/fe-channels.h"
19 #define SILC_CLIENT_PUBLIC_KEY_NAME "public_key.pub"
20 #define SILC_CLIENT_PRIVATE_KEY_NAME "private_key.prv"
22 #define SILC_CLIENT_DEF_PKCS "rsa"
23 #define SILC_CLIENT_DEF_PKCS_LEN 1024
25 SilcClient silc_client;
26 const char *silc_version_string = SILC_PROTOCOL_VERSION_STRING;
30 extern SilcClientOperations ops;
32 static void silc_say(SilcClient client, SilcClientConnection conn,
35 SILC_SERVER_REC *server;
39 server = conn == NULL ? NULL : conn->context;
42 str = g_strdup_vprintf(msg, va);
43 printtext(server, "#silc", MSGLEVEL_CRAP, "%s", str);
48 static void silc_channel_message(SilcClient c, SilcClientConnection conn,
49 SilcClientEntry client,
50 SilcChannelEntry channel, char *msg)
52 SILC_SERVER_REC *server;
54 SILC_CHANNEL_REC *chanrec;
56 server = conn == NULL ? NULL : conn->context;
57 chanrec = silc_channel_find_entry(server, channel);
59 nick = client == NULL ? NULL : silc_nicklist_find(chanrec, client);
60 signal_emit("message public", 6, server, msg,
61 nick == NULL ? "(unknown)" : nick->nick,
62 nick == NULL ? NULL : nick->host,
66 static void silc_private_message(SilcClient c, SilcClientConnection conn,
67 SilcClientEntry client, char *msg)
69 SILC_SERVER_REC *server;
71 server = conn == NULL ? NULL : conn->context;
72 signal_emit("message private", 4, server, msg,
73 client == NULL ? "(unknown)" : client->nickname,
74 client == NULL ? NULL : client->username);
82 #define MAX_NOTIFY (sizeof(notifies)/sizeof(notifies[0]))
83 static NOTIFY_REC notifies[] = {
84 { SILC_NOTIFY_TYPE_NONE, NULL },
85 { SILC_NOTIFY_TYPE_INVITE, "invite" },
86 { SILC_NOTIFY_TYPE_JOIN, "join" },
87 { SILC_NOTIFY_TYPE_LEAVE, "leave" },
88 { SILC_NOTIFY_TYPE_SIGNOFF, "signoff" },
89 { SILC_NOTIFY_TYPE_TOPIC_SET, "topic" },
90 { SILC_NOTIFY_TYPE_NICK_CHANGE, "nick" },
91 { SILC_NOTIFY_TYPE_CMODE_CHANGE, "cmode" },
92 { SILC_NOTIFY_TYPE_CUMODE_CHANGE, "cumode" },
93 { SILC_NOTIFY_TYPE_MOTD, "motd" }
96 static void silc_notify(SilcClient client, SilcClientConnection conn,
97 SilcNotifyType type, ...)
99 SILC_SERVER_REC *server;
102 server = conn == NULL ? NULL : conn->context;
105 if (type == SILC_NOTIFY_TYPE_NONE) {
106 /* some generic notice from server */
107 printtext(server, NULL, MSGLEVEL_CRAP, "%s",
108 (char *) va_arg(va, char *));
109 } else if (type < MAX_NOTIFY) {
110 /* send signal about the notify event */
113 g_snprintf(signal, sizeof(signal), "silc event %s",
114 notifies[type].name);
115 signal_emit(signal, 2, server, va);
118 printtext(server, NULL, MSGLEVEL_CRAP,
119 "Unknown notify %d", type);
124 static void silc_connect(SilcClient client, SilcClientConnection conn, int success)
126 SILC_SERVER_REC *server = conn->context;
129 server->connected = TRUE;
130 signal_emit("event connected", 1, server);
132 server->connection_lost = TRUE;
133 server->conn->context = NULL;
134 server_disconnect(SERVER(server));
138 static void silc_disconnect(SilcClient client, SilcClientConnection conn)
140 SILC_SERVER_REC *server = conn->context;
142 server->conn->context = NULL;
144 server->connection_lost = TRUE;
145 server_disconnect(SERVER(server));
148 static void silc_command(SilcClient client, SilcClientConnection conn,
149 SilcClientCommandContext cmd_context, int success,
154 static void silc_command_reply(SilcClient client, SilcClientConnection conn,
155 SilcCommandPayload cmd_payload, int success,
157 SilcCommandStatus status, ...)
159 SILC_SERVER_REC *server = conn->context;
160 SILC_CHANNEL_REC *chanrec;
163 va_start(va, status);
165 /*g_snprintf(signal, sizeof(signal), "silc command reply %s",
166 silc_commands[type]);
167 signal_emit(signal, 2, server, va);*/
170 case SILC_COMMAND_JOIN: {
171 char *channel, *mode;
173 channel = va_arg(va, char *);
174 (void)va_arg(va, SilcChannelEntry);
175 mode = silc_client_chmode(va_arg(va, unsigned int));
177 chanrec = silc_channel_find(server, channel);
178 if (chanrec != NULL && !success)
179 channel_destroy(CHANNEL(chanrec));
180 else if (chanrec == NULL && success)
181 chanrec = silc_channel_create(server, channel, TRUE);
183 g_free_not_null(chanrec->mode);
184 chanrec->mode = g_strdup(mode == NULL ? "" : mode);
185 signal_emit("channel mode changed", 1, chanrec);
188 case SILC_COMMAND_NICK: {
189 SilcClientEntry client = va_arg(va, SilcClientEntry);
192 old = g_strdup(server->nick);
193 server_change_nick(SERVER(server), client->nickname);
194 nicklist_rename_unique(SERVER(server),
195 server->conn->local_entry, server->nick,
196 client, client->nickname);
198 signal_emit("message own_nick", 4,
199 server, server->nick, old, "");
203 case SILC_COMMAND_USERS: {
204 SilcChannelEntry channel;
205 SilcChannelUser user;
208 channel = va_arg(va, SilcChannelEntry);
209 chanrec = silc_channel_find_entry(server, channel);
213 silc_list_start(channel->clients);
214 while ((user = silc_list_get(channel->clients)) != NULL)
215 silc_nicklist_insert(chanrec, user, FALSE);
217 ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry));
218 nicklist_set_own(CHANNEL(chanrec), ownnick);
219 signal_emit("channel joined", 1, chanrec);
220 fe_channels_nicklist(CHANNEL(chanrec),
221 CHANNEL_NICKLIST_FLAG_ALL);
229 static int silc_verify_server_key(SilcClient client, SilcClientConnection conn,
230 unsigned char *pk, unsigned int pk_len,
231 SilcSKEPKType pk_type)
236 static unsigned char *silc_ask_passphrase(SilcClient client,
237 SilcClientConnection conn)
242 static int silc_get_auth_method(SilcClient client, SilcClientConnection conn,
243 char *hostname, unsigned short port,
244 SilcProtocolAuthMeth *auth_meth,
245 unsigned char **auth_data,
246 unsigned int *auth_data_len)
251 static void silc_failure(SilcClient client, SilcClientConnection conn,
252 SilcProtocol protocol, void *failure)
256 static int key_agreement(SilcClient client, SilcClientConnection conn,
257 SilcClientEntry client_entry, char *hostname,
263 SilcClientOperations ops = {
265 silc_channel_message,
266 silc_private_message,
272 silc_get_auth_method,
273 silc_verify_server_key,
279 /* Loads public and private key from files. */
281 static void silc_client_create_key_pair(char *pkcs_name, int bits,
283 SilcPublicKey *pub_key,
284 SilcPrivateKey *prv_key)
289 unsigned int key_len;
291 rng = silc_rng_alloc();
293 silc_rng_global_init(rng);
295 silc_pkcs_alloc(pkcs_name, &pkcs);
296 pkcs->pkcs->init(pkcs->context, bits, rng);
298 /* Create public key */
299 key = silc_pkcs_get_public_key(pkcs, &key_len);
300 *pub_key = silc_pkcs_public_key_alloc(pkcs->pkcs->name, identifier,
303 memset(key, 0, sizeof(key_len));
306 /* Create private key */
307 key = silc_pkcs_get_private_key(pkcs, &key_len);
308 *prv_key = silc_pkcs_private_key_alloc(pkcs->pkcs->name, key, key_len);
310 memset(key, 0, sizeof(key_len));
314 silc_pkcs_free(pkcs);
317 static int read_keyfiles(SilcClient client, char *public_file,
322 if (stat(public_file, &statbuf) != 0 ||
323 stat(private_file, &statbuf) != 0)
326 if (!silc_pkcs_load_private_key(private_file, &client->private_key,
327 SILC_PKCS_FILE_BIN) &&
328 !silc_pkcs_load_private_key(private_file, &client->private_key,
332 if (!silc_pkcs_load_public_key(public_file, &client->public_key,
333 SILC_PKCS_FILE_PEM) &&
334 !silc_pkcs_load_public_key(public_file, &client->public_key,
341 static char *silc_create_identifier(SilcClient client)
343 char hostname[256], *email, *ret;
345 if (gethostname(hostname, sizeof(hostname)) != 0)
348 email = g_strdup_printf("%s@%s", client->username, hostname);
349 ret = silc_pkcs_encode_identifier(client->username, hostname,
350 client->realname, email,
356 static int load_keys(SilcClient client)
358 char *public_file, *private_file;
361 public_file = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(),
362 SILC_CLIENT_PUBLIC_KEY_NAME);
363 private_file = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(),
364 SILC_CLIENT_PRIVATE_KEY_NAME);
366 if (!read_keyfiles(client, public_file, private_file)) {
367 /* couldn't read key files, recreate them */
368 identifier = silc_create_identifier(client);
369 silc_client_create_key_pair(SILC_CLIENT_DEF_PKCS,
370 SILC_CLIENT_DEF_PKCS_LEN,
373 &client->private_key);
374 silc_free(identifier);
376 silc_pkcs_save_public_key(public_file, client->public_key,
378 silc_pkcs_save_private_key(private_file, client->private_key,
379 NULL, SILC_PKCS_FILE_BIN);
383 g_free(private_file);
387 static int my_silc_scheduler(void)
389 silc_schedule_one(0);
393 static CHATNET_REC *create_chatnet(void)
395 return g_malloc0(sizeof(CHATNET_REC));
398 static SERVER_SETUP_REC *create_server_setup(void)
400 return g_malloc0(sizeof(SERVER_SETUP_REC));
403 static CHANNEL_SETUP_REC *create_channel_setup(void)
405 return g_malloc0(sizeof(CHANNEL_SETUP_REC));
408 static SERVER_CONNECT_REC *create_server_connect(void)
410 return g_malloc0(sizeof(SILC_SERVER_CONNECT_REC));
413 /* Command line option variables */
414 void silc_core_init(void)
416 CHAT_PROTOCOL_REC *rec;
418 silc_client = silc_client_alloc(&ops, NULL);
419 silc_client->username = g_strdup(settings_get_str("user_name"));
420 silc_client->hostname = silc_net_localhost();
421 silc_client->realname = g_strdup(settings_get_str("real_name"));
423 if (!load_keys(silc_client)) {
428 silc_client_init(silc_client);
430 rec = g_new0(CHAT_PROTOCOL_REC, 1);
432 rec->fullname = "Secure Internet Live Conferencing";
433 rec->chatnet = "silcnet";
435 rec->create_chatnet = create_chatnet;
436 rec->create_server_setup = create_server_setup;
437 rec->create_channel_setup = create_channel_setup;
438 rec->create_server_connect = create_server_connect;
440 rec->server_connect = (SERVER_REC *(*) (SERVER_CONNECT_REC *))
442 rec->channel_create =
443 (CHANNEL_REC *(*) (SERVER_REC *, const char *, int))
446 (QUERY_REC *(*) (const char *, const char *, int))
449 chat_protocol_register(rec);
453 silc_channels_init();
456 idletag = g_timeout_add(100, (GSourceFunc) my_silc_scheduler, NULL);
459 void silc_core_deinit(void)
462 signal_emit("chat protocol deinit", 1,
463 chat_protocol_find("SILC"));
465 silc_server_deinit();
466 silc_channels_deinit();
467 silc_queries_deinit();
469 chat_protocol_unregister("SILC");
471 g_source_remove(idletag);
474 g_free(silc_client->username);
475 g_free(silc_client->realname);
476 silc_client_free(silc_client);