X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fsilc%2Fcore%2Fclient_ops.c;h=79be2e8c7b4eef61cc9c1e9d7bbbcd1e63e4c332;hb=017dec75a98209fbef49eb496c2269b0c49e736d;hp=0a7234c42c658c96ae546b6775aa8fb26540b638;hpb=251d90aa6d310f4711884e97c338ed4638f62c0c;p=silc.git diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 0a7234c4..79be2e8c 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -45,7 +45,7 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, SilcVerifyPublicKey completion, void *context); void silc_say(SilcClient client, SilcClientConnection conn, - char *msg, ...) + SilcClientMessageType type, char *msg, ...) { SILC_SERVER_REC *server; va_list va; @@ -184,10 +184,15 @@ void silc_notify(SilcClient client, SilcClientConnection conn, or connecting failed. This is also the first time application receives the SilcClientConnection objecet which it should save somewhere. */ -void silc_connect(SilcClient client, SilcClientConnection conn, int success) +void silc_connect(SilcClient client, SilcClientConnection conn, int success) { SILC_SERVER_REC *server = conn->context; + if (!server && !success) { + silc_client_close_connection(client, NULL, conn); + return; + } + if (success) { server->connected = TRUE; signal_emit("event connected", 1, server); @@ -223,6 +228,23 @@ void silc_command(SilcClient client, SilcClientConnection conn, SilcClientCommandContext cmd_context, int success, SilcCommand command) { + SILC_SERVER_REC *server = conn->context; + + if (!success) + return; + + switch(command) { + case SILC_COMMAND_INVITE: + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITING, + cmd_context->argv[2], + (cmd_context->argv[1][0] == '*' ? + (char *)conn->current_channel->channel_name : + (char *)cmd_context->argv[1])); + break; + default: + break; + } } /* Client info resolving callback when JOIN command reply is received. @@ -311,9 +333,10 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, switch(command) { case SILC_COMMAND_WHOIS: { - char buf[1024], *nickname, *username, *realname; + char buf[1024], *nickname, *username, *realname, *nick; uint32 idle, mode; SilcBuffer channels; + SilcClientEntry client_entry; if (status == SILC_STATUS_ERR_NO_SUCH_NICK || status == SILC_STATUS_ERR_NO_SUCH_CLIENT_ID) { @@ -331,7 +354,7 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, if (!success) return; - (void)va_arg(vp, SilcClientEntry); + client_entry = va_arg(vp, SilcClientEntry); nickname = va_arg(vp, char *); username = va_arg(vp, char *); realname = va_arg(vp, char *); @@ -339,9 +362,14 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, mode = va_arg(vp, uint32); idle = va_arg(vp, uint32); + silc_parse_userfqdn(nickname, &nick, NULL); printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, - SILCTXT_WHOIS_USERINFO, nickname, username, - realname); + SILCTXT_WHOIS_USERINFO, nickname, + client_entry->username, client_entry->hostname, + nick, client_entry->nickname); + printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, + SILCTXT_WHOIS_REALNAME, realname); + silc_free(nick); if (channels) { SilcDList list = silc_channel_payload_parse_list(channels); @@ -431,18 +459,24 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, { SilcChannelEntry channel; char *invite_list; + SilcArgumentPayload args; + int argc = 0; if (!success) return; channel = va_arg(vp, SilcChannelEntry); invite_list = va_arg(vp, char *); - + + args = silc_command_get_args(cmd_payload); + if (args) + argc = silc_argument_get_arg_num(args); + if (invite_list) printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_INVITE_LIST, channel->channel_name, invite_list); - else + else if (argc == 3) printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_CHANNEL_NO_INVITE_LIST, channel->channel_name); @@ -457,6 +491,9 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, SilcBuffer client_id_list; uint32 list_count; + if (!success) + return; + channel = va_arg(vp, char *); channel_entry = va_arg(vp, SilcChannelEntry); modei = va_arg(vp, uint32); @@ -469,22 +506,19 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, list_count = va_arg(vp, uint32); client_id_list = va_arg(vp, SilcBuffer); - if (!success) - return; - chanrec = silc_channel_find(server, channel); - if (chanrec != NULL && !success) - channel_destroy(CHANNEL(chanrec)); - else if (chanrec == NULL && success) + if (!chanrec) chanrec = silc_channel_create(server, channel, TRUE); - + if (topic) { g_free_not_null(chanrec->topic); chanrec->topic = *topic == '\0' ? NULL : g_strdup(topic); signal_emit("channel topic changed", 1, chanrec); } - mode = silc_client_chmode(modei, channel_entry); + mode = silc_client_chmode(modei, + channel_entry->channel_key->cipher->name, + channel_entry->hmac->hmac->name); g_free_not_null(chanrec->mode); chanrec->mode = g_strdup(mode == NULL ? "" : mode); signal_emit("channel mode changed", 1, chanrec); @@ -644,18 +678,29 @@ silc_command_reply(SilcClient client, SilcClientConnection conn, unsigned char *pk; uint32 pk_len; + if (!success) + return; + id_type = va_arg(vp, uint32); entry = va_arg(vp, void *); public_key = va_arg(vp, SilcPublicKey); - - pk = silc_pkcs_public_key_encode(public_key, &pk_len); - - if (id_type == SILC_ID_CLIENT) - silc_verify_public_key_internal(client, conn, SILC_SOCKET_TYPE_CLIENT, + + if (public_key) { + pk = silc_pkcs_public_key_encode(public_key, &pk_len); + + silc_verify_public_key_internal(client, conn, + (id_type == SILC_ID_CLIENT ? + SILC_SOCKET_TYPE_CLIENT : + SILC_SOCKET_TYPE_SERVER), pk, pk_len, SILC_SKE_PK_TYPE_SILC, NULL, NULL); - silc_free(pk); + silc_free(pk); + } else { + printformat_module("fe-common/silc", server, NULL, + MSGLEVEL_CRAP, SILCTXT_GETKEY_NOKEY); + } } + break; case SILC_COMMAND_TOPIC: { @@ -922,7 +967,7 @@ void ask_passphrase_completion(const char *passphrase, void *context) } void silc_ask_passphrase(SilcClient client, SilcClientConnection conn, - SilcAskPassphrase completion, void *context) + SilcAskPassphrase completion, void *context) { AskPassphrase p = silc_calloc(1, sizeof(*p)); p->completion = completion; @@ -932,34 +977,69 @@ void silc_ask_passphrase(SilcClient client, SilcClientConnection conn, "Passphrase: ", ENTRY_REDIRECT_FLAG_HIDDEN, p); } +typedef struct { + SilcGetAuthMeth completion; + void *context; +} *InternalGetAuthMethod; + +/* 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) +{ + InternalGetAuthMethod internal = (InternalGetAuthMethod)context; + + switch (auth_meth) { + case SILC_AUTH_NONE: + /* No authentication required. */ + (*internal->completion)(TRUE, auth_meth, NULL, 0, internal->context); + break; + case SILC_AUTH_PASSWORD: + /* Do not ask the passphrase from user, the library will ask it if + we do not provide it here. */ + (*internal->completion)(TRUE, auth_meth, NULL, 0, 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); +} + /* 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. */ -int silc_get_auth_method(SilcClient client, SilcClientConnection conn, - char *hostname, uint16 port, - SilcProtocolAuthMeth *auth_meth, - unsigned char **auth_data, - uint32 *auth_data_len) +void silc_get_auth_method(SilcClient client, SilcClientConnection conn, + char *hostname, uint16 port, + SilcGetAuthMeth completion, void *context) { - bool ret = TRUE; - SILC_SERVER_REC *server = conn ? conn->context : NULL; + InternalGetAuthMethod internal; /* XXX must resolve from configuration whether this connection has any specific authentication data */ - *auth_meth = SILC_AUTH_NONE; - *auth_data = NULL; - *auth_data_len = 0; - - if (ret == FALSE) { - printformat_module("fe-common/silc", server, NULL, - MSGLEVEL_MODES, SILCTXT_AUTH_METH_UNRESOLVED); - } + /* 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; - return ret; + silc_client_request_authentication_method(client, conn, + silc_get_auth_method_callback, + internal); } /* Notifies application that failure packet was received. This is called @@ -999,6 +1079,9 @@ void silc_failure(SilcClient client, SilcClientConnection conn, 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 (protocol->protocol->type == SILC_PROTOCOL_CLIENT_CONNECTION_AUTH) { @@ -1023,7 +1106,7 @@ int silc_key_agreement(SilcClient client, SilcClientConnection conn, SilcKeyAgreementCallback *completion, void **context) { - char portstr[6]; + char portstr[12]; /* We will just display the info on the screen and return FALSE and user will have to start the key agreement with a command. */