X-Git-Url: http://git.silcnet.org/gitweb/?p=runtime.git;a=blobdiff_plain;f=apps%2Fsilcd%2Fserver.c;h=7453f5f5d1bcb8c832aefaebf41b5d6da0ddb1d2;hp=2b0f291ce3f3635302824fef557187d39d3fe978;hb=da798b47cf2734868609f6563b73386335fa1f76;hpb=8ef48975ffcb3daee6167e9766c2b344c73152d1 diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 2b0f291c..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 @@ -24,6 +24,7 @@ SILC_TASK_CALLBACK(silc_server_get_stats); SILC_TASK_CALLBACK(silc_server_connect_router); +SILC_TASK_CALLBACK(silc_server_connect_to_router_retry); SILC_TASK_CALLBACK(silc_server_do_rekey); SILC_TASK_CALLBACK(silc_server_purge_expired_clients); static void silc_server_accept_new_connection(SilcNetStatus status, @@ -102,12 +103,13 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine, !(idata->status & SILC_IDLIST_STATUS_REGISTERED)) && packet->type != SILC_PACKET_NEW_CLIENT && packet->type != SILC_PACKET_NEW_SERVER && + packet->type != SILC_PACKET_RESUME_CLIENT && packet->type != SILC_PACKET_CONNECTION_AUTH_REQUEST && packet->type != SILC_PACKET_DISCONNECT) return FALSE; - /* NEW_CLIENT and NEW_SERVER 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) && (idata->status & SILC_IDLIST_STATUS_REGISTERED)) @@ -129,7 +131,8 @@ static SilcBool silc_server_packet_receive(SilcPacketEngine engine, silc_id_str2id(packet->src_id, packet->src_id_len, packet->src_id_type, &client_id, sizeof(client_id))) { if (!SILC_ID_CLIENT_COMPARE(client->id, &client_id)) { - SILC_LOG_DEBUG(("Packet source is not same as sender")); + SILC_LOG_DEBUG(("Packet source is not same as sender, packet %s", + silc_get_packet_name(packet->type))); return FALSE; } } @@ -199,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 && @@ -265,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); @@ -665,6 +672,10 @@ void silc_server_free(SilcServer server) } } + silc_schedule_task_del_by_context(server->schedule, server); + silc_schedule_uninit(server->schedule); + server->schedule = NULL; + silc_idcache_free(server->local_list->clients); silc_idcache_free(server->local_list->servers); silc_idcache_free(server->local_list->channels); @@ -682,10 +693,6 @@ void silc_server_free(SilcServer server) silc_skr_free(server->repository); silc_packet_engine_stop(server->packet_engine); - silc_schedule_task_del_by_context(server->schedule, server); - silc_schedule_uninit(server->schedule); - server->schedule = NULL; - silc_free(server->local_list); silc_free(server->global_list); silc_free(server->server_name); @@ -876,12 +883,16 @@ SilcBool silc_server_init(SilcServer server) the ID list. */ id_entry = silc_idlist_add_server(server->local_list, strdup(server->server_name), - server->server_type, server->id, NULL, NULL); + server->server_type, + silc_id_dup(server->id, SILC_ID_SERVER), + NULL, NULL); if (!id_entry) { SILC_LOG_ERROR(("Could not add local server to cache")); goto err; } id_entry->data.status |= SILC_IDLIST_STATUS_REGISTERED; + id_entry->data.conn_type = (server->server_type == SILC_SERVER ? + SILC_CONN_SERVER : SILC_CONN_ROUTER); server->id_entry = id_entry; /* Create secondary TCP listeners */ @@ -910,15 +921,19 @@ SilcBool silc_server_init(SilcServer server) } } + if (server->server_type != SILC_ROUTER) { + server->stat.servers = 1; + server->stat.cell_servers = 1; + } else { + server->stat.routers = 1; + } + /* If we are normal server we'll retrieve network statisticial information once in a while from the router. */ if (server->server_type != SILC_ROUTER) silc_schedule_task_add_timeout(server->schedule, silc_server_get_stats, server, 10, 0); - if (server->server_type == SILC_ROUTER) - server->stat.routers++; - /* Start packet engine */ server->packet_engine = silc_packet_engine_start(server->rng, server->server_type == SILC_ROUTER, @@ -1197,6 +1212,9 @@ void silc_server_stop(SilcServer server) while ((ps = silc_dlist_get(list))) { SilcIDListData idata = silc_packet_get_context(ps); + if (!silc_packet_stream_is_valid(ps)) + continue; + if (idata) idata->status &= ~SILC_IDLIST_STATUS_DISABLED; @@ -1205,7 +1223,7 @@ void silc_server_stop(SilcServer server) silc_server_free_sock_user_data(server, ps, "Server is shutting down"); } - silc_dlist_uninit(list); + silc_packet_engine_free_streams_list(list); } /* We are not connected to network anymore */ @@ -1217,6 +1235,14 @@ void silc_server_stop(SilcServer server) silc_server_http_uninit(server); + /* Cancel any possible retry timeouts */ + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_router); + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_to_router_retry); + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_to_router); + silc_schedule_stop(server->schedule); SILC_LOG_DEBUG(("Server stopped")); @@ -1319,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 */ @@ -1331,6 +1357,8 @@ 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; } @@ -1356,11 +1384,18 @@ 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; } + /* Statistics */ + server->stat.my_servers++; + if (server->server_type == SILC_ROUTER) + server->stat.servers++; + SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers)); + silc_idlist_add_data(id_entry, (SilcIDListData)entry); break; @@ -1380,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; @@ -1419,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; @@ -1431,6 +1468,12 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, SILC_IDLIST_STATUS_LOCAL); idata->sconn = sconn; + /* Statistics */ + server->stat.my_routers++; + if (server->server_type == SILC_ROUTER) + server->stat.routers++; + SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers)); + if (!sconn->backup) { /* Mark this router our primary router if we're still standalone */ if (server->standalone) { @@ -1468,6 +1511,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, silc_server_backup_add(server, server->id_entry, ip, sconn->remote_port, TRUE); } +#if 0 } else { /* We already have primary router. Disconnect this connection */ SILC_LOG_DEBUG(("We already have primary router, disconnect")); @@ -1479,6 +1523,7 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, silc_server_connection_free(sconn); silc_free(entry); return; +#endif /* 0 */ } } else { /* Add this server to be our backup router */ @@ -1494,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; @@ -1514,19 +1560,11 @@ silc_server_ke_auth_compl(SilcConnAuth connauth, SilcBool success, /* Set the entry as packet stream context */ silc_packet_set_context(sconn->sock, id_entry); - out: /* Call the completion callback to indicate that we've connected to the router */ if (sconn && sconn->callback) (*sconn->callback)(server, id_entry, sconn->callback_context); - /* Free the temporary connection data context */ - if (sconn) { - silc_server_config_unref(&sconn->conn); - silc_free(sconn->remote_host); - silc_free(sconn->backup_replace_ip); - silc_free(sconn); - } if (sconn == server->router_conn) server->router_conn = NULL; @@ -1554,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 */ @@ -1567,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; } @@ -1585,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; } @@ -1604,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; } @@ -1625,10 +1668,12 @@ static void silc_server_ke_completed(SilcSKE ske, SilcSKEStatus status, } } + entry->data.rekey = rekey; + /* Start connection authentication */ - sconn->op = - silc_connauth_initiator(connauth, server->server_type == SILC_ROUTER ? - SILC_CONN_ROUTER : SILC_CONN_SERVER, auth_meth, + entry->op = + silc_connauth_initiator(connauth, server->server_type == SILC_SERVER ? + SILC_CONN_SERVER : SILC_CONN_ROUTER, auth_meth, auth_data, auth_data_len, silc_server_ke_auth_compl, sconn); } @@ -1689,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) { @@ -1706,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 @@ -1773,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 */ @@ -1800,6 +1845,7 @@ static void silc_server_connection_established(SilcNetStatus status, silc_schedule_task_add_timeout(sconn->server->schedule, silc_server_connect_to_router_retry, sconn, 1, 0); + silc_dlist_del(server->conns, sconn); } else { if (sconn->callback) (*sconn->callback)(server, NULL, sconn->callback_context); @@ -1883,7 +1929,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) "normal server" : server->server_type == SILC_ROUTER ? "router" : "backup router/normal server"))); - /* XXX */ if (!server->config->routers) { /* There wasn't a configured router, we will continue but we don't have a connection to outside world. We will be standalone server. */ @@ -1892,6 +1937,12 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) return; } + /* Cancel any possible retry timeouts */ + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_router); + silc_schedule_task_del_by_callback(server->schedule, + silc_server_connect_to_router_retry); + /* Create the connections to all our routes */ for (ptr = server->config->routers; ptr; ptr = ptr->next) { @@ -1947,6 +1998,7 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) sconn = silc_calloc(1, sizeof(*sconn)); if (!sconn) continue; + sconn->server = server; sconn->remote_host = strdup(ptr->host); sconn->remote_port = ptr->port; sconn->backup = ptr->backup_router; @@ -1957,7 +2009,6 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router) SILC_LOG_DEBUG(("Created connection %p", sconn)); - /* XXX */ if (!server->router_conn && !sconn->backup) server->router_conn = sconn; @@ -2007,7 +2058,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth, if (cconfig->publickeys) *repository = server->repository; - entry->data.conn_type = conn_type; + if (cconfig->publickeys) { + if (server->config->prefer_passphrase_auth) { + *repository = NULL; + } else { + *passphrase = NULL; + *passphrase_len = 0; + } + } + + entry->conn_type = conn_type; return TRUE; } @@ -2028,7 +2088,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth, if (sconfig->publickeys) *repository = server->repository; - entry->data.conn_type = conn_type; + if (sconfig->publickeys) { + if (server->config->prefer_passphrase_auth) { + *repository = NULL; + } else { + *passphrase = NULL; + *passphrase_len = 0; + } + } + + entry->conn_type = conn_type; return TRUE; } @@ -2043,7 +2112,16 @@ silc_server_accept_get_auth(SilcConnAuth connauth, if (rconfig->publickeys) *repository = server->repository; - entry->data.conn_type = conn_type; + if (rconfig->publickeys) { + if (server->config->prefer_passphrase_auth) { + *repository = NULL; + } else { + *passphrase = NULL; + *passphrase_len = 0; + } + } + + entry->conn_type = conn_type; return TRUE; } @@ -2077,19 +2155,20 @@ 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; } SILC_LOG_DEBUG(("Checking whether connection is allowed")); - switch (entry->data.conn_type) { + switch (entry->conn_type) { case SILC_CONN_CLIENT: { SilcClientEntry client; SilcServerConfigClient *conn = entry->cconfig.ref_ptr; /* Verify whether this connection is after all allowed to connect */ - if (!silc_server_connection_allowed(server, sock, entry->data.conn_type, + if (!silc_server_connection_allowed(server, sock, entry->conn_type, &server->config->param, conn->param, silc_connauth_get_ske(connauth))) { @@ -2115,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. */ @@ -2139,9 +2219,11 @@ 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; + entry->data.conn_type = SILC_CONN_CLIENT; /* Statistics */ server->stat.my_clients++; @@ -2169,6 +2251,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, } /* Add public key to repository */ + SILC_LOG_DEBUG(("Add client public key to repository")); if (!silc_server_get_public_key_by_client(server, client, NULL)) silc_skr_add_public_key_simple(server->repository, entry->data.public_key, @@ -2195,7 +2278,7 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, and we do not have connection to primary router, do not allow the connection. */ if (server->server_type == SILC_BACKUP_ROUTER && - entry->data.conn_type == SILC_CONN_SERVER && + entry->conn_type == SILC_CONN_SERVER && !SILC_PRIMARY_ROUTE(server)) { SILC_LOG_INFO(("Will not accept server connection because we do " "not have primary router connection established")); @@ -2203,14 +2286,15 @@ 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; } - if (entry->data.conn_type == SILC_CONN_ROUTER) { + if (entry->conn_type == SILC_CONN_ROUTER) { /* Verify whether this connection is after all allowed to connect */ if (!silc_server_connection_allowed(server, sock, - entry->data.conn_type, + entry->conn_type, &server->config->param, rconn ? rconn->param : NULL, silc_connauth_get_ske(connauth))) { @@ -2242,10 +2326,10 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, } } - if (entry->data.conn_type == SILC_CONN_SERVER) { + if (entry->conn_type == SILC_CONN_SERVER) { /* Verify whether this connection is after all allowed to connect */ if (!silc_server_connection_allowed(server, sock, - entry->data.conn_type, + entry->conn_type, &server->config->param, srvconn ? srvconn->param : NULL, silc_connauth_get_ske(connauth))) { @@ -2290,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. */ @@ -2301,11 +2386,11 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, } SILC_LOG_DEBUG(("Remote host is %s", - entry->data.conn_type == SILC_CONN_SERVER ? + entry->conn_type == SILC_CONN_SERVER ? "server" : (backup_router ? "backup router" : "router"))); SILC_LOG_INFO(("Connection %s (%s) is %s", entry->hostname, - entry->ip, entry->data.conn_type == SILC_CONN_SERVER ? + entry->ip, entry->conn_type == SILC_CONN_SERVER ? "server" : (backup_router ? "backup router" : "router"))); @@ -2314,15 +2399,15 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, server. We mark ourselves as router for this server if we really are router. */ new_server = - silc_idlist_add_server((entry->data.conn_type == SILC_CONN_SERVER ? + silc_idlist_add_server((entry->conn_type == SILC_CONN_SERVER ? server->local_list : (backup_router ? server->local_list : server->global_list)), NULL, - (entry->data.conn_type == SILC_CONN_SERVER ? + (entry->conn_type == SILC_CONN_SERVER ? SILC_SERVER : SILC_ROUTER), NULL, - (entry->data.conn_type == SILC_CONN_SERVER ? + (entry->conn_type == SILC_CONN_SERVER ? server->id_entry : (backup_router ? server->id_entry : NULL)), sock); @@ -2330,10 +2415,12 @@ 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; } entry->data.status |= SILC_IDLIST_STATUS_LOCAL; + entry->data.conn_type = entry->conn_type; id_entry = (void *)new_server; @@ -2359,9 +2446,11 @@ silc_server_accept_auth_compl(SilcConnAuth connauth, SilcBool success, if (entry->data.conn_type == SILC_CONN_SERVER) { server->stat.my_servers++; server->stat.servers++; + SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers)); } else { server->stat.my_routers++; server->stat.routers++; + SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers)); } /* Check whether this connection is to be our primary router connection @@ -2450,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; } @@ -2462,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, @@ -2472,6 +2563,8 @@ silc_server_accept_completed(SilcSKE ske, SilcSKEStatus status, pk = silc_pkcs_public_key_encode(idata->public_key, &pk_len); silc_hash_make(server->sha1hash, pk, pk_len, idata->fingerprint); + silc_hash_alloc(silc_hash_get_name(prop->hash), &idata->hash); + SILC_LOG_DEBUG(("Starting connection authentication")); server->stat.auth_attempts++; @@ -2482,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; } @@ -2560,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; } @@ -2578,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; } @@ -2587,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; @@ -2622,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, @@ -2696,8 +2794,8 @@ SILC_TASK_CALLBACK(silc_server_do_rekey) SILC_CONNTYPE_STRING(idata->conn_type))); /* Allocate SKE */ - ske = silc_ske_alloc(server->rng, server->schedule, server->repository, - server->public_key, server->private_key, sock); + ske = silc_ske_alloc(server->rng, server->schedule, NULL, + server->public_key, NULL, sock); if (!ske) return; @@ -2749,8 +2847,8 @@ static void silc_server_rekey(SilcServer server, SilcPacketStream sock, SILC_CONNTYPE_STRING(idata->conn_type))); /* Allocate SKE */ - ske = silc_ske_alloc(server->rng, server->schedule, server->repository, - server->public_key, server->private_key, sock); + ske = silc_ske_alloc(server->rng, server->schedule, NULL, + server->public_key, NULL, sock); if (!ske) { silc_packet_free(packet); return; @@ -2771,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 */ @@ -2784,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), @@ -2799,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, @@ -2890,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 @@ -2928,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) { @@ -3114,22 +3222,26 @@ void silc_server_free_sock_user_data(SilcServer server, if (idata->sconn) silc_server_connection_free(idata->sconn); - /* Free the server entry */ - silc_server_backup_del(server, user_data); - silc_server_backup_replaced_del(server, user_data); - silc_idlist_del_data(user_data); - if (!silc_idlist_del_server(server->local_list, user_data)) - silc_idlist_del_server(server->global_list, user_data); + /* Statistics */ if (idata->conn_type == SILC_CONN_SERVER) { server->stat.my_servers--; server->stat.servers--; - } else { + SILC_LOG_DEBUG(("my_servers %d", server->stat.my_servers)); + } else if (idata->conn_type == SILC_CONN_ROUTER) { server->stat.my_routers--; server->stat.routers--; + SILC_LOG_DEBUG(("my_routers %d", server->stat.my_routers)); } if (server->server_type == SILC_ROUTER) server->stat.cell_servers--; + /* Free the server entry */ + silc_server_backup_del(server, user_data); + silc_server_backup_replaced_del(server, user_data); + silc_idlist_del_data(user_data); + if (!silc_idlist_del_server(server->local_list, user_data)) + silc_idlist_del_server(server->global_list, user_data); + if (backup_router && backup_router != server->id_entry) { /* Announce all of our stuff that was created about 5 minutes ago. The backup router knows all the other stuff already. */ @@ -3936,6 +4048,9 @@ static void silc_server_announce_get_clients(SilcServer server, if (!client->connection && !client->router) continue; + SILC_LOG_DEBUG(("Announce Client ID %s", + silc_id_render(client->id, SILC_ID_CLIENT))); + idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT); *clients = silc_buffer_realloc(*clients, @@ -4043,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 }; @@ -4054,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); @@ -4078,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 = @@ -4163,6 +4281,9 @@ void silc_server_announce_get_channel_users(SilcServer server, while (silc_hash_table_get(&htl, NULL, (void *)&chl)) { clidp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT); + SILC_LOG_DEBUG(("JOIN Client %s", silc_id_render(chl->client->id, + SILC_ID_CLIENT))); + /* JOIN Notify */ tmp = silc_server_announce_encode_notify(SILC_NOTIFY_TYPE_JOIN, 2, clidp->data, @@ -4256,6 +4377,9 @@ void silc_server_announce_get_channels(SilcServer server, else announce = TRUE; + SILC_LOG_DEBUG(("Announce Channel ID %s", + silc_id_render(channel->id, SILC_ID_CHANNEL))); + silc_id_id2str(channel->id, SILC_ID_CHANNEL, cid, sizeof(cid), &id_len); name_len = strlen(channel->channel_name); @@ -4560,10 +4684,10 @@ void silc_server_announce_watches(SilcServer server, /* Assembles user list and users mode list from the `channel'. */ SilcBool silc_server_get_users_on_channel(SilcServer server, - SilcChannelEntry channel, - SilcBuffer *user_list, - SilcBuffer *mode_list, - SilcUInt32 *user_count) + SilcChannelEntry channel, + SilcBuffer *user_list, + SilcBuffer *mode_list, + SilcUInt32 *user_count) { SilcChannelClientEntry chl; SilcHashTableList htl;