s Set/unset channel as secret channel
k Enable/disable channel private key usage (*)
i Set/unset channel as invite only channel
- t Set/unset that only channel operator or
+ t Set/unset that only channel operator or
founder may set channel topic
m Set/unset user silencing. Normal users
are not able to talk on channel. (*)
server. If these are omitted then the default
SILC keypair is used. Normally you do not need
to provide these arguments.
+ C [{[+|-]<pubkeyfile> }] (*)
+ Set/unset channel public key mode, and add/remove
+ channel publics key from the channel public key
+ list. When this mode is set only those users
+ whose public keys has been added to the list are
+ able to join the channel. Channel founder may set
+ this mode and operate on the channel public key
+ list.
+
+ To add public key to the list give command:
+ CMODE +C +/path/to/the/public_key_file.pub
+
+ To remove one public key from the list give
+ command:
+ CMODE +C -/path/to/the/public_key_file.pub
+
+ To add or remove more than one public keys add as
+ many public key file paths as necessary.
+
+ When this mode is unset (-C), all public keys are
+ removed from the list. If +C is given without
+ arguments the current channel public key list is
+ displayed.
Multiple modes can be set/unset at once if the modes does not
require any arguments. If mode requires an argument then only
@SYNTAX:join@
-Joins a specified channel. Channel names usually begin with #-sign,
-but note that the #-sign is not mandatory in channel names.
+Joins a specified channel. Note that, in SILC the #-sign is NOT
+mandatory part of the channel names, and names "#foo" and "foo" will
+join to two different channels.
If -cipher is provided and the channel does not exist the cipher to
secure the channel messages on the channel will be set to <cipher>. If
and join the channel. Only the client who set the founder mode on the
channel is able to use -founder option.
+If the channel has the +C (channel public key authentication,
+see /HELP CMODE) mode set then the user joining the channel must
+provide the -auth option to JOIN command. This option will attempt to
+authenticate the user on the channel. If the user's public key has
+not been added to the channel's public key list, user will not be
+able to join. User may optionally provide the <pubkeyfile>,
+<privkeyfile> and <privkey passphrase> to authenticate with some other
+key pair than with the user's default key pair.
+
JOIN is aliased to J by default.
Description
See also: LEAVE, WINDOW CLOSE, CMODE, CUMODE
-
/*
- modules-formats.c
+ module-formats.c
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 Pekka Riikonen
+ Copyright (C) 2001 - 2003 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
{ "no_msgs_sent", "You have not sent a message to anyone yet", 0 },
{ "own_msg_private_signed", "{ownprivmsg_signed msg $0}$1", 2, { 0, 0 } },
{ "own_msg_private_query_signed", "{ownprivmsgnick_signed {ownprivnick $2}}$1", 3, { 0, 0, 0 } },
+ { "channel_pk_list", "Channel {channel $0} Public Key List:", 1, { 0 } },
+ { "channel_pk_list_entry", "$0 - {channel $1}: $2 $3: Fingerprint (SHA1) {ban $4} (Babbleprint (SHA1) {ban $5})", 6, { 1, 0, 0, 0, 0, 0 } },
+ { "channel_pk_no_list", "No Channel Public Key List for {channel $0}", 1, { 0 } },
/* WHOIS, WHOWAS and USERS (alias WHO) messages */
{ NULL, "Who Queries", 0 },
/*
- modules-formats.h
+ module-formats.h
- Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 Pekka Riikonen
+ Copyright (C) 2001 - 2003 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
+ the Free Software Foundation; version 2 of the License.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
enum {
SILCTXT_MODULE_NAME,
-
+
SILCTXT_FILL_1,
-
+
SILCTXT_CHANNEL_FOUNDER_YOU,
SILCTXT_CHANNEL_FOUNDER,
SILCTXT_CHANNEL_TOPIC,
SILCTXT_NO_MSGS_SENT,
SILCTXT_OWN_MSG_PRIVATE_SIGNED,
SILCTXT_OWN_MSG_PRIVATE_QUERY_SIGNED,
+ SILCTXT_CHANNEL_PK_LIST,
+ SILCTXT_CHANNEL_PK_LIST_ENTRY,
+ SILCTXT_CHANNEL_PK_NO_LIST,
SILCTXT_FILL_2,
g_slist_free(windows);
}
+static void silc_parse_channel_public_keys(SILC_SERVER_REC *server,
+ SilcChannelEntry channel_entry,
+ SilcBuffer channel_pubkeys)
+{
+ SilcUInt16 argc;
+ SilcArgumentPayload chpks;
+ unsigned char *pk;
+ SilcUInt32 pk_len, type;
+ int c = 1;
+ char *fingerprint, *babbleprint;
+ SilcPublicKey pubkey;
+ SilcPublicKeyIdentifier ident;
+
+ 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;
+
+ 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);
+
+ 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 : "",
+ 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_argument_payload_free(chpks);
+}
+
void silc_say(SilcClient client, SilcClientConnection conn,
SilcClientMessageType type, char *msg, ...)
{
char buf[512];
char *name, *tmp;
GSList *list1, *list_tmp;
+ SilcBuffer buffer;
SILC_LOG_DEBUG(("Start"));
idtype = va_arg(va, int);
entry = va_arg(va, void *);
mode = va_arg(va, SilcUInt32);
- (void)va_arg(va, char *);
- (void)va_arg(va, char *);
+ (void)va_arg(va, char *); /* cipher */
+ (void)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 */
channel = va_arg(va, SilcChannelEntry);
tmp = silc_client_chmode(mode,
channel2->channel_name);
}
+ /* Print the channel public key list */
+ if (buffer)
+ silc_parse_channel_public_keys(server, channel, buffer);
+
silc_free(tmp);
break;
after application has called the command. Just to tell application
that the command really was processed. */
+static bool cmode_list_chpks = FALSE;
+
void silc_command(SilcClient client, SilcClientConnection conn,
SilcClientCommandContext cmd_context, bool success,
SilcCommand command, SilcStatus status)
server->no_reconnect = TRUE;
break;
+ case SILC_COMMAND_CMODE:
+ if (cmd_context->argc == 3 &&
+ !strcmp(cmd_context->argv[2], "+C"))
+ cmode_list_chpks = TRUE;
+ else
+ cmode_list_chpks = FALSE;
+ break;
+
default:
break;
}
}
/* Parse an invite or ban list */
-void silc_parse_inviteban_list(SilcClient client,
- SilcClientConnection conn,
- SILC_SERVER_REC *server,
- SilcChannelEntry channel,
- const char *list_type,
- SilcArgumentPayload list)
+void silc_parse_inviteban_list(SilcClient client,
+ SilcClientConnection conn,
+ SILC_SERVER_REC *server,
+ SilcChannelEntry channel,
+ const char *list_type,
+ SilcArgumentPayload list)
{
unsigned char *tmp;
SilcUInt32 type, len;
SilcChannelEntry channel;
SilcBuffer payload;
SilcArgumentPayload invite_list;
- SilcUInt32 argc;
+ SilcUInt16 argc;
if (!success)
return;
SilcChannelEntry channel;
SilcBuffer payload;
SilcArgumentPayload ban_list;
- SilcUInt32 argc;
+ SilcUInt16 argc;
if (!success)
return;
}
break;
+ case SILC_COMMAND_CMODE:
+ {
+ SilcChannelEntry channel_entry;
+ SilcBuffer channel_pubkeys;
+
+ channel_entry = va_arg(vp, SilcChannelEntry);
+ (void)va_arg(vp, SilcUInt32);
+ (void)va_arg(vp, SilcPublicKey);
+ channel_pubkeys = va_arg(vp, SilcBuffer);
+
+ if (!success || !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);
+ else
+ printformat_module("fe-common/silc", server, NULL,
+ MSGLEVEL_CRAP, SILCTXT_CHANNEL_PK_NO_LIST,
+ channel_entry->channel_name);
+ }
+ break;
+
}
va_end(vp);
/*
silc-server.c : irssi
- Copyright (C) 2000 - 2001 Timo Sirainen
- Pekka Riikonen <priikone@poseidon.pspt.fi>
+ Copyright (C) 2000 - 2003 Timo Sirainen
+ Pekka Riikonen <priikone@silcnet.org>
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
SilcMessageFlags flags)
{
SILC_CHANNEL_REC *rec;
-
+
rec = silc_channel_find(server, channel);
if (rec == NULL || rec->entry == NULL) {
cmd_return_error_value(CMDERR_NOT_JOINED, FALSE);
}
- silc_client_send_channel_message(silc_client, server->conn, rec->entry,
+ silc_client_send_channel_message(silc_client, server->conn, rec->entry,
NULL, flags, msg, strlen(msg), TRUE);
return TRUE;
}
char *nickname = NULL;
if (!clients_count) {
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
"%s: There is no such client", rec->nick);
} else {
if (clients_count > 1) {
/* Find the correct one. The rec->nick might be a formatted nick
so this will find the correct one. */
- clients = silc_client_get_clients_local(silc_client, server->conn,
- nickname, rec->nick,
+ clients = silc_client_get_clients_local(silc_client, server->conn,
+ nickname, rec->nick,
&clients_count);
if (!clients) {
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
"%s: There is no such client", rec->nick);
silc_free(nickname);
goto out;
/* Still check for exact math for nickname, this compares the
real (formatted) nickname and the nick (maybe formatted) that
- use gave. This is to assure that `nick' does not match
+ use gave. This is to assure that `nick' does not match
`nick@host'. */
if (strcasecmp(rec->nick, clients[0]->nickname)) {
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
"%s: There is no such client", rec->nick);
goto out;
}
/* Send the private message */
- silc_client_send_private_message(client, conn, target,
+ silc_client_send_private_message(client, conn, target,
rec->flags,
rec->msg, rec->len,
TRUE);
}
-
+
out:
g_free(rec->nick);
g_free(rec->msg);
}
/* Find client entry */
- clients = silc_client_get_clients_local(silc_client, server->conn,
+ clients = silc_client_get_clients_local(silc_client, server->conn,
nickname, nick, &clients_count);
if (!clients) {
rec = g_new0(PRIVMSG_REC, 1);
/* Send the private message directly */
silc_free(nickname);
- silc_client_send_private_message(silc_client, server->conn,
+ silc_client_send_private_message(silc_client, server->conn,
clients[0], flags,
msg, msg_len, TRUE);
return TRUE;
QUERY_REC *query;
char *mime_data;
int mime_data_len;
-
- if (!(IS_SILC_SERVER(server)) || (data == NULL) || (to == NULL) ||
+
+ if (!(IS_SILC_SERVER(server)) || (data == NULL) || (to == NULL) ||
(enc == NULL) || (type == NULL))
return;
-
+
#define SILC_MIME_HEADER "MIME-Version: 1.0\r\nContent-Type: %s\r\nContent-Transfer-Encoding: %s\r\n\r\n"
mime_data_len = data_len + strlen(SILC_MIME_HEADER) - 4
if (IS_SILC_CHANNEL(to)) {
channel = SILC_CHANNEL(to);
- silc_client_send_channel_message(silc_client, server->conn, channel->entry,
+ silc_client_send_channel_message(silc_client, server->conn, channel->entry,
NULL, SILC_MESSAGE_FLAG_DATA,
mime_data, mime_data_len, TRUE);
} else if (IS_SILC_QUERY(to)) {
query = SILC_QUERY(to);
silc_send_msg(server, query->name, mime_data, mime_data_len,
SILC_MESSAGE_FLAG_DATA);
-
+
}
silc_free(mime_data);
silc_free(message);
}
-void silc_send_heartbeat(SilcSocketConnection sock,
+void silc_send_heartbeat(SilcSocketConnection sock,
void *hb_context)
{
SILC_SERVER_REC *server = SILC_SERVER(hb_context);
SILC_SERVER_REC *server;
g_return_val_if_fail(IS_SILC_SERVER_CONNECT(conn), NULL);
- if (conn->address == NULL || *conn->address == '\0')
+ if (conn->address == NULL || *conn->address == '\0')
return NULL;
if (conn->nick == NULL || *conn->nick == '\0') {
silc_say_error("Cannot connect: nickname is not set");
server->connrec = (SILC_SERVER_CONNECT_REC *)conn;
server_connect_ref(conn);
- if (server->connrec->port <= 0)
+ if (server->connrec->port <= 0)
server->connrec->port = 706;
server_connect_init((SERVER_REC *)server);
}
}
-/* Return a string of all channels in server in server->channels_join()
+/* Return a string of all channels in server in server->channels_join()
format */
char *silc_server_get_channels(SILC_SERVER_REC *server)
chans = g_string_new(NULL);
for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
CHANNEL_REC *channel = tmp->data;
-
+
g_string_sprintfa(chans, "%s,", channel->name);
}
ret = chans->str;
g_string_free(chans, FALSE);
-
+
return ret;
}
/* SYNTAX: FILE ACCEPT [<nickname>] */
/* SYNTAX: FILE CLOSE [<nickname>] */
/* SYNTAX: FILE */
-/* SYNTAX: JOIN <channel> [<passphrase>] [-cipher <cipher>] [-hmac <hmac>] [-founder] */
+/* SYNTAX: JOIN <channel> [<passphrase>] [-cipher <cipher>] [-hmac <hmac>] [-founder] [-auth [<pubkeyfile> <privkeyfile> [<privkey passphrase>]]]*/
/* SYNTAX: DETACH */
/* SYNTAX: WATCH [<-add | -del> <nickname>] */
/* SYNTAX: STATS */
char *target, *origtarget, *msg;
void *free_arg;
int free_ret, target_type;
-
+
g_return_if_fail(data != NULL);
if (server == NULL || !server->connected)
cmd_param_error(CMDERR_NOT_CONNECTED);
if (status == SILC_CLIENT_FILE_MONITOR_ERROR) {
if (error == SILC_CLIENT_FILE_NO_SUCH_FILE)
printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
- SILCTXT_FILE_ERROR_NO_SUCH_FILE,
- client_entry->nickname,
+ SILCTXT_FILE_ERROR_NO_SUCH_FILE,
+ client_entry->nickname,
filepath ? filepath : "[N/A]");
else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED)
printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
- SILCTXT_FILE_ERROR_PERMISSION_DENIED,
+ SILCTXT_FILE_ERROR_PERMISSION_DENIED,
client_entry->nickname);
else
printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
FileGetClients internal = (FileGetClients)context;
if (!clients) {
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Unknown nick: %s",
internal->nick);
silc_free(internal->data);
silc_free(internal->nick);
if (!strcasecmp(argv[1], "close"))
type = 3;
}
-
+
if (type == 0)
cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS);
MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[3]);
goto out;
}
-
+
/* Find client entry */
entrys = silc_client_get_clients_local(silc_client, conn, nickname,
argv[3], &entry_count);
do_not_bind = TRUE;
}
- ret =
- silc_client_file_send(silc_client, conn, silc_client_file_monitor,
+ ret =
+ silc_client_file_send(silc_client, conn, silc_client_file_monitor,
server, local_ip, local_port, do_not_bind,
client_entry, argv[2], &session_id);
if (ret == SILC_CLIENT_FILE_OK) {
client_entry->nickname);
if (ret == SILC_CLIENT_FILE_NO_SUCH_FILE)
printformat_module("fe-common/silc", NULL, NULL, MSGLEVEL_CRAP,
- SILCTXT_FILE_ERROR_NO_SUCH_FILE,
+ SILCTXT_FILE_ERROR_NO_SUCH_FILE,
client_entry->nickname, argv[2]);
}
MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
goto out;
}
-
+
/* Find client entry */
entrys = silc_client_get_clients_local(silc_client, conn, nickname,
argv[2], &entry_count);
goto out;
}
- ret = silc_client_file_receive(silc_client, conn,
+ ret = silc_client_file_receive(silc_client, conn,
silc_client_file_monitor, server, NULL,
server->current_session->session_id);
if (ret != SILC_CLIENT_FILE_OK) {
silc_dlist_start(server->ftp_sessions);
while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) {
if (ftp->client_entry == client_entry && !ftp->filepath) {
- ret = silc_client_file_receive(silc_client, conn,
+ ret = silc_client_file_receive(silc_client, conn,
silc_client_file_monitor, server,
NULL, ftp->session_id);
if (ret != SILC_CLIENT_FILE_OK) {
MSGLEVEL_CRAP, SILCTXT_BAD_NICK, argv[2]);
goto out;
}
-
+
/* Find client entry */
entrys = silc_client_get_clients_local(silc_client, conn, nickname,
argv[2], &entry_count);
MSGLEVEL_CRAP, SILCTXT_FILE_NA);
goto out;
}
-
- silc_client_file_close(silc_client, conn,
+
+ silc_client_file_close(silc_client, conn,
server->current_session->session_id);
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_FILE_CLOSED,
while ((ftp = silc_dlist_get(server->ftp_sessions)) != SILC_LIST_END) {
printformat_module("fe-common/silc", server, NULL,
MSGLEVEL_CRAP, SILCTXT_FILE_SHOW_LINE,
- ftp->client_entry->nickname,
+ ftp->client_entry->nickname,
ftp->send ? "send" : "receive",
(SilcUInt32)(ftp->offset + 1023) / 1024,
(SilcUInt32)(ftp->filesize + 1023) / 1024,
</tt>
<br /> <br />
-The first argument 'client' is the SILC Client Library context, the 'conn'
+The first argument 'client' is the SILC Client Library context, the 'conn'
is the context for the connection to the remote server, the 'cmd_payload'
is the raw SilcCommandPayload and application usually ignores it, the
'success' boolean value indicates whether the earlier command was a success
<br /> <br />
Rest of the arguments are 'command' specific and implementation should
handle them by the SilcCommand for example in a <tt>switch</tt> statement.
-The commands are defined in lib/silccore/silccomand.h header file. A short
+The commands are defined in lib/silccore/silccomand.h header file. A short
example:
<br /> <br />
<br /> <br />
The following table describes all commands and arguments that the client
-library sends in the 'command_reply' client operation to the application.
-By default all arguments that the library sends to application are valid
-pointers. However, it is possible that some pointers may be NULL. If
-this is the case it is separately mentioned that the argument may be NULL.
+library sends in the 'command_reply' client operation to the application.
+By default all arguments that the library sends to application are valid
+pointers. However, it is possible that some pointers may be NULL. If
+this is the case it is separately mentioned that the argument may be NULL.
In this case application must ignore that argument. The 'command_reply'
arguments per SilcCommand is as follows:
<tr>
<td><small>SILC_COMMAND_CMODE</td>
<td><small>
-Returns channel's mode after changing it.
+Returns channel's mode after changing it. Optionally may also return
+founder's public key when it was set. It may also return the channel
+public key list when the list was altered. The 'founder_key' and
+'channel_pubkeys' arguments may be NULL. The 'channel_pubkeys' is an
+Argument List Payload where each argument includes one Public Key
+Payload.
</td>
-<td width="50%"><small>SilcChannelEntry channel, SilcUInt32 mode
+<td width="50%"><small>SilcChannelEntry channel, SilcUInt32 mode,
+SilcPublicKey founder_key, SilcBuffer channel_pubkeys
</td>
</tr>
<td><small>SILC_COMMAND_GETKEY</td>
<td><small>
Returns public key of client or server. The 'public_key' may be NULL.
-The 'entry_type' is used to check what type of pointer the entry' is. For
+The 'entry_type' is used to check what type of pointer the entry' is. For
SILC_ID_CLIENT SilcClientEntry and for SILC_ID_SERVER SilcServerEntry.
</td>
<td width="50%"><small>SilcIdType entry_type, void *entry,
</table>
<br /> <br />
-SILC protocol defines some additional commands but command replies to
+SILC protocol defines some additional commands but command replies to
those commands are not delivered to the application. Only the command
replies listed above are delivered to application.
</tt>
<br /> <br />
-The first argument 'client' is the SILC Client Library context, the `conn'
-is the context for the connection to the remote server, and the `type' is
-the notify type enumeration sent by the server. Rest of the arguments are
-`type' specific and implementation should handle them by the
-SilcNotifyType for example in a <tt>switch</tt> statement. The notify
-types are defined in lib/silccore/silcnotify.h header file. A short
+The first argument 'client' is the SILC Client Library context, the `conn'
+is the context for the connection to the remote server, and the `type' is
+the notify type enumeration sent by the server. Rest of the arguments are
+`type' specific and implementation should handle them by the
+SilcNotifyType for example in a <tt>switch</tt> statement. The notify
+types are defined in lib/silccore/silcnotify.h header file. A short
example:
<br /> <br />
<b>Arguments</b>
<br /> <br />
-The following table describes all notify types and arguments that the
-client library sends in the 'notify' client operation to the application.
-By default all arguments that the library sends to application are valid
-pointers. However, it is possible that some pointers may be NULL. If
-this is the case it is separately mentioned that the argument may be NULL.
-In this case application must ignore that argument. The SilcNotifyType
+The following table describes all notify types and arguments that the
+client library sends in the 'notify' client operation to the application.
+By default all arguments that the library sends to application are valid
+pointers. However, it is possible that some pointers may be NULL. If
+this is the case it is separately mentioned that the argument may be NULL.
+In this case application must ignore that argument. The SilcNotifyType
arguments per notify type is as follows:
<br /> <br />
<tr>
<td><small>SILC_NOTIFY_TYPE_INVITE</td>
<td><small>
-Sent to the client if the user is invited on a channel. The 'channel_name'
+Sent to the client if the user is invited on a channel. The 'channel_name'
argument may be NULL.
</td>
<td width="50%"><small>SilcClientChannel channel, char *channel_name,
<tr>
<td><small>SILC_NOTIFY_TYPE_SIGNOFF</td>
<td><small>
-Sent when someone signoff the SILC network. The 'signoff_message' may be
-NULL. The 'leaving_client' SilcClientEntry may be incomplete and contain
-NULL pointers, application must check it's pointers before attempting to
+Sent when someone signoff the SILC network. The 'signoff_message' may be
+NULL. The 'leaving_client' SilcClientEntry may be incomplete and contain
+NULL pointers, application must check it's pointers before attempting to
display for example nickname information.
</td>
<td width="50%"><small>SilcClientEntry signoff_client, char *signoff_message
<td><small>SILC_NOTIFY_TYPE_TOPIC_SET</td>
<td><small>
Sent when the topic of a channel is set/changed. The 'setter_id_type'
-is used to check what type of pointer the 'setter_entry' is. For
-SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
+is used to check what type of pointer the 'setter_entry' is. For
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
SILC_ID_CHANNEL SilcChannelEntry.
</td>
<td width="50%"><small>SilcIdType setter_id_type, void *setter_entry,
<tr>
<td><small>SILC_NOTIFY_TYPE_NICK_CHANGE</td>
<td><small>
-Sent when someone changes their nickname. The 'old_client_entry' includes
-the old nickname and the 'new_client_entry' includes the new nickname.
-Application must understand that the 'old_client_entry' pointer becomes
+Sent when someone changes their nickname. The 'old_client_entry' includes
+the old nickname and the 'new_client_entry' includes the new nickname.
+Application must understand that the 'old_client_entry' pointer becomes
invalid after returning from the function.
</td>
<td width="50%"><small>SilcClientEntry old_client_entry,
<td><small>SILC_NOTIFY_TYPE_CMODE_CHANGE</td>
<td><small>
Sent when channel's mode has changed. The 'changer_id_type'
-is used to check what type of pointer the 'changer_entry' is. For
-SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
-SILC_ID_CHANNEL SilcChannelEntry. The 'mode' is the mode mask after the
-change. The 'hmac_name' argument may be NULL.
+is used to check what type of pointer the 'changer_entry' is. For
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
+SILC_ID_CHANNEL SilcChannelEntry. The 'mode' is the mode mask after the
+change. The `cipher_name' is the cipher set for the channel.
+The `hmac_name' is the HMAC set for the channel. The `passphrase'
+is the passphrase that was set for the channel. The `founder_key' is the
+founder's public key when it was set for the channel. The `channel_pubkeys'
+is an Argument List Payload where each argument is Public Key Payload
+containing one channel public key. The arguments 'cipher_name', 'hmac_name',
+'passphrase', 'founder_key' and 'channel_pubkeys' may be NULL.
</td>
<td width="50%"><small>SilcIdType changer_id_type, void *changer_entry,
-SilcUInt32 mode, NULL, char *hmac_name, SilcChannelEntry channel
+SilcUInt32 mode, char *cipher_name, char *hmac_name, char *passphrase,
+SilcPublicKey founder_key, SilcBuffer channel_pubkeys, SilcChannelEntry channel
</td>
</tr>
<td><small>SILC_NOTIFY_TYPE_CUMODE_CHANGE</td>
<td><small>
Sent when a users mode on a channel has changed. The 'changer_id_type'
-is used to check what type of pointer the 'changer_entry' is. For
-SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
+is used to check what type of pointer the 'changer_entry' is. For
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for
SILC_ID_CHANNEL SilcChannelEntry. The 'mode' is the mode mask after the
change. The 'target_client' is the client whose mode was changed.
</td>
<tr>
<td><small>SILC_NOTIFY_TYPE_CHANNEL_CHANGE</td>
<td><small>
-Sent when a channel's Channel ID changes. It is possible that channel's
-ID changes and this notify is sent by the server when this happens.
-Usually application does not need to handle this notify type and may
+Sent when a channel's Channel ID changes. It is possible that channel's
+ID changes and this notify is sent by the server when this happens.
+Usually application does not need to handle this notify type and may
safely ignore it when received.
</td>
<td width="50%"><small>SilcChannelEntry channel
<tr>
<td><small>SILC_NOTIFY_TYPE_SERVER_SIGNOFF</td>
<td><small>
-Sent when a server quits the network. The 'clients' is an array
-SilcClientEntry pointers of size of 'clients_count'. Each client in the
+Sent when a server quits the network. The 'clients' is an array
+SilcClientEntry pointers of size of 'clients_count'. Each client in the
entry is one client signing off from the SILC network.
</td>
<td width="50%"><small>NULL, SilcClientEntry *clients, SilcUInt32 clients_count
<tr>
<td><small>SILC_NOTIFY_TYPE_KICKED</td>
<td><small>
-Sent when a client (possibly our client) is kicked from a channel. The
-'kick_message' may be NULL. If our client was kicked then 'kicked' is our
+Sent when a client (possibly our client) is kicked from a channel. The
+'kick_message' may be NULL. If our client was kicked then 'kicked' is our
local SilcClientEntry pointer.
</td>
<td width="50%"><small>SilcClientEntry kicked, char *kick_message,
<tr>
<td><small>SILC_NOTIFY_TYPE_KILLED</td>
<td><small>
-Sent when a client (possibly our client) is killed from the network. The
-'kill_message' may be NULL. If our client was killed then 'killed' is our
-local SilcClientEntry pointer. The 'killer_type' is used to check what
-type of pointer the 'killer' is. For SILC_ID_CLIENT SilcClientEntry, for
+Sent when a client (possibly our client) is killed from the network. The
+'kill_message' may be NULL. If our client was killed then 'killed' is our
+local SilcClientEntry pointer. The 'killer_type' is used to check what
+type of pointer the 'killer' is. For SILC_ID_CLIENT SilcClientEntry, for
SILC_ID_SERVER SilcServerEntry and for SILC_ID_CHANNEL SilcChannelEntry.
</td>
<td width="50%"><small>SilcClientEntry killed, char *kill_message,
<td><small>SILC_NOTIFY_TYPE_ERROR</td>
<td><small>
Sent when an error occurs while handling some operation (except command)
-from the client. Application usually cannot handle this notify type and
+from the client. Application usually cannot handle this notify type and
may safely ignore it.
</td>
<td width="50%"><small>SilcStatus error
<tr>
<td><small>SILC_NOTIFY_TYPE_WATCH</td>
<td><small>
-Sent to notify some status change of a client we are wathing. The
-SILC_COMMAND_WATCH is used to manage clients we are wathing and this
-notify type is used to deliver information about that client. If the
-client just changed nickname the 'new_nickname' includes the new nickname.
-Otherwise this pointer is NULL. The 'user_mode' is the client's mode in
-the SILC network. The 'notification' contains the notify type that
-happened for the 'watched_client' (for example
+Sent to notify some status change of a client we are wathing. The
+SILC_COMMAND_WATCH is used to manage clients we are wathing and this
+notify type is used to deliver information about that client. If the
+client just changed nickname the 'new_nickname' includes the new nickname.
+Otherwise this pointer is NULL. The 'user_mode' is the client's mode in
+the SILC network. The 'notification' contains the notify type that
+happened for the 'watched_client' (for example
SILC_NOTIFY_TYPE_NICK_CHANGE if the client changed their nickname).
</td>
<td width="50%"><small>SilcClientEntry watched_client, char *new_nickname,
</table>
<br /> <br />
-SILC protocol defines some additional notify types but those notify types
-are not delivered to the application. Some of those notify types are only
-delivered between servers and routers and clients never receive them.
+SILC protocol defines some additional notify types but those notify types
+are not delivered to the application. Some of those notify types are only
+delivered between servers and routers and clients never receive them.
Only the notify types listed above are delivered to application.
/*
- client_notify.c
+ client_notify.c
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2003 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
} *SilcClientNotifyResolve;
SILC_TASK_CALLBACK(silc_client_notify_check_client)
-{
+{
SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
SilcClient client = res->context;
SilcClientConnection conn = res->sock->user_data;
static void silc_client_notify_by_server_pending(void *context, void *context2)
{
SilcClientNotifyResolve res = (SilcClientNotifyResolve)context;
- SilcClientCommandReplyContext reply =
+ SilcClientCommandReplyContext reply =
(SilcClientCommandReplyContext)context2;
SILC_LOG_DEBUG(("Start"));
}
}
-/* Attaches to the channel's resolving cmd ident and calls the
+/* Attaches to the channel's resolving cmd ident and calls the
notify handling with `packet' after it's received. */
static void silc_client_channel_wait(SilcClient client,
silc_client_command_register(client, SILC_COMMAND_IDENTIFY, NULL, NULL,
silc_client_command_reply_identify_i, 0,
++conn->cmd_ident);
- silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
+ silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
conn->cmd_ident, 1, 5, idp->data, idp->len);
silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY, conn->cmd_ident,
silc_client_notify_by_server_pending, res);
switch(type) {
case SILC_NOTIFY_TYPE_NONE:
/* Notify application */
- client->internal->ops->notify(client, conn, type,
+ client->internal->ops->notify(client, conn, type,
silc_argument_get_arg_type(args, 1, NULL));
break;
case SILC_NOTIFY_TYPE_INVITE:
- /*
+ /*
* Someone invited me to a channel. Find Client and Channel entries
* for the application.
*/
-
+
SILC_LOG_DEBUG(("Notify: INVITE"));
/* Get Channel ID */
/* Find Client entry and if not found query it */
client_entry = silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry) {
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
}
goto out;
/* Notify application */
- client->internal->ops->notify(client, conn, type, channel, tmp,
+ client->internal->ops->notify(client, conn, type, channel, tmp,
client_entry);
break;
if (!client_entry) {
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
}
res->packet = silc_packet_context_dup(packet);
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
client_entry->resolve_cmd_ident,
silc_client_notify_by_server_pending,
res);
/* Do new resolving */
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
client_entry->resolve_cmd_ident = conn->cmd_ident;
* Someone has left a channel. We will remove it from the channel but
* we'll keep it in the cache in case we'll need it later.
*/
-
+
SILC_LOG_DEBUG(("Notify: LEAVE"));
/* Get Client ID */
goto out;
/* Find Client entry */
- client_entry =
+ client_entry =
silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry)
goto out;
}
/* Some client implementations actually quit network by first doing
- LEAVE and then immediately SIGNOFF. We'll check for this by doing
+ LEAVE and then immediately SIGNOFF. We'll check for this by doing
check for the client after 5 - 34 seconds. If it is not valid after
that we'll remove the client from cache. */
if (!silc_hash_table_count(client_entry->channels)) {
goto out;
/* Find Client entry */
- client_entry =
+ client_entry =
silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry)
goto out;
if (!client_entry) {
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
}
if (!server) {
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_SERVER, server_id);
server = silc_client_add_server(client, conn, NULL, NULL, server_id);
if (!server)
res->packet = silc_packet_context_dup(packet);
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
server->resolve_cmd_ident,
silc_client_notify_by_server_pending, res);
goto out;
}
-
+
/* Save the pointer to the client_entry pointer */
client_entry = (SilcClientEntry)server;
} else {
if (!client_entry) {
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CHANNEL, channel_id);
goto out;
}
/*
* Someone changed their nickname. If we don't have entry for the new
* ID we will query it and return here after it's done. After we've
- * returned we fetch the old entry and free it and notify the
+ * returned we fetch the old entry and free it and notify the
* application.
*/
res->packet = silc_packet_context_dup(packet);
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
client_entry->resolve_cmd_ident,
silc_client_notify_by_server_pending, res);
goto out;
client_entry->id, client_entry, 0, NULL);
/* Notify application */
- client->internal->ops->notify(client, conn, type,
+ client->internal->ops->notify(client, conn, type,
client_entry, client_entry);
break;
}
/* Create new client entry, and save all old information with the
new nickname and client ID */
- client_entry2 = silc_client_add_client(client, conn, NULL, NULL,
+ client_entry2 = silc_client_add_client(client, conn, NULL, NULL,
client_entry->realname,
- silc_id_dup(client_id,
+ silc_id_dup(client_id,
SILC_ID_CLIENT), 0);
if (!client_entry2)
goto out;
/* Remove the old from cache */
silc_idcache_del_by_context(conn->internal->client_cache, client_entry);
-
+
/* Replace old ID entry with new one on all channels. */
silc_client_replace_from_channels(client, conn, client_entry,
client_entry2);
/* Notify application */
- client->internal->ops->notify(client, conn, type,
+ client->internal->ops->notify(client, conn, type,
client_entry, client_entry2);
-
+
/* Free old client entry */
silc_client_del_client_entry(client, conn, client_entry);
break;
case SILC_NOTIFY_TYPE_CMODE_CHANGE:
- /*
- * Someone changed a channel mode
- */
+ {
+ /*
+ * Someone changed a channel mode
+ */
+ char *passphrase, *cipher, *hmac;
+ SilcPublicKey founder_key = NULL;
+ SilcBufferStruct chpks;
- SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
+ SILC_LOG_DEBUG(("Notify: CMODE_CHANGE"));
- /* Get channel entry */
- channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
- SILC_ID_CHANNEL);
- if (!channel_id)
- goto out;
- channel = silc_client_get_channel_by_id(client, conn, channel_id);
- if (!channel)
- goto out;
+ /* Get channel entry */
+ channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
+ SILC_ID_CHANNEL);
+ if (!channel_id)
+ goto out;
+ channel = silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!channel)
+ goto out;
- /* Get ID */
- tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
- if (!tmp)
- goto out;
- id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
- if (!id)
- goto out;
+ /* Get ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+ if (!id)
+ goto out;
- /* Find Client entry */
- if (id_type == SILC_ID_CLIENT) {
/* Find Client entry */
- client_id = id;
- client_entry = silc_client_get_client_by_id(client, conn, client_id);
- if (!client_entry) {
- silc_client_channel_set_wait(client, conn, channel,
- conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
- SILC_ID_CLIENT, client_id);
- goto out;
- }
+ if (id_type == SILC_ID_CLIENT) {
+ /* Find Client entry */
+ client_id = id;
+ client_entry = silc_client_get_client_by_id(client, conn, client_id);
+ if (!client_entry) {
+ silc_client_channel_set_wait(client, conn, channel,
+ conn->cmd_ident + 1);
+ silc_client_notify_by_server_resolve(client, conn, packet,
+ SILC_ID_CLIENT, client_id);
+ goto out;
+ }
- if (!client_entry->nickname) {
- if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
- /* Attach to existing resolving */
+ if (!client_entry->nickname) {
+ if (client_entry->status & SILC_CLIENT_STATUS_RESOLVING) {
+ /* Attach to existing resolving */
+ SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
+ res->packet = silc_packet_context_dup(packet);
+ res->context = client;
+ res->sock = silc_socket_dup(conn->sock);
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ client_entry->resolve_cmd_ident,
+ silc_client_notify_by_server_pending,
+ res);
+ goto out;
+ }
+
+ /* Do new resolving */
+ silc_client_channel_set_wait(client, conn, channel,
+ conn->cmd_ident + 1);
+ silc_client_notify_by_server_resolve(client, conn, packet,
+ SILC_ID_CLIENT, client_id);
+ client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
+ client_entry->resolve_cmd_ident = conn->cmd_ident;
+ goto out;
+ }
+ } else if (id_type == SILC_ID_SERVER) {
+ /* Find Server entry */
+ server_id = id;
+ server = silc_client_get_server_by_id(client, conn, server_id);
+ if (!server) {
+ silc_client_channel_set_wait(client, conn, channel,
+ conn->cmd_ident + 1);
+ silc_client_notify_by_server_resolve(client, conn, packet,
+ SILC_ID_SERVER, server_id);
+ server = silc_client_add_server(client, conn, NULL, NULL, server_id);
+ if (!server)
+ goto out;
+
+ server->resolve_cmd_ident = conn->cmd_ident;
+ server_id = NULL;
+ goto out;
+ }
+
+ /* If entry being resoled, wait for it before processing this notify */
+ if (server->resolve_cmd_ident) {
SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
res->packet = silc_packet_context_dup(packet);
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
- client_entry->resolve_cmd_ident,
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ server->resolve_cmd_ident,
silc_client_notify_by_server_pending,
res);
goto out;
}
- /* Do new resolving */
- silc_client_channel_set_wait(client, conn, channel,
- conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
- SILC_ID_CLIENT, client_id);
- client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
- client_entry->resolve_cmd_ident = conn->cmd_ident;
- goto out;
- }
- } else if (id_type == SILC_ID_SERVER) {
- /* Find Server entry */
- server_id = id;
- server = silc_client_get_server_by_id(client, conn, server_id);
- if (!server) {
- silc_client_channel_set_wait(client, conn, channel,
- conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
- SILC_ID_SERVER, server_id);
- server = silc_client_add_server(client, conn, NULL, NULL, server_id);
- if (!server)
+ /* Save the pointer to the client_entry pointer */
+ client_entry = (SilcClientEntry)server;
+ } else {
+ /* Find Channel entry */
+ silc_free(channel_id);
+ channel_id = id;
+ client_entry = (SilcClientEntry)
+ silc_client_get_channel_by_id(client, conn, channel_id);
+ if (!client_entry) {
+ silc_client_channel_set_wait(client, conn, channel,
+ conn->cmd_ident + 1);
+ silc_client_notify_by_server_resolve(client, conn, packet,
+ SILC_ID_CHANNEL, channel_id);
goto out;
-
- server->resolve_cmd_ident = conn->cmd_ident;
- server_id = NULL;
- goto out;
+ }
}
- /* If entry being resoled, wait for it before processing this notify */
- if (server->resolve_cmd_ident) {
- SilcClientNotifyResolve res = silc_calloc(1, sizeof(*res));
- res->packet = silc_packet_context_dup(packet);
- res->context = client;
- res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
- server->resolve_cmd_ident,
- silc_client_notify_by_server_pending, res);
+ /* Get the mode */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)
goto out;
- }
-
- /* Save the pointer to the client_entry pointer */
- client_entry = (SilcClientEntry)server;
- } else {
- /* Find Channel entry */
- silc_free(channel_id);
- channel_id = id;
- client_entry = (SilcClientEntry)
- silc_client_get_channel_by_id(client, conn, channel_id);
- if (!client_entry) {
- silc_client_channel_set_wait(client, conn, channel,
- conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
- SILC_ID_CHANNEL, channel_id);
+
+ SILC_GET32_MSB(mode, tmp);
+
+ /* If information is being resolved for this channel, wait for it */
+ if (channel->resolve_cmd_ident) {
+ silc_client_channel_wait(client, conn, channel, packet);
goto out;
}
- }
- /* Get the mode */
- tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
- if (!tmp)
- goto out;
+ /* Save the new mode */
+ channel->mode = mode;
- SILC_GET32_MSB(mode, tmp);
+ /* Get the cipher */
+ cipher = silc_argument_get_arg_type(args, 3, &tmp_len);
- /* If information is being resolved for this channel, wait for it */
- if (channel->resolve_cmd_ident) {
- silc_client_channel_wait(client, conn, channel, packet);
- goto out;
- }
+ /* Get the hmac */
+ hmac = silc_argument_get_arg_type(args, 4, &tmp_len);
+ if (hmac) {
+ unsigned char hash[32];
+
+ if (channel->hmac)
+ silc_hmac_free(channel->hmac);
+ if (!silc_hmac_alloc(hmac, NULL, &channel->hmac))
+ goto out;
- /* Save the new mode */
- channel->mode = mode;
+ silc_hash_make(silc_hmac_get_hash(channel->hmac),
+ channel->key, channel->key_len / 8,
+ hash);
+ silc_hmac_set_key(channel->hmac, hash,
+ silc_hash_len(silc_hmac_get_hash(channel->hmac)));
+ memset(hash, 0, sizeof(hash));
+ }
- /* Get the hmac */
- tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
- if (tmp) {
- unsigned char hash[32];
+ /* Get the passphrase if it was set */
+ passphrase = silc_argument_get_arg_type(args, 5, &tmp_len);
- if (channel->hmac)
- silc_hmac_free(channel->hmac);
- if (!silc_hmac_alloc(tmp, NULL, &channel->hmac))
- goto out;
+ /* Get the channel founder key if it was set */
+ tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
+ if (tmp) {
+ if (!silc_pkcs_public_key_payload_decode(tmp, tmp_len, &founder_key))
+ founder_key = NULL;
+ }
- silc_hash_make(silc_hmac_get_hash(channel->hmac),
- channel->key, channel->key_len / 8,
- hash);
- silc_hmac_set_key(channel->hmac, hash,
- silc_hash_len(silc_hmac_get_hash(channel->hmac)));
- memset(hash, 0, sizeof(hash));
+ /* Get the channel public key that was added or removed */
+ tmp = silc_argument_get_arg_type(args, 7, &tmp_len);
+ if (tmp)
+ silc_buffer_set(&chpks, tmp, tmp_len);
+
+ /* Notify application. The channel entry is sent last as this notify
+ is for channel but application don't know it from the arguments
+ sent by server. */
+ client->internal->ops->notify(client, conn, type, id_type,
+ client_entry, mode, cipher, hmac,
+ passphrase, founder_key,
+ tmp ? &chpks : NULL, channel);
+
+ if (founder_key)
+ silc_pkcs_public_key_free(founder_key);
}
-
- /* Notify application. The channel entry is sent last as this notify
- is for channel but application don't know it from the arguments
- sent by server. */
- client->internal->ops->notify(client, conn, type, id_type,
- client_entry, mode, NULL, tmp, channel);
break;
case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
if (!client_entry) {
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
}
res->packet = silc_packet_context_dup(packet);
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
client_entry->resolve_cmd_ident,
silc_client_notify_by_server_pending,
res);
/* Do new resolving */
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
client_entry->status |= SILC_CLIENT_STATUS_RESOLVING;
client_entry->resolve_cmd_ident = conn->cmd_ident;
if (!server) {
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_SERVER, server_id);
server = silc_client_add_server(client, conn, NULL, NULL, server_id);
if (!server)
res->packet = silc_packet_context_dup(packet);
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
server->resolve_cmd_ident,
silc_client_notify_by_server_pending, res);
goto out;
if (!client_entry) {
silc_client_channel_set_wait(client, conn, channel,
conn->cmd_ident + 1);
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CHANNEL, channel_id);
goto out;
}
goto out;
/* Find target Client entry */
- client_entry2 =
+ client_entry2 =
silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry2) {
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
}
is for channel but application don't know it from the arguments
sent by server. */
client->internal->ops->notify(client, conn, type,
- id_type, client_entry, mode,
+ id_type, client_entry, mode,
client_entry2, channel);
break;
tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
if (!tmp)
goto out;
-
+
/* Notify application */
client->internal->ops->notify(client, conn, type, tmp);
break;
/* Find kicker's client entry and if not found resolve it */
client_entry2 = silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry2) {
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
} else {
/* Notify application. The channel entry is sent last as this notify
is for channel but application don't know it from the arguments
sent by server. */
- client->internal->ops->notify(client, conn, type, client_entry, tmp,
+ client->internal->ops->notify(client, conn, type, client_entry, tmp,
client_entry2, channel);
/* Remove kicked client from channel */
if (id_type == SILC_ID_CLIENT) {
/* Find Client entry */
client_id = id;
- client_entry2 = silc_client_get_client_by_id(client, conn,
+ client_entry2 = silc_client_get_client_by_id(client, conn,
client_id);
if (!client_entry) {
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
}
server_id = id;
server = silc_client_get_server_by_id(client, conn, server_id);
if (!server) {
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_SERVER, server_id);
server = silc_client_add_server(client, conn, NULL, NULL,
server_id);
res->packet = silc_packet_context_dup(packet);
res->context = client;
res->sock = silc_socket_dup(conn->sock);
- silc_client_command_pending(conn, SILC_COMMAND_NONE,
+ silc_client_command_pending(conn, SILC_COMMAND_NONE,
server->resolve_cmd_ident,
silc_client_notify_by_server_pending,
res);
goto out;
}
-
+
/* Save the pointer to the client_entry pointer */
client_entry2 = (SilcClientEntry)server;
} else {
channel_id = id;
channel = silc_client_get_channel_by_id(client, conn, channel_id);
if (!channel) {
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CHANNEL, channel_id);
goto out;
}
-
+
/* Save the pointer to the client_entry pointer */
client_entry2 = (SilcClientEntry)channel;
silc_free(channel_id);
}
/* Notify application. */
- client->internal->ops->notify(client, conn, type, client_entry,
+ client->internal->ops->notify(client, conn, type, client_entry,
comment, id_type, client_entry2);
if (client_entry != conn->local_entry)
silc_client_del_client(client, conn, client_entry);
}
break;
-
+
case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
{
/*
client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
if (!client_id)
goto out;
-
+
/* Get the client entry */
client_entry = silc_client_get_client_by_id(client, conn, client_id);
if (client_entry) {
- clients = silc_realloc(clients, sizeof(*clients) *
+ clients = silc_realloc(clients, sizeof(*clients) *
(clients_count + 1));
clients[clients_count] = client_entry;
clients_count++;
/* Notify application. We don't keep server entries so the server
entry is returned as NULL. The client's are returned as array
of SilcClientEntry pointers. */
- client->internal->ops->notify(client, conn, type, NULL,
+ client->internal->ops->notify(client, conn, type, NULL,
clients, clients_count);
for (i = 0; i < clients_count; i++) {
/* Find Client entry and if not found query it */
client_entry = silc_client_get_client_by_id(client, conn, client_id);
if (!client_entry) {
- silc_client_notify_by_server_resolve(client, conn, packet,
+ silc_client_notify_by_server_resolve(client, conn, packet,
SILC_ID_CLIENT, client_id);
goto out;
}
/*
- command.c
+ command.c
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2003 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
x->internal->ops->say((x), (c), SILC_CLIENT_MESSAGE_ERROR, \
"You are not connected to a server, use /SERVER to connect");
-/* Command operation that is called at the end of all commands.
+/* Command operation that is called at the end of all commands.
Usage: COMMAND(status); */
#define COMMAND(status) cmd->client->internal->ops->command(cmd->client, \
cmd->conn, cmd, TRUE, cmd->command->cmd, (status))
va_start(ap, argc);
packet = silc_command_payload_encode_vap(command, ident, argc, ap);
- silc_client_packet_send(client, conn->sock, SILC_PACKET_COMMAND,
- NULL, 0, NULL, NULL, packet->data,
+ silc_client_packet_send(client, conn->sock, SILC_PACKET_COMMAND,
+ NULL, 0, NULL, NULL, packet->data,
packet->len, TRUE);
silc_buffer_free(packet);
}
ctx->argv = argv;
ctx->argv_lens = argv_lens;
ctx->argv_types = argv_types;
-
+
/* Call the command */
cmd->command(ctx, NULL);
SilcClientCommandPendingCallbacks
silc_client_command_pending_check(SilcClientConnection conn,
SilcClientCommandReplyContext ctx,
- SilcCommand command,
+ SilcCommand command,
SilcUInt16 ident,
SilcUInt32 *callbacks_count)
{
return ctx;
}
-/* Command WHOIS. This command is used to query information about
+/* Command WHOIS. This command is used to query information about
specific user. */
SILC_CLIENT_CMD_FUNC(whois)
/* Given without arguments fetches client's own information */
if (cmd->argc < 2) {
buffer = silc_id_payload_encode(cmd->conn->local_id, SILC_ID_CLIENT);
- silc_client_command_send(cmd->client, cmd->conn, SILC_COMMAND_WHOIS,
+ silc_client_command_send(cmd->client, cmd->conn, SILC_COMMAND_WHOIS,
++conn->cmd_ident,
1, 4, buffer->data, buffer->len);
silc_buffer_free(buffer);
if (cmd->argc == 2) {
buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOIS,
++conn->cmd_ident, 1,
- 1, cmd->argv[1],
+ 1, cmd->argv[1],
cmd->argv_lens[1]);
} else {
if (!strcasecmp(cmd->argv[2], "-details"))
}
if (cmd->argc < 2 || cmd->argc > 3) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /WHOWAS <nickname>[@<server>] [<count>]");
COMMAND_ERROR((cmd->argc < 2 ? SILC_STATUS_ERR_NOT_ENOUGH_PARAMS :
SILC_STATUS_ERR_TOO_MANY_PARAMS));
if (cmd->argc == 2) {
buffer = silc_command_payload_encode_va(SILC_COMMAND_WHOWAS,
++conn->cmd_ident, 1,
- 1, cmd->argv[1],
+ 1, cmd->argv[1],
cmd->argv_lens[1]);
} else {
int c = atoi(cmd->argv[2]);
silc_client_command_free(cmd);
}
-/* Command IDENTIFY. This command is used to query information about
- specific user, especially ID's.
+/* Command IDENTIFY. This command is used to query information about
+ specific user, especially ID's.
NOTE: This command is used only internally by the client library
and application MUST NOT call this command directly. */
goto out;
if (cmd->argc == 2) {
- buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
++conn->cmd_ident, 1,
1, cmd->argv[1],
cmd->argv_lens[1]);
int c = atoi(cmd->argv[2]);
memset(count, 0, sizeof(count));
SILC_PUT32_MSB(c, count);
- buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_IDENTIFY,
++conn->cmd_ident, 2,
1, cmd->argv[1],
cmd->argv_lens[1],
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /NICK <nickname>");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
/* Show current nickname */
if (cmd->argc < 2) {
if (cmd->conn) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
- "Your nickname is %s on server %s",
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ "Your nickname is %s on server %s",
conn->nickname, conn->remote_host);
} else {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Your nickname is %s", conn->nickname);
}
/* Send the NICK command */
buffer = silc_command_payload_encode(SILC_COMMAND_NICK, 1,
&cmd->argv[1],
- &cmd->argv_lens[1],
+ &cmd->argv_lens[1],
&cmd->argv_types[1],
++cmd->conn->cmd_ident);
silc_client_packet_send(cmd->client, cmd->conn->sock,
}
if (!idp)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_LIST,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_LIST,
++conn->cmd_ident, 0);
else
- buffer = silc_command_payload_encode_va(SILC_COMMAND_LIST,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_LIST,
++conn->cmd_ident, 1,
1, idp->data, idp->len);
/* Send TOPIC command to the server */
idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
if (cmd->argc > 2)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC,
- ++conn->cmd_ident, 2,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC,
+ ++conn->cmd_ident, 2,
1, idp->data, idp->len,
- 2, cmd->argv[2],
+ 2, cmd->argv[2],
strlen(cmd->argv[2]));
else
- buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_TOPIC,
++conn->cmd_ident, 1,
1, idp->data, idp->len);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(idp);
nickname = strdup(cmd->argv[2]);
/* Find client entry */
- client_entry = silc_idlist_get_client(client, conn, nickname,
+ client_entry = silc_idlist_get_client(client, conn, nickname,
cmd->argv[2], TRUE);
if (!client_entry) {
if (cmd->pending) {
COMMAND_ERROR(SILC_STATUS_ERR_NO_SUCH_NICK);
goto out;
}
-
+
/* Client entry not found, it was requested thus mark this to be
pending command. */
- silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
+ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
conn->cmd_ident,
- silc_client_command_invite,
+ silc_client_command_invite,
silc_client_command_dup(cmd));
cmd->pending = 1;
goto out;
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
if (client_entry) {
clidp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
- buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE,
++conn->cmd_ident, 4,
1, chidp->data, chidp->len,
2, clidp->data, clidp->len,
args ? args->len : 0);
silc_buffer_free(clidp);
} else {
- buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_INVITE,
++conn->cmd_ident, 3,
1, chidp->data, chidp->len,
3, args ? action : NULL,
args ? args->len : 0);
}
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(chidp);
}
/* Command QUIT. Closes connection with current server. */
-
+
SILC_CLIENT_CMD_FUNC(quit)
{
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
}
if (cmd->argc > 1)
- buffer = silc_command_payload_encode(SILC_COMMAND_QUIT, cmd->argc - 1,
+ buffer = silc_command_payload_encode(SILC_COMMAND_QUIT, cmd->argc - 1,
&cmd->argv[1], &cmd->argv_lens[1],
&cmd->argv_types[1], 0);
else
buffer = silc_command_payload_encode(SILC_COMMAND_QUIT, 0,
NULL, NULL, NULL, 0);
- silc_client_packet_send(cmd->client, cmd->conn->sock, SILC_PACKET_COMMAND,
- NULL, 0, NULL, NULL,
+ silc_client_packet_send(cmd->client, cmd->conn->sock, SILC_PACKET_COMMAND,
+ NULL, 0, NULL, NULL,
buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
SilcClientConnection conn = cmd->conn;
SilcClientEntry target;
char *nickname = NULL;
-
+
/* Parse the typed nickname. */
if (client->internal->params->nickname_parse)
client->internal->params->nickname_parse(cmd->argv[1], &nickname);
nickname = strdup(cmd->argv[1]);
/* Get the target client */
- target = silc_idlist_get_client(cmd->client, conn, nickname,
+ target = silc_idlist_get_client(cmd->client, conn, nickname,
cmd->argv[1], FALSE);
if (target)
/* Remove the client from all channels and free it */
SILC_CLIENT_CMD_FUNC(kill_remove)
{
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
- SilcClientCommandReplyContext reply =
+ SilcClientCommandReplyContext reply =
(SilcClientCommandReplyContext)context2;
SilcStatus status;
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /KILL <nickname> [<comment>] [-pubkey]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
nickname = strdup(cmd->argv[1]);
/* Get the target client */
- target = silc_idlist_get_client(cmd->client, conn, nickname,
+ target = silc_idlist_get_client(cmd->client, conn, nickname,
cmd->argv[1], TRUE);
if (!target) {
if (cmd->pending) {
/* Client entry not found, it was requested thus mark this to be
pending command. */
- silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
- conn->cmd_ident,
- silc_client_command_kill,
+ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
+ conn->cmd_ident,
+ silc_client_command_kill,
silc_client_command_dup(cmd));
cmd->pending = 1;
goto out;
/* Send the KILL command to the server */
idp = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
buffer =
- silc_command_payload_encode_va(SILC_COMMAND_KILL,
- ++conn->cmd_ident, 3,
+ silc_command_payload_encode_va(SILC_COMMAND_KILL,
+ ++conn->cmd_ident, 3,
1, idp->data, idp->len,
2, comment, comment ? strlen(comment) : 0,
3, auth ? auth->data : NULL,
/* Send the command */
if (name)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_INFO, 0, 1,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_INFO, 0, 1,
1, name, strlen(name));
else
buffer = silc_command_payload_encode(SILC_COMMAND_INFO, 0,
NULL, NULL, NULL, 0);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
if (name)
goto out;
}
- idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
-
+ idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
+
/* Send the command */
buffer = silc_command_payload_encode_va(SILC_COMMAND_STATS,
++conn->cmd_ident, 1,
SILC_ID_SERVER, idp->data, idp->len);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(idp);
silc_client_command_free(cmd);
}
-/* Command PING. Sends ping to server. This is used to test the
+/* Command PING. Sends ping to server. This is used to test the
communication channel. */
SILC_CLIENT_CMD_FUNC(ping)
goto out;
}
- idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
+ idp = silc_id_payload_encode(conn->remote_id, SILC_ID_SERVER);
/* Send the command */
- buffer = silc_command_payload_encode_va(SILC_COMMAND_PING, 0, 1,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_PING, 0, 1,
1, idp->data, idp->len);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(idp);
conn->internal->ping[i].dest_name = strdup(conn->remote_host);
conn->internal->ping_count++;
}
-
+
/* Notify application */
COMMAND(SILC_STATUS_OK);
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
SilcClientConnection conn = cmd->conn;
SilcChannelEntry channel;
- SilcBuffer buffer, idp, auth = NULL;
+ SilcBuffer buffer, idp, auth = NULL, cauth = NULL;
char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
int i, passphrase_len = 0;
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
-
+
/* See if we have joined to the requested channel already */
channel = silc_client_get_channel(cmd->client, conn, cmd->argv[1]);
if (channel && silc_client_on_channel(channel, conn->local_entry))
} else if (!strcasecmp(cmd->argv[i], "-founder")) {
auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
cmd->client->private_key,
- cmd->client->rng,
+ cmd->client->rng,
cmd->client->sha1hash,
conn->local_id,
SILC_ID_CLIENT);
i++;
+ } else if (!strcasecmp(cmd->argv[i], "-auth")) {
+ SilcPublicKey pubkey = cmd->client->public_key;
+ SilcPrivateKey privkey = cmd->client->private_key;
+ unsigned char *pk, pkhash[20], *pubdata;
+ SilcUInt32 pk_len;
+
+ if (cmd->argc >= i + 3) {
+ char *pass = "";
+ if (cmd->argc >= i + 4) {
+ pass = cmd->argv[i + 3];
+ i++;
+ }
+ if (!silc_load_key_pair(cmd->argv[i + 1], cmd->argv[i + 2], pass,
+ NULL, &pubkey, &privkey)) {
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+ "Could not load key pair, check your arguments");
+ COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ goto out;
+ }
+ i += 2;
+ }
+
+ pk = silc_pkcs_public_key_encode(pubkey, &pk_len);
+ silc_hash_make(cmd->client->sha1hash, pk, pk_len, pkhash);
+ silc_free(pk);
+ pubdata = silc_rng_get_rn_data(cmd->client->rng, 128);
+ memcpy(pubdata, pkhash, 20);
+ cauth = silc_auth_public_key_auth_generate_wpub(pubkey, privkey,
+ pubdata, 128,
+ cmd->client->sha1hash,
+ conn->local_id,
+ SILC_ID_CLIENT);
+ memset(pubdata, 0, 128);
+ silc_free(pubdata);
+ i++;
} else {
/* Passphrases must be UTF-8 encoded, so encode if it is not */
if (!silc_utf8_valid(cmd->argv[i], cmd->argv_lens[i])) {
- passphrase_len = silc_utf8_encoded_len(cmd->argv[i],
+ passphrase_len = silc_utf8_encoded_len(cmd->argv[i],
cmd->argv_lens[i], 0);
pu8 = silc_calloc(passphrase_len, sizeof(*pu8));
passphrase_len = silc_utf8_encode(cmd->argv[i], cmd->argv_lens[i],
/* Send JOIN command to the server */
buffer =
- silc_command_payload_encode_va(SILC_COMMAND_JOIN, 0, 6,
+ silc_command_payload_encode_va(SILC_COMMAND_JOIN, 0, 7,
1, name, strlen(name),
2, idp->data, idp->len,
3, passphrase, passphrase_len,
4, cipher, cipher ? strlen(cipher) : 0,
5, hmac, hmac ? strlen(hmac) : 0,
6, auth ? auth->data : NULL,
- auth ? auth->len : 0);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ auth ? auth->len : 0,
+ 7, cauth ? cauth->data : NULL,
+ cauth ? cauth->len : 0);
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(idp);
- if (auth)
- silc_buffer_free(auth);
+ silc_buffer_free(auth);
+ silc_buffer_free(cauth);
if (passphrase)
memset(passphrase, 0, strlen(passphrase));
silc_free(passphrase);
/* Send TOPIC command to the server */
if (cmd->argc == 1)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 0, 1,
- 1, conn->remote_host,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 0, 1,
+ 1, conn->remote_host,
strlen(conn->remote_host));
else
- buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 0, 1,
- 1, cmd->argv[1],
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_MOTD, 0, 1,
+ 1, cmd->argv[1],
cmd->argv_lens[1]);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /UMODE +|-<modes>");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
/* Send the command packet. We support sending only one mode at once
that requires an argument. */
- buffer =
- silc_command_payload_encode_va(SILC_COMMAND_UMODE, ++conn->cmd_ident, 2,
- 1, idp->data, idp->len,
+ buffer =
+ silc_command_payload_encode_va(SILC_COMMAND_UMODE, ++conn->cmd_ident, 2,
+ 1, idp->data, idp->len,
2, modebuf, sizeof(modebuf));
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(idp);
}
if (cmd->argc < 3) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
mode |= SILC_CHANNEL_MODE_ULIMIT;
type = 3;
if (cmd->argc < 4) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
mode |= SILC_CHANNEL_MODE_PASSPHRASE;
type = 4;
if (cmd->argc < 4) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
mode |= SILC_CHANNEL_MODE_CIPHER;
type = 5;
if (cmd->argc < 4) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
mode |= SILC_CHANNEL_MODE_HMAC;
type = 6;
if (cmd->argc < 4) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CMODE <channel> +|-<modes> [{ <arguments>}]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
pk = silc_pkcs_public_key_payload_encode(pubkey);
auth = silc_auth_public_key_auth_generate(pubkey, privkey,
- cmd->client->rng,
+ cmd->client->rng,
cmd->client->sha1hash,
conn->local_id,
SILC_ID_CLIENT);
mode &= ~SILC_CHANNEL_MODE_FOUNDER_AUTH;
}
break;
+ case 'C':
+ if (add) {
+ int k;
+ bool chadd = FALSE;
+ SilcPublicKey chpk = NULL;
+
+ mode |= SILC_CHANNEL_MODE_CHANNEL_AUTH;
+ type = 9;
+
+ if (cmd->argc == 3) {
+ /* Send empty command to receive the public key list. */
+ chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
+ silc_client_command_send(cmd->client, conn, SILC_COMMAND_CMODE,
+ 0, 1, 1, chidp->data, chidp->len);
+ silc_buffer_free(chidp);
+
+ /* Notify application */
+ COMMAND(SILC_STATUS_OK);
+ goto out;
+ }
+
+ if (cmd->argc >= 4) {
+ auth = silc_buffer_alloc_size(2);
+ silc_buffer_format(auth,
+ SILC_STR_UI_SHORT(cmd->argc - 3),
+ SILC_STR_END);
+ }
+
+ for (k = 3; k < cmd->argc; k++) {
+ if (cmd->argv[k][0] == '+')
+ chadd = TRUE;
+ if (!silc_pkcs_load_public_key(cmd->argv[k] + 1, &chpk,
+ SILC_PKCS_FILE_PEM))
+ if (!silc_pkcs_load_public_key(cmd->argv[k] + 1, &chpk,
+ SILC_PKCS_FILE_BIN)) {
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
+ "Could not load public key %s, check the filename",
+ cmd->argv[k]);
+ COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+ silc_buffer_free(auth);
+ goto out;
+ }
+
+ if (chpk) {
+ pk = silc_pkcs_public_key_payload_encode(chpk);
+ auth = silc_argument_payload_encode_one(auth, pk->data, pk->len,
+ chadd ? 0x00 : 0x01);
+ silc_pkcs_public_key_free(chpk);
+ silc_buffer_free(pk);
+ pk = NULL;
+ }
+ }
+
+ arg = auth->data;
+ arg_len = auth->len;
+ } else {
+ mode &= ~SILC_CHANNEL_MODE_CHANNEL_AUTH;
+ }
+ break;
default:
COMMAND_ERROR(SILC_STATUS_ERR_UNKNOWN_MODE);
goto out;
/* Send the command packet. We support sending only one mode at once
that requires an argument. */
if (type && arg) {
- buffer =
+ buffer =
silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 4,
- 1, chidp->data, chidp->len,
+ 1, chidp->data, chidp->len,
2, modebuf, sizeof(modebuf),
type, arg, arg_len,
8, pk ? pk->data : NULL,
pk ? pk->len : 0);
} else {
- buffer =
+ buffer =
silc_command_payload_encode_va(SILC_COMMAND_CMODE, 0, 2,
- 1, chidp->data, chidp->len,
+ 1, chidp->data, chidp->len,
2, modebuf, sizeof(modebuf));
}
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(chidp);
}
if (cmd->argc < 4) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CUMODE <channel> +|-<modes> <nickname>[@<server>]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
/* Client entry not found, it was requested thus mark this to be
pending command. */
- silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
- conn->cmd_ident,
- silc_client_command_cumode,
+ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
+ conn->cmd_ident,
+ silc_client_command_cumode,
silc_client_command_dup(cmd));
cmd->pending = 1;
goto out;
}
-
+
/* Get the current mode */
chu = silc_client_on_channel(channel, client_entry);
if (chu)
/* Send the command packet. We support sending only one mode at once
that requires an argument. */
- buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE, 0,
- auth ? 4 : 3,
- 1, chidp->data, chidp->len,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_CUMODE, 0,
+ auth ? 4 : 3,
+ 1, chidp->data, chidp->len,
2, modebuf, 4,
3, clidp->data, clidp->len,
- 4, auth ? auth->data : NULL,
+ 4, auth ? auth->data : NULL,
auth ? auth->len : 0);
-
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(chidp);
silc_buffer_free(clidp);
if (auth)
silc_buffer_free(auth);
-
+
/* Notify application */
COMMAND(SILC_STATUS_OK);
}
if (cmd->argc < 3) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /KICK <channel> <nickname> [<comment>]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
nickname = strdup(cmd->argv[2]);
/* Get the target client */
- target = silc_idlist_get_client(cmd->client, conn, nickname,
+ target = silc_idlist_get_client(cmd->client, conn, nickname,
cmd->argv[2], FALSE);
if (!target) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"No such client: %s", cmd->argv[2]);
COMMAND_ERROR(SILC_STATUS_ERR_NO_SUCH_NICK);
goto out;
idp = silc_id_payload_encode(id_cache->id, SILC_ID_CHANNEL);
idp2 = silc_id_payload_encode(target->id, SILC_ID_CLIENT);
if (cmd->argc == 3)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 0, 2,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 0, 2,
1, idp->data, idp->len,
2, idp2->data, idp2->len);
else
- buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 0, 3,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_KICK, 0, 3,
1, idp->data, idp->len,
2, idp2->data, idp2->len,
- 3, cmd->argv[3],
+ 3, cmd->argv[3],
strlen(cmd->argv[3]));
silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
data, data_len);
}
- buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER, 0, 2,
- 1, cmd->argv[1],
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_OPER, 0, 2,
+ 1, cmd->argv[1],
strlen(cmd->argv[1]),
2, auth ? auth->data : NULL,
auth ? auth->len : 0);
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /OPER <username> [-pubkey]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
static void silc_client_command_silcoper_send(unsigned char *data,
- SilcUInt32 data_len,
+ SilcUInt32 data_len,
void *context)
{
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
data, data_len);
}
- buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER, 0, 2,
- 1, cmd->argv[1],
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_SILCOPER, 0, 2,
+ 1, cmd->argv[1],
strlen(cmd->argv[1]),
2, auth ? auth->data : NULL,
auth ? auth->len : 0);
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /SILCOPER <username> [-pubkey]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
char *name, *ban = NULL;
unsigned char action[1];
SilcPublicKey pubkey = NULL;
-
+
if (!cmd->conn) {
SILC_NOT_CONNECTED(cmd->client, cmd->conn);
COMMAND_ERROR(SILC_STATUS_ERR_NOT_REGISTERED);
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /BAN <channel> "
"[+|-[<nickname>[@<server>[!<username>[@hostname>]]]]]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
/* Send the command */
- buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_BAN,
++conn->cmd_ident, 3,
1, chidp->data, chidp->len,
2, args ? action : NULL,
args ? 1 : 0,
3, args ? args->data : NULL,
args ? args->len : 0);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(chidp);
buffer = silc_command_payload_encode_va(SILC_COMMAND_DETACH,
++conn->cmd_ident, 0);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
goto out;
}
- buffer = silc_command_payload_encode_va(SILC_COMMAND_WATCH,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_WATCH,
++conn->cmd_ident, 2,
1, idp->data, idp->len,
type, cmd->argv[2],
cmd->argv_lens[2]);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
}
if (cmd->argc != 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /LEAVE <channel>");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
/* Send LEAVE command to the server */
idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
- buffer = silc_command_payload_encode_va(SILC_COMMAND_LEAVE, 0, 1,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_LEAVE, 0, 1,
1, idp->data, idp->len);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(idp);
}
if (cmd->argc != 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /USERS <channel>");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
/* Send USERS command to the server */
- buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS,
- ++conn->cmd_ident, 1,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS,
+ ++conn->cmd_ident, 1,
2, name, strlen(name));
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND,
- NULL, 0, NULL, NULL, buffer->data,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND,
+ NULL, 0, NULL, NULL, buffer->data,
buffer->len, TRUE);
silc_buffer_free(buffer);
}
if (cmd->argc < 2) {
- client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
+ client->internal->ops->say(client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /GETKEY <nickname or server name>");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
if (!cmd->pending) {
/* This will send the IDENTIFY command for nickname */
silc_idlist_get_client(client, conn, nickname, cmd->argv[1], TRUE);
- silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
- conn->cmd_ident,
- silc_client_command_getkey,
+ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
+ conn->cmd_ident,
+ silc_client_command_getkey,
silc_client_command_dup(cmd));
cmd->pending = 1;
goto out;
} else {
- SilcClientCommandReplyContext reply =
+ SilcClientCommandReplyContext reply =
(SilcClientCommandReplyContext)context2;
SilcStatus error;
silc_command_get_status(reply->payload, NULL, &error);
if (error == SILC_STATUS_ERR_NO_SUCH_NICK) {
/* This sends the IDENTIFY command to resolve the server. */
- silc_client_command_register(client, SILC_COMMAND_IDENTIFY,
+ silc_client_command_register(client, SILC_COMMAND_IDENTIFY,
NULL, NULL,
silc_client_command_reply_identify_i, 0,
++conn->cmd_ident);
silc_client_command_send(client, conn, SILC_COMMAND_IDENTIFY,
- conn->cmd_ident, 1,
+ conn->cmd_ident, 1,
2, cmd->argv[1], cmd->argv_lens[1]);
- silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
- conn->cmd_ident,
- silc_client_command_getkey,
+ silc_client_command_pending(conn, SILC_COMMAND_IDENTIFY,
+ conn->cmd_ident,
+ silc_client_command_getkey,
silc_client_command_dup(cmd));
goto out;
}
/* If server was not found, then we've resolved both nickname and
server and did not find anybody. */
if (error == SILC_STATUS_ERR_NO_SUCH_SERVER) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s",
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s",
silc_get_status_message(SILC_STATUS_ERR_NO_SUCH_NICK));
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s",
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR, "%s",
silc_get_status_message(error));
COMMAND_ERROR(SILC_STATUS_ERR_NO_SUCH_NICK);
goto out;
idp = silc_id_payload_encode(client_entry->id, SILC_ID_CLIENT);
}
- buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY, 0, 1,
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_GETKEY, 0, 1,
1, idp->data, idp->len);
- silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
+ silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
silc_buffer_free(buffer);
silc_buffer_free(idp);
searched using the silc_client_command_find by that name. The
`command_function' is the function to be called when the command is
executed, and the `command_reply_function' is the function to be
- called after the server has sent reply back to the command.
+ called after the server has sent reply back to the command.
The `ident' is optional identifier for the command. If non-zero
the `command_reply_function' for the command type `command' will be
- called only if the command reply sent by server includes the
+ called only if the command reply sent by server includes the
command identifier `ident'. Application usually does not need it
and set it to zero value. */
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CONNECT <server> [<port>]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
if (cmd->argc == 3)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 2,
- 1, cmd->argv[1],
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 2,
+ 1, cmd->argv[1],
strlen(cmd->argv[1]),
2, port, 4);
else
buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CONNECT, 0, 1,
- 1, cmd->argv[1],
+ 1, cmd->argv[1],
strlen(cmd->argv[1]));
silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
/* CLOSE command. Close server connection to the remote server */
-
+
SILC_CLIENT_CMD_FUNC(close)
{
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
}
if (cmd->argc < 2) {
- SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
+ SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_INFO,
"Usage: /CLOSE <server> [<port>]");
COMMAND_ERROR(SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
goto out;
}
if (cmd->argc == 3)
- buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 2,
- 1, cmd->argv[1],
+ buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 2,
+ 1, cmd->argv[1],
strlen(cmd->argv[1]),
2, port, 4);
else
buffer = silc_command_payload_encode_va(SILC_COMMAND_PRIV_CLOSE, 0, 1,
- 1, cmd->argv[1],
+ 1, cmd->argv[1],
strlen(cmd->argv[1]));
silc_client_packet_send(cmd->client, conn->sock, SILC_PACKET_COMMAND, NULL,
0, NULL, NULL, buffer->data, buffer->len, TRUE);
out:
silc_client_command_free(cmd);
}
-
+
/* SHUTDOWN command. Shutdowns the server. */
SILC_CLIENT_CMD_FUNC(shutdown)
}
/* Send the command */
- silc_client_command_send(cmd->client, cmd->conn,
+ silc_client_command_send(cmd->client, cmd->conn,
SILC_COMMAND_PRIV_SHUTDOWN, 0, 0);
/* Notify application */
void silc_client_commands_register(SilcClient client)
{
- silc_list_init(client->internal->commands, struct SilcClientCommandStruct,
+ silc_list_init(client->internal->commands, struct SilcClientCommandStruct,
next);
SILC_CLIENT_CMD(whois, WHOIS, "WHOIS", 3);
/* Get arguments */
args = silc_command_get_args(payload);
-
+
/* Get the command */
command = silc_command_get(payload);
switch (command) {
silc_command_get_ident(payload),
1, 11, buffer->data, buffer->len);
silc_client_packet_send(client, sock, SILC_PACKET_COMMAND_REPLY,
- NULL, 0, NULL, NULL, packet->data,
+ NULL, 0, NULL, NULL, packet->data,
packet->len, TRUE);
silc_buffer_free(packet);
silc_buffer_free(buffer);
SilcChannelID *channel_id;
SilcChannelEntry channel;
SilcUInt32 len;
+ SilcPublicKey public_key = NULL;
+ SilcBufferStruct channel_pubkeys;
if (cmd->error != SILC_STATUS_OK) {
SAY(cmd->client, conn, SILC_CLIENT_MESSAGE_ERROR,
SILC_GET32_MSB(mode, tmp);
channel->mode = mode;
+ /* Get founder public key */
+ tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
+ if (tmp) {
+ if (!silc_pkcs_public_key_payload_decode(tmp, len, &public_key))
+ public_key = NULL;
+ }
+
+ /* Get channel public key(s) */
+ tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
+ if (tmp)
+ silc_buffer_set(&channel_pubkeys, tmp, len);
+
/* Notify application */
- COMMAND_REPLY((SILC_ARGS, channel, mode));
+ COMMAND_REPLY((SILC_ARGS, channel, mode, public_key,
+ tmp ? &channel_pubkeys : NULL));
silc_free(channel_id);
out:
+ if (public_key)
+ silc_pkcs_public_key_free(public_key);
SILC_CLIENT_PENDING_EXEC(cmd, SILC_COMMAND_CMODE);
silc_client_command_reply_free(cmd);
}
SilcChannelID *id; /* Channel ID */
SilcUInt32 mode; /* Channel mode */
- /* All clients that has joined this channel */
+ /* All clients that has joined this channel. The key to the table is the
+ SilcClientEntry and the context is SilcChannelUser context. */
SilcHashTable user_list;
/* Channel keys */
/*
- silcauth.c
+ silcauth.c
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2002 Pekka Riikonen
+ Copyright (C) 2001 - 2003 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
return NULL;
}
- if (newp->len != buffer.len ||
+ if (newp->len != buffer.len ||
newp->random_len + newp->auth_len > buffer.len - 8) {
silc_auth_payload_free(newp);
return NULL;
return payload->auth_method;
}
+/* Get the public data from the auth payload. */
+
+unsigned char *silc_auth_get_public_data(SilcAuthPayload payload,
+ SilcUInt32 *pubdata_len)
+{
+ if (pubdata_len)
+ *pubdata_len = (SilcUInt32)payload->random_len;
+
+ return payload->random_data;
+}
+
/* Get the authentication data. If this is passphrase it is UTF-8 encoded. */
unsigned char *silc_auth_get_data(SilcAuthPayload payload,
SilcUInt32 *auth_len)
{
if (auth_len)
- *auth_len = payload->auth_len;
+ *auth_len = (SilcUInt32)payload->auth_len;
return payload->auth_data;
}
const void *id, SilcIdType type)
{
unsigned char *randomdata;
- unsigned char auth_data[2048 + 1];
- SilcUInt32 auth_len;
- unsigned char *tmp;
- SilcUInt32 tmp_len;
SilcBuffer buf;
- SilcPKCS pkcs;
-
- SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
/* Get 256 bytes of random data */
if (rng)
if (!randomdata)
return NULL;
+ buf = silc_auth_public_key_auth_generate_wpub(public_key, private_key,
+ randomdata, 256, hash,
+ id, type);
+
+ memset(randomdata, 0, 256);
+ silc_free(randomdata);
+
+ return buf;
+}
+
+/* Generates Authentication Payload with authentication data. This is used
+ to do public key based authentication. This generates the random data
+ and the actual authentication data. Returns NULL on error. */
+
+SilcBuffer
+silc_auth_public_key_auth_generate_wpub(SilcPublicKey public_key,
+ SilcPrivateKey private_key,
+ const unsigned char *pubdata,
+ SilcUInt32 pubdata_len,
+ SilcHash hash,
+ const void *id, SilcIdType type)
+{
+ unsigned char auth_data[2048 + 1];
+ SilcUInt32 auth_len;
+ unsigned char *tmp;
+ SilcUInt32 tmp_len;
+ SilcBuffer buf;
+ SilcPKCS pkcs;
+
+ SILC_LOG_DEBUG(("Generating Authentication Payload with data"));
+
/* Encode the auth data */
- tmp = silc_auth_public_key_encode_data(public_key, randomdata, 256, id,
+ tmp = silc_auth_public_key_encode_data(public_key, pubdata, pubdata_len, id,
type, &tmp_len);
if (!tmp)
return NULL;
if (silc_pkcs_get_key_len(pkcs) / 8 > sizeof(auth_data) - 1 ||
!silc_pkcs_sign_with_hash(pkcs, hash, tmp, tmp_len, auth_data,
&auth_len)) {
- memset(randomdata, 0, 256);
memset(tmp, 0, tmp_len);
silc_free(tmp);
- silc_free(randomdata);
silc_pkcs_free(pkcs);
return NULL;
}
/* Encode Authentication Payload */
- buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, randomdata, 256,
+ buf = silc_auth_payload_encode(SILC_AUTH_PUBLIC_KEY, pubdata, pubdata_len,
auth_data, auth_len);
memset(tmp, 0, tmp_len);
memset(auth_data, 0, sizeof(auth_data));
- memset(randomdata, 0, 256);
silc_free(tmp);
- silc_free(randomdata);
silc_pkcs_free(pkcs);
return buf;
/*
- silcauth.h
+ silcauth.h
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2001 - 2002 Pekka Riikonen
+ Copyright (C) 2001 - 2003 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
* DESCRIPTION
*
* Implementations of the SILC Authentication Payload and authentication
- * routines. The SILC Authentication Payload is used to deliver
- * authentication data usually from client to server in purpose of
+ * routines. The SILC Authentication Payload is used to deliver
+ * authentication data usually from client to server in purpose of
* gaining access to some service. The Payload and the authentication
* routines supports both passphrase and public key (signature) based
* authentication.
/****d* silccore/SilcAuthAPI/SilcAuthMethod
*
* NAME
- *
+ *
* typedef SilcUInt16 SilcAuthMethod;
*
* DESCRIPTION
/****s* silccore/SilcAuthAPI/SilcAuthPayload
*
* NAME
- *
- * typedef struct SilcAuthPayloadStruct *SilcAuthPayload;
+ *
+ * typedef struct SilcAuthPayloadStruct *SilcAuthPayload;
*
*
* DESCRIPTION
***/
SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload);
+/****f* silccore/SilcAuthAPI/silc_auth_get_public_data
+ *
+ * SYNOPSIS
+ *
+ * unsigned char *silc_auth_get_public_data(SilcAuthPayload payload,
+ * SilcUInt32 *pubdata_len);
+ *
+ * DESCRIPTION
+ *
+ * Returns the public data (usually random data) from the payload.
+ * Caller must not free the returned data.
+ *
+ ***/
+unsigned char *silc_auth_get_public_data(SilcAuthPayload payload,
+ SilcUInt32 *pubdata_len);
+
/****f* silccore/SilcAuthAPI/silc_auth_get_data
*
* SYNOPSIS
* SilcPrivateKey private_key,
* SilcRng rng,
* SilcHash hash,
- * const void *id,
+ * const void *id,
* SilcIdType type);
*
* DESCRIPTION
SilcRng rng, SilcHash hash,
const void *id, SilcIdType type);
+/****f* silccore/SilcAuthAPI/silc_auth_public_key_auth_generate_wpub
+ *
+ * SYNOPSIS
+ *
+ * SilcBuffer
+ * silc_auth_public_key_auth_generate_wpub(SilcPublicKey public_key,
+ * SilcPrivateKey private_key,
+ * const unsigned char *pubdata,
+ * SilcUInt32 pubdata_len,
+ * SilcHash hash,
+ * const void *id,
+ * SilcIdType type);
+ *
+ * DESCRIPTION
+ *
+ * Same as silc_auth_public_key_auth_generate but takes the public data
+ * (usually random data) as argument. This function can be used when
+ * the public data must be something else than purely random or its
+ * structure mut be set before signing.
+ *
+ ***/
+SilcBuffer
+silc_auth_public_key_auth_generate_wpub(SilcPublicKey public_key,
+ SilcPrivateKey private_key,
+ const unsigned char *pubdata,
+ SilcUInt32 pubdata_len,
+ SilcHash hash,
+ const void *id, SilcIdType type);
+
/****f* silccore/SilcAuthAPI/silc_auth_public_key_auth_verify
*
* SYNOPSIS
*
* bool silc_auth_public_key_auth_verify(SilcAuthPayload payload,
- * SilcPublicKey public_key,
+ * SilcPublicKey public_key,
* SilcHash hash,
* const void *id, SilcIdType type);
*
*
* bool silc_auth_public_key_auth_verify_data(const unsigned char *payload,
* SilcUInt32 payload_len,
- * SilcPublicKey public_key,
+ * SilcPublicKey public_key,
* SilcHash hash,
- * const void *id,
+ * const void *id,
* SilcIdType type);
*
* DESCRIPTION
***/
bool silc_auth_public_key_auth_verify_data(const unsigned char *payload,
SilcUInt32 payload_len,
- SilcPublicKey public_key,
+ SilcPublicKey public_key,
SilcHash hash,
const void *id, SilcIdType type);
*
* SYNOPSIS
*
- * bool silc_auth_verify(SilcAuthPayload payload,
+ * bool silc_auth_verify(SilcAuthPayload payload,
* SilcAuthMethod auth_method,
- * const void *auth_data, SilcUInt32 auth_data_len,
+ * const void *auth_data, SilcUInt32 auth_data_len,
* SilcHash hash, const void *id, SilcIdType type);
*
* DESCRIPTION
*
- * Verifies the authentication data directly from the Authentication
+ * Verifies the authentication data directly from the Authentication
* Payload. Supports all authentication methods. If the authentication
* method is passphrase based then the `auth_data' and `auth_data_len'
* are the passphrase and its length. The passphrase MUST be UTF-8
*
***/
bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method,
- const void *auth_data, SilcUInt32 auth_data_len,
+ const void *auth_data, SilcUInt32 auth_data_len,
SilcHash hash, const void *id, SilcIdType type);
/****f* silccore/SilcAuthAPI/silc_auth_verify_data
*
* SYNOPSIS
*
- * bool silc_auth_verify_data(const unsigned char *payload,
+ * bool silc_auth_verify_data(const unsigned char *payload,
* SilcUInt32 payload_len,
- * SilcAuthMethod auth_method,
+ * SilcAuthMethod auth_method,
* const void *auth_data,
- * SilcUInt32 auth_data_len, SilcHash hash,
+ * SilcUInt32 auth_data_len, SilcHash hash,
* const void *id, SilcIdType type);
- *
+ *
* DESCRIPTION
*
* Same as silc_auth_verify but the payload has not been parsed yet.
- * Verifies the authentication data directly from the Authentication
+ * Verifies the authentication data directly from the Authentication
* Payload. Supports all authentication methods. If the authentication
* method is passphrase based then the `auth_data' and `auth_data_len'
* are the passphrase and its length. The passphrase MUST be UTF-8
* `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored.
*
***/
-bool silc_auth_verify_data(const unsigned char *payload,
+bool silc_auth_verify_data(const unsigned char *payload,
SilcUInt32 payload_len,
SilcAuthMethod auth_method, const void *auth_data,
- SilcUInt32 auth_data_len, SilcHash hash,
+ SilcUInt32 auth_data_len, SilcHash hash,
const void *id, SilcIdType type);
/****s* silccore/SilcAuthAPI/SilcKeyAgreementPayload
*
* NAME
- *
+ *
* typedef struct SilcKeyAgreementPayloadStruct *SilcKeyAgreementPayload;
*
* DESCRIPTION
*
* SYNOPSIS
*
- * SilcKeyAgreementPayload
+ * SilcKeyAgreementPayload
* silc_key_agreement_payload_parse(const unsigned char *payload,
* SilcUInt32 payload_len);
*
* Parses and returns an allocated Key Agreement payload.
*
***/
-SilcKeyAgreementPayload
+SilcKeyAgreementPayload
silc_key_agreement_payload_parse(const unsigned char *payload,
SilcUInt32 payload_len);
/*
- silcpkcs.c
+ silcpkcs.c
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2003 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
const SilcPKCSObject silc_default_pkcs[] =
{
/* RSA with PKCS #1 (Uses directly routines from Raw RSA operations) */
- { "rsa",
+ { "rsa",
silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
silc_rsa_get_private_key, silc_rsa_set_public_key,
silc_rsa_set_private_key, silc_rsa_context_len,
silc_pkcs1_sign, silc_pkcs1_verify },
/* Raw RSA operations */
- { "rsa-raw",
+ { "rsa-raw",
silc_rsa_init, silc_rsa_clear_keys, silc_rsa_get_public_key,
silc_rsa_get_private_key, silc_rsa_set_public_key,
silc_rsa_set_private_key, silc_rsa_context_len,
return FALSE;
}
-/* Function that registers all the default PKCS (all builtin PKCS).
+/* Function that registers all the default PKCS (all builtin PKCS).
The application may use this to register the default PKCS if specific
PKCS in any specific order is not wanted. */
while ((entry = silc_dlist_get(silc_pkcs_list)) != SILC_LIST_END) {
len += strlen(entry->name);
list = silc_realloc(list, len + 1);
-
- memcpy(list + (len - strlen(entry->name)),
+
+ memcpy(list + (len - strlen(entry->name)),
entry->name, strlen(entry->name));
memcpy(list + len, ",", 1);
len++;
entry = (SilcPKCSObject *)&(silc_default_pkcs[i]);
len += strlen(entry->name);
list = silc_realloc(list, len + 1);
-
- memcpy(list + (len - strlen(entry->name)),
+
+ memcpy(list + (len - strlen(entry->name)),
entry->name, strlen(entry->name));
memcpy(list + len, ",", 1);
len++;
SilcUInt32 silc_pkcs_public_key_set(SilcPKCS pkcs, SilcPublicKey public_key)
{
- pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
+ pkcs->key_len = pkcs->pkcs->set_public_key(pkcs->context, public_key->pk,
public_key->pk_len);
return pkcs->key_len;
}
SilcUInt32 silc_pkcs_private_key_set(SilcPKCS pkcs, SilcPrivateKey private_key)
{
SilcUInt32 key_len;
- key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
+ key_len = pkcs->pkcs->set_private_key(pkcs->context, private_key->prv,
private_key->prv_len);
if (!pkcs->key_len)
pkcs->key_len = key_len;
/* Verifies signature */
-bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
- SilcUInt32 signature_len, unsigned char *data,
+bool silc_pkcs_verify(SilcPKCS pkcs, unsigned char *signature,
+ SilcUInt32 signature_len, unsigned char *data,
SilcUInt32 data_len)
{
- return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
+ return pkcs->pkcs->verify(pkcs->context, signature, signature_len,
data, data_len);
}
/* Verifies signature with hash. The `data' is hashed and verified against
the `signature'. */
-bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
- unsigned char *signature,
- SilcUInt32 signature_len,
- unsigned char *data,
+bool silc_pkcs_verify_with_hash(SilcPKCS pkcs, SilcHash hash,
+ unsigned char *signature,
+ SilcUInt32 signature_len,
+ unsigned char *data,
SilcUInt32 data_len)
{
unsigned char hashr[32];
SILC_LOG_HEXDUMP(("Hash"), hashr, hash_len);
- ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
+ ret = pkcs->pkcs->verify(pkcs->context, signature, signature_len,
hashr, hash_len);
memset(hashr, 0, sizeof(hashr));
return ret;
}
-/* Encodes and returns SILC public key identifier. If some of the
+/* Encodes and returns SILC public key identifier. If some of the
arguments is NULL those are not encoded into the identifier string.
Protocol says that at least username and host must be provided. */
(email ? strlen(email) : 0) +
(org ? strlen(org) : 0) +
(country ? strlen(country) : 0);
-
+
if (len < 3)
return NULL;
SILC_STR_UI32_STRING(username),
SILC_STR_END);
silc_buffer_pull(buf, 3 + strlen(username));
- tlen = 3 + strlen(username);
+ tlen = 3 + strlen(username);
}
-
+
if (host) {
silc_buffer_format(buf,
SILC_STR_UI32_STRING(", "),
SILC_STR_UI32_STRING(host),
SILC_STR_END);
silc_buffer_pull(buf, 5 + strlen(host));
- tlen += 5 + strlen(host);
+ tlen += 5 + strlen(host);
}
if (realname) {
SILC_STR_UI32_STRING(realname),
SILC_STR_END);
silc_buffer_pull(buf, 5 + strlen(realname));
- tlen += 5 + strlen(realname);
+ tlen += 5 + strlen(realname);
}
if (email) {
SILC_STR_UI32_STRING(email),
SILC_STR_END);
silc_buffer_pull(buf, 4 + strlen(email));
- tlen += 4 + strlen(email);
+ tlen += 4 + strlen(email);
}
if (org) {
SILC_STR_UI32_STRING(org),
SILC_STR_END);
silc_buffer_pull(buf, 4 + strlen(org));
- tlen += 4 + strlen(org);
+ tlen += 4 + strlen(org);
}
if (country) {
SILC_STR_UI32_STRING(country),
SILC_STR_END);
silc_buffer_pull(buf, 4 + strlen(country));
- tlen += 4 + strlen(country);
+ tlen += 4 + strlen(country);
}
silc_buffer_push(buf, buf->data - buf->head);
ident->org = strdup(item + strcspn(cp, "=") + 1);
else if (strstr(item, "C="))
ident->country = strdup(item + strcspn(cp, "=") + 1);
-
+
cp += len;
if (strlen(cp) == 0)
cp = NULL;
else
cp += 1;
-
+
if (item)
silc_free(item);
}
/* Allocates SILC style public key formed from sent arguments. All data
is duplicated. */
-SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
+SilcPublicKey silc_pkcs_public_key_alloc(const char *name,
const char *identifier,
- const unsigned char *pk,
+ const unsigned char *pk,
SilcUInt32 pk_len)
{
SilcPublicKey public_key;
SILC_STR_UI32_STRING(public_key->name),
SILC_STR_UI_SHORT(strlen(public_key->identifier)),
SILC_STR_UI32_STRING(public_key->identifier),
- SILC_STR_UI_XNSTRING(public_key->pk,
+ SILC_STR_UI_XNSTRING(public_key->pk,
public_key->pk_len),
SILC_STR_END);
unsigned char *
silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
- char *pkcs, char *identifier,
+ char *pkcs, char *identifier,
SilcUInt32 *len)
{
SilcBuffer buf;
if (ret == -1)
goto err;
- if (pkcs_len < 1 || identifier_len < 3 ||
+ if (pkcs_len < 1 || identifier_len < 3 ||
pkcs_len + identifier_len > totlen)
goto err;
goto err;
/* Try to set the key. If this fails the key must be malformed. This
- code assumes that the PKCS routine checks the format of the key.
+ code assumes that the PKCS routine checks the format of the key.
(check only if PKCS are registered) */
if (SILC_PKCS_LIST) {
silc_pkcs_alloc(pkcs_name, &alg);
goto err;
silc_pkcs_free(alg);
}
-
+
if (public_key) {
*public_key = silc_calloc(1, sizeof(**public_key));
(*public_key)->len = totlen;
silc_buffer_format(buf,
SILC_STR_UI_SHORT(strlen(private_key->name)),
SILC_STR_UI32_STRING(private_key->name),
- SILC_STR_UI_XNSTRING(private_key->prv,
+ SILC_STR_UI_XNSTRING(private_key->prv,
private_key->prv_len),
SILC_STR_END);
silc_buffer_set(&buf, data, data_len);
/* Get algorithm name and identifier */
- ret =
+ ret =
silc_buffer_unformat(&buf,
SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
SILC_STR_END);
goto err;
/* Try to set the key. If this fails the key must be malformed. This
- code assumes that the PKCS routine checks the format of the key.
+ code assumes that the PKCS routine checks the format of the key.
(check only if PKCS are registered) */
if (SILC_PKCS_LIST) {
silc_pkcs_alloc(pkcs_name, &alg);
}
silc_pkcs_free(alg);
}
-
+
if (private_key) {
*private_key = silc_calloc(1, sizeof(**private_key));
(*private_key)->name = pkcs_name;
}
/* Derive the encryption key from the provided key material. The key
- is 256 bits length, and derived by taking hash of the data, then
+ is 256 bits length, and derived by taking hash of the data, then
re-hashing the data and the previous digest, and using the first and
second digest as the key. */
silc_hash_init(sha1);
SILC_LOG_DEBUG(("Loading public key `%s' with %s encoding", filename,
encoding == SILC_PKCS_FILE_PEM ? "Base64" :
encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
-
+
old = data = silc_file_readfile(filename, &data_len);
if (!data)
return FALSE;
data = silc_pem_decode(data, len, &len);
memset(old, 0, data_len);
silc_free(old);
- old = data;
+ old = data;
data_len = len;
break;
}
SILC_LOG_DEBUG(("Loading private key `%s' with %s encoding", filename,
encoding == SILC_PKCS_FILE_PEM ? "Base64" :
encoding == SILC_PKCS_FILE_BIN ? "Binary" : "Unkonwn"));
-
+
old = data = silc_file_readfile(filename, &data_len);
if (!data)
return FALSE;
}
/* Derive the decryption key from the provided key material. The key
- is 256 bits length, and derived by taking hash of the data, then
+ is 256 bits length, and derived by taking hash of the data, then
re-hashing the data and the previous digest, and using the first and
second digest as the key. */
silc_hash_init(sha1);
* Register option `name' in the entity `ent'. If `cb' is not NULL, it
* will be called with the *val pointer pointing to an internally
* allocated storage of type described by `type'.
+ *
* If `type' is SILC_CONFIG_ARG_BLOCK, then `subtable' must be a valid
* pointer to a SilcConfigTable array specifying the options in the
* sub-block.
+ *
* If the option `name' was already registered in this sub-block or it
* matches the reserved word "Include", then this function returns FALSE,
* otherwise it returns TRUE.
* Register the tableset of options `table' automatically in the entity
* `ent'. If defined in the table, the callback functions will be called
* all with the same context `context'.
+ *
* The `table' array must be terminated with an entry with the name field
* set to NULL.
+ *
* If the table contains invalid data this function returns FALSE, otherwise
* it returns TRUE. If a calling to this function failed, you must destroy
* and recreate the entity before retrying, as it's impossible to detect
*
* Enter the main parsing loop. When this function returns the parsing
* is finished in the current block (and sub-blocks).
+ *
* When this function exits, the entity is already destroyed, because
* of this you should set it to NULL right after the function call.
*
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2003 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
if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)
strncat(string, "f", 1);
+ if (mode & SILC_CHANNEL_MODE_CHANNEL_AUTH)
+ strncat(string, "C", 1);
+
if (mode & SILC_CHANNEL_MODE_SILENCE_USERS)
strncat(string, "m", 1);
if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
strncat(string, "M", 1);
-
+
if (mode & SILC_CHANNEL_MODE_CIPHER)
strncat(string, "c", 1);
-
+
if (mode & SILC_CHANNEL_MODE_HMAC)
strncat(string, "h", 1);
/* Return TRUE if `smaller' is smaller than `bigger'. */
-bool silc_compare_timeval(struct timeval *smaller,
+bool silc_compare_timeval(struct timeval *smaller,
struct timeval *bigger)
{
if ((smaller->tv_sec < bigger->tv_sec) ||