Author: Pekka Riikonen <priikone@silcnet.org>
- 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
!(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))
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;
}
}
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 &&
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);
}
}
+ 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);
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);
}
}
+ 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,
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;
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);
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 */
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;
}
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;
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;
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;
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) {
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;
/* 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)
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 */
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;
}
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;
}
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;
}
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,
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) {
/* 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
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 */
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;
}
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;
}
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;
}
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))) {
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. */
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++;
}
/* 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,
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"));
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))) {
}
}
- 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))) {
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. */
}
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")));
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);
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;
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_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,
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++;
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;
}
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;
}
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;
}
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;
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,
SILC_TASK_CALLBACK(silc_server_close_connection_final)
{
- silc_packet_stream_destroy(context);
+ silc_packet_stream_unref(context);
}
/* Closes connection to socket connection */
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),
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,
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
if (!idata)
return;
- silc_schedule_task_del_by_context(server->schedule, sock);
+ silc_schedule_task_del_by_all(server->schedule, 0, silc_server_do_rekey,
+ sock);
/* Cancel active protocols */
if (idata) {
{
SilcBuffer list, idp, idp2, tmp2;
SilcUInt32 type;
+ void *ptype;
SilcHashTableList htl;
const unsigned char a[1] = { 0x03 };
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);
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 =