X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fsilc%2Fcore%2Fclient_ops.c;h=38e90d0844553855d9cc38cc2497756754e37975;hb=52e57c880aba9c5e89f59d962eb9af75670b76e0;hp=44c7b0a32b2c8e6cff34cbeb2c18ff35263f41cc;hpb=c257b555225193e54d85daf541d29578b3c93882;p=silc.git diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 44c7b0a3..38e90d08 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -2,9 +2,9 @@ client_ops.c - Author: Pekka Riikonen + Author: Pekka Riikonen - Copyright (C) 2001 - 2005 Pekka Riikonen + Copyright (C) 2001 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,9 +46,8 @@ static void silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, - const char *name, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, + const char *name, SilcConnectionType conn_type, + SilcPublicKey public_key, SilcVerifyPublicKey completion, void *context); char *silc_get_session_filename(SILC_SERVER_REC *server) @@ -164,49 +163,48 @@ silc_print_nick_change(SILC_SERVER_REC *server, const char *newnick, static void silc_parse_channel_public_keys(SILC_SERVER_REC *server, SilcChannelEntry channel_entry, - SilcBuffer channel_pubkeys) + SilcDList channel_pubkeys) { - SilcUInt16 argc; - SilcArgumentPayload chpks; - unsigned char *pk; + SilcArgumentDecodedList e; + SilcPublicKey pubkey; + SilcSILCPublicKey silc_pubkey; SilcUInt32 pk_len, type; - int c = 1; + unsigned char *pk; char *fingerprint, *babbleprint; - SilcPublicKey pubkey; - SilcPublicKeyIdentifier ident; + int c = 1; printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_LIST, channel_entry->channel_name); - SILC_GET16_MSB(argc, channel_pubkeys->data); - chpks = silc_argument_payload_parse(channel_pubkeys->data + 2, - channel_pubkeys->len - 2, argc); - if (!chpks) - return; + silc_dlist_start(channel_pubkeys); + while ((e = silc_dlist_get(channel_pubkeys))) { + pubkey = e->argument; + type = e->arg_type; + + if (silc_pkcs_get_type(pubkey) != SILC_PKCS_SILC) + continue; + + pk = silc_pkcs_public_key_encode(pubkey, &pk_len); + if (!pk) + continue; - pk = silc_argument_get_first_arg(chpks, &type, &pk_len); - while (pk) { - fingerprint = silc_hash_fingerprint(NULL, pk + 4, pk_len - 4); - babbleprint = silc_hash_babbleprint(NULL, pk + 4, pk_len - 4); - silc_pkcs_public_key_payload_decode(pk, pk_len, &pubkey); - ident = silc_pkcs_decode_identifier(pubkey->identifier); + fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); + babbleprint = silc_hash_babbleprint(NULL, pk, pk_len); + silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, pubkey); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_LIST_ENTRY, c++, channel_entry->channel_name, type == 0x00 ? "Added" : "Removed", - ident->realname ? ident->realname : "", + silc_pubkey->identifier.realname ? + silc_pubkey->identifier.realname : "", fingerprint, babbleprint); silc_free(fingerprint); silc_free(babbleprint); - silc_pkcs_public_key_free(pubkey); - silc_pkcs_free_identifier(ident); - pk = silc_argument_get_next_arg(chpks, &type, &pk_len); + silc_free(pk); } - - silc_argument_payload_free(chpks); } void silc_say(SilcClient client, SilcClientConnection conn, @@ -238,32 +236,29 @@ void silc_say_error(char *msg, ...) va_end(va); } -/* try to verify a message using locally stored public key data */ +/* Try to verify a message using locally stored public key data */ + int verify_message_signature(SilcClientEntry sender, - SilcMessageSignedPayload sig, SilcMessagePayload message) { SilcPublicKey pk; char file[256], filename[256]; char *fingerprint, *fingerprint2; - unsigned char *pk_data; + const unsigned char *pk_data; SilcUInt32 pk_datalen; struct stat st; int ret = SILC_MSG_SIGNED_VERIFIED, i; - if (sig == NULL) - return SILC_MSG_SIGNED_UNKNOWN; - /* get public key from the signature payload and compare it with the one stored in the client entry */ - pk = silc_message_signed_get_public_key(sig, &pk_data, &pk_datalen); + pk = silc_message_signed_get_public_key(message, &pk_data, &pk_datalen); if (pk != NULL) { fingerprint = silc_hash_fingerprint(NULL, pk_data, pk_datalen); - if (sender->fingerprint) { + if (sender->fingerprint[0]) { fingerprint2 = silc_fingerprint(sender->fingerprint, - sender->fingerprint_len); + sizeof(sender->fingerprint)); if (strcmp(fingerprint, fingerprint2)) { /* since the public key differs from the senders public key, the verification _failed_ */ @@ -273,9 +268,9 @@ int verify_message_signature(SilcClientEntry sender, } silc_free(fingerprint2); } - } else if (sender->fingerprint) + } else if (sender->fingerprint[0]) fingerprint = silc_fingerprint(sender->fingerprint, - sender->fingerprint_len); + sizeof(sender->fingerprint)); else /* no idea, who or what signed that message ... */ return SILC_MSG_SIGNED_UNKNOWN; @@ -297,9 +292,7 @@ int verify_message_signature(SilcClientEntry sender, SilcPublicKey cached_pk=NULL; /* try to load the file */ - if (!silc_pkcs_load_public_key(filename, &cached_pk, SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(filename, &cached_pk, - SILC_PKCS_FILE_BIN)) { + if (!silc_pkcs_load_public_key(filename, &cached_pk)) { printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_COULD_NOT_LOAD, "client"); if (pk == NULL) @@ -316,8 +309,8 @@ int verify_message_signature(SilcClientEntry sender, } /* the public key is now in pk, our "level of trust" in ret */ - if ((pk) && silc_message_signed_verify(sig, message, pk, - silc_client->sha1hash)!= SILC_AUTH_OK) + if ((pk) && silc_message_signed_verify(message, pk, + sha1hash) != SILC_AUTH_OK) ret = SILC_MSG_SIGNED_FAILED; if (pk) @@ -326,74 +319,74 @@ int verify_message_signature(SilcClientEntry sender, return ret; } -char * silc_unescape_data(const char *escaped_data, SilcUInt32 *length) +char *silc_unescape_data(const char *escaped_data, SilcUInt32 *length) { - char *data, *ptr; - int i = 0, j = 0, len = strlen(escaped_data); - - data = silc_calloc(len, sizeof(char)); - - while (i < len) { - ptr = memchr(escaped_data + i, 1, len - i); - if (ptr) { - int inc = (ptr - escaped_data) - i; - memcpy(data + j, escaped_data + i, inc); - j += inc; - i += inc + 2; - data[j++] = *(ptr + 1) - 1; - } else { - memcpy(data + j, escaped_data + i, len - i); - j += (len - i); - break; - } + char *data, *ptr; + int i = 0, j = 0, len = strlen(escaped_data); + + data = silc_calloc(len, sizeof(char)); + + while (i < len) { + ptr = memchr(escaped_data + i, 1, len - i); + if (ptr) { + int inc = (ptr - escaped_data) - i; + memcpy(data + j, escaped_data + i, inc); + j += inc; + i += inc + 2; + data[j++] = *(ptr + 1) - 1; + } else { + memcpy(data + j, escaped_data + i, len - i); + j += (len - i); + break; } + } - *length = j; - return data; + *length = j; + return data; } -char * silc_escape_data(const char *data, SilcUInt32 len) +char *silc_escape_data(const char *data, SilcUInt32 len) { - char *escaped_data, *ptr, *ptr0, *ptr1; - int i = 0, j = 0; - - escaped_data = silc_calloc(2 * len, sizeof(char)); - - while (i < len) { - ptr0 = memchr(data + i, 0, len - i); - ptr1 = memchr(data + i, 1, len - i); - - ptr = (ptr0 < ptr1 ? (ptr0 ? ptr0 : ptr1) : (ptr1 ? ptr1 : ptr0)); - - if (ptr) { - int inc = (ptr - data) - i; - if (inc) - memcpy(escaped_data + j, data + i, inc); - j += inc; - i += inc; - escaped_data[j++] = 1; - escaped_data[j++] = *(data + i++) + 1; - } else { - memcpy(escaped_data + j, data + i, len - i); - j += (len - i); - break; - } + char *escaped_data, *ptr, *ptr0, *ptr1; + int i = 0, j = 0; + + escaped_data = silc_calloc(2 * len, sizeof(char)); + + while (i < len) { + ptr0 = memchr(data + i, 0, len - i); + ptr1 = memchr(data + i, 1, len - i); + + ptr = (ptr0 < ptr1 ? (ptr0 ? ptr0 : ptr1) : (ptr1 ? ptr1 : ptr0)); + + if (ptr) { + int inc = (ptr - data) - i; + if (inc) + memcpy(escaped_data + j, data + i, inc); + j += inc; + i += inc; + escaped_data[j++] = 1; + escaped_data[j++] = *(data + i++) + 1; + } else { + memcpy(escaped_data + j, data + i, len - i); + j += (len - i); + break; } + } - return escaped_data; + return escaped_data; } void silc_emit_mime_sig(SILC_SERVER_REC *server, WI_ITEM_REC *item, - const char *data, SilcUInt32 data_len, const char *nick, - int verified) + const char *data, SilcUInt32 data_len, + const char *nick, int verified) { - char *escaped_data; + char *escaped_data; - escaped_data = silc_escape_data(data, data_len); + escaped_data = silc_escape_data(data, data_len); - signal_emit("mime", 5, server, item, escaped_data, nick, verified); + signal_emit("mime", 5, server, item, escaped_data, nick, verified); - silc_free(escaped_data); + silc_free(escaped_data); } @@ -428,13 +421,14 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, SilcChannelUser chu = silc_client_on_channel(channel, sender); if (chu) nick = silc_nicklist_insert(chanrec, chu, FALSE); + if (!nick) + return; } /* If the messages is digitally signed, verify it, if possible. */ if (flags & SILC_MESSAGE_FLAG_SIGNED) { if (!settings_get_bool("ignore_message_signatures")) { - SilcMessageSignedPayload sig = silc_message_get_signature(payload); - verified = verify_message_signature(sender, sig, payload); + verified = verify_message_signature(sender, payload); } else { flags &= ~SILC_MESSAGE_FLAG_SIGNED; } @@ -442,8 +436,8 @@ void silc_channel_message(SilcClient client, SilcClientConnection conn, if (flags & SILC_MESSAGE_FLAG_DATA) { silc_emit_mime_sig(server, (WI_ITEM_REC *)chanrec, message, message_len, - nick == NULL ? NULL : nick->nick, - flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1); + nick == NULL ? NULL : nick->nick, + flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1); message = NULL; } @@ -559,15 +553,14 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, server = conn == NULL ? NULL : conn->context; memset(userhost, 0, sizeof(userhost)); - if (sender->username) + if (sender->username[0]) snprintf(userhost, sizeof(userhost) - 1, "%s@%s", sender->username, sender->hostname); /* If the messages is digitally signed, verify it, if possible. */ if (flags & SILC_MESSAGE_FLAG_SIGNED) { if (!settings_get_bool("ignore_message_signatures")) { - SilcMessageSignedPayload sig = silc_message_get_signature(payload); - verified = verify_message_signature(sender, sig, payload); + verified = verify_message_signature(sender, payload); } else { flags &= ~SILC_MESSAGE_FLAG_SIGNED; } @@ -575,11 +568,11 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, if (flags & SILC_MESSAGE_FLAG_DATA) { silc_emit_mime_sig(server, - sender->nickname ? + sender->nickname[0] ? (WI_ITEM_REC *)query_find(SERVER(server), sender->nickname) : NULL, message, message_len, - sender->nickname ? sender->nickname : "[]", + sender->nickname[0] ? sender->nickname : "[]", flags & SILC_MESSAGE_FLAG_SIGNED ? verified : -1); message = NULL; } @@ -600,24 +593,24 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, cp, message_len); if (flags & SILC_MESSAGE_FLAG_SIGNED) signal_emit("message silc signed_private_action", 6, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL, verified); else signal_emit("message silc private_action", 5, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, NULL); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL); silc_free(dm); } else { if (flags & SILC_MESSAGE_FLAG_SIGNED) signal_emit("message silc signed_private_action", 6, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL, verified); else signal_emit("message silc private_action", 5, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, NULL); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL); } else if (flags & SILC_MESSAGE_FLAG_NOTICE) if(flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { @@ -632,24 +625,24 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, cp, message_len); if (flags & SILC_MESSAGE_FLAG_SIGNED) signal_emit("message silc signed_private_notice", 6, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL, verified); else signal_emit("message silc private_notice", 5, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, NULL); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL); silc_free(dm); } else { if (flags & SILC_MESSAGE_FLAG_SIGNED) signal_emit("message silc signed_private_notice", 6, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL, verified); else signal_emit("message silc private_notice", 5, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, NULL); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, NULL); } else { if (flags & SILC_MESSAGE_FLAG_UTF8 && !silc_term_utf8()) { @@ -666,24 +659,24 @@ void silc_private_message(SilcClient client, SilcClientConnection conn, cp, message_len); if (flags & SILC_MESSAGE_FLAG_SIGNED) signal_emit("message signed_private", 5, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, verified); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, verified); else signal_emit("message private", 4, server, cp, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL); silc_free(dm); return; } if (flags & SILC_MESSAGE_FLAG_SIGNED) signal_emit("message signed_private", 5, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL, verified); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL, verified); else signal_emit("message private", 4, server, message, - sender->nickname ? sender->nickname : "[]", - sender->username ? userhost : NULL); + sender->nickname[0] ? sender->nickname : "[]", + sender->username[0] ? userhost : NULL); } } @@ -709,9 +702,9 @@ void silc_notify(SilcClient client, SilcClientConnection conn, void *entry; SilcUInt32 mode; char buf[512]; - char *name, *tmp; + char *name, *tmp, *cipher, *hmac; GSList *list1, *list_tmp; - SilcBuffer buffer; + SilcDList chpks, clients; SILC_LOG_DEBUG(("Start")); @@ -736,11 +729,10 @@ void silc_notify(SilcClient client, SilcClientConnection conn, name = va_arg(va, char *); client_entry = va_arg(va, SilcClientEntry); - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message invite", 4, server, channel ? channel->channel_name : - name, client_entry->nickname, buf); + silc_snprintf(buf, sizeof(buf) - 1, "%s@%s", + client_entry->username, client_entry->hostname); + signal_emit("message invite", 4, server, name, + client_entry->nickname, buf); break; case SILC_NOTIFY_TYPE_JOIN: @@ -756,7 +748,10 @@ void silc_notify(SilcClient client, SilcClientConnection conn, if (client_entry == server->conn->local_entry) { /* You joined to channel */ chanrec = silc_channel_find(server, channel->channel_name); - if (chanrec != NULL && !chanrec->joined) + if (chanrec == NULL) + chanrec = silc_channel_create(server, channel->channel_name, + channel->channel_name, TRUE); + if (!chanrec->joined) chanrec->entry = channel; } else { chanrec = silc_channel_find_entry(server, channel); @@ -768,12 +763,41 @@ void silc_notify(SilcClient client, SilcClientConnection conn, } memset(buf, 0, sizeof(buf)); - if (client_entry->username) - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); + if (client_entry->username[0]) + snprintf(buf, sizeof(buf) - 1, "%s@%s", + client_entry->username, client_entry->hostname); signal_emit("message join", 4, server, channel->channel_name, client_entry->nickname, - client_entry->username == NULL ? "" : buf); + !client_entry->username[0] ? "" : buf); + + /* If there are multiple same nicknames on channel now, tell it to user. */ + if (client_entry != server->conn->local_entry) { + char *nick, tmp[32]; + int count = 0; + + silc_client_nickname_parse(client, conn, client_entry->nickname, &nick); + clients = silc_client_get_clients_local(client, conn, nick, TRUE); + if (!clients || silc_dlist_count(clients) < 2) { + silc_free(nick); + silc_client_list_free(client, conn, clients); + break; + } + silc_dlist_start(clients); + while ((client_entry2 = silc_dlist_get(clients))) + if (silc_client_on_channel(channel, client_entry2)) + count++; + if (count > 1) { + silc_snprintf(tmp, sizeof(tmp), "%d", silc_dlist_count(clients)); + printformat_module("fe-common/silc", server, channel->channel_name, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_MANY_NICKS, + tmp, nick); + printformat_module("fe-common/silc", server, channel->channel_name, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS, + buf, client_entry->nickname); + } + silc_client_list_free(client, conn, clients); + silc_free(nick); + } break; case SILC_NOTIFY_TYPE_LEAVE: @@ -791,7 +815,7 @@ void silc_notify(SilcClient client, SilcClientConnection conn, snprintf(buf, sizeof(buf) - 1, "%s@%s", client_entry->username, client_entry->hostname); signal_emit("message part", 5, server, channel->channel_name, - client_entry->nickname, client_entry->username ? + client_entry->nickname, client_entry->username[0] ? buf : "", client_entry->nickname); chanrec = silc_channel_find_entry(server, channel); @@ -800,6 +824,35 @@ void silc_notify(SilcClient client, SilcClientConnection conn, if (nickrec != NULL) nicklist_remove(CHANNEL(chanrec), NICK(nickrec)); } + + /* If there is only one client with this same nickname on channel now + change it to the base format if it is formatted nickname. */ + if (channel) { + silc_client_nickname_parse(client, conn, client_entry->nickname, &name); + clients = silc_client_get_clients_local(client, conn, name, TRUE); + if (!clients || silc_dlist_count(clients) != 2) { + silc_free(name); + silc_client_list_free(client, conn, clients); + break; + } + silc_dlist_start(clients); + client_entry2 = silc_dlist_get(clients); + if (client_entry2 == client_entry) + client_entry2 = silc_dlist_get(clients); + if (silc_client_on_channel(channel, client_entry2)) { + silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname); + silc_client_nickname_format(client, conn, client_entry2, TRUE); + if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) { + nicklist_rename_unique(SERVER(server), client_entry2, buf, + client_entry2, client_entry2->nickname); + printformat_module("fe-common/silc", server, channel->channel_name, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS, + buf, client_entry2->nickname); + } + } + silc_client_list_free(client, conn, clients); + silc_free(name); + } break; case SILC_NOTIFY_TYPE_SIGNOFF: @@ -811,21 +864,16 @@ void silc_notify(SilcClient client, SilcClientConnection conn, client_entry = va_arg(va, SilcClientEntry); tmp = va_arg(va, char *); + channel = va_arg(va, SilcChannelEntry); silc_server_free_ftp(server, client_entry); - /* Print only if we have the nickname. If this cliente has just quit - when we were only resolving it, it is possible we don't have the - nickname. */ - if (client_entry->nickname) { - memset(buf, 0, sizeof(buf)); - if (client_entry->username) - snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry->username, client_entry->hostname); - signal_emit("message quit", 4, server, client_entry->nickname, - client_entry->username ? buf : "", - tmp ? tmp : ""); - } + memset(buf, 0, sizeof(buf)); + if (client_entry->username) + snprintf(buf, sizeof(buf) - 1, "%s@%s", + client_entry->username, client_entry->hostname); + signal_emit("message quit", 4, server, client_entry->nickname, + client_entry->username[0] ? buf : "", tmp ? tmp : ""); list1 = nicklist_get_same_unique(SERVER(server), client_entry); for (list_tmp = list1; list_tmp != NULL; list_tmp = @@ -835,6 +883,35 @@ void silc_notify(SilcClient client, SilcClientConnection conn, nicklist_remove(channel, nickrec); } + + /* If there is only one client with this same nickname on channel now + change it to the base format if it is formatted nickname. */ + if (channel) { + silc_client_nickname_parse(client, conn, client_entry->nickname, &name); + clients = silc_client_get_clients_local(client, conn, name, TRUE); + if (!clients || silc_dlist_count(clients) != 2) { + silc_free(name); + silc_client_list_free(client, conn, clients); + break; + } + silc_dlist_start(clients); + client_entry2 = silc_dlist_get(clients); + if (client_entry2 == client_entry) + client_entry2 = silc_dlist_get(clients); + if (silc_client_on_channel(channel, client_entry2)) { + silc_snprintf(buf, sizeof(buf), "%s", client_entry2->nickname); + silc_client_nickname_format(client, conn, client_entry2, TRUE); + if (!silc_utf8_strcasecmp(buf, client_entry2->nickname)) { + nicklist_rename_unique(SERVER(server), client_entry2, buf, + client_entry2, client_entry2->nickname); + printformat_module("fe-common/silc", server, channel->channel_name, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_USER_APPEARS, + buf, client_entry2->nickname); + } + } + silc_client_list_free(client, conn, clients); + silc_free(name); + } break; case SILC_NOTIFY_TYPE_TOPIC_SET: @@ -900,19 +977,18 @@ void silc_notify(SilcClient client, SilcClientConnection conn, SILC_LOG_DEBUG(("Notify: NICK_CHANGE")); client_entry = va_arg(va, SilcClientEntry); - client_entry2 = va_arg(va, SilcClientEntry); + name = va_arg(va, char *); /* old nickname */ - if (!strcmp(client_entry->nickname, client_entry2->nickname)) + if (!strcmp(client_entry->nickname, name)) break; memset(buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf) - 1, "%s@%s", - client_entry2->username, client_entry2->hostname); + client_entry->username, client_entry->hostname); nicklist_rename_unique(SERVER(server), - client_entry, client_entry->nickname, - client_entry2, client_entry2->nickname); - signal_emit("message nick", 4, server, client_entry2->nickname, - client_entry->nickname, buf); + client_entry, name, + client_entry, client_entry->nickname); + signal_emit("message nick", 4, server, client_entry->nickname, name, buf); break; case SILC_NOTIFY_TYPE_CMODE_CHANGE: @@ -925,18 +1001,15 @@ void silc_notify(SilcClient client, SilcClientConnection conn, idtype = va_arg(va, int); entry = va_arg(va, void *); mode = va_arg(va, SilcUInt32); - (void)va_arg(va, char *); /* cipher */ - (void)va_arg(va, char *); /* hmac */ + cipher = va_arg(va, char *); /* cipher */ + hmac = va_arg(va, char *); /* hmac */ (void)va_arg(va, char *); /* passphrase */ (void)va_arg(va, SilcPublicKey); /* founder key */ - buffer = va_arg(va, SilcBuffer); /* channel public keys */ + chpks = va_arg(va, SilcDList); /* channel public keys */ channel = va_arg(va, SilcChannelEntry); - tmp = silc_client_chmode(mode, - channel->channel_key ? - silc_cipher_get_name(channel->channel_key) : "", - channel->hmac ? - silc_hmac_get_name(channel->hmac) : ""); + tmp = silc_client_chmode(mode, cipher ? cipher : "", + hmac ? hmac : ""); chanrec = silc_channel_find_entry(server, channel); if (chanrec != NULL) { @@ -966,8 +1039,8 @@ void silc_notify(SilcClient client, SilcClientConnection conn, } /* Print the channel public key list */ - if (buffer) - silc_parse_channel_public_keys(server, channel, buffer); + if (chpks) + silc_parse_channel_public_keys(server, channel, chpks); silc_free(tmp); break; @@ -1160,34 +1233,32 @@ void silc_notify(SilcClient client, SilcClientConnection conn, /* * Server has quit the network. */ - int i; - SilcClientEntry *clients; - SilcUInt32 clients_count; + SilcDList clients; - SILC_LOG_DEBUG(("Notify: SIGNOFF")); + SILC_LOG_DEBUG(("Notify: SERVER_SIGNOFF")); (void)va_arg(va, void *); - clients = va_arg(va, SilcClientEntry *); - clients_count = va_arg(va, SilcUInt32); + clients = va_arg(va, SilcDList); - for (i = 0; i < clients_count; i++) { + silc_dlist_start(clients); + while ((client_entry = silc_dlist_get(clients))) { memset(buf, 0, sizeof(buf)); /* Print only if we have the nickname. If this client has just quit when we were only resolving it, it is possible we don't have the nickname. */ - if (clients[i]->nickname) { - if (clients[i]->username) + if (client_entry->nickname[0]) { + if (client_entry->username[0]) snprintf(buf, sizeof(buf) - 1, "%s@%s", - clients[i]->username, clients[i]->hostname); - signal_emit("message quit", 4, server, clients[i]->nickname, - clients[i]->username ? buf : "", + client_entry->username, client_entry->hostname); + signal_emit("message quit", 4, server, client_entry->nickname, + client_entry->username[0] ? buf : "", "server signoff"); } - silc_server_free_ftp(server, clients[i]); + silc_server_free_ftp(server, client_entry); - list1 = nicklist_get_same_unique(SERVER(server), clients[i]); + list1 = nicklist_get_same_unique(SERVER(server), client_entry); for (list_tmp = list1; list_tmp != NULL; list_tmp = list_tmp->next->next) { CHANNEL_REC *channel = list_tmp->data; @@ -1275,114 +1346,6 @@ void silc_notify(SilcClient client, SilcClientConnection conn, va_end(va); } -/* Called to indicate that connection was either successfully established - or connecting failed. This is also the first time application receives - the SilcClientConnection object which it should save somewhere. */ - -void silc_connect(SilcClient client, SilcClientConnection conn, - SilcClientConnectionStatus status) -{ - SILC_SERVER_REC *server = conn->context; - - if (!server || server->disconnected) { - silc_client_close_connection(client, conn); - return; - } - - switch (status) { - case SILC_CLIENT_CONN_SUCCESS: - /* We have successfully connected to server */ - if ((client->nickname != NULL) && - (strcmp(client->nickname, client->username))) - silc_queue_enable(conn); /* enable queueing until we have our nick */ - server->connected = TRUE; - signal_emit("event connected", 1, server); - break; - - case SILC_CLIENT_CONN_SUCCESS_RESUME: - /* We have successfully resumed old detached session */ - server->connected = TRUE; - signal_emit("event connected", 1, server); - - /* If we resumed old session check whether we need to update - our nickname */ - if (strcmp(server->nick, conn->local_entry->nickname)) { - char *old; - old = g_strdup(server->nick); - server_change_nick(SERVER(server), conn->local_entry->nickname); - nicklist_rename_unique(SERVER(server), - conn->local_entry, server->nick, - conn->local_entry, conn->local_entry->nickname); - signal_emit("message own_nick", 4, server, server->nick, old, ""); - g_free(old); - } - - /* remove the detach data now */ - { - char *file; - - file = silc_get_session_filename(server); - - unlink(file); - silc_free(file); - } - break; - - default: - { - char * file; - - file = silc_get_session_filename(server); - - if (silc_file_size(file) > 0) - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_CRAP, SILCTXT_REATTACH_FAILED, file); - - silc_free(file); - - server->connection_lost = TRUE; - if (server->conn) - server->conn->context = NULL; - server_disconnect(SERVER(server)); - - break; - } - } -} - -/* Called to indicate that connection was disconnected to the server. */ - -void silc_disconnect(SilcClient client, SilcClientConnection conn, - SilcStatus status, const char *message) -{ - SILC_SERVER_REC *server = conn->context; - - SILC_LOG_DEBUG(("Start")); - - if (!server || server->connection_lost) - return; - - if (server->conn && server->conn->local_entry) { - nicklist_rename_unique(SERVER(server), - server->conn->local_entry, server->nick, - server->conn->local_entry, - silc_client->username); - silc_change_nick(server, silc_client->username); - } - - if (message) - silc_say(client, conn, SILC_CLIENT_MESSAGE_AUDIT, - "Server closed connection: %s (%d) %s", - silc_get_status_message(status), status, - message ? message : ""); - - if (server->conn) - server->conn->context = NULL; - server->conn = NULL; - server->connection_lost = TRUE; - server_disconnect(SERVER(server)); -} - /* Command handler. This function is called always in the command function. If error occurs it will be called as well. `conn' is the associated client connection. `cmd_context' is the command context that was @@ -1392,11 +1355,11 @@ void silc_disconnect(SilcClient client, SilcClientConnection conn, after application has called the command. Just to tell application that the command really was processed. */ -static bool cmode_list_chpks = FALSE; +static SilcBool cmode_list_chpks = FALSE; void silc_command(SilcClient client, SilcClientConnection conn, - SilcClientCommandContext cmd_context, bool success, - SilcCommand command, SilcStatus status) + SilcBool success, SilcCommand command, SilcStatus status, + SilcUInt32 argc, unsigned char **argv) { SILC_SERVER_REC *server = conn->context; @@ -1410,13 +1373,13 @@ void silc_command(SilcClient client, SilcClientConnection conn, switch (command) { case SILC_COMMAND_INVITE: - if (cmd_context->argc > 2) + if (argc > 2) printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITING, - cmd_context->argv[2], - (cmd_context->argv[1][0] == '*' ? + argv[2], + (argv[1][0] == '*' ? (char *)conn->current_channel->channel_name : - (char *)cmd_context->argv[1])); + (char *)argv[1])); break; case SILC_COMMAND_DETACH: @@ -1424,8 +1387,7 @@ void silc_command(SilcClient client, SilcClientConnection conn, break; case SILC_COMMAND_CMODE: - if (cmd_context->argc == 3 && - !strcmp(cmd_context->argv[2], "+C")) + if (argc == 3 && !strcmp(argv[2], "+C")) cmode_list_chpks = TRUE; else cmode_list_chpks = FALSE; @@ -1436,85 +1398,11 @@ void silc_command(SilcClient client, SilcClientConnection conn, } } -typedef struct { - SilcChannelEntry channel; - bool retry; -} *SilcJoinResolve; - -/* Client info resolving callback when JOIN command reply is received. - This will cache all users on the channel. */ - -static void silc_client_join_get_users(SilcClient client, - SilcClientConnection conn, - SilcClientEntry *clients, - SilcUInt32 clients_count, - void *context) -{ - SilcJoinResolve r = context; - SilcChannelEntry channel = r->channel; - SilcHashTableList htl; - SilcChannelUser chu; - SILC_SERVER_REC *server = conn->context; - SILC_CHANNEL_REC *chanrec; - SilcClientEntry founder = NULL; - NICK_REC *ownnick; - - SILC_LOG_DEBUG(("Start, channel %s, %d users", channel->channel_name, - silc_hash_table_count(channel->user_list))); - - if (!clients && r->retry < 1) { - /* Retry to resolve */ - r->retry++; - silc_client_get_clients_by_channel(client, conn, channel, - silc_client_join_get_users, context); - return; - } - - chanrec = silc_channel_find(server, channel->channel_name); - if (chanrec == NULL) - return; - - silc_hash_table_list(channel->user_list, &htl); - while (silc_hash_table_get(&htl, NULL, (void *)&chu)) { - if (!chu->client->nickname) - continue; - if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) - founder = chu->client; - silc_nicklist_insert(chanrec, chu, FALSE); - } - silc_hash_table_list_reset(&htl); - - ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry)); - nicklist_set_own(CHANNEL(chanrec), ownnick); - signal_emit("channel joined", 1, chanrec); - chanrec->entry = channel; - - if (chanrec->topic) - printformat_module("fe-common/silc", server, channel->channel_name, - MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC, - channel->channel_name, chanrec->topic); - - if (founder) { - if (founder == conn->local_entry) { - printformat_module("fe-common/silc", - server, channel->channel_name, MSGLEVEL_CRAP, - SILCTXT_CHANNEL_FOUNDER_YOU, - channel->channel_name); - signal_emit("nick mode changed", 2, chanrec, ownnick); - } else - printformat_module("fe-common/silc", - server, channel->channel_name, MSGLEVEL_CRAP, - SILCTXT_CHANNEL_FOUNDER, - channel->channel_name, founder->nickname); - } -} - typedef struct { SilcClient client; SilcClientConnection conn; void *entry; SilcIdType id_type; - char *fingerprint; } *GetkeyContext; void silc_getkey_cb(bool success, void *context) @@ -1524,17 +1412,32 @@ void silc_getkey_cb(bool success, void *context) char *name = (getkey->id_type == SILC_ID_CLIENT ? ((SilcClientEntry)getkey->entry)->nickname : ((SilcServerEntry)getkey->entry)->server_name); + SilcPublicKey public_key = (getkey->id_type == SILC_ID_CLIENT ? + ((SilcClientEntry)getkey->entry)->public_key : + ((SilcServerEntry)getkey->entry)->public_key); + SilcSILCPublicKey silc_pubkey; + + silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key); if (success) { - printformat_module("fe-common/silc", NULL, NULL, - MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED, entity, name); + if (getkey->id_type == SILC_ID_CLIENT) + printformat_module("fe-common/silc", NULL, NULL, + MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED_CLIENT, + name, + silc_pubkey->identifier.realname ? + silc_pubkey->identifier.realname : "", + silc_pubkey->identifier.email ? + silc_pubkey->identifier.email : ""); + else + printformat_module("fe-common/silc", NULL, NULL, + MSGLEVEL_CRAP, SILCTXT_PUBKEY_VERIFIED, + entity, name); } else { printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOTVERIFIED, entity, name); } - silc_free(getkey->fingerprint); silc_free(getkey); } @@ -1564,13 +1467,13 @@ void silc_parse_inviteban_list(SilcClient client, MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_LIST, channel->channel_name, list_type); - /* parse the list */ + /* Parse the list */ tmp = silc_argument_get_first_arg(list, &type, &len); while (tmp) { switch (type) { case 1: { - /* an invite string */ + /* An invite string */ char **list; int i=0; @@ -1590,7 +1493,7 @@ void silc_parse_inviteban_list(SilcClient client, case 2: { - /* a public key */ + /* A public key */ char *fingerprint, *babbleprint; /* tmp is Public Key Payload, take public key from it. */ @@ -1607,32 +1510,29 @@ void silc_parse_inviteban_list(SilcClient client, case 3: { - /* a client ID */ - SilcClientID *client_id; + /* A Client ID */ SilcClientEntry client_entry; + SilcID id; - client_id = silc_id_payload_parse_id(tmp, len, NULL); - - if (client_id == NULL) { + if (!silc_id_payload_parse_id(tmp, len, &id)) { silc_say_error("Invalid data in %s list encountered", list_type); break; } - client_entry = silc_client_get_client_by_id(client, conn, client_id); - + client_entry = silc_client_get_client_by_id(client, conn, + &id.u.client_id); if (client_entry) { printformat_module("fe-common/silc", server, (chanrec ? chanrec->visible_name : NULL), MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITEBAN_STRING, ++counter, channel->channel_name, list_type, client_entry->nickname); + silc_client_unref_client(client, conn, client_entry); } else { resolving = TRUE; - silc_client_get_client_by_id_resolve(client, conn, client_id, + silc_client_get_client_by_id_resolve(client, conn, &id.u.client_id, NULL, NULL, NULL); } - - silc_free(client_id); } break; @@ -1640,6 +1540,7 @@ void silc_parse_inviteban_list(SilcClient client, /* "trash" */ silc_say_error("Unkown type in %s list: %u (len %u)", list_type, type, len); + break; } tmp = silc_argument_get_next_arg(list, &type, &len); } @@ -1667,17 +1568,12 @@ void silc_parse_inviteban_list(SilcClient client, and each command defines the number and type of arguments it passes to the application (on error they are not sent). */ -void -silc_command_reply(SilcClient client, SilcClientConnection conn, - SilcCommandPayload cmd_payload, bool success, - SilcCommand command, SilcStatus status, ...) - +void silc_command_reply(SilcClient client, SilcClientConnection conn, + SilcCommand command, SilcStatus status, + SilcStatus error, va_list vp) { SILC_SERVER_REC *server = conn->context; SILC_CHANNEL_REC *chanrec; - va_list vp; - - va_start(vp, status); SILC_LOG_DEBUG(("Start")); @@ -1686,41 +1582,30 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, { char buf[1024], *nickname, *username, *realname, *nick; unsigned char *fingerprint; - SilcUInt32 idle, mode; - SilcBuffer channels, user_modes; + SilcUInt32 idle, mode, *user_modes; + SilcDList channels; SilcClientEntry client_entry; SilcDList attrs; if (status == SILC_STATUS_ERR_NO_SUCH_NICK) { /* Print the unknown nick for user */ - unsigned char *tmp = - silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 2, NULL); + char *tmp = va_arg(vp, char *); if (tmp) - silc_say_error("%s: %s", tmp, - silc_get_status_message(status)); + silc_say_error("%s: %s", tmp, silc_get_status_message(status)); break; } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { /* Try to find the entry for the unknown client ID, since we might have, and print the nickname of it for user. */ - SilcUInt32 tmp_len; - unsigned char *tmp = - silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 2, &tmp_len); - if (tmp) { - SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, - NULL); - if (client_id) { - client_entry = silc_client_get_client_by_id(client, conn, - client_id); - if (client_entry && client_entry->nickname) - silc_say_error("%s: %s", client_entry->nickname, - silc_get_status_message(status)); - silc_free(client_id); - } + SilcClientID *id = va_arg(vp, SilcClientID *); + if (id) { + client_entry = silc_client_get_client_by_id(client, conn, id); + if (client_entry && client_entry->nickname[0]) + silc_say_error("%s: %s", client_entry->nickname, + silc_get_status_message(status)); + silc_client_unref_client(client, conn, client_entry); } break; - } else if (!success) { + } else if (SILC_STATUS_IS_ERROR(status)) { silc_say_error("WHOIS: %s", silc_get_status_message(status)); return; } @@ -1729,14 +1614,14 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, nickname = va_arg(vp, char *); username = va_arg(vp, char *); realname = va_arg(vp, char *); - channels = va_arg(vp, SilcBuffer); + channels = va_arg(vp, SilcDList); mode = va_arg(vp, SilcUInt32); idle = va_arg(vp, SilcUInt32); fingerprint = va_arg(vp, unsigned char *); - user_modes = va_arg(vp, SilcBuffer); + user_modes = va_arg(vp, SilcUInt32 *); attrs = va_arg(vp, SilcDList); - silc_parse_userfqdn(nickname, &nick, NULL); + silc_client_nickname_parse(client, conn, client_entry->nickname, &nick); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_WHOIS_USERINFO, nickname, client_entry->username, client_entry->hostname, @@ -1746,33 +1631,25 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, silc_free(nick); if (channels && user_modes) { - SilcUInt32 *umodes; - SilcDList list = silc_channel_payload_parse_list(channels->data, - channels->len); - if (list && silc_get_mode_list(user_modes, silc_dlist_count(list), - &umodes)) { - SilcChannelPayload entry; - int i = 0; + SilcChannelPayload entry; + int i = 0; - memset(buf, 0, sizeof(buf)); - silc_dlist_start(list); - while ((entry = silc_dlist_get(list)) != SILC_LIST_END) { - SilcUInt32 name_len; - char *m = silc_client_chumode_char(umodes[i++]); - char *name = silc_channel_get_name(entry, &name_len); - - if (m) - silc_strncat(buf, sizeof(buf) - 1, m, strlen(m)); - silc_strncat(buf, sizeof(buf) - 1, name, name_len); - silc_strncat(buf, sizeof(buf) - 1, " ", 1); - silc_free(m); - } - - printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_CHANNELS, buf); - silc_channel_payload_list_free(list); - silc_free(umodes); + memset(buf, 0, sizeof(buf)); + silc_dlist_start(channels); + while ((entry = silc_dlist_get(channels))) { + SilcUInt32 name_len; + char *m = silc_client_chumode_char(user_modes[i++]); + char *name = silc_channel_get_name(entry, &name_len); + + if (m) + silc_strncat(buf, sizeof(buf) - 1, m, strlen(m)); + silc_strncat(buf, sizeof(buf) - 1, name, name_len); + silc_strncat(buf, sizeof(buf) - 1, " ", 1); + silc_free(m); } + + printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, + SILCTXT_WHOIS_CHANNELS, buf); } if (mode) { @@ -1805,57 +1682,17 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, } break; - case SILC_COMMAND_IDENTIFY: - { - SilcClientEntry client_entry; - - if (status == SILC_STATUS_ERR_NO_SUCH_NICK) { - /* Print the unknown nick for user */ - unsigned char *tmp = - silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 2, NULL); - if (tmp) - silc_say_error("%s: %s", tmp, - silc_get_status_message(status)); - break; - } else if (status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { - /* Try to find the entry for the unknown client ID, since we - might have, and print the nickname of it for user. */ - SilcUInt32 tmp_len; - unsigned char *tmp = - silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 2, &tmp_len); - if (tmp) { - SilcClientID *client_id = silc_id_payload_parse_id(tmp, tmp_len, - NULL); - if (client_id) { - client_entry = silc_client_get_client_by_id(client, conn, - client_id); - if (client_entry && client_entry->nickname) - silc_say_error("%s: %s", client_entry->nickname, - silc_get_status_message(status)); - silc_free(client_id); - } - } - break; - } - - break; - } - case SILC_COMMAND_WHOWAS: { char *nickname, *username, *realname; if (status == SILC_STATUS_ERR_NO_SUCH_NICK) { - char *tmp = - silc_argument_get_arg_type(silc_command_get_args(cmd_payload), - 2, NULL); + char *tmp = va_arg(vp, char *); if (tmp) silc_say_error("%s: %s", tmp, silc_get_status_message(status)); break; - } else if (!success) { + } else if (SILC_STATUS_IS_ERROR(status)) { silc_say_error("WHOWAS: %s", silc_get_status_message(status)); return; } @@ -1874,51 +1711,56 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, case SILC_COMMAND_INVITE: { SilcChannelEntry channel; - SilcBuffer payload; SilcArgumentPayload invite_list; - SilcUInt16 argc; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) return; channel = va_arg(vp, SilcChannelEntry); - payload = va_arg(vp, SilcBuffer); - - if (payload) { - SILC_GET16_MSB(argc, payload->data); - invite_list = silc_argument_payload_parse(payload->data + 2, - payload->len - 2, argc); - if (invite_list) { - silc_parse_inviteban_list(client, conn, server, channel, - "invite", invite_list); - silc_argument_payload_free(invite_list); - } - } + invite_list = va_arg(vp, SilcArgumentPayload); + + if (invite_list) + silc_parse_inviteban_list(client, conn, server, channel, + "invite", invite_list); } break; case SILC_COMMAND_JOIN: { - char *channel, *mode, *topic; + char *channel, *mode, *topic, *cipher, *hmac; SilcUInt32 modei; + SilcHashTableList *user_list; SilcChannelEntry channel_entry; - SilcBuffer client_id_list; - SilcUInt32 list_count; - - if (!success) + SilcChannelUser chu; + SilcClientEntry founder = NULL; + NICK_REC *ownnick; + + if (SILC_STATUS_IS_ERROR(status)) { + if (status == SILC_STATUS_ERR_NO_SUCH_SERVER) { + char *tmp = va_arg(vp, char *); + if (tmp) + silc_say_error("JOIN: %s: %s", tmp, + silc_get_status_message(status)); + return; + } + if (status == SILC_STATUS_ERR_NO_SUCH_CHANNEL) { + char *tmp = va_arg(vp, char *); + if (tmp) + silc_say_error("JOIN: %s: %s", tmp, + silc_get_status_message(status)); + return; + } + silc_say_error("JOIN: %s", silc_get_status_message(status)); return; + } channel = va_arg(vp, char *); channel_entry = va_arg(vp, SilcChannelEntry); modei = va_arg(vp, SilcUInt32); - (void)va_arg(vp, SilcUInt32); - (void)va_arg(vp, unsigned char *); - (void)va_arg(vp, unsigned char *); - (void)va_arg(vp, unsigned char *); + user_list = va_arg(vp, SilcHashTableList *); topic = va_arg(vp, char *); - (void)va_arg(vp, unsigned char *); - list_count = va_arg(vp, SilcUInt32); - client_id_list = va_arg(vp, SilcBuffer); + cipher = va_arg(vp, char *); + hmac = va_arg(vp, char *); chanrec = silc_channel_find(server, channel); if (!chanrec) @@ -1947,23 +1789,45 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, silc_free(dm); } - mode = silc_client_chmode(modei, - channel_entry->channel_key ? - silc_cipher_get_name(channel_entry-> - channel_key) : "", - channel_entry->hmac ? - silc_hmac_get_name(channel_entry->hmac) : ""); + mode = silc_client_chmode(modei, cipher ? cipher : "", hmac ? hmac : ""); g_free_not_null(chanrec->mode); chanrec->mode = g_strdup(mode == NULL ? "" : mode); signal_emit("channel mode changed", 1, chanrec); - /* Resolve the client information */ - { - SilcJoinResolve r = silc_calloc(1, sizeof(*r)); - r->channel = channel_entry; - silc_client_get_clients_by_list(client, conn, list_count, - client_id_list, - silc_client_join_get_users, r); + /* Get user list */ + while (silc_hash_table_get(user_list, NULL, (void *)&chu)) { + if (!chu->client->nickname[0]) + continue; + if (chu->mode & SILC_CHANNEL_UMODE_CHANFO) + founder = chu->client; + silc_nicklist_insert(chanrec, chu, FALSE); + } + + ownnick = NICK(silc_nicklist_find(chanrec, conn->local_entry)); + if (!ownnick) + break; + nicklist_set_own(CHANNEL(chanrec), ownnick); + signal_emit("channel joined", 1, chanrec); + chanrec->entry = channel_entry; + + if (chanrec->topic) + printformat_module("fe-common/silc", server, + channel_entry->channel_name, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_TOPIC, + channel_entry->channel_name, chanrec->topic); + + if (founder) { + if (founder == conn->local_entry) { + printformat_module("fe-common/silc", + server, channel_entry->channel_name, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER_YOU, + channel_entry->channel_name); + signal_emit("nick mode changed", 2, chanrec, ownnick); + } else + printformat_module("fe-common/silc", + server, channel_entry->channel_name, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_FOUNDER, + channel_entry->channel_name, founder->nickname); } break; @@ -1975,30 +1839,30 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry = va_arg(vp, SilcClientEntry); GSList *nicks; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) { + silc_say_error("NICK: %s", silc_get_status_message(status)); return; + } nicks = nicklist_get_same(SERVER(server), client_entry->nickname); if ((nicks != NULL) && - (strcmp(SERVER(server)->nick, client_entry->nickname))) { + (strcmp(SERVER(server)->nick, client_entry->nickname))) { char buf[512]; SilcClientEntry collider, old; old = ((SILC_NICK_REC *)(nicks->next->data))->silc_user->client; - collider = silc_client_get_client_by_id(client, conn, - old->id); - + collider = silc_client_get_client_by_id(client, conn, &old->id); if (collider != client_entry) { - - memset(buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf) - 1, "%s@%s", - collider->username, collider->hostname); + memset(buf, 0, sizeof(buf)); + snprintf(buf, sizeof(buf) - 1, "%s@%s", + collider->username, collider->hostname); nicklist_rename_unique(SERVER(server), - old, old->nickname, - collider, collider->nickname); + old, old->nickname, + collider, collider->nickname); silc_print_nick_change(server, collider->nickname, - client_entry->nickname, buf); + client_entry->nickname, buf); } + silc_client_unref_client(client, conn, collider); } if (nicks != NULL) @@ -2026,13 +1890,11 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, char users[20]; char tmp[256], *cp, *dm = NULL; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) return; (void)va_arg(vp, SilcChannelEntry); name = va_arg(vp, char *); - if (!name) - return; topic = va_arg(vp, char *); usercount = va_arg(vp, int); @@ -2071,7 +1933,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, SilcUInt32 mode; char *reason; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) return; mode = va_arg(vp, SilcUInt32); @@ -2106,8 +1968,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, break; case SILC_COMMAND_OPER: - if (!success) + if (SILC_STATUS_IS_ERROR(status)) { + silc_say_error("OPER: %s", silc_get_status_message(status)); return; + } server->umode |= SILC_UMODE_SERVER_OPERATOR; signal_emit("user mode changed", 2, server, NULL); @@ -2117,8 +1981,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, break; case SILC_COMMAND_SILCOPER: - if (!success) + if (SILC_STATUS_IS_ERROR(status)) { + silc_say_error("SILCOPER: %s", silc_get_status_message(status)); return; + } server->umode |= SILC_UMODE_ROUTER_OPERATOR; signal_emit("user mode changed", 2, server, NULL); @@ -2133,8 +1999,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel; SilcChannelUser chu; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) { + silc_say_error("USERS: %s", silc_get_status_message(status)); return; + } channel = va_arg(vp, SilcChannelEntry); @@ -2147,7 +2015,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, SilcClientEntry e = chu->client; char stat[5], *mode; - if (!e->nickname) + if (!e->nickname[0]) continue; memset(stat, 0, sizeof(stat)); @@ -2174,8 +2042,8 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, printformat_module("fe-common/silc", server, channel->channel_name, MSGLEVEL_CRAP, SILCTXT_USERS, e->nickname, stat, - e->username ? e->username : "", - e->hostname ? e->hostname : "", + e->username[0] ? e->username : "", + e->hostname[0] ? e->hostname : "", e->realname ? e->realname : ""); if (mode) silc_free(mode); @@ -2187,26 +2055,17 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, case SILC_COMMAND_BAN: { SilcChannelEntry channel; - SilcBuffer payload; - SilcArgumentPayload ban_list; - SilcUInt16 argc; + SilcArgumentPayload invite_list; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) return; channel = va_arg(vp, SilcChannelEntry); - payload = va_arg(vp, SilcBuffer); - - if (payload) { - SILC_GET16_MSB(argc, payload->data); - ban_list = silc_argument_payload_parse(payload->data + 2, - payload->len - 2, argc); - if (ban_list) { - silc_parse_inviteban_list(client, conn, server, channel, - "ban", ban_list); - silc_argument_payload_free(ban_list); - } - } + invite_list = va_arg(vp, SilcArgumentPayload); + + if (invite_list) + silc_parse_inviteban_list(client, conn, server, channel, + "ban", invite_list); } break; @@ -2215,27 +2074,24 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, SilcIdType id_type; void *entry; SilcPublicKey public_key; - unsigned char *pk; - SilcUInt32 pk_len; GetkeyContext getkey; char *name; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) { + silc_say_error("GETKEY: %s", silc_get_status_message(status)); return; + } id_type = va_arg(vp, SilcUInt32); entry = va_arg(vp, void *); public_key = va_arg(vp, SilcPublicKey); if (public_key) { - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - getkey = silc_calloc(1, sizeof(*getkey)); getkey->entry = entry; getkey->id_type = id_type; getkey->client = client; getkey->conn = conn; - getkey->fingerprint = silc_hash_fingerprint(NULL, pk, pk_len); name = (id_type == SILC_ID_CLIENT ? ((SilcClientEntry)entry)->nickname : @@ -2243,11 +2099,9 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, silc_verify_public_key_internal(client, conn, name, (id_type == SILC_ID_CLIENT ? - SILC_SOCKET_TYPE_CLIENT : - SILC_SOCKET_TYPE_SERVER), - pk, pk_len, SILC_SKE_PK_TYPE_SILC, - silc_getkey_cb, getkey); - silc_free(pk); + SILC_CONN_CLIENT : + SILC_CONN_SERVER), + public_key, silc_getkey_cb, getkey); } else { printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_NOKEY); @@ -2261,7 +2115,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, char *server_name; char *server_info; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) return; server_entry = va_arg(vp, SilcServerEntry); @@ -2282,7 +2136,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, char *topic; char tmp[256], *cp, *dm = NULL; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) return; channel = va_arg(vp, SilcChannelEntry); @@ -2326,126 +2180,99 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, case SILC_COMMAND_STATS: { - SilcUInt32 starttime, uptime, my_clients, my_channels, my_server_ops, - my_router_ops, cell_clients, cell_channels, cell_servers, - clients, channels, servers, routers, server_ops, router_ops; - SilcUInt32 buf_len; - SilcBufferStruct buf; - unsigned char *tmp_buf; + SilcClientStats *cstats; char tmp[40]; const char *tmptime; int days, hours, mins, secs; - if (!success) + if (SILC_STATUS_IS_ERROR(status)) return; - tmp_buf = va_arg(vp, unsigned char *); - buf_len = va_arg(vp, SilcUInt32); - - if (!tmp_buf || !buf_len) { + cstats = va_arg(vp, SilcClientStats *); + if (!cstats) { printtext(server, NULL, MSGLEVEL_CRAP, "No statistics available"); return; } - /* Get statistics structure */ - silc_buffer_set(&buf, tmp_buf, buf_len); - silc_buffer_unformat(&buf, - SILC_STR_UI_INT(&starttime), - SILC_STR_UI_INT(&uptime), - SILC_STR_UI_INT(&my_clients), - SILC_STR_UI_INT(&my_channels), - SILC_STR_UI_INT(&my_server_ops), - SILC_STR_UI_INT(&my_router_ops), - SILC_STR_UI_INT(&cell_clients), - SILC_STR_UI_INT(&cell_channels), - SILC_STR_UI_INT(&cell_servers), - SILC_STR_UI_INT(&clients), - SILC_STR_UI_INT(&channels), - SILC_STR_UI_INT(&servers), - SILC_STR_UI_INT(&routers), - SILC_STR_UI_INT(&server_ops), - SILC_STR_UI_INT(&router_ops), - SILC_STR_END); - - tmptime = silc_get_time(starttime); + tmptime = silc_time_string(cstats->starttime); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local server start time", tmptime); - days = uptime / (24 * 60 * 60); - uptime -= days * (24 * 60 * 60); - hours = uptime / (60 * 60); - uptime -= hours * (60 * 60); - mins = uptime / 60; - uptime -= mins * 60; - secs = uptime; + days = cstats->uptime / (24 * 60 * 60); + cstats->uptime -= days * (24 * 60 * 60); + hours = cstats->uptime / (60 * 60); + cstats->uptime -= hours * (60 * 60); + mins = cstats->uptime / 60; + cstats->uptime -= mins * 60; + secs = cstats->uptime; snprintf(tmp, sizeof(tmp) - 1, "%d days %d hours %d mins %d secs", days, hours, mins, secs); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local server uptime", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_clients); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_clients); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local server clients", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_channels); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_channels); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local server channels", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_server_ops); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_server_ops); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local server operators", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)my_router_ops); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->my_router_ops); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local router operators", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_clients); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_clients); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local cell clients", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_channels); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_channels); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local cell channels", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cell_servers); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->cell_servers); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Local cell servers", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)clients); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->clients); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Total clients", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)channels); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->channels); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Total channels", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)servers); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->servers); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Total servers", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)routers); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->routers); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Total routers", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)server_ops); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->server_ops); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Total server operators", tmp); - snprintf(tmp, sizeof(tmp) - 1, "%d", (int)router_ops); + snprintf(tmp, sizeof(tmp) - 1, "%d", (int)cstats->router_ops); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_STATS, "Total router operators", tmp); @@ -2455,20 +2282,20 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, case SILC_COMMAND_CMODE: { SilcChannelEntry channel_entry; - SilcBuffer channel_pubkeys; + SilcDList chpks; channel_entry = va_arg(vp, SilcChannelEntry); (void)va_arg(vp, SilcUInt32); (void)va_arg(vp, SilcPublicKey); - channel_pubkeys = va_arg(vp, SilcBuffer); + chpks = va_arg(vp, SilcDList); - if (!success || !cmode_list_chpks || + if (SILC_STATUS_IS_ERROR(status) || !cmode_list_chpks || !channel_entry || !channel_entry->channel_name) return; /* Print the channel public key list */ - if (channel_pubkeys) - silc_parse_channel_public_keys(server, channel_entry, channel_pubkeys); + if (chpks) + silc_parse_channel_public_keys(server, channel_entry, chpks); else printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST, @@ -2479,14 +2306,53 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, case SILC_COMMAND_LEAVE: { - /* we might be cycling, so disable queueing again */ + if (SILC_STATUS_IS_ERROR(status)) + return; + + /* We might be cycling, so disable queueing again */ silc_queue_disable(conn); } break; - } + case SILC_COMMAND_DETACH: + { + /* Save the detachment data to file. */ + char *file; + SilcBuffer detach; + + if (SILC_STATUS_IS_ERROR(status)) + return; - va_end(vp); + detach = va_arg(vp, SilcBuffer); + file = silc_get_session_filename(server); + silc_file_writefile(file, silc_buffer_data(detach), + silc_buffer_len(detach)); + silc_free(file); + } + break; + + case SILC_COMMAND_KILL: + { + SilcClientEntry client_entry; + + if (SILC_STATUS_IS_ERROR(status)) { + silc_say_error("KILL: %s", silc_get_status_message(status)); + return; + } + + client_entry = va_arg(vp, SilcClientEntry); + if (!client_entry || !client_entry->nickname[0]) + break; + + /* Print this only if the killed client isn't joined on channels. + If it is, we receive KILLED notify and we'll print this there. */ + if (!silc_hash_table_count(client_entry->channels)) + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_KILLED, + client_entry->nickname, + conn->local_entry->nickname, ""); + } + } } typedef struct { @@ -2495,9 +2361,7 @@ typedef struct { char *filename; char *entity; char *entity_name; - unsigned char *pk; - SilcUInt32 pk_len; - SilcSKEPKType pk_type; + SilcPublicKey public_key; SilcVerifyPublicKey completion; void *context; } *PublicKeyVerify; @@ -2512,8 +2376,8 @@ static void verify_public_key_completion(const char *line, void *context) verify->completion(TRUE, verify->context); /* Save the key for future checking */ - silc_pkcs_save_public_key_data(verify->filename, verify->pk, - verify->pk_len, SILC_PKCS_FILE_PEM); + silc_pkcs_save_public_key(verify->filename, verify->public_key, + SILC_PKCS_FILE_BASE64); } else { /* Call the completion */ if (verify->completion) @@ -2528,7 +2392,6 @@ static void verify_public_key_completion(const char *line, void *context) silc_free(verify->filename); silc_free(verify->entity); silc_free(verify->entity_name); - silc_free(verify->pk); silc_free(verify); } @@ -2539,34 +2402,51 @@ static void verify_public_key_completion(const char *line, void *context) static void silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, - const char *name, SilcSocketType conn_type, - unsigned char *pk, SilcUInt32 pk_len, - SilcSKEPKType pk_type, + const char *name, + SilcConnectionType conn_type, + SilcPublicKey public_key, SilcVerifyPublicKey completion, void *context) { - int i; + PublicKeyVerify verify; char file[256], filename[256], filename2[256], *ipf, *hostf = NULL; char *fingerprint, *babbleprint, *format; + SilcPublicKey local_pubkey; + SilcSILCPublicKey silc_pubkey; + SilcUInt16 port; + const char *hostname, *ip; + unsigned char *pk; + SilcUInt32 pk_len; struct passwd *pw; struct stat st; - char *entity = ((conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) ? + char *entity = ((conn_type == SILC_CONN_SERVER || + conn_type == SILC_CONN_ROUTER) ? "server" : "client"); - PublicKeyVerify verify; + int i; - if (pk_type != SILC_SKE_PK_TYPE_SILC) { + if (silc_pkcs_get_type(public_key) != SILC_PKCS_SILC) { printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_UNSUPPORTED, - entity, pk_type); + entity, silc_pkcs_get_type(public_key)); + if (completion) + completion(FALSE, context); + return; + } + + /* Encode public key */ + pk = silc_pkcs_public_key_encode(public_key, &pk_len); + if (!pk) { if (completion) completion(FALSE, context); return; } + silc_pubkey = silc_pkcs_get_context(SILC_PKCS_SILC, public_key); + pw = getpwuid(getuid()); if (!pw) { if (completion) completion(FALSE, context); + silc_free(pk); return; } @@ -2574,16 +2454,19 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, memset(filename2, 0, sizeof(filename2)); memset(file, 0, sizeof(file)); - if (conn_type == SILC_SOCKET_TYPE_SERVER || - conn_type == SILC_SOCKET_TYPE_ROUTER) { + /* Get remote host information */ + silc_socket_stream_get_info(silc_packet_stream_get_stream(conn->stream), + NULL, &hostname, &ip, &port); + + if (conn_type == SILC_CONN_SERVER || + conn_type == SILC_CONN_ROUTER) { if (!name) { - snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - conn->sock->ip, conn->sock->port); + snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, ip, port); snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s", get_irssi_dir(), entity, file); snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - conn->sock->hostname, conn->sock->port); + hostname, port); snprintf(filename2, sizeof(filename2) - 1, "%s/%skeys/%s", get_irssi_dir(), entity, file); @@ -2591,7 +2474,7 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, hostf = filename2; } else { snprintf(file, sizeof(file) - 1, "%skey_%s_%d.pub", entity, - name, conn->sock->port); + name, port); snprintf(filename, sizeof(filename) - 1, "%s/%skeys/%s", get_irssi_dir(), entity, file); @@ -2621,12 +2504,10 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, verify->conn = conn; verify->filename = strdup(ipf); verify->entity = strdup(entity); - verify->entity_name = (conn_type != SILC_SOCKET_TYPE_CLIENT ? - (name ? strdup(name) : strdup(conn->sock->hostname)) + verify->entity_name = (conn_type != SILC_CONN_CLIENT ? + (name ? strdup(name) : strdup(hostname)) : NULL); - verify->pk = silc_memdup(pk, pk_len); - verify->pk_len = pk_len; - verify->pk_type = pk_type; + verify->public_key = public_key; verify->completion = completion; verify->context = context; @@ -2637,6 +2518,13 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? verify->entity_name : entity); + if (conn_type == SILC_CONN_CLIENT && name && + silc_pubkey->identifier.realname) + printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, + SILCTXT_PUBKEY_RECEIVED_CLIENT, name, + silc_pubkey->identifier.realname, + silc_pubkey->identifier.email ? + silc_pubkey->identifier.email : ""); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, @@ -2647,25 +2535,27 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); return; } else { /* The key already exists, verify it. */ - SilcPublicKey public_key; unsigned char *encpk; SilcUInt32 encpk_len; /* Load the key file, try for both IP filename and hostname filename */ - if (!silc_pkcs_load_public_key(ipf, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(ipf, &public_key, - SILC_PKCS_FILE_BIN) && - (!hostf || (!silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_PEM) && - !silc_pkcs_load_public_key(hostf, &public_key, - SILC_PKCS_FILE_BIN)))) { + if (!silc_pkcs_load_public_key(ipf, &local_pubkey) && + (!hostf || (!silc_pkcs_load_public_key(hostf, &local_pubkey)))) { printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? verify->entity_name : entity); + if (conn_type == SILC_CONN_CLIENT && name && + silc_pubkey->identifier.realname) + printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, + SILCTXT_PUBKEY_RECEIVED_CLIENT, name, + silc_pubkey->identifier.realname, + silc_pubkey->identifier.email ? + silc_pubkey->identifier.email : ""); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, @@ -2678,15 +2568,24 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); return; } /* Encode the key data */ - encpk = silc_pkcs_public_key_encode(public_key, &encpk_len); + encpk = silc_pkcs_public_key_encode(local_pubkey, &encpk_len); if (!encpk) { printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? verify->entity_name : entity); + if (conn_type == SILC_CONN_CLIENT && name && + silc_pubkey->identifier.realname) + printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, + SILCTXT_PUBKEY_RECEIVED_CLIENT, name, + silc_pubkey->identifier.realname, + silc_pubkey->identifier.email ? + silc_pubkey->identifier.email : ""); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, @@ -2699,14 +2598,24 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); return; } + silc_pkcs_public_key_free(local_pubkey); /* Compare the keys */ if (memcmp(encpk, pk, encpk_len)) { printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_RECEIVED,verify->entity_name ? verify->entity_name : entity); + if (conn_type == SILC_CONN_CLIENT && name && + silc_pubkey->identifier.realname) + printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, + SILCTXT_PUBKEY_RECEIVED_CLIENT, name, + silc_pubkey->identifier.realname, + silc_pubkey->identifier.email ? + silc_pubkey->identifier.email : ""); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_PUBKEY_FINGERPRINT, entity, fingerprint); printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, @@ -2725,18 +2634,23 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); + silc_free(encpk); + silc_free(pk); return; } /* Local copy matched */ if (completion) completion(TRUE, context); + silc_free(encpk); silc_free(fingerprint); + silc_free(babbleprint); silc_free(verify->filename); silc_free(verify->entity); silc_free(verify->entity_name); - silc_free(verify->pk); silc_free(verify); + silc_free(pk); } } @@ -2747,12 +2661,11 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, void silc_verify_public_key(SilcClient client, SilcClientConnection conn, - SilcSocketType conn_type, unsigned char *pk, - SilcUInt32 pk_len, SilcSKEPKType pk_type, + SilcConnectionType conn_type, + SilcPublicKey public_key, SilcVerifyPublicKey completion, void *context) { - silc_verify_public_key_internal(client, conn, NULL, conn_type, pk, - pk_len, pk_type, + silc_verify_public_key_internal(client, conn, NULL, conn_type, public_key, completion, context); } @@ -2787,131 +2700,60 @@ void silc_ask_passphrase(SilcClient client, SilcClientConnection conn, typedef struct { SilcGetAuthMeth completion; void *context; -} *InternalGetAuthMethod; +} *GetAuthMethod; -/* Callback called when we've received the authentication method information - from the server after we've requested it. This will get the authentication - data from the user if needed. */ - -static void silc_get_auth_method_callback(SilcClient client, - SilcClientConnection conn, - SilcAuthMethod auth_meth, - void *context) +static void silc_get_auth_ask_passphrase(const unsigned char *passphrase, + SilcUInt32 passphrase_len, + void *context) { - InternalGetAuthMethod internal = (InternalGetAuthMethod)context; - - SILC_LOG_DEBUG(("Start")); - - switch (auth_meth) { - case SILC_AUTH_NONE: - /* No authentication required. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - case SILC_AUTH_PASSWORD: - { - /* Check whether we find the password for this server in our - configuration. If not, then don't provide so library will ask - it from the user. */ - SERVER_SETUP_REC *setup = server_setup_find_port(conn->remote_host, - conn->remote_port); - if (!setup || !setup->password) { - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - } - - (*internal->completion)(TRUE, auth_meth, setup->password, - strlen(setup->password), internal->context); - } - break; - case SILC_AUTH_PUBLIC_KEY: - /* Do not get the authentication data now, the library will generate - it using our default key, if we do not provide it here. */ - /* XXX In the future when we support multiple local keys and multiple - local certificates we will need to ask from user which one to use. */ - (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); - break; - } - - silc_free(internal); + GetAuthMethod a = context; + a->completion(passphrase ? SILC_AUTH_PASSWORD : SILC_AUTH_NONE, + passphrase, passphrase_len, a->context); + silc_free(a); } -/* Find authentication method and authentication data by hostname and - port. The hostname may be IP address as well. The found authentication - method and authentication data is returned to `auth_meth', `auth_data' - and `auth_data_len'. The function returns TRUE if authentication method - is found and FALSE if not. `conn' may be NULL. */ +/* Find authentication data by hostname and port. The hostname may be IP + address as well.*/ void silc_get_auth_method(SilcClient client, SilcClientConnection conn, char *hostname, SilcUInt16 port, + SilcAuthMethod auth_meth, SilcGetAuthMeth completion, void *context) { - InternalGetAuthMethod internal; + SERVER_SETUP_REC *setup; SILC_LOG_DEBUG(("Start")); - /* If we do not have this connection configured by the user in a - configuration file then resolve the authentication method from the - server for this session. */ - internal = silc_calloc(1, sizeof(*internal)); - internal->completion = completion; - internal->context = context; - - silc_client_request_authentication_method(client, conn, - silc_get_auth_method_callback, - internal); -} - -/* Notifies application that failure packet was received. This is called - if there is some protocol active in the client. The `protocol' is the - protocol context. The `failure' is opaque pointer to the failure - indication. Note, that the `failure' is protocol dependant and application - must explicitly cast it to correct type. Usually `failure' is 32 bit - failure type (see protocol specs for all protocol failure types). */ - -void silc_failure(SilcClient client, SilcClientConnection conn, - SilcProtocol protocol, void *failure) -{ - SILC_LOG_DEBUG(("Start")); - - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_KEY_EXCHANGE) { - SilcSKEStatus status = (SilcSKEStatus)failure; - - if (status == SILC_SKE_STATUS_BAD_VERSION) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_BAD_VERSION); - if (status == SILC_SKE_STATUS_UNSUPPORTED_PUBLIC_KEY) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_UNSUPPORTED_PUBLIC_KEY); - if (status == SILC_SKE_STATUS_UNKNOWN_GROUP) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_UNKNOWN_GROUP); - if (status == SILC_SKE_STATUS_UNKNOWN_CIPHER) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_UNKNOWN_CIPHER); - if (status == SILC_SKE_STATUS_UNKNOWN_PKCS) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_UNKNOWN_PKCS); - if (status == SILC_SKE_STATUS_UNKNOWN_HASH_FUNCTION) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_UNKNOWN_HASH_FUNCTION); - if (status == SILC_SKE_STATUS_UNKNOWN_HMAC) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_UNKNOWN_HMAC); - if (status == SILC_SKE_STATUS_INCORRECT_SIGNATURE) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_INCORRECT_SIGNATURE); - if (status == SILC_SKE_STATUS_INVALID_COOKIE) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_KE_INVALID_COOKIE); + if (auth_meth == SILC_AUTH_PUBLIC_KEY) { + /* Returning NULL will cause library to use our private key configured + for this connection */ + completion(SILC_AUTH_PUBLIC_KEY, NULL, 0, context); + return; } - if (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { - SilcUInt32 err = (SilcUInt32)failure; + /* Check whether we find the password for this server in our + configuration. If it's set, always send it server. */ + setup = server_setup_find_port(hostname, port); + if (setup && setup->password) { + completion(SILC_AUTH_PASSWORD, setup->password, strlen(setup->password), + context); + return; + } - if (err == SILC_AUTH_FAILED) - printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, - SILCTXT_AUTH_FAILED); + /* Didn't find password. If server wants it, ask it from user. */ + if (auth_meth == SILC_AUTH_PASSWORD) { + GetAuthMethod a; + a = silc_calloc(1, sizeof(*a)); + if (a) { + a->completion = completion; + a->context = context; + silc_ask_passphrase(client, conn, silc_get_auth_ask_passphrase, a); + return; + } } + + /* No authentication */ + completion(SILC_AUTH_NONE, NULL, 0, context); } /* Asks whether the user would like to perform the key agreement protocol. @@ -2921,20 +2763,22 @@ void silc_failure(SilcClient client, SilcClientConnection conn, desired (application may start it later by calling the function silc_client_perform_key_agreement). */ -bool silc_key_agreement(SilcClient client, SilcClientConnection conn, +void silc_key_agreement(SilcClient client, SilcClientConnection conn, SilcClientEntry client_entry, const char *hostname, - SilcUInt16 port, SilcKeyAgreementCallback *completion, - void **context) + SilcUInt16 protocol, SilcUInt16 port) { - char portstr[12]; + char portstr[12], protostr[5]; SILC_LOG_DEBUG(("Start")); /* We will just display the info on the screen and return FALSE and user will have to start the key agreement with a command. */ - if (hostname) + if (hostname) { snprintf(portstr, sizeof(portstr) - 1, "%d", port); + snprintf(protostr, sizeof(protostr) - 1, "%s", protocol == 1 ? "UDP" : + "TCP"); + } if (!hostname) printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, @@ -2942,12 +2786,7 @@ bool silc_key_agreement(SilcClient client, SilcClientConnection conn, else printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP, SILCTXT_KEY_AGREEMENT_REQUEST_HOST, - client_entry->nickname, hostname, portstr); - - *completion = NULL; - *context = NULL; - - return FALSE; + client_entry->nickname, hostname, portstr, protostr); } /* Notifies application that file transfer protocol session is being @@ -2999,38 +2838,6 @@ void silc_ftp(SilcClient client, SilcClientConnection conn, client_entry->nickname, hostname, portstr); } -/* Delivers SILC session detachment data indicated by `detach_data' to the - application. If application has issued SILC_COMMAND_DETACH command - the client session in the SILC network is not quit. The client remains - in the network but is detached. The detachment data may be used later - to resume the session in the SILC Network. The appliation is - responsible of saving the `detach_data', to for example in a file. - - The detachment data can be given as argument to the functions - silc_client_connect_to_server, or silc_client_add_connection when - creating connection to remote server, inside SilcClientConnectionParams - structure. If it is provided the client library will attempt to resume - the session in the network. After the connection is created - successfully, the application is responsible of setting the user - interface for user into the same state it was before detaching (showing - same channels, channel modes, etc). It can do this by fetching the - information (like joined channels) from the client library. */ - -void -silc_detach(SilcClient client, SilcClientConnection conn, - const unsigned char *detach_data, SilcUInt32 detach_data_len) -{ - SILC_SERVER_REC *server = conn->context; - char *file; - - /* Save the detachment data to file. */ - - file = silc_get_session_filename(server); - silc_file_writefile(file, detach_data, detach_data_len); - silc_free(file); -} - - /* SILC client operations */ SilcClientOperations ops = { silc_say, @@ -3039,13 +2846,9 @@ SilcClientOperations ops = { silc_notify, silc_command, silc_command_reply, - silc_connect, - silc_disconnect, silc_get_auth_method, silc_verify_public_key, silc_ask_passphrase, - silc_failure, silc_key_agreement, silc_ftp, - silc_detach, };