SilcNotifyPayload payload;
SilcNotifyType type;
SilcArgumentPayload args;
- SilcChannelID *channel_id;
+ SilcChannelID *channel_id, *channel_id2;
SilcClientID *client_id, *client_id2;
SilcChannelEntry channel;
SilcClientEntry client;
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, &idata);
+ packet->dst_id_len, NULL, &idata);
if (dst_sock)
/* Relay the packet */
silc_server_relay_packet(server, dst_sock, idata->send_key,
goto out;
client =
- silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
+ silc_idlist_add_client(server->global_list, NULL, 0, NULL, NULL,
silc_id_dup(client_id, SILC_ID_CLIENT),
sock->user_data, NULL);
if (!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_INVITE:
- SILC_LOG_DEBUG(("INVITE notify (not-impl XXX)"));
+
+ if (packet->dst_id_type == SILC_ID_CLIENT)
+ goto out;
+
+ SILC_LOG_DEBUG(("INVITE notify"));
+
+ /* Get 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 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;
+ }
+ }
+ silc_free(channel_id);
+
+ /* Get the added invite */
+ tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+ if (tmp) {
+ if (!channel->invite_list)
+ channel->invite_list = silc_calloc(tmp_len + 2,
+ sizeof(*channel->invite_list));
+ else
+ channel->invite_list = silc_realloc(channel->invite_list,
+ sizeof(*channel->invite_list) *
+ (tmp_len +
+ strlen(channel->invite_list) +
+ 2));
+ if (tmp[tmp_len - 1] == ',')
+ tmp[tmp_len - 1] = '\0';
+
+ strncat(channel->invite_list, tmp, tmp_len);
+ strncat(channel->invite_list, ",", 1);
+ }
+
+ /* Get the deleted invite */
+ tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
+ if (tmp && channel->invite_list) {
+ char *start, *end, *n;
+
+ if (!strncmp(channel->invite_list, tmp,
+ strlen(channel->invite_list) - 1)) {
+ silc_free(channel->invite_list);
+ channel->invite_list = NULL;
+ } else {
+ start = strstr(channel->invite_list, tmp);
+ if (start && strlen(start) >= tmp_len) {
+ end = start + tmp_len;
+ n = silc_calloc(strlen(channel->invite_list) - tmp_len, sizeof(*n));
+ strncat(n, channel->invite_list, start - channel->invite_list);
+ strncat(n, end + 1, ((channel->invite_list +
+ strlen(channel->invite_list)) - end) - 1);
+ silc_free(channel->invite_list);
+ channel->invite_list = n;
+ }
+ }
+ }
+
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:
break;
+ case SILC_NOTIFY_TYPE_BAN:
+ /*
+ * Save the ban
+ */
+
+ SILC_LOG_DEBUG(("BAN notify"));
+
+ /* Get 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 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;
+ }
+ }
+ silc_free(channel_id);
+
+ /* Get the new ban and add it to the ban list */
+ tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
+ if (tmp) {
+ if (!channel->ban_list)
+ channel->ban_list = silc_calloc(tmp_len + 2,
+ sizeof(*channel->ban_list));
+ else
+ channel->ban_list = silc_realloc(channel->ban_list,
+ sizeof(*channel->ban_list) *
+ (tmp_len +
+ strlen(channel->ban_list) + 2));
+ strncat(channel->ban_list, tmp, tmp_len);
+ strncat(channel->ban_list, ",", 1);
+ }
+
+ /* Get the ban to be removed and remove it from the list */
+ tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+ if (tmp && channel->ban_list) {
+ char *start, *end, *n;
+
+ if (!strcmp(channel->ban_list, tmp)) {
+ silc_free(channel->ban_list);
+ channel->ban_list = NULL;
+ } else {
+ start = strstr(channel->ban_list, tmp);
+ if (start && strlen(start) >= tmp_len) {
+ end = start + tmp_len;
+ n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
+ strncat(n, channel->ban_list, start - channel->ban_list);
+ strncat(n, end + 1, ((channel->ban_list +
+ strlen(channel->ban_list)) - end) - 1);
+ silc_free(channel->ban_list);
+ channel->ban_list = n;
+ }
+ }
+ }
+
+ break;
+
/* Ignore rest of the notify types for now */
case SILC_NOTIFY_TYPE_NONE:
case SILC_NOTIFY_TYPE_MOTD:
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, &idata);
+ packet->dst_id_len, NULL, &idata);
if (!dst_sock)
return;
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, &idata);
+ packet->dst_id_len, NULL, &idata);
if (!dst_sock)
return;
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);
}
sizeof(unsigned char));
memcpy(hash, ((SilcClientID *)id)->hash,
sizeof(((SilcClientID *)id)->hash));
- entry = silc_idlist_add_client(id_list, hash, NULL, NULL, id,
- router, NULL);
+ entry = silc_idlist_add_client(id_list, hash,
+ sizeof(((SilcClientID *)id)->hash),
+ NULL, NULL, id, router, NULL);
entry->nickname = NULL;
entry->data.registered = TRUE;
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:
/* Get the route to the client */
dst_sock = silc_server_get_client_route(server, packet->dst_id,
- packet->dst_id_len, &idata);
+ packet->dst_id_len, NULL, &idata);
if (!dst_sock)
return;
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);
+}