+Tue May 7 11:07:16 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added the founder's public key delivery to the
+ CUMODE_CHANGE notify type as well. Updated the protocol
+ specs and the code. Affected files are silcd/packet_send.[ch],
+ silcd/packet_receive.c and silcd/command.c.
+
Mon May 6 19:46:12 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
* Added silc_pkcs_public_key_copy function into the
/* SYNTAX: FILE RECEIVE [<nickname>] */
/* SYNTAX: FILE CLOSE [<nickname>] */
/* SYNTAX: FILE */
-/* SYNTAX: JOIN <channel> [<passphrase>] [-cipher <cipher>] [-hmac <hmac>] [-founder <-pubkey|passwd>] */
+/* SYNTAX: JOIN <channel> [<passphrase>] [-cipher <cipher>] [-hmac <hmac>] [-founder] */
/* SYNTAX: DETACH */
/* SYNTAX: WATCH [<-add | -del> <nickname>] */
idata->public_key)) {
/* Check whether the client is to become founder */
if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
- channel->founder_key, 0,
- idata->hash, client->id, SILC_ID_CLIENT)) {
+ channel->founder_key, 0, server->sha1hash,
+ client->id, SILC_ID_CLIENT)) {
umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
founder = TRUE;
}
/* Distribute the channel key to all backup routers. */
silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
keyp->data, keyp->len, FALSE, TRUE);
- }
- /* If client became founder by providing correct founder auth data
- notify the mode change to the channel. */
- if (founder) {
- SILC_PUT32_MSB(chl->mode, mode);
- silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
- SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
- clidp->data, clidp->len,
- mode, 4, clidp->data, clidp->len);
+ /* If client became founder by providing correct founder auth data
+ notify the mode change to the channel. */
+ if (founder) {
+ SILC_PUT32_MSB(chl->mode, mode);
+ tmp = silc_pkcs_public_key_encode(channel->founder_key, &tmp_len);
+ silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
+ SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
+ clidp->data, clidp->len,
+ mode, 4, clidp->data, clidp->len,
+ tmp, tmp_len);
+ silc_free(tmp);
- /* Set CUMODE notify type to network */
- if (!server->standalone)
- silc_server_send_notify_cumode(server, server->router->connection,
- server->server_type == SILC_ROUTER ?
- TRUE : FALSE, channel,
- chl->mode, client->id, SILC_ID_CLIENT,
- client->id);
+ /* Set CUMODE notify type to network */
+ if (!server->standalone)
+ silc_server_send_notify_cumode(server, server->router->connection,
+ server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, channel,
+ chl->mode, client->id, SILC_ID_CLIENT,
+ client->id, channel->founder_key);
+ }
}
silc_buffer_free(reply);
/* Verify the payload before setting the mode */
if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY,
- idata->public_key, 0, idata->hash,
+ idata->public_key, 0, server->sha1hash,
client->id, SILC_ID_CLIENT)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
SILC_STATUS_ERR_AUTH_FAILED,
SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
int notify = FALSE;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
+ SilcPublicKey founder_key = NULL;
+ unsigned char *fkey = NULL;
+ SilcUInt32 fkey_len = 0;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
/* Verify the authentication payload */
if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
- channel->founder_key, 0, idata->hash,
+ channel->founder_key, 0, server->sha1hash,
client->id, SILC_ID_CLIENT)) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
SILC_STATUS_ERR_AUTH_FAILED, 0);
sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
notify = TRUE;
+ founder_key = channel->founder_key;
+ fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
}
} else {
if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
/* Send notify to channel, notify only if mode was actually changed. */
if (notify) {
silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
- SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
+ SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
idp->data, idp->len,
tmp_mask, 4,
- tmp_id, tmp_len);
+ tmp_id, tmp_len,
+ fkey, fkey_len);
/* Set CUMODE notify type to network */
if (!server->standalone)
TRUE : FALSE, channel,
target_mask, client->id,
SILC_ID_CLIENT,
- target_client->id);
+ target_client->id, founder_key);
}
/* Send command reply to sender */
silc_buffer_free(idp);
out:
+ silc_free(fkey);
silc_server_command_free(cmd);
}
server->server_type == SILC_ROUTER) {
/* Check whether this client is allowed to be channel founder on
this channel. */
+ SilcPublicKey founder_key;
/* If channel doesn't have founder auth mode then it's impossible
that someone would be getting founder rights with CUMODE command.
if (!(mode & SILC_CHANNEL_UMODE_CHANFO))
break;
- /* XXX Founder not found of the channel. Since the founder auth mode
+ /* Founder not found of the channel. Since the founder auth mode
is set on the channel now check whether this is the client that
- originally set the mode. If we don't have the public key it
- is resolved first.
+ originally set the mode. */
+
+ /* Get public key that must be present in notify */
+ tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
+ if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
+ &founder_key)) {
+ mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, sock, channel, chl, mode);
+ notify_sent = TRUE;
+ break;
+ }
+
+ /* Now match the public key we have cached and publick key sent.
+ They must match. */
if (!silc_pkcs_public_key_compare(channel->founder_key,
- client->data.public_key))
- */
-
+ client->data.public_key)) {
+ mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+ silc_server_force_cumode_change(server, sock, channel, chl, mode);
+ notify_sent = TRUE;
+ break;
+ }
}
SILC_LOG_DEBUG(("Changing the channel user mode"));
/* Verify the authentication payload. This has to be successful in
order to allow the resuming */
- if (!silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
+ if (!idata->hash ||
+ !silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
detached_client->data.public_key, 0,
idata->hash, detached_client->id,
SILC_ID_CLIENT)) {
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL, SILC_NOTIFY_TYPE_CMODE_CHANGE,
- 5, idp->data, idp->len,
+ 6, idp->data, idp->len,
mode, 4,
cipher, cipher ? strlen(cipher) : 0,
hmac, hmac ? strlen(hmac) : 0,
SilcChannelEntry channel,
SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
- SilcClientID *target)
+ SilcClientID *target,
+ SilcPublicKey founder_key)
{
SilcBuffer idp1, idp2;
- unsigned char mode[4];
+ unsigned char mode[4], *key = NULL;
+ SilcUInt32 key_len = 0;
idp1 = silc_id_payload_encode((void *)id, id_type);
idp2 = silc_id_payload_encode((void *)target, SILC_ID_CLIENT);
SILC_PUT32_MSB(mode_mask, mode);
+ if (founder_key)
+ key = silc_pkcs_public_key_encode(founder_key, &key_len);
silc_server_send_notify_dest(server, sock, broadcast, (void *)channel->id,
SILC_ID_CHANNEL,
- SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
+ SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
idp1->data, idp1->len,
mode, 4,
- idp2->data, idp2->len);
+ idp2->data, idp2->len,
+ key, key_len);
+ silc_free(key);
silc_buffer_free(idp1);
silc_buffer_free(idp2);
}
SilcChannelEntry channel,
SilcUInt32 mode_mask,
void *id, SilcIdType id_type,
- SilcClientID *target);
+ SilcClientID *target,
+ SilcPublicKey founder_key);
void silc_server_send_notify_signoff(SilcServer server,
SilcSocketConnection sock,
bool broadcast,
silc_schedule_task_del_by_context(server->schedule, channel->rekey);
silc_server_channel_delete(server, channel);
- silc_buffer_free(clidp);
continue;
}
SilcBuffer chidp, clidp;
SilcBuffer tmp;
int len;
- unsigned char mode[4];
+ unsigned char mode[4], *fkey = NULL;
+ SilcUInt32 fkey_len = 0;
SILC_LOG_DEBUG(("Start"));
/* CUMODE notify for mode change on the channel */
SILC_PUT32_MSB(chl->mode, mode);
+ if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && channel->founder_key)
+ fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_CUMODE_CHANGE,
- 3, clidp->data, clidp->len,
+ 4, clidp->data, clidp->len,
mode, 4,
- clidp->data, clidp->len);
+ clidp->data, clidp->len,
+ fkey, fkey_len);
len = tmp->len;
*channel_users_modes =
silc_buffer_realloc(*channel_users_modes,
silc_buffer_put(*channel_users_modes, tmp->data, tmp->len);
silc_buffer_pull(*channel_users_modes, len);
silc_buffer_free(tmp);
-
+ silc_free(fkey);
silc_buffer_free(clidp);
}
silc_hash_table_list_reset(&htl);
{
SilcBuffer killed, killer;
+ SILC_LOG_DEBUG(("Killing client %s",
+ silc_id_render(remote_client->id, SILC_ID_CLIENT)));
+
/* Send the KILL notify packets. First send it to the channel, then
to our primary router and then directly to the client who is being
killed right now. */
SilcBuffer idp1, idp2;
unsigned char cumode[4];
+ SILC_LOG_DEBUG(("Start"));
+
silc_server_send_notify_cumode(server, sock, FALSE, channel, forced_mode,
server->id, SILC_ID_SERVER,
- chl->client->id);
+ chl->client->id, NULL);
idp1 = silc_id_payload_encode(server->id, SILC_ID_SERVER);
idp2 = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
idp2->data, idp2->len);
silc_buffer_free(idp1);
silc_buffer_free(idp2);
+
+ return TRUE;
}
privileges the same way as the client had given the
SILC_COMMAND_CUMODE command to gain founder privileges. The
client is still able to join the channel even if the founder
- privileges could not be gained.
+ privileges could not be gained. The hash function used with
+ the <founder payload> MUST be sha1.
The server MUST check whether the user is allowed to join to
the requested channel. Various modes set to the channel affect
used to verify the payload is the public key of the
client sending this command. The mode may be set only
if the <auth payload> was verified successfully. The
- server also MUST save the founder's public key.
+ server also MUST save the founder's public key. The
+ hash function used with the <auth payload> MUST be sha1.
The public key of the founder is sent in the
SILC_NOTIFY_TYPE_CMODE_CHANGE notify type so that other
sent only to the clients which is joined on the channel where
the target client is on.
- Max Arguments: 3
- Arguments: (1) <ID Payload> (2) <mode mask>
- (3) <Target Client ID>
+ Max Arguments: 4
+ Arguments: (1) <ID Payload> (2) <mode mask>
+ (3) <Target Client ID> (3) [<founder pubkey>]
The <ID Payload> is the ID (usually Client ID but it can be
Server ID as well when the router is enforcing user's mode
change) of the entity which changed the mode. The <mode mask>
is the new mode mask of the channel. The <Target Client ID>
- is the client which mode was changed.
+ is the client which mode was changed. The <founder pubkey>
+ is the public key of the channel founder and is sent only
+ when first setting the channel founder mode using the
+ SILC_COMMAND_CUMODE command, and when sending this notify.
9 SILC_NOTIFY_TYPE_MOTD
Authentication Data = sign(HASH);
The hash() and the sign() are the hash function and the public key
-cryptography function selected in the SKE protocol. The public key
+cryptography function selected in the SKE protocol, unless otherwise
+stated in the context where this payload is used. The public key
is SILC style public key unless certificates are used. The ID is the
entity's ID (Client or Server ID) which is authenticating itself. The
ID encoding is described in [SILC2]. The random bytes are non-zero
} else if (!strcasecmp(cmd->argv[i], "-hmac") && cmd->argc > i + 1) {
hmac = cmd->argv[i + 1];
i++;
- } else if (!strcasecmp(cmd->argv[i], "-founder") && cmd->argc > i + 1) {
- if (!strcasecmp(cmd->argv[i + 1], "-pubkey")) {
- auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
- cmd->client->private_key,
- cmd->client->rng, conn->hash,
- conn->local_id,
- SILC_ID_CLIENT);
- } else {
- auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0,
- cmd->argv[i + 1],
- cmd->argv_lens[i + 1]);
- }
+ } 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->internal->
+ sha1hash,
+ conn->local_id,
+ SILC_ID_CLIENT);
i++;
} else {
/* Passphrases must be UTF-8 encoded, so encode if it is not */
auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
cmd->client->private_key,
cmd->client->rng,
- conn->hash,
+ cmd->client->internal->
+ sha1hash,
conn->local_id,
SILC_ID_CLIENT);
arg = auth->data;
break;
case 'f':
if (add) {
- if (cmd->argc == 5) {
- if (!strcasecmp(cmd->argv[4], "-pubkey")) {
- auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
- cmd->client->private_key,
- cmd->client->rng,
- conn->hash,
- conn->local_id,
- SILC_ID_CLIENT);
- } else {
- auth = silc_auth_payload_encode(SILC_AUTH_PASSWORD, NULL, 0,
- cmd->argv[4], cmd->argv_lens[4]);
- }
- }
+ auth = silc_auth_public_key_auth_generate(cmd->client->public_key,
+ cmd->client->private_key,
+ cmd->client->rng,
+ cmd->client->internal->
+ sha1hash,
+ conn->local_id,
+ SILC_ID_CLIENT);
mode |= SILC_CHANNEL_UMODE_CHANFO;
} else {
mode &= ~SILC_CHANNEL_UMODE_CHANFO;