SilcNotifyPayload payload;
SilcNotifyType type;
SilcArgumentPayload args;
- SilcChannelID *channel_id;
+ SilcChannelID *channel_id, *channel_id2;
SilcClientID *client_id, *client_id2;
SilcChannelEntry channel;
SilcClientEntry client;
/* Change mode */
channel->mode = mode;
silc_free(channel_id);
+
+ /* Get the hmac */
+ tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
+ if (tmp) {
+ unsigned char hash[32];
+
+ if (channel->hmac)
+ silc_hmac_free(channel->hmac);
+ if (!silc_hmac_alloc(tmp, NULL, &channel->hmac))
+ goto out;
+
+ /* Set the HMAC key out of current channel key. The client must do
+ this locally. */
+ silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8,
+ hash);
+ silc_hmac_set_key(channel->hmac, hash,
+ silc_hash_len(channel->hmac->hash));
+ memset(hash, 0, sizeof(hash));
+ }
+
break;
case SILC_NOTIFY_TYPE_CUMODE_CHANGE:
break;
case SILC_NOTIFY_TYPE_CHANNEL_CHANGE:
- SILC_LOG_DEBUG(("CHANNEL CHANGE notify (not-impl XXX)"));
+ /*
+ * Distribute to the local clients on the channel and change the
+ * channel ID.
+ */
+
+ SILC_LOG_DEBUG(("CHANNEL CHANGE"));
+
+ /* Get the old Channel ID */
+ tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+ if (!tmp)
+ goto out;
+ channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id)
+ goto out;
+
+ /* Get the channel entry */
+ channel = silc_idlist_find_channel_by_id(server->global_list,
+ channel_id, NULL);
+ if (!channel) {
+ channel = silc_idlist_find_channel_by_id(server->local_list,
+ channel_id, NULL);
+ if (!channel) {
+ silc_free(channel_id);
+ goto out;
+ }
+ }
+
+ /* Send the notify to the channel */
+ silc_server_packet_send_to_channel(server, sock, channel, packet->type,
+ FALSE, packet->buffer->data,
+ packet->buffer->len, FALSE);
+
+ /* Get the new Channel ID */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (!tmp)
+ goto out;
+ channel_id2 = silc_id_payload_parse_id(tmp, tmp_len);
+ if (!channel_id2)
+ goto out;
+
+ /* Replace the Channel ID */
+ if (!silc_idlist_replace_channel_id(server->global_list, channel_id,
+ channel_id2))
+ silc_idlist_replace_channel_id(server->local_list, channel_id,
+ channel_id2);
+
+ silc_free(channel_id);
+ silc_free(channel_id2);
+
break;
case SILC_NOTIFY_TYPE_SERVER_SIGNOFF:
sock->type == SILC_SOCKET_TYPE_ROUTER &&
!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
SilcBuffer chp;
- unsigned int iv_len, i, data_len;
+ unsigned int iv_len, i;
+ unsigned short data_len, flags;
iv_len = silc_cipher_get_block_len(channel->channel_key);
if (channel->iv[0] == '\0')
silc_hash_make(server->md5hash, channel->iv, iv_len, channel->iv);
/* Encode new payload. This encrypts it also. */
- SILC_GET16_MSB(data_len, packet->buffer->data);
- chp = silc_channel_message_payload_encode(data_len,
- packet->buffer->data + 2,
+ SILC_GET16_MSB(flags, packet->buffer->data);
+ SILC_GET16_MSB(data_len, packet->buffer->data + 2);
+ chp = silc_channel_message_payload_encode(flags, data_len,
+ packet->buffer->data + 4,
iv_len, channel->iv,
channel->channel_key,
- channel->hmac, server->rng);
+ channel->hmac);
silc_buffer_put(packet->buffer, chp->data, chp->len);
silc_buffer_free(chp);
}
if (sock->type == SILC_SOCKET_TYPE_SERVER)
server->stat.cell_clients++;
server->stat.clients++;
-
-#if 0
- /* XXX Adding two ID's with same IP number replaces the old entry thus
- gives wrong route. Thus, now disabled until figured out a better way
- to do this or when removed the whole thing. This could be removed
- because entry->router->connection gives always the most optimal route
- for the ID anyway (unless new routes (faster perhaps) are established
- after receiving this ID, this we don't know however). */
- /* Add route cache for this ID */
- silc_server_route_add(silc_server_route_hash(
- ((SilcClientID *)id)->ip.s_addr,
- server->id->port), ((SilcClientID *)id)->ip.s_addr,
- router);
-#endif
}
break;
if (sock->type == SILC_SOCKET_TYPE_SERVER)
server->stat.cell_servers++;
server->stat.servers++;
-
-#if 0
- /* Add route cache for this ID */
- silc_server_route_add(silc_server_route_hash(
- ((SilcServerID *)id)->ip.s_addr,
- ((SilcServerID *)id)->port),
- ((SilcServerID *)id)->ip.s_addr,
- router);
-#endif
break;
case SILC_ID_CHANNEL:
silc_server_relay_packet(server, dst_sock, idata->send_key,
idata->hmac, packet, FALSE);
}
+
+/* Received connection auth request packet that is used during connection
+ phase to resolve the mandatory authentication method. This packet can
+ actually be received at anytime but usually it is used only during
+ the connection authentication phase. Now, protocol says that this packet
+ can come from client or server, however, we support only this coming
+ from client and expect that server's always knows what authentication
+ method to use. */
+
+void silc_server_connection_auth_request(SilcServer server,
+ SilcSocketConnection sock,
+ SilcPacketContext *packet)
+{
+ SilcServerConfigSectionClientConnection *client = NULL;
+ unsigned short conn_type;
+ int ret;
+ SilcAuthMethod auth_meth;
+
+ SILC_LOG_DEBUG(("Start"));
+
+ if (packet->src_id_type && packet->src_id_type != SILC_ID_CLIENT)
+ return;
+
+ /* Parse the payload */
+ ret = silc_buffer_unformat(packet->buffer,
+ SILC_STR_UI_SHORT(&conn_type),
+ SILC_STR_UI_SHORT(NULL),
+ SILC_STR_END);
+ if (ret == -1)
+ return;
+
+ if (conn_type != SILC_SOCKET_TYPE_CLIENT)
+ return;
+
+ /* Get the authentication method for the client */
+ auth_meth = SILC_AUTH_NONE;
+ client = silc_server_config_find_client_conn(server->config,
+ sock->ip,
+ sock->port);
+ if (!client)
+ client = silc_server_config_find_client_conn(server->config,
+ sock->hostname,
+ sock->port);
+ if (client)
+ auth_meth = client->auth_meth;
+
+ /* Send it back to the client */
+ silc_server_send_connection_auth_request(server, sock,
+ conn_type,
+ auth_meth);
+}