X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fpacket_receive.c;h=73424a68988fe7b2016030d9c8de39bb8f33b7a9;hb=805fddcf6431e784f9f77114782a90c9d12f9cbe;hp=313004f8330efaa3b62ddddeed7e66ac77c24d9e;hpb=f9f6dfe319b9ee24fd24963003a230fa0ab11d47;p=silc.git diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index 313004f8..73424a68 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -46,8 +46,17 @@ static void silc_server_notify_process(SilcServer server, SilcUInt32 tmp_len, tmp2_len; SilcBool local, ret; - if (idata->conn_type == SILC_CONN_CLIENT || - packet->src_id_type != SILC_ID_SERVER || !packet->dst_id) { + if (idata->conn_type == SILC_CONN_CLIENT) { + SILC_LOG_DEBUG(("Notify received from client, drop it")); + return; + } + + if (packet->src_id_type != SILC_ID_SERVER){ + SILC_LOG_DEBUG(("Bad notify packet received")); + return; + } + + if (!packet->dst_id) { SILC_LOG_DEBUG(("Bad notify packet received")); return; } @@ -69,8 +78,10 @@ static void silc_server_notify_process(SilcServer server, /* Parse the Notify Payload */ payload = silc_notify_payload_parse(buffer->data, silc_buffer_len(buffer)); - if (!payload) + if (!payload) { + SILC_LOG_DEBUG(("Marlformed notify payload")); return; + } /* If we are router and this packet is not already broadcast packet we will broadcast it. The sending socket really cannot be router or @@ -84,8 +95,10 @@ static void silc_server_notify_process(SilcServer server, /* Packet is destined to channel */ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, packet->dst_id_type, &channel_id, - sizeof(channel_id))) + sizeof(channel_id))) { + SILC_LOG_DEBUG(("Malformed destination ID in notify packet")); goto out; + } silc_server_packet_send_dest(server, SILC_PRIMARY_ROUTE(server), packet->type, packet->flags | @@ -112,8 +125,10 @@ static void silc_server_notify_process(SilcServer server, type = silc_notify_get_type(payload); args = silc_notify_get_args(payload); - if (!args) + if (!args) { + SILC_LOG_DEBUG(("Notify doesn't have any arguments, drop it")); goto out; + } switch(type) { case SILC_NOTIFY_TYPE_JOIN: @@ -133,7 +148,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, SILC_ID_GET_ID(id), NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL))); goto out; } } @@ -251,7 +267,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, &channel_id, NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(&channel_id, SILC_ID_CHANNEL))); goto out; } } @@ -316,10 +333,12 @@ static void silc_server_notify_process(SilcServer server, SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); silc_schedule_task_del_by_context(server->schedule, client); - /* Remove from public key hash table. */ - if (client->data.public_key) - silc_hash_table_del_by_context(server->pk_hash, client->data.public_key, - client); + /* Remove client's public key from repository, this will free it too. */ + if (client->data.public_key) { + silc_skr_del_public_key(server->repository, client->data.public_key, + client); + client->data.public_key = NULL; + } /* Remove the client from all channels. */ silc_server_remove_from_channels(server, NULL, client, TRUE, @@ -337,6 +356,9 @@ static void silc_server_notify_process(SilcServer server, client->mode = 0; client->router = NULL; client->connection = NULL; + client->data.created = silc_time(); + silc_dlist_del(server->expired_clients, client); + silc_dlist_add(server->expired_clients, client); break; case SILC_NOTIFY_TYPE_TOPIC_SET: @@ -380,7 +402,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, &channel_id, NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(&channel_id, SILC_ID_CHANNEL))); goto out; } } @@ -500,7 +523,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, &channel_id, NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(&channel_id, SILC_ID_CHANNEL))); goto out; } } @@ -820,7 +844,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, &channel_id, NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(&channel_id, SILC_ID_CHANNEL))); goto out; } } @@ -1007,7 +1032,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, SILC_ID_GET_ID(id), NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL))); goto out; } } @@ -1076,7 +1102,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->global_list, SILC_ID_GET_ID(id), NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL))); goto out; } } @@ -1205,12 +1232,12 @@ static void silc_server_notify_process(SilcServer server, /* Get client entry */ client = silc_idlist_find_client_by_id(server->global_list, - SILC_ID_GET_ID(id), + SILC_ID_GET_ID(id2), TRUE, &cache); local = FALSE; if (!client) { client = silc_idlist_find_client_by_id(server->local_list, - SILC_ID_GET_ID(id), + SILC_ID_GET_ID(id2), TRUE, &cache); local = TRUE; if (!client) @@ -1237,13 +1264,8 @@ static void silc_server_notify_process(SilcServer server, if (local) silc_server_del_from_watcher_list(server, client); - /* Remove from public key hash table. */ - if (client->data.public_key) - silc_hash_table_del_by_context(server->pk_hash, - client->data.public_key, - client); - /* Remove the client */ + silc_dlist_del(server->expired_clients, client); silc_idlist_del_data(client); silc_idlist_del_client(local ? server->local_list : server->global_list, client); @@ -1307,7 +1329,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, &channel_id, NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL))); goto out; } } @@ -1459,11 +1482,12 @@ static void silc_server_notify_process(SilcServer server, silc_server_check_watcher_list(server, client, NULL, SILC_NOTIFY_TYPE_KILLED); - /* Remove from public key hash table. */ - if (client->data.public_key) - silc_hash_table_del_by_context(server->pk_hash, - client->data.public_key, - client); + /* Remove client's public key from repository, this will free it too. */ + if (client->data.public_key) { + silc_skr_del_public_key(server->repository, client->data.public_key, + client); + client->data.public_key = NULL; + } /* Update statistics */ server->stat.clients--; @@ -1483,6 +1507,9 @@ static void silc_server_notify_process(SilcServer server, client->mode = 0; client->router = NULL; client->connection = NULL; + client->data.created = silc_time(); + silc_dlist_del(server->expired_clients, client); + silc_dlist_add(server->expired_clients, client); break; } @@ -1565,7 +1592,8 @@ static void silc_server_notify_process(SilcServer server, channel = silc_idlist_find_channel_by_id(server->local_list, SILC_ID_GET_ID(id), NULL); if (!channel) { - SILC_LOG_DEBUG(("Notify for unknown channel")); + SILC_LOG_DEBUG(("Notify for unknown channel %s", + silc_id_render(SILC_ID_GET_ID(id), SILC_ID_CHANNEL))); goto out; } } @@ -1639,13 +1667,9 @@ static void silc_server_notify_process(SilcServer server, if (!client) goto out; - if (client->data.public_key) - silc_hash_table_del_by_context(server->pk_hash, - client->data.public_key, - client); - silc_server_remove_from_channels(server, NULL, client, TRUE, NULL, TRUE, FALSE); + silc_dlist_del(server->expired_clients, client); silc_idlist_del_data(client); silc_idlist_del_client(server->global_list, client); } @@ -1658,6 +1682,7 @@ static void silc_server_notify_process(SilcServer server, break; default: + SILC_LOG_DEBUG(("Unsupported notify %d", type)); break; } @@ -1670,6 +1695,7 @@ void silc_server_notify(SilcServer server, SilcPacket packet) { silc_server_notify_process(server, sock, packet, &packet->buffer); + silc_packet_free(packet); } void silc_server_notify_list(SilcServer server, @@ -1710,6 +1736,7 @@ void silc_server_notify_list(SilcServer server, silc_buffer_pull(&packet->buffer, len); } + silc_packet_free(packet); silc_buffer_free(buffer); } @@ -1732,7 +1759,7 @@ void silc_server_private_message(SilcServer server, if (packet->src_id_type != SILC_ID_CLIENT || packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) - return; + goto out; /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, @@ -1744,7 +1771,7 @@ void silc_server_private_message(SilcServer server, if (client && client->mode & SILC_UMODE_DETACHED) { SILC_LOG_DEBUG(("Client is detached, discarding packet")); - return; + goto out; } /* Send SILC_NOTIFY_TYPE_ERROR to indicate that such destination ID @@ -1753,7 +1780,7 @@ void silc_server_private_message(SilcServer server, packet->dst_id_len, packet->dst_id_type); if (!idp) - return; + goto out; error = SILC_STATUS_ERR_NO_SUCH_CLIENT_ID; if (packet->src_id_type == SILC_ID_CLIENT) { @@ -1772,18 +1799,21 @@ void silc_server_private_message(SilcServer server, } silc_buffer_free(idp); - return; + goto out; } /* Check whether destination client wishes to receive private messages */ if (client && !(packet->flags & SILC_PACKET_FLAG_PRIVMSG_KEY) && client->mode & SILC_UMODE_BLOCK_PRIVMSG) { SILC_LOG_DEBUG(("Client blocks private messages, discarding packet")); - return; + goto out; } /* Send the private message */ silc_server_packet_route(server, dst_sock, packet); + + out: + silc_packet_free(packet); } /* Received private message key packet.. This packet is never for us. It is to @@ -1801,21 +1831,24 @@ void silc_server_private_message_key(SilcServer server, SILC_LOG_DEBUG(("Start")); if (packet->src_id_type != SILC_ID_CLIENT || - packet->dst_id_type != SILC_ID_CLIENT) - return; - - if (!packet->dst_id) + packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) { + silc_packet_free(packet); return; + } /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, packet->dst_id_len, NULL, &idata, NULL); - if (!dst_sock) + if (!dst_sock) { + silc_packet_free(packet); return; + } /* Relay the packet */ silc_server_packet_route(server, dst_sock, packet); + + silc_packet_free(packet); } /* Processes incoming command reply packet. The command reply packet may @@ -1832,18 +1865,23 @@ void silc_server_command_reply(SilcServer server, SILC_LOG_DEBUG(("Start")); - if (packet->dst_id_type == SILC_ID_CHANNEL) + if (packet->dst_id_type == SILC_ID_CHANNEL) { + silc_packet_free(packet); return; + } if (packet->dst_id_type == SILC_ID_CLIENT) { /* Destination must be one of ours */ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CLIENT, - &id, sizeof(id))) + &id, sizeof(id))) { + silc_packet_free(packet); return; + } client = silc_idlist_find_client_by_id(server->local_list, &id, TRUE, NULL); if (!client) { SILC_LOG_ERROR(("Cannot process command reply to unknown client")); + silc_packet_free(packet); return; } } @@ -1852,6 +1890,7 @@ void silc_server_command_reply(SilcServer server, /* For now this must be for us */ if (memcmp(packet->dst_id, server->id_string, server->id_string_len)) { SILC_LOG_ERROR(("Cannot process command reply to unknown server")); + silc_packet_free(packet); return; } } @@ -1862,6 +1901,8 @@ void silc_server_command_reply(SilcServer server, /* Relay the packet to the client */ if (packet->dst_id_type == SILC_ID_CLIENT && client) silc_server_packet_route(server, client->connection, packet); + + silc_packet_free(packet); } /* Process received channel message. The message can be originated from @@ -1875,7 +1916,6 @@ void silc_server_channel_message(SilcServer server, SilcChannelID id; SilcClientID cid; SilcID sid; - void *sender_id = NULL; SilcClientEntry sender_entry = NULL; SilcIDListData idata; SilcChannelClientEntry chl; @@ -1886,13 +1926,13 @@ void silc_server_channel_message(SilcServer server, /* Sanity checks */ if (packet->dst_id_type != SILC_ID_CHANNEL) { SILC_LOG_DEBUG(("Received bad message for channel, dropped")); - return; + goto out; } /* Find channel entry */ if (!silc_id_str2id(packet->dst_id, packet->dst_id_len, SILC_ID_CHANNEL, &id, sizeof(id))) - return; + goto out; channel = silc_idlist_find_channel_by_id(server->local_list, &id, NULL); if (!channel) { channel = silc_idlist_find_channel_by_id(server->global_list, &id, NULL); @@ -1906,7 +1946,7 @@ void silc_server_channel_message(SilcServer server, packet->dst_id_len, packet->dst_id_type); if (!idp) - return; + goto out; error = SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID; if (packet->src_id_type == SILC_ID_CLIENT) { @@ -1924,7 +1964,7 @@ void silc_server_channel_message(SilcServer server, } silc_buffer_free(idp); - return; + goto out; } } @@ -1932,7 +1972,7 @@ void silc_server_channel_message(SilcServer server, not client (as it can be server as well) we don't do the check. */ if (!silc_id_str2id2(packet->src_id, packet->src_id_len, packet->src_id_type, &sid)) - return; + goto out; if (sid.type == SILC_ID_CLIENT) { sender_entry = silc_idlist_find_client_by_id(server->local_list, SILC_ID_GET_ID(sid), @@ -1946,7 +1986,7 @@ void silc_server_channel_message(SilcServer server, if (!sender_entry || !silc_server_client_on_channel(sender_entry, channel, &chl)) { SILC_LOG_DEBUG(("Client not on channel")); - return; + goto out; } /* If channel is moderated check that client is allowed to send @@ -1955,17 +1995,17 @@ void silc_server_channel_message(SilcServer server, !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) && !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) { SILC_LOG_DEBUG(("Channel is silenced from normal users")); - return; + goto out; } if (channel->mode & SILC_CHANNEL_MODE_SILENCE_OPERS && chl->mode & SILC_CHANNEL_UMODE_CHANOP && !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) { SILC_LOG_DEBUG(("Channel is silenced from operators")); - return; + goto out; } if (chl->mode & SILC_CHANNEL_UMODE_QUIET) { SILC_LOG_DEBUG(("Sender is quieted on the channel")); - return; + goto out; } /* If the packet is coming from router, but the client entry is local @@ -1976,16 +2016,19 @@ void silc_server_channel_message(SilcServer server, if (server->server_type == SILC_ROUTER && idata->conn_type == SILC_CONN_ROUTER && local) { SILC_LOG_DEBUG(("Channel message rerouted to the sender, drop it")); - return; + goto out; } } /* Distribute the packet to our local clients. This will send the packet for further routing as well, if needed. */ - silc_server_packet_relay_to_channel(server, sock, channel, sender_id, - packet->src_id_type, sender_entry, - packet->buffer.data, + silc_server_packet_relay_to_channel(server, sock, channel, + SILC_ID_GET_ID(sid), sid.type, + sender_entry, packet->buffer.data, silc_buffer_len(&packet->buffer)); + + out: + silc_packet_free(packet); } /* Received channel key packet. We distribute the key to all of our locally @@ -2001,13 +2044,16 @@ void silc_server_channel_key(SilcServer server, if (packet->src_id_type != SILC_ID_SERVER || (server->server_type == SILC_ROUTER && !server->backup_router && - idata->conn_type == SILC_CONN_ROUTER)) + idata->conn_type == SILC_CONN_ROUTER)) { + silc_packet_free(packet); return; + } /* Save the channel key */ channel = silc_server_save_channel_key(server, buffer, NULL); if (!channel) { SILC_LOG_ERROR(("Bad channel key from %s", idata->sconn->remote_host)); + silc_packet_free(packet); return; } @@ -2015,13 +2061,14 @@ void silc_server_channel_key(SilcServer server, we will also send it to locally connected servers. */ silc_server_send_channel_key(server, sock, channel, FALSE); - if (server->server_type != SILC_BACKUP_ROUTER) { + if (server->server_type != SILC_BACKUP_ROUTER) /* Distribute to local cell backup routers. */ silc_server_backup_send(server, (SilcServerEntry)idata, SILC_PACKET_CHANNEL_KEY, 0, buffer->data, silc_buffer_len(buffer), FALSE, TRUE); - } + + silc_packet_free(packet); } /* Received New Client packet and processes it. Creates Client ID for the @@ -2036,42 +2083,35 @@ SilcClientEntry silc_server_new_client(SilcServer server, SilcClientEntry client; SilcClientID *client_id; char *username = NULL, *realname = NULL; - SilcUInt16 username_len; + SilcUInt16 username_len, nickname_len; SilcUInt32 id_len, tmp_len; int ret; - char *host, *nickname, *nicknamec; + char *host, *nickname = NULL, *nicknamec; const char *hostname, *ip; SILC_LOG_DEBUG(("Creating new client")); - if (idata->conn_type != SILC_CONN_CLIENT) + if (idata->conn_type != SILC_CONN_CLIENT) { + silc_packet_free(packet); return NULL; + } /* Take client entry */ client = (SilcClientEntry)idata; - silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL); + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, &hostname, &ip, NULL); - /* Remove the old cache entry. */ - if (!silc_idcache_del_by_context(server->local_list->clients, client, - NULL)) { - SILC_LOG_INFO(("Unauthenticated client attempted to register to network")); - silc_server_disconnect_remote(server, sock, - SILC_STATUS_ERR_NOT_AUTHENTICATED, NULL); - silc_server_free_sock_user_data(server, sock, NULL); - return NULL; - } + SILC_LOG_DEBUG(("%s %s", ip, hostname)); /* Make sure this client hasn't registered already */ if (idata->status & SILC_IDLIST_STATUS_REGISTERED) { - silc_server_disconnect_remote(server, sock, - SILC_STATUS_ERR_OPERATION_ALLOWED, - "Too many registrations"); - silc_server_free_sock_user_data(server, sock, NULL); + silc_packet_free(packet); return NULL; } /* Parse incoming packet */ ret = silc_buffer_unformat(buffer, + SILC_STR_ADVANCE, SILC_STR_UI16_NSTRING_ALLOC(&username, &username_len), SILC_STR_UI16_STRING_ALLOC(&realname), @@ -2085,6 +2125,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, SILC_STATUS_ERR_INCOMPLETE_INFORMATION, NULL); silc_server_free_sock_user_data(server, sock, NULL); + silc_packet_free(packet); return NULL; } @@ -2097,32 +2138,49 @@ SilcClientEntry silc_server_new_client(SilcServer server, SILC_STATUS_ERR_INCOMPLETE_INFORMATION, NULL); silc_server_free_sock_user_data(server, sock, NULL); + silc_packet_free(packet); return NULL; } if (username_len > 128) { - username[128] = '\0'; username_len = 128; + username[username_len - 1] = '\0'; + } + + /* Take nickname from NEW_CLIENT packet, if present */ + if (silc_buffer_unformat(buffer, + SILC_STR_UI16_NSTRING_ALLOC(&nickname, + &nickname_len), + SILC_STR_END) >= 0) { + if (nickname_len > 128) { + nickname_len = 128; + nickname[nickname_len - 1] = '\0'; + } + } + + /* Nickname is initially same as username, if not present in NEW_CLIENT */ + if (!nickname) { + nickname = strdup(username); + nickname_len = strlen(nickname); } /* Check for valid username string */ - nicknamec = silc_identifier_check(username, username_len, + nicknamec = silc_identifier_check(nickname, nickname_len, SILC_STRING_UTF8, 128, &tmp_len); if (!nicknamec) { silc_free(username); silc_free(realname); + silc_free(nickname); SILC_LOG_ERROR(("Client %s (%s) sent bad username string '%s', closing " "connection", hostname, ip, username)); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_INCOMPLETE_INFORMATION, NULL); silc_server_free_sock_user_data(server, sock, NULL); + silc_packet_free(packet); return NULL; } - /* Nickname is initially same as username */ - nickname = strdup(username); - /* Make sanity checks for the hostname of the client. If the hostname is provided in the `username' check that it is the same than the resolved hostname, or if not resolved the hostname that appears in @@ -2136,6 +2194,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, host = silc_memdup(username + tlen + 1, strlen(username) - tlen - 1); if (strcmp(hostname, ip) && strcmp(hostname, host)) { + silc_free(nickname); silc_free(username); silc_free(host); silc_free(realname); @@ -2145,6 +2204,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, SILC_STATUS_ERR_INCOMPLETE_INFORMATION, NULL); silc_server_free_sock_user_data(server, sock, NULL); + silc_packet_free(packet); return NULL; } @@ -2152,6 +2212,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, client->data.public_key); phostname = strdup(silc_pubkey->identifier.host); if (!strcmp(hostname, ip) && phostname && strcmp(phostname, host)) { + silc_free(nickname); silc_free(username); silc_free(host); silc_free(phostname); @@ -2162,6 +2223,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, SILC_STATUS_ERR_INCOMPLETE_INFORMATION, NULL); silc_server_free_sock_user_data(server, sock, NULL); + silc_packet_free(packet); return NULL; } @@ -2178,6 +2240,8 @@ SilcClientEntry silc_server_new_client(SilcServer server, username = newusername; } + SILC_LOG_DEBUG(("%s %s", ip, hostname)); + /* Create Client ID */ if (!silc_id_create_client_id(server, server->id, server->rng, server->md5hash, nicknamec, @@ -2185,6 +2249,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_BAD_NICKNAME, NULL); silc_server_free_sock_user_data(server, sock, NULL); + silc_packet_free(packet); return NULL; } @@ -2214,10 +2279,8 @@ SilcClientEntry silc_server_new_client(SilcServer server, client->userinfo = realname ? realname : strdup(username); client->id = client_id; id_len = silc_id_get_len(client_id, SILC_ID_CLIENT); - - /* Add the client again to the ID cache */ - silc_idcache_add(server->local_list->clients, nicknamec, - client_id, client); + silc_idcache_update_by_context(server->local_list->clients, client, + client_id, nicknamec, TRUE); /* Notify our router about new client on the SILC network */ silc_server_send_new_id(server, SILC_PRIMARY_ROUTE(server), @@ -2243,6 +2306,7 @@ SilcClientEntry silc_server_new_client(SilcServer server, if (server->server_type == SILC_ROUTER) silc_server_check_watcher_list(server, client, NULL, 0); + silc_packet_free(packet); return client; } @@ -2271,12 +2335,15 @@ SilcServerEntry silc_server_new_server(SilcServer server, SILC_LOG_DEBUG(("Creating new server")); if (idata->conn_type != SILC_CONN_SERVER && - idata->conn_type != SILC_CONN_ROUTER) + idata->conn_type != SILC_CONN_ROUTER) { + silc_packet_free(packet); return NULL; + } /* Take server entry */ new_server = (SilcServerEntry)idata; - silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL); + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, &hostname, &ip, NULL); /* Statistics */ if (server->server_type == SILC_ROUTER) @@ -2530,7 +2597,8 @@ static void silc_server_new_id_real(SilcServer server, id_type = silc_id_payload_get_type(idp); - silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL); + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, &hostname, &ip, NULL); /* Normal server cannot have other normal server connections */ server_entry = (SilcServerEntry)idata; @@ -2600,7 +2668,8 @@ static void silc_server_new_id_real(SilcServer server, global list. Cell wide information however is kept in the local list. */ entry = silc_idlist_add_client(id_list, NULL, NULL, NULL, - &id, router, NULL); + silc_id_dup(&id, SILC_ID_CLIENT), + router, NULL); if (!entry) { SILC_LOG_ERROR(("Could not add new client to the ID Cache")); @@ -2620,19 +2689,20 @@ static void silc_server_new_id_real(SilcServer server, silc_server_check_watcher_list(server, entry, NULL, 0); if (server->server_type == SILC_ROUTER) { - /* Add the client's public key to hash table or get the key with + /* Add the client's public key to repository or get the key with GETKEY command. */ if (entry->data.public_key) { - if (!silc_hash_table_find_by_context(server->pk_hash, - entry->data.public_key, - entry, NULL)) - silc_hash_table_add(server->pk_hash, entry->data.public_key, - entry); - } else + if (!silc_server_get_public_key_by_client(server, entry, NULL)) + silc_skr_add_public_key_simple(server->repository, + entry->data.public_key, + SILC_SKR_USAGE_IDENTIFICATION, + entry, NULL); + } else { silc_server_send_command(server, router_sock, SILC_COMMAND_GETKEY, ++server->cmd_ident, 1, 1, buffer->data, silc_buffer_len(buffer)); + } } } break; @@ -2678,7 +2748,8 @@ static void silc_server_new_id_real(SilcServer server, /* As a router we keep information of all global information in our global list. Cell wide information however is kept in the local list. */ - entry = silc_idlist_add_server(id_list, NULL, 0, &id, router, + entry = silc_idlist_add_server(id_list, NULL, 0, + silc_id_dup(&id, SILC_ID_SERVER), router, router_sock); if (!entry) { SILC_LOG_ERROR(("Could not add new server to the ID Cache")); @@ -2731,6 +2802,7 @@ void silc_server_new_id(SilcServer server, SilcPacketStream sock, SilcPacket packet) { silc_server_new_id_real(server, sock, packet, &packet->buffer, TRUE); + silc_packet_free(packet); } /* Receoved New Id List packet, list of New ID payloads inside one @@ -2746,8 +2818,10 @@ void silc_server_new_id_list(SilcServer server, SilcPacketStream sock, SILC_LOG_DEBUG(("Processing New ID List")); if (idata->conn_type == SILC_CONN_CLIENT || - packet->src_id_type != SILC_ID_SERVER) + packet->src_id_type != SILC_ID_SERVER) { + silc_packet_free(packet); return; + } /* If the sender of this packet is server and we are router we need to broadcast this packet to other routers in the network. Broadcast @@ -2769,8 +2843,10 @@ void silc_server_new_id_list(SilcServer server, SilcPacketStream sock, } idp = silc_buffer_alloc(256); - if (!idp) + if (!idp) { + silc_packet_free(packet); return; + } while (silc_buffer_len(&packet->buffer)) { SILC_GET16_MSB(id_len, packet->buffer.data + 2); @@ -2789,6 +2865,7 @@ void silc_server_new_id_list(SilcServer server, SilcPacketStream sock, } silc_buffer_free(idp); + silc_packet_free(packet); } /* Received New Channel packet. Information about new channels in the @@ -2914,9 +2991,12 @@ static void silc_server_new_channel_process(SilcServer server, } /* Create the channel with the provided Channel ID */ - channel = silc_server_create_new_channel_with_id(server, NULL, NULL, - channel_name, - &channel_id, FALSE); + channel = + silc_server_create_new_channel_with_id( + server, NULL, NULL, + channel_name, + silc_id_dup(&channel_id, SILC_ID_CHANNEL), + FALSE); if (!channel) { silc_channel_payload_free(payload); return; @@ -3079,6 +3159,7 @@ void silc_server_new_channel(SilcServer server, SilcPacket packet) { silc_server_new_channel_process(server, sock, packet, &packet->buffer); + silc_packet_free(packet); } /* Received New Channel List packet, list of New Channel List payloads inside @@ -3096,12 +3177,16 @@ void silc_server_new_channel_list(SilcServer server, if (idata->conn_type == SILC_CONN_CLIENT || packet->src_id_type != SILC_ID_SERVER || - server->server_type == SILC_SERVER) + server->server_type == SILC_SERVER) { + silc_packet_free(packet); return; + } buffer = silc_buffer_alloc(512); - if (!buffer) + if (!buffer) { + silc_packet_free(packet); return; + } while (silc_buffer_len(&packet->buffer)) { SILC_GET16_MSB(len1, packet->buffer.data); @@ -3125,6 +3210,7 @@ void silc_server_new_channel_list(SilcServer server, } silc_buffer_free(buffer); + silc_packet_free(packet); } /* Received key agreement packet. This packet is never for us. It is to @@ -3142,21 +3228,23 @@ void silc_server_key_agreement(SilcServer server, SILC_LOG_DEBUG(("Start")); if (packet->src_id_type != SILC_ID_CLIENT || - packet->dst_id_type != SILC_ID_CLIENT) - return; - - if (!packet->dst_id) + packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) { + silc_packet_free(packet); return; + } /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, packet->dst_id_len, NULL, &idata, NULL); - if (!dst_sock) + if (!dst_sock) { + silc_packet_free(packet); return; + } /* Relay the packet */ silc_server_packet_route(server, dst_sock, packet); + silc_packet_free(packet); } /* Received connection auth request packet that is used during connection @@ -3179,21 +3267,22 @@ void silc_server_connection_auth_request(SilcServer server, if (packet->src_id_type && packet->src_id_type != SILC_ID_CLIENT) { SILC_LOG_DEBUG(("Request not from client")); + silc_packet_free(packet); return; } - silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL); + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, &hostname, &ip, NULL); /* 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_CONN_CLIENT) + if (ret == -1 || conn_type != SILC_CONN_CLIENT) { + silc_packet_free(packet); return; + } /* Get the authentication method for the client */ auth_meth = SILC_AUTH_NONE; @@ -3217,6 +3306,7 @@ void silc_server_connection_auth_request(SilcServer server, /* Send it back to the client */ silc_server_send_connection_auth_request(server, sock, conn_type, auth_meth); + silc_packet_free(packet); } /* Received file transger packet. This packet is never for us. It is to @@ -3234,21 +3324,23 @@ void silc_server_ftp(SilcServer server, SILC_LOG_DEBUG(("Start")); if (packet->src_id_type != SILC_ID_CLIENT || - packet->dst_id_type != SILC_ID_CLIENT) - return; - - if (!packet->dst_id) + packet->dst_id_type != SILC_ID_CLIENT || !packet->dst_id) { + silc_packet_free(packet); return; + } /* Get the route to the client */ dst_sock = silc_server_get_client_route(server, packet->dst_id, packet->dst_id_len, NULL, &idata, NULL); - if (!dst_sock) + if (!dst_sock) { + silc_packet_free(packet); return; + } /* Relay the packet */ silc_server_packet_route(server, dst_sock, packet); + silc_packet_free(packet); } typedef struct { @@ -3269,7 +3361,8 @@ SILC_SERVER_CMD_FUNC(resume_resolve) SILC_LOG_DEBUG(("Start")); - silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL); + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, &hostname, &ip, NULL); if (!reply || !silc_command_get_status(reply->payload, NULL, NULL)) { SILC_LOG_ERROR(("Client %s (%s) tried to resume unknown client, " @@ -3343,9 +3436,13 @@ void silc_server_resume_client(SilcServer server, SilcHashTableList htl; SilcChannelClientEntry chl; SilcServerResumeResolve r; + SilcPublicKey public_key; const char *cipher, *hostname, *ip; - silc_socket_stream_get_info(sock, NULL, &hostname, &ip, NULL); + SILC_LOG_DEBUG(("Resuming client")); + + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), + NULL, &hostname, &ip, NULL); if (silc_buffer_unformat(buffer, SILC_STR_UI16_NSTRING(&id_string, &id_len), @@ -3588,21 +3685,35 @@ void silc_server_resume_client(SilcServer server, silc_packet_set_context(sock, detached_client); detached_client->connection = sock; - if (detached_client->data.public_key) - silc_hash_table_del_by_context(server->pk_hash, - detached_client->data.public_key, - detached_client); - if (idata->public_key) - silc_hash_table_del_by_context(server->pk_hash, - idata->public_key, idata); + if (detached_client->data.public_key) { + /* Delete the detached client's public key from repository */ + silc_skr_del_public_key(server->repository, + detached_client->data.public_key, + detached_client); + detached_client->data.public_key = NULL; + } + + if (idata->public_key) { + /* Delete the resuming client's public key from repository. It will + be added later again. */ + public_key = silc_pkcs_public_key_copy(idata->public_key); + silc_skr_del_public_key(server->repository, idata->public_key, idata); + idata->public_key = public_key; + } /* Take new keys and stuff into use in the old entry */ silc_idlist_del_data(detached_client); silc_idlist_add_data(detached_client, idata); + idata->public_key = NULL; - if (detached_client->data.public_key) - silc_hash_table_add(server->pk_hash, - detached_client->data.public_key, detached_client); + if (detached_client->data.public_key) { + /* Add the resumed client's public key back to repository. */ + if (!silc_server_get_public_key_by_client(server, detached_client, NULL)) + silc_skr_add_public_key_simple(server->repository, + detached_client->data.public_key, + SILC_SKR_USAGE_IDENTIFICATION, + detached_client, NULL); + } detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED; detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED; @@ -3610,6 +3721,7 @@ void silc_server_resume_client(SilcServer server, detached_client->data.status &= ~SILC_IDLIST_STATUS_RESUME_RES; detached_client->mode &= ~SILC_UMODE_DETACHED; server->stat.my_detached--; + silc_dlist_del(server->expired_clients, detached_client); /* We are finished - reset resuming client */ detached_client->resuming_client = NULL; @@ -3627,6 +3739,7 @@ void silc_server_resume_client(SilcServer server, silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, FALSE, FALSE); silc_server_del_from_watcher_list(server, client); + silc_dlist_del(server->expired_clients, client); if (!silc_idlist_del_client(server->local_list, client)) silc_idlist_del_client(server->global_list, client); client = detached_client; @@ -3705,14 +3818,17 @@ void silc_server_resume_client(SilcServer server, silc_buffer_free(nidp); } - /* Add the client again to the ID cache to get it to correct list */ - if (!silc_idcache_del_by_context(server->local_list->clients, client, - NULL)) - silc_idcache_del_by_context(server->global_list->clients, client, NULL); - silc_free(client->id); - *client->id = client_id; - silc_idcache_add(server->local_list->clients, nicknamec, - client->id, client); + /* Update entry */ + if (!silc_idcache_update_by_context(server->local_list->clients, client, + &client_id, NULL, FALSE)) + silc_idcache_update_by_context(server->global_list->clients, client, + &client_id, NULL, FALSE); + + /* Move entry to local list if it is in global list */ + if (silc_idcache_find_by_context(server->global_list->clients, client, + &id_cache)) + silc_idcache_move(server->global_list->clients, + server->local_list->clients, id_cache); /* Send some nice info to the client */ silc_server_send_connect_notifys(server, sock, client); @@ -3830,15 +3946,19 @@ void silc_server_resume_client(SilcServer server, /* Client is detached, and now it is resumed. Remove the detached mode and mark that it is resumed. */ - if (detached_client->data.public_key) - silc_hash_table_del_by_context(server->pk_hash, - detached_client->data.public_key, - detached_client); + if (detached_client->data.public_key) { + /* Delete the detached client's public key from repository */ + silc_skr_del_public_key(server->repository, + detached_client->data.public_key, + detached_client); + detached_client->data.public_key = NULL; + } silc_idlist_del_data(detached_client); detached_client->mode &= ~SILC_UMODE_DETACHED; detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED; detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL; + silc_dlist_del(server->expired_clients, detached_client); /* Check if anyone is watching this client */ if (server->server_type == SILC_ROUTER) @@ -3869,15 +3989,18 @@ void silc_server_resume_client(SilcServer server, server_entry->server_type == SILC_ROUTER) local = FALSE; - /* Change the client to correct list. */ - if (!silc_idcache_del_by_context(server->local_list->clients, - detached_client, NULL)) - silc_idcache_del_by_context(server->global_list->clients, - detached_client, NULL); - silc_idcache_add(local && server->server_type == SILC_ROUTER ? - server->local_list->clients : - server->global_list->clients, nicknamec, - detached_client->id, detached_client); + /* Move entry to correct list */ + if (local && server->server_type == SILC_ROUTER) { + if (silc_idcache_find_by_context(server->global_list->clients, + detached_client, &id_cache)) + silc_idcache_move(server->global_list->clients, + server->local_list->clients, id_cache); + } else { + if (silc_idcache_find_by_context(server->local_list->clients, + detached_client, &id_cache)) + silc_idcache_move(server->local_list->clients, + server->global_list->clients, id_cache); + } /* Change the owner of the client */ detached_client->router = server_entry;