/* Set log files where log message should be saved. */
server->config->server = server;
- silc_server_config_setlogfiles(server->config);
/* Register all configured ciphers, PKCS and hash functions. */
if (!silc_server_config_register_ciphers(server->config))
server->schedule = silc_schedule_init(SILC_SERVER_MAX_CONNECTIONS);
if (!server->schedule)
goto err0;
-
+
/* Add the first task to the scheduler. This is task that is executed by
timeout. It expires as soon as the caller calls silc_server_run. This
task performs authentication protocol and key exchange with our
SILC_TASK_PRI_NORMAL);
server->listenning = TRUE;
+ /* Send log file configuration */
+ silc_server_config_setlogfiles(server->config, server->schedule);
+
/* If server connections has been configured then we must be router as
normal server cannot have server connections, only router connections. */
if (server->config->servers) {
return FALSE;
}
-/* Fork server to background and set gid+uid to non-root */
+/* Fork server to background */
void silc_server_daemonise(SilcServer server)
{
int i;
- i = fork ();
+ SILC_LOG_DEBUG(("Forking SILC server to background"));
- if (i) {
- if (i > 0) {
- if (geteuid())
- SILC_LOG_DEBUG(("Server started as user"));
- else
- SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
+ i = fork();
- SILC_LOG_DEBUG(("Forking SILC server to background"));
- exit(0);
- } else {
- SILC_LOG_DEBUG(("fork() failed, cannot proceed"));
- exit(1);
- }
+ if (i < 0) {
+ SILC_LOG_DEBUG(("fork() failed, cannot proceed"));
+ exit(1);
+ }
+ else if (i) {
+ if (geteuid())
+ SILC_LOG_DEBUG(("Server started as user"));
+ else
+ SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
+ exit(0);
}
setsid();
}
{
/* Are we executing silcd as root or a regular user? */
if (!geteuid()) {
-
struct passwd *pw;
struct group *gr;
char *user, *group;
{
SILC_LOG_DEBUG(("Stopping server"));
- silc_schedule_stop(server->schedule);
- silc_schedule_uninit(server->schedule);
+ if (server->schedule) {
+ silc_schedule_stop(server->schedule);
+ silc_schedule_uninit(server->schedule);
+ server->schedule = NULL;
+ }
silc_server_protocols_unregister();
sconn->backup_replace_port = ptr->backup_replace_port;
}
+ if (!server->router_conn && !sconn->backup)
+ server->router_conn = sconn;
+
silc_schedule_task_add(server->schedule, fd,
silc_server_connect_router,
(void *)sconn, 0, 1, SILC_TASK_TIMEOUT,
silc_free(sconn->backup_replace_ip);
silc_free(sconn);
}
+ if (sconn == server->router_conn)
+ server->router_conn = NULL;
/* Free the protocol object */
if (sock->protocol == protocol)
sock->hostname,
port);
if (!cconfig && !sconfig && !rconfig) {
+ SILC_LOG_INFO(("Connection %s (%s) is not allowed",
+ sock->hostname, sock->ip));
silc_server_disconnect_remote(server, sock,
"Server closed connection: "
"Connection refused");
close the connection */
if (SILC_IS_DISCONNECTING(sock)) {
if (sock->user_data)
- silc_server_free_sock_user_data(server, sock);
+ silc_server_free_sock_user_data(server, sock, NULL);
silc_server_close_connection(server, sock);
return;
}
SILC_LOG_DEBUG(("Premature EOF from connection %d", sock->sock));
SILC_SET_DISCONNECTING(sock);
- if (sock->user_data)
- silc_server_free_sock_user_data(server, sock);
+ if (sock->user_data) {
+ char tmp[128];
+ if (silc_socket_get_error(sock, tmp, sizeof(tmp) - 1))
+ silc_server_free_sock_user_data(server, sock, tmp);
+ else
+ silc_server_free_sock_user_data(server, sock, NULL);
+ } else if (server->router_conn && server->router_conn->sock == sock &&
+ !server->router && server->standalone)
+ silc_schedule_task_add(server->schedule, 0,
+ silc_server_connect_to_router,
+ server, 1, 0,
+ SILC_TASK_TIMEOUT,
+ SILC_TASK_PRI_NORMAL);
+
silc_server_close_connection(server, sock);
return;
}
/* Process the packet. This will call the parser that will then
decrypt and parse the packet. */
- silc_packet_receive_process(sock, server->server_type == SILC_ROUTER ?
- TRUE : FALSE, cipher, hmac, sequence,
- silc_server_packet_parse, server);
+ ret = silc_packet_receive_process(sock, server->server_type == SILC_ROUTER ?
+ TRUE : FALSE, cipher, hmac, sequence,
+ silc_server_packet_parse, server);
+
+ /* If this socket connection is not authenticated yet and the packet
+ processing failed we will drop the connection since it can be
+ a malicious flooder. */
+ if (sock->type == SILC_SOCKET_TYPE_UNKNOWN && ret == FALSE &&
+ (!sock->protocol || sock->protocol->protocol->type ==
+ SILC_PROTOCOL_SERVER_KEY_EXCHANGE)) {
+ SILC_LOG_DEBUG(("Bad data sent from unknown connection %d", sock->sock));
+ SILC_SET_DISCONNECTING(sock);
+
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ silc_server_close_connection(server, sock);
+ }
}
/* Parses whole packet, received earlier. */
if (!(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
packet->dst_id_type == SILC_ID_SERVER &&
sock->type != SILC_SOCKET_TYPE_CLIENT &&
- memcmp(packet->dst_id, server->id_string, packet->dst_id_len)) {
+ memcmp(packet->dst_id, server->id_string, server->id_string_len)) {
/* Route the packet to fastest route for the destination ID */
void *id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
SilcSocketConnection sock,
SilcClientEntry client,
int notify,
- char *signoff)
+ const char *signoff)
{
FreeClientInternal i = silc_calloc(1, sizeof(*i));
/* Remove client from all channels */
if (notify)
silc_server_remove_from_channels(server, NULL, client,
- TRUE, signoff, TRUE);
+ TRUE, (char *)signoff, TRUE);
else
silc_server_remove_from_channels(server, NULL, client,
FALSE, NULL, FALSE);
+ /* Update statistics */
+ server->stat.my_clients--;
+ server->stat.clients--;
+ if (server->server_type == SILC_ROUTER)
+ server->stat.cell_clients--;
+ SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
+ SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
+
/* We will not delete the client entry right away. We will take it
into history (for WHOWAS command) for 5 minutes */
i->server = server;
client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
client->router = NULL;
client->connection = NULL;
-
- /* Free the client entry and everything in it */
- server->stat.my_clients--;
- server->stat.clients--;
- if (server->server_type == SILC_ROUTER)
- server->stat.cell_clients--;
+ client->mode = 0;
}
/* Frees user_data pointer from socket connection object. This also sends
entities. */
void silc_server_free_sock_user_data(SilcServer server,
- SilcSocketConnection sock)
+ SilcSocketConnection sock,
+ const char *signoff_message)
{
SILC_LOG_DEBUG(("Start"));
case SILC_SOCKET_TYPE_CLIENT:
{
SilcClientEntry user_data = (SilcClientEntry)sock->user_data;
- silc_server_free_client_data(server, sock, user_data, TRUE, NULL);
+ silc_server_free_client_data(server, sock, user_data, TRUE,
+ signoff_message);
break;
}
case SILC_SOCKET_TYPE_SERVER:
/* Check whether we have a backup router connection */
if (!backup_router || backup_router == user_data) {
silc_schedule_task_add(server->schedule, 0,
- silc_server_connect_to_router,
+ silc_server_connect_to_router,
server, 1, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_NORMAL);
/* If we have protocol active we must assure that we call the protocol's
final callback so that all the memory is freed. */
if (sock->protocol) {
+ silc_protocol_cancel(sock->protocol, server->schedule);
sock->protocol->state = SILC_PROTOCOL_STATE_ERROR;
silc_protocol_execute_final(sock->protocol, server->schedule);
+ sock->protocol = NULL;
return;
}
if (sock->user_data)
- silc_server_free_sock_user_data(server, sock);
+ silc_server_free_sock_user_data(server, sock, NULL);
silc_server_disconnect_remote(server, sock, "Server closed connection: "
"Connection timeout");
payload = silc_channel_key_payload_parse(key_payload->data,
key_payload->len);
if (!payload) {
- SILC_LOG_ERROR(("Bad channel key payload, dropped"));
+ SILC_LOG_ERROR(("Bad channel key payload received, dropped"));
channel = NULL;
goto out;
}
SilcIDCacheEntry cache;
bool global;
+ SILC_LOG_DEBUG(("Start"));
+
for (i = 0; i < user_count; i++) {
/* Client ID */
SILC_GET16_MSB(idp_len, user_list->data + 2);
it using WHOIS command. */
SilcClientEntry silc_server_get_client_resolve(SilcServer server,
- SilcClientID *client_id)
+ SilcClientID *client_id,
+ bool *resolved)
{
SilcClientEntry client;
+ if (resolved)
+ *resolved = FALSE;
+
client = silc_idlist_find_client_by_id(server->local_list, client_id,
TRUE, NULL);
if (!client) {
buffer->data, buffer->len, FALSE);
silc_buffer_free(idp);
silc_buffer_free(buffer);
+
+ if (resolved)
+ *resolved = TRUE;
+
return NULL;
}