X-Git-Url: http://git.silcnet.org/gitweb/?p=runtime.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fserver.c;h=7453f5f5d1bcb8c832aefaebf41b5d6da0ddb1d2;hp=9f68e5b8f4fd869ea3f6ff407652e432b4ea4a52;hb=da798b47cf2734868609f6563b73386335fa1f76;hpb=ee4396c2b0129375d07aadb3f63af668c67d490d diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 9f68e5b8..7453f5f5 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -108,11 +108,10 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine, packet->type != SILC_PACKET_DISCONNECT) return FALSE; - /* NEW_CLIENT, NEW_SERVER and RESUME_CLIENT are accepted only without - source ID and for unregistered connection. */ + /* NEW_CLIENT and NEW_SERVER are accepted only without source ID and + for unregistered connection. */ if (packet->src_id && (packet->type == SILC_PACKET_NEW_CLIENT || - packet->type == SILC_PACKET_NEW_SERVER || - packet->type == SILC_PACKET_RESUME_CLIENT) && + packet->type == SILC_PACKET_NEW_SERVER) && (idata->status & SILC_IDLIST_STATUS_REGISTERED)) return FALSE; @@ -203,6 +202,7 @@ static void silc_server_packet_eos(SilcPacketEngine engine, if (server->router_conn && server->router_conn->sock == stream && !server->router && server->standalone) { silc_server_create_connections(server); + silc_server_free_sock_user_data(server, stream, NULL); } else { /* If backup disconnected then mark that resuming will not be allowed */ if (server->server_type == SILC_ROUTER && !server->backup_router && @@ -269,6 +269,9 @@ static void silc_server_packet_error(SilcPacketEngine engine, SILC_CONNTYPE_STRING(idata->conn_type), silc_packet_error_string(error))); + if (!silc_packet_stream_is_valid(stream)) + return; + silc_schedule_task_add_timeout(server->schedule, silc_server_packet_error_timeout, stream, 0, 0); @@ -1342,9 +1345,9 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SilcID remote_id; const char *ip; - SILC_LOG_DEBUG(("Connection authentication completed")); + SILC_LOG_DEBUG(("Connection %p authentication completed", sconn)); - sconn->op = NULL; + entry->op = NULL; if (success == FALSE) { /* Authentication failed */ @@ -1354,6 +1357,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_AUTH_FAILED, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); return; } @@ -1380,6 +1384,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); silc_free(entry); return; @@ -1410,6 +1415,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); silc_free(entry); return; @@ -1449,6 +1455,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); silc_free(entry); return; @@ -1532,6 +1539,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_AUTH_FAILED, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); silc_free(entry); return; @@ -1584,7 +1592,9 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, SilcHmac hmac_send, hmac_receive; SilcHash hash; - sconn->op = NULL; + SILC_LOG_DEBUG(("Connection %p, SKE completed", sconn)); + + entry->op = NULL; if (status != SILC_SKE_STATUS_OK) { /* SKE failed */ @@ -1597,6 +1607,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); return; } @@ -1615,6 +1626,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); return; } @@ -1634,6 +1646,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); + silc_server_free_sock_user_data(server, sconn->sock, NULL); silc_server_connection_free(sconn); return; } @@ -1658,7 +1671,7 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, entry->data.rekey = rekey; /* Start connection authentication */ - sconn->op = + entry->op = silc_connauth_initiator(connauth, server->server_type == SILC_SERVER ? SILC_CONN_SERVER : SILC_CONN_ROUTER, auth_meth, auth_data, auth_data_len, @@ -1721,7 +1734,7 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) params.flags |= SILC_SKE_SP_FLAG_PFS; /* Start SILC Key Exchange protocol */ - SILC_LOG_DEBUG(("Starting key exchange protocol")); + SILC_LOG_DEBUG(("Starting key exchange protocol, connection %p", sconn)); ske = silc_ske_alloc(server->rng, server->schedule, server->repository, server->public_key, server->private_key, sconn); if (!ske) { @@ -1738,7 +1751,7 @@ void silc_server_start_key_exchange(SilcServerConnection sconn) /* Start key exchange protocol */ params.version = silc_version_string; params.timeout_secs = server->config->key_exchange_timeout; - sconn->op = silc_ske_initiator(ske, sconn->sock, ¶ms, NULL); + entry->op = silc_ske_initiator(ske, sconn->sock, ¶ms, NULL); } /* Timeout callback that will be called to retry connecting to remote @@ -1805,7 +1818,7 @@ static void silc_server_connection_established(SilcNetStatus status, switch (status) { case SILC_NET_OK: - SILC_LOG_DEBUG(("Connection to %s:%d established", + SILC_LOG_DEBUG(("Connection %p to %s:%d established", sconn, sconn->remote_host, sconn->remote_port)); /* Continue with key exchange protocol */ @@ -2142,6 +2155,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, server->stat.auth_failures++; silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + silc_server_free_sock_user_data(server, sock, NULL); goto out; } @@ -2180,6 +2194,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_PERM_DENIED, "We do not have connection to backup " "router established, try later"); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; /* From here on, wait 20 seconds for the backup router to appear. */ @@ -2204,6 +2219,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, server->stat.auth_failures++; silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED, NULL); + silc_server_free_sock_user_data(server, sock, NULL); goto out; } entry->data.status |= SILC_IDLIST_STATUS_LOCAL; @@ -2270,6 +2286,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_PERM_DENIED, "We do not have connection to primary " "router established, try later"); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; goto out; } @@ -2357,6 +2374,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_STATUS_ERR_PERM_DENIED, "We do not have connection to backup " "router established, try later"); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; /* From here on, wait 20 seconds for the backup router to appear. */ @@ -2397,6 +2415,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_LOG_ERROR(("Could not add new server to cache")); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_AUTH_FAILED, NULL); + silc_server_free_sock_user_data(server, sock, NULL); server->stat.auth_failures++; goto out; } @@ -2520,6 +2539,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, silc_ske_free(ske); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + silc_server_free_sock_user_data(server, sock, NULL); return; } @@ -2532,6 +2552,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, silc_ske_free(ske); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_KEY_EXCHANGE_FAILED, NULL); + silc_server_free_sock_user_data(server, sock, NULL); return; } silc_packet_set_keys(sock, send_key, receive_key, hmac_send, @@ -2554,6 +2575,7 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, silc_ske_free(ske); silc_server_disconnect_remote(server, sock, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + silc_server_free_sock_user_data(server, sock, NULL); return; } @@ -2632,6 +2654,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_BANNED_FROM_SERVER, deny->reason); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } @@ -2650,6 +2673,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, server->stat.conn_failures++; silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_BANNED_FROM_SERVER, NULL); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } @@ -2659,6 +2683,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, server->stat.conn_failures++; silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } entry->hostname = hostname; @@ -2694,6 +2719,7 @@ static void silc_server_accept_new_connection(SilcNetStatus status, server->stat.conn_failures++; silc_server_disconnect_remote(server, packet_stream, SILC_STATUS_ERR_RESOURCE_LIMIT, NULL); + silc_server_free_sock_user_data(server, packet_stream, NULL); return; } silc_ske_set_callbacks(ske, silc_server_verify_key, @@ -2843,7 +2869,7 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock, SILC_TASK_CALLBACK(silc_server_close_connection_final) { - silc_packet_stream_destroy(context); + silc_packet_stream_unref(context); } /* Closes connection to socket connection */ @@ -2856,6 +2882,9 @@ void silc_server_close_connection(SilcServer server, const char *hostname; SilcUInt16 port; + if (!silc_packet_stream_is_valid(sock)) + return; + memset(tmp, 0, sizeof(tmp)); // silc_socket_get_error(sock, tmp, sizeof(tmp)); silc_socket_stream_get_info(silc_packet_stream_get_stream(sock), @@ -2871,6 +2900,11 @@ void silc_server_close_connection(SilcServer server, idata->sconn = NULL; } + /* Take a reference and then destroy the stream. The last reference + is released later in a timeout callback. */ + silc_packet_stream_ref(sock); + silc_packet_stream_destroy(sock); + /* Close connection with timeout */ server->stat.conn_num--; silc_schedule_task_del_by_all(server->schedule, 0, @@ -2962,8 +2996,10 @@ void silc_server_free_client_data(SilcServer server, SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR); silc_schedule_task_del_by_context(server->schedule, client); - if (client->data.sconn) + if (client->data.sconn) { silc_server_connection_free(client->data.sconn); + client->data.sconn = NULL; + } /* We will not delete the client entry right away. We will take it into history (for WHOWAS command) for 5 minutes, unless we're @@ -3000,7 +3036,7 @@ void silc_server_free_sock_user_data(SilcServer server, if (!idata) return; - silc_schedule_task_del_by_context(server->schedule, sock); + // silc_schedule_task_del_by_context(server->schedule, sock); /* Cancel active protocols */ if (idata) { @@ -4122,6 +4158,7 @@ void silc_server_announce_get_inviteban(SilcServer server, { SilcBuffer list, idp, idp2, tmp2; SilcUInt32 type; + void *ptype; SilcHashTableList htl; const unsigned char a[1] = { 0x03 }; @@ -4133,9 +4170,10 @@ void silc_server_announce_get_inviteban(SilcServer server, type = silc_hash_table_count(channel->invite_list); SILC_PUT16_MSB(type, list->data); silc_hash_table_list(channel->invite_list, &htl); - while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) - list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2), - type); + while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) + list = silc_argument_payload_encode_one(list, tmp2->data, + silc_buffer_len(tmp2), + SILC_PTR_TO_32(ptype)); silc_hash_table_list_reset(&htl); idp2 = silc_id_payload_encode(server->id, SILC_ID_SERVER); @@ -4157,9 +4195,10 @@ void silc_server_announce_get_inviteban(SilcServer server, type = silc_hash_table_count(channel->ban_list); SILC_PUT16_MSB(type, list->data); silc_hash_table_list(channel->ban_list, &htl); - while (silc_hash_table_get(&htl, (void *)&type, (void *)&tmp2)) - list = silc_argument_payload_encode_one(list, tmp2->data, silc_buffer_len(tmp2), - type); + while (silc_hash_table_get(&htl, (void *)&ptype, (void *)&tmp2)) + list = silc_argument_payload_encode_one(list, tmp2->data, + silc_buffer_len(tmp2), + SILC_PTR_TO_32(ptype)); silc_hash_table_list_reset(&htl); *ban =