X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Fsilcd%2Fpacket_receive.c;h=73424a68988fe7b2016030d9c8de39bb8f33b7a9;hb=805fddcf6431e784f9f77114782a90c9d12f9cbe;hp=c6ec4501980cc43f3b725f9b72b6bc7777343d44;hpb=cbc144f6d31ef9d08feb0c8d1b938519f5d450e0;p=silc.git diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index c6ec4501..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; } @@ -1891,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; @@ -1998,9 +2022,9 @@ void silc_server_channel_message(SilcServer server, /* 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: @@ -2123,12 +2147,30 @@ SilcClientEntry silc_server_new_client(SilcServer server, 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, @@ -2139,21 +2181,6 @@ SilcClientEntry silc_server_new_client(SilcServer server, return NULL; } - /* Take nickname from NEW_CLIENT packet, if present */ - if (silc_buffer_unformat(buffer, - SILC_STR_UI16_NSTRING_ALLOC(&nickname, - &nickname_len), - SILC_STR_END)) { - 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); - /* 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 @@ -2167,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); @@ -2184,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); @@ -2639,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")); @@ -2659,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; @@ -2717,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")); @@ -2959,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; @@ -3401,8 +3436,11 @@ void silc_server_resume_client(SilcServer server, SilcHashTableList htl; SilcChannelClientEntry chl; SilcServerResumeResolve r; + SilcPublicKey public_key; const char *cipher, *hostname, *ip; + SILC_LOG_DEBUG(("Resuming client")); + silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), NULL, &hostname, &ip, NULL); @@ -3647,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; @@ -3669,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; @@ -3686,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; @@ -3764,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); @@ -3889,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) @@ -3928,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;