+Tue Apr 17 21:18:19 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
+
+ * Fixed the [AdminConnection] server config section to support
+ multiple entries. Affected file silcd/serverconfig.c.
+
+ * Added support into the server to check the validity of the
+ incoming connection before executing any KE or authentication
+ protocols.
+
+ * The connection configuration is now saved to the KE and
+ connection auth protocol contexts and not fetched anymore in
+ the protocol. Affected files silcd/server.c, silcd/protocol.[ch].
+
+ * The local hosts listenning address and port is also resolved
+ now when starting the server. We want to have the socket object
+ to include the real address and port for the listener. Added
+ new function silc_net_check_local_by_sock into the files
+ lib/silcutil/silcnet.[ch].
+
+ * Fixed a broadcast bug in server -> do not broadcast if we
+ are standalone.
+
+ * Fixed a routing bug. Do not route broadcast packets ever.
+ Broadcast packets must be processed always and not routed since
+ they may be destined to some other host than yourself and thus
+ would get routed without no good reason. Affected file is
+ silcd/server.c.
+
+ * Added function silc_server_config_is_primary_route to check
+ whether primary router connection has been configured (a router
+ configuration that we are initiating). If there is not, we
+ will assume that there is only two routers in the SILC network
+ and we will use the incoming router connection as our primary
+ route. Affected files silcd/serverconfig.[ch], silcd/server.c.
+
+ * Changed the order of the broadcasting. Broadcast _after_ the
+ packet has been processed not before. Affected file is
+ silcd/server.c.
+
+ * Fixed a [ClientConnection] parsing bug. The port was never
+ parsed correctly thus resulting to port 0. Affected file
+ silcd/serverconfig.c.
+
+ * Fixed silc_server_send_notify_args -> it ignored the `broadcast'
+ argument and did not set the broadcast packet flag. Affected
+ file silcd/packet_send.c. Fixed same bug in the function
+ silc_server_send_notify as well.
+
+ * If we receive NEW_ID packet for our own ID in the server, ignore
+ the packet.
+
Mon Apr 16 12:10:33 EEST 2001 Pekka Riikonen <priikone@poseidon.pspt.fi>
* Updated TODO.
own resolver stuff (through scheduler, if possible without writing
too much own stuff) or use threads.
- o [AdminConnection] config section does not work correctly, it takes
- only one entry and ignores the other -> authentication fails.
-
o [DenyConnection] config section is not implemented.
o The backup router support described in the protocol specification
break;
case SILC_ID_SERVER:
+ /* If the ID is mine, ignore it. */
+ if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
+ SILC_LOG_DEBUG(("Ignoring my own ID as new ID"));
+ break;
+ }
+
SILC_LOG_DEBUG(("New server id(%s) from [%s] %s",
silc_id_render(id, SILC_ID_SERVER),
sock->type == SILC_SOCKET_TYPE_SERVER ?
"Server" : "Router", sock->hostname));
-
+
/* As a router we keep information of all global information in our global
list. Cell wide information however is kept in the local list. */
silc_idlist_add_server(id_list, NULL, 0, id, router, router_sock);
va_start(ap, argc);
packet = silc_notify_payload_encode(type, argc, ap);
- silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY, 0,
+ silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY,
+ broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
}
SilcBuffer packet;
packet = silc_notify_payload_encode_args(type, argc, args);
- silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY, 0,
+ silc_server_packet_send(server, sock, SILC_PACKET_NOTIFY,
+ broadcast ? SILC_PACKET_FLAG_BROADCAST : 0,
packet->data, packet->len, FALSE);
silc_buffer_free(packet);
}
/* Remote end is client */
if (conn_type == SILC_SOCKET_TYPE_CLIENT) {
- SilcServerConfigSectionClientConnection *client = NULL;
- client = silc_server_config_find_client_conn(server->config,
- ctx->sock->ip,
- ctx->sock->port);
- if (!client)
- client = silc_server_config_find_client_conn(server->config,
- ctx->sock->hostname,
- ctx->sock->port);
+ SilcServerConfigSectionClientConnection *client = ctx->config;
if (client) {
switch(client->auth_meth) {
/* Remote end is server */
if (conn_type == SILC_SOCKET_TYPE_SERVER) {
- SilcServerConfigSectionServerConnection *serv = NULL;
- serv = silc_server_config_find_server_conn(server->config,
- ctx->sock->ip,
- ctx->sock->port);
- if (!serv)
- serv = silc_server_config_find_server_conn(server->config,
- ctx->sock->hostname,
- ctx->sock->port);
-
+ SilcServerConfigSectionServerConnection *serv = ctx->config;
+
if (serv) {
switch(serv->auth_meth) {
case SILC_AUTH_NONE:
/* Remote end is router */
if (conn_type == SILC_SOCKET_TYPE_ROUTER) {
- SilcServerConfigSectionServerConnection *serv = NULL;
- serv = silc_server_config_find_router_conn(server->config,
- ctx->sock->ip,
- ctx->sock->port);
- if (!serv)
- serv = silc_server_config_find_router_conn(server->config,
- ctx->sock->hostname,
- ctx->sock->port);
-
+ SilcServerConfigSectionServerConnection *serv = ctx->config;
+
if (serv) {
switch(serv->auth_meth) {
case SILC_AUTH_NONE:
void *dest_id;
SilcIdType dest_id_type;
+ /* Pointer to the configuration. */
+ void *config;
+
SilcTask timeout_task;
SilcPacketContext *packet;
SilcSKE ske;
void *dest_id;
SilcIdType dest_id_type;
+ /* Pointer to the configuration. */
+ void *config;
+
SilcTask timeout_task;
SilcPacketContext *packet;
uint16 conn_type;
&newsocket);
server->sockets[sock[i]] = newsocket;
+
+ /* Perform name and address lookups to resolve the listenning address
+ and port. */
+ if (!silc_net_check_local_by_sock(sock[i], &newsocket->hostname,
+ &newsocket->ip)) {
+ if ((server->params->require_reverse_mapping && !newsocket->hostname) ||
+ !newsocket->ip) {
+ SILC_LOG_ERROR(("IP/DNS lookup failed for local host %s",
+ newsocket->hostname ? newsocket->hostname :
+ newsocket->ip ? newsocket->ip : ""));
+ server->stat.conn_failures++;
+ goto err0;
+ }
+ if (!newsocket->hostname)
+ newsocket->hostname = strdup(newsocket->ip);
+ }
+ newsocket->port = silc_net_get_local_port(sock[i]);
/* Put the allocated socket pointer also to the entry allocated above
for fast back-referencing to the socket list. */
SilcServer server = (SilcServer)context;
SilcSocketConnection newsocket;
SilcServerKEInternalContext *proto_ctx;
- int sock;
+ int sock, port;
+ void *config;
SILC_LOG_DEBUG(("Accepting new connection"));
}
newsocket->port = silc_net_get_remote_port(sock);
+ /* Register the connection for network input and output. This sets
+ that scheduler will listen for incoming packets for this connection
+ and sets that outgoing packets may be sent to this connection as well.
+ However, this doesn't set the scheduler for outgoing traffic, it
+ will be set separately by calling SILC_SET_CONNECTION_FOR_OUTPUT,
+ later when outgoing data is available. */
+ SILC_REGISTER_CONNECTION_FOR_IO(sock);
+
+ /* Check whether we have configred this sort of connection at all. We
+ have to check all configurations since we don't know what type of
+ connection this is. */
+ port = server->sockets[fd]->port; /* Listenning port */
+ if (!(config = silc_server_config_find_client_conn(server->config,
+ newsocket->ip, port)))
+ if (!(config = silc_server_config_find_client_conn(server->config,
+ newsocket->hostname,
+ port)))
+ if (!(config = silc_server_config_find_server_conn(server->config,
+ newsocket->ip,
+ port)))
+ if (!(config = silc_server_config_find_server_conn(server->config,
+ newsocket->hostname,
+ port)))
+ if (!(config =
+ silc_server_config_find_router_conn(server->config,
+ newsocket->ip, port)))
+ if (!(config =
+ silc_server_config_find_router_conn(server->config,
+ newsocket->hostname,
+ port))) {
+ silc_server_disconnect_remote(server, newsocket,
+ "Server closed connection: "
+ "Connection refused");
+ server->stat.conn_failures++;
+ return;
+ }
+
+ /* The connection is allowed */
+
SILC_LOG_INFO(("Incoming connection from %s (%s)", newsocket->hostname,
newsocket->ip));
proto_ctx->sock = newsocket;
proto_ctx->rng = server->rng;
proto_ctx->responder = TRUE;
+ proto_ctx->config = config;
/* Prepare the connection for key exchange protocol. We allocate the
protocol but will not start it yet. The connector will be the
context, 60, 0,
SILC_TASK_TIMEOUT,
SILC_TASK_PRI_LOW);
-
- /* Register the connection for network input and output. This sets
- that scheduler will listen for incoming packets for this connection
- and sets that outgoing packets may be sent to this connection as well.
- However, this doesn't set the scheduler for outgoing traffic, it
- will be set separately by calling SILC_SET_CONNECTION_FOR_OUTPUT,
- later when outgoing data is available. */
- SILC_REGISTER_CONNECTION_FOR_IO(sock);
}
/* Second part of accepting new connection. Key exchange protocol has been
proto_ctx->responder = TRUE;
proto_ctx->dest_id_type = ctx->dest_id_type;
proto_ctx->dest_id = ctx->dest_id;
+ proto_ctx->config = ctx->config;
/* Free old protocol as it is finished now */
silc_protocol_free(protocol);
case SILC_SOCKET_TYPE_ROUTER:
{
SilcServerEntry new_server;
+ SilcServerConfigSectionServerConnection *conn = ctx->config;
SILC_LOG_DEBUG(("Remote host is %s",
sock->type == SILC_SOCKET_TYPE_SERVER ?
server->stat.servers++;
id_entry = (void *)new_server;
-
- /* There is connection to other server now, if it is router then
- we will have connection to outside world. If we are router but
- normal server connected to us then we will remain standalone,
- if we are standlone. */
+
+ /* Check whether this connection is to be our primary router connection
+ if we dont' already have the primary route. */
if (server->standalone && sock->type == SILC_SOCKET_TYPE_ROUTER) {
+ if (silc_server_config_is_primary_route(server->config) &&
+ !conn->initiator)
+ break;
+
SILC_LOG_DEBUG(("We are not standalone server anymore"));
server->standalone = FALSE;
if (!server->id_entry->router) {
server->router = id_entry;
}
}
+
break;
}
default:
if (server->server_type == SILC_ROUTER) {
/* Route the packet if it is not destined to us. Other ID types but
server are handled separately after processing them. */
- if (packet->dst_id_type == SILC_ID_SERVER &&
+ if (!(packet->flags & SILC_PACKET_FLAG_BROADCAST) &&
+ packet->dst_id_type == SILC_ID_SERVER &&
sock->type != SILC_SOCKET_TYPE_CLIENT &&
SILC_ID_SERVER_COMPARE(packet->dst_id, server->id_string)) {
silc_free(id);
goto out;
}
-
+ }
+
+ /* Parse the incoming packet type */
+ silc_server_packet_parse_type(server, sock, packet);
+
+ if (server->server_type == SILC_ROUTER) {
/* Broadcast packet if it is marked as broadcast packet and it is
originated from router and we are router. */
if (sock->type == SILC_SOCKET_TYPE_ROUTER &&
- packet->flags & SILC_PACKET_FLAG_BROADCAST) {
+ packet->flags & SILC_PACKET_FLAG_BROADCAST &&
+ !server->standalone) {
silc_server_packet_broadcast(server, server->router->connection, packet);
}
}
- /* Parse the incoming packet type */
- silc_server_packet_parse_type(server, sock, packet);
-
out:
/* silc_buffer_clear(sock->inbuf); */
silc_packet_context_free(packet);
argv_types);
silc_server_send_notify_args(server,
server->router->connection,
- server->server_type ==
- SILC_SERVER ? FALSE : TRUE,
+ server->server_type == SILC_SERVER ?
+ FALSE : TRUE,
SILC_NOTIFY_TYPE_SERVER_SIGNOFF,
argc, args);
silc_buffer_free(args);
ret = silc_config_get_token(line, &tmp);
if (ret < 0)
break;
- if (ret == 0) {
+ if (ret) {
config->clients->port = atoi(tmp);
silc_free(tmp);
}
config->clients = config->clients->prev;
while (config->servers && config->servers->prev)
config->servers = config->servers->prev;
+ while (config->admins && config->admins->prev)
+ config->admins = config->admins->prev;
while (config->routers && config->routers->prev)
config->routers = config->routers->prev;
}
/* Returns client authentication information from server configuration
- by host (name or ip). */
+ by host (name or ip). If `port' is non-null then both name or IP and
+ the port must match. */
SilcServerConfigSectionClientConnection *
silc_server_config_find_client_conn(SilcServerConfig config,
{
int i;
SilcServerConfigSectionClientConnection *client = NULL;
+ bool match = FALSE;
if (!host)
return NULL;
for (i = 0; client; i++) {
if (silc_string_compare(client->host, host))
+ match = TRUE;
+
+ if (port && client->port != port)
+ match = FALSE;
+
+ if (match)
break;
+
client = client->next;
}
}
/* Returns server connection info from server configuartion by host
- (name or ip). */
+ (name or ip). If `port' is non-null then both name or IP and the port
+ must match. */
SilcServerConfigSectionServerConnection *
silc_server_config_find_server_conn(SilcServerConfig config,
{
int i;
SilcServerConfigSectionServerConnection *serv = NULL;
+ bool match = FALSE;
if (!host)
return NULL;
serv = config->servers;
for (i = 0; serv; i++) {
if (silc_string_compare(serv->host, host))
+ match = TRUE;
+
+ if (port && serv->port != port)
+ match = FALSE;
+
+ if (match)
break;
+
serv = serv->next;
}
{
int i;
SilcServerConfigSectionServerConnection *serv = NULL;
+ bool match = FALSE;
if (!host)
return NULL;
serv = config->routers;
for (i = 0; serv; i++) {
if (silc_string_compare(serv->host, host))
+ match = TRUE;
+
+ if (port && serv->port != port)
+ match = FALSE;
+
+ if (match)
break;
+
serv = serv->next;
}
return serv;
}
+/* Returns TRUE if configuartion for a router connection that we are
+ initiating exists. */
+
+bool silc_server_config_is_primary_route(SilcServerConfig config)
+{
+ int i;
+ SilcServerConfigSectionServerConnection *serv = NULL;
+ bool found = FALSE;
+
+ serv = config->routers;
+ for (i = 0; serv; i++) {
+ if (serv->initiator == TRUE) {
+ found = TRUE;
+ break;
+ }
+
+ serv = serv->next;
+ }
+
+ return found;
+}
+
/* Returns Admin connection configuration by host, username and/or
nickname. */
uint16 port;
char *version;
uint32 class;
- int initiator;
+ bool initiator;
struct SilcServerConfigSectionServerConnectionStruct *next;
struct SilcServerConfigSectionServerConnectionStruct *prev;
} SilcServerConfigSectionServerConnection;
SilcServerConfigSectionServerConnection *
silc_server_config_find_router_conn(SilcServerConfig config,
char *host, int port);
+bool silc_server_config_is_primary_route(SilcServerConfig config);
SilcServerConfigSectionAdminConnection *
silc_server_config_find_admin(SilcServerConfig config,
char *host, char *username, char *nickname);
return TRUE;
}
+/* Performs lookups for local name and IP address. This peforms reverse
+ lookup as well to verify that the IP has FQDN. */
+
+bool silc_net_check_local_by_sock(int sock, char **hostname, char **ip)
+{
+ struct sockaddr_in local;
+ struct hostent *dest;
+ char *host_ip = NULL;
+ char host_name[1024];
+ int rval, len;
+ int i;
+
+ *hostname = NULL;
+ *ip = NULL;
+
+ SILC_LOG_DEBUG(("Resolving local hostname and IP address"));
+
+ memset(&local, 0, sizeof(local));
+ len = sizeof(local);
+ rval = getsockname(sock, (struct sockaddr *)&local, &len);
+ if (rval < 0)
+ return FALSE;
+
+ host_ip = inet_ntoa(local.sin_addr);
+ if (!host_ip)
+ return FALSE;
+
+ *ip = silc_calloc(strlen(host_ip) + 1, sizeof(char));
+ memcpy(*ip, host_ip, strlen(host_ip));
+
+ /* Get host by address */
+ dest = gethostbyaddr((char *)&local.sin_addr,
+ sizeof(struct in_addr), AF_INET);
+ if (!dest)
+ return FALSE;
+
+ /* Get same host by name to see that the local host really is
+ the who it says it is */
+ memset(host_name, 0, sizeof(host_name));
+ memcpy(host_name, dest->h_name, strlen(dest->h_name));
+
+ *hostname = silc_calloc(strlen(host_name) + 1, sizeof(char));
+ memcpy(*hostname, host_name, strlen(host_name));
+ SILC_LOG_DEBUG(("Resolved hostname `%s'", *hostname));
+
+ dest = gethostbyname(host_name);
+ if (!dest)
+ return FALSE;
+
+ /* Find the address from list */
+ for (i = 0; dest->h_addr_list[i]; i++)
+ if (!memcmp(dest->h_addr_list[i], &local.sin_addr,
+ sizeof(struct in_addr)))
+ break;
+ if (!dest->h_addr_list[i])
+ return FALSE;
+
+ silc_free(*ip);
+ *ip = silc_calloc(strlen(host_ip) + 1, sizeof(char));
+ memcpy(*ip, host_ip, strlen(host_ip));
+ SILC_LOG_DEBUG(("Resolved IP address `%s'", *ip));
+
+ return TRUE;
+}
+
/* Return remote port by socket. */
uint16 silc_net_get_remote_port(int sock)
int silc_net_set_socket_opt(int sock, int level, int option, int on);
int silc_net_is_ip(const char *addr);
bool silc_net_check_host_by_sock(int sock, char **hostname, char **ip);
+bool silc_net_check_local_by_sock(int sock, char **hostname, char **ip);
uint16 silc_net_get_remote_port(int sock);
uint16 silc_net_get_local_port(int sock);
char *silc_net_localhost();