From 981c96d5e7e5d654c0da7912626a44afcc960bed Mon Sep 17 00:00:00 2001 From: Pekka Riikonen Date: Tue, 17 Apr 2001 22:17:01 +0000 Subject: [PATCH] updates. --- CHANGES | 51 ++++++++++++++++++ TODO | 3 -- apps/silcd/packet_receive.c | 8 ++- apps/silcd/packet_send.c | 6 ++- apps/silcd/protocol.c | 31 ++--------- apps/silcd/protocol.h | 6 +++ apps/silcd/server.c | 103 ++++++++++++++++++++++++++++-------- apps/silcd/serverconfig.c | 56 ++++++++++++++++++-- apps/silcd/serverconfig.h | 3 +- lib/silcutil/silcnet.c | 65 +++++++++++++++++++++++ lib/silcutil/silcnet.h | 1 + 11 files changed, 275 insertions(+), 58 deletions(-) diff --git a/CHANGES b/CHANGES index a03d3512..939fa274 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,54 @@ +Tue Apr 17 21:18:19 EEST 2001 Pekka Riikonen + + * 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 * Updated TODO. diff --git a/TODO b/TODO index bed19134..658383a9 100644 --- a/TODO +++ b/TODO @@ -48,9 +48,6 @@ TODO/bugs In SILC Server 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 diff --git a/apps/silcd/packet_receive.c b/apps/silcd/packet_receive.c index e5669d7e..b6caf4ef 100644 --- a/apps/silcd/packet_receive.c +++ b/apps/silcd/packet_receive.c @@ -1601,11 +1601,17 @@ static void silc_server_new_id_real(SilcServer server, 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); diff --git a/apps/silcd/packet_send.c b/apps/silcd/packet_send.c index c64ef04b..00f30978 100644 --- a/apps/silcd/packet_send.c +++ b/apps/silcd/packet_send.c @@ -866,7 +866,8 @@ void silc_server_send_notify(SilcServer server, 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); } @@ -884,7 +885,8 @@ void silc_server_send_notify_args(SilcServer server, 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); } diff --git a/apps/silcd/protocol.c b/apps/silcd/protocol.c index a13d193c..10e74a9d 100644 --- a/apps/silcd/protocol.c +++ b/apps/silcd/protocol.c @@ -665,14 +665,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* 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) { @@ -734,15 +727,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* 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: @@ -803,15 +789,8 @@ SILC_TASK_CALLBACK(silc_server_protocol_connection_auth) /* 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: diff --git a/apps/silcd/protocol.h b/apps/silcd/protocol.h index 99f2e720..f5ab3c5b 100644 --- a/apps/silcd/protocol.h +++ b/apps/silcd/protocol.h @@ -43,6 +43,9 @@ typedef struct { void *dest_id; SilcIdType dest_id_type; + /* Pointer to the configuration. */ + void *config; + SilcTask timeout_task; SilcPacketContext *packet; SilcSKE ske; @@ -76,6 +79,9 @@ typedef struct { void *dest_id; SilcIdType dest_id_type; + /* Pointer to the configuration. */ + void *config; + SilcTask timeout_task; SilcPacketContext *packet; uint16 conn_type; diff --git a/apps/silcd/server.c b/apps/silcd/server.c index 288a5734..7a88cad3 100644 --- a/apps/silcd/server.c +++ b/apps/silcd/server.c @@ -239,6 +239,23 @@ int silc_server_init(SilcServer server) &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. */ @@ -929,7 +946,8 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection) SilcServer server = (SilcServer)context; SilcSocketConnection newsocket; SilcServerKEInternalContext *proto_ctx; - int sock; + int sock, port; + void *config; SILC_LOG_DEBUG(("Accepting new connection")); @@ -977,6 +995,45 @@ SILC_TASK_CALLBACK(silc_server_accept_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)); @@ -987,6 +1044,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection) 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 @@ -1007,14 +1065,6 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection) 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 @@ -1093,6 +1143,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_second) 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); @@ -1192,6 +1243,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) 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 ? @@ -1224,12 +1276,14 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) 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) { @@ -1237,6 +1291,7 @@ SILC_TASK_CALLBACK(silc_server_accept_new_connection_final) server->router = id_entry; } } + break; } default: @@ -1473,7 +1528,8 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real) 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)) { @@ -1489,18 +1545,21 @@ SILC_TASK_CALLBACK(silc_server_packet_parse_real) 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); @@ -2334,8 +2393,8 @@ int silc_server_remove_clients_by_server(SilcServer server, 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); diff --git a/apps/silcd/serverconfig.c b/apps/silcd/serverconfig.c index 1a9abdf3..d099e7dd 100644 --- a/apps/silcd/serverconfig.c +++ b/apps/silcd/serverconfig.c @@ -760,7 +760,7 @@ int silc_server_config_parse_lines(SilcServerConfig config, ret = silc_config_get_token(line, &tmp); if (ret < 0) break; - if (ret == 0) { + if (ret) { config->clients->port = atoi(tmp); silc_free(tmp); } @@ -1106,6 +1106,8 @@ int silc_server_config_parse_lines(SilcServerConfig config, 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; @@ -1422,7 +1424,8 @@ void silc_server_config_register_hmacs(SilcServerConfig config) } /* 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, @@ -1430,6 +1433,7 @@ silc_server_config_find_client_conn(SilcServerConfig config, { int i; SilcServerConfigSectionClientConnection *client = NULL; + bool match = FALSE; if (!host) return NULL; @@ -1441,7 +1445,14 @@ silc_server_config_find_client_conn(SilcServerConfig config, 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; } @@ -1452,7 +1463,8 @@ silc_server_config_find_client_conn(SilcServerConfig config, } /* 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, @@ -1460,6 +1472,7 @@ silc_server_config_find_server_conn(SilcServerConfig config, { int i; SilcServerConfigSectionServerConnection *serv = NULL; + bool match = FALSE; if (!host) return NULL; @@ -1470,7 +1483,14 @@ silc_server_config_find_server_conn(SilcServerConfig config, 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; } @@ -1489,6 +1509,7 @@ silc_server_config_find_router_conn(SilcServerConfig config, { int i; SilcServerConfigSectionServerConnection *serv = NULL; + bool match = FALSE; if (!host) return NULL; @@ -1499,7 +1520,14 @@ silc_server_config_find_router_conn(SilcServerConfig config, 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; } @@ -1509,6 +1537,28 @@ silc_server_config_find_router_conn(SilcServerConfig config, 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. */ diff --git a/apps/silcd/serverconfig.h b/apps/silcd/serverconfig.h index 885c32eb..5b6c3aa9 100644 --- a/apps/silcd/serverconfig.h +++ b/apps/silcd/serverconfig.h @@ -131,7 +131,7 @@ typedef struct SilcServerConfigSectionServerConnectionStruct { uint16 port; char *version; uint32 class; - int initiator; + bool initiator; struct SilcServerConfigSectionServerConnectionStruct *next; struct SilcServerConfigSectionServerConnectionStruct *prev; } SilcServerConfigSectionServerConnection; @@ -269,6 +269,7 @@ silc_server_config_find_server_conn(SilcServerConfig config, 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); diff --git a/lib/silcutil/silcnet.c b/lib/silcutil/silcnet.c index 71fd0667..0f240b7c 100644 --- a/lib/silcutil/silcnet.c +++ b/lib/silcutil/silcnet.c @@ -299,6 +299,71 @@ bool silc_net_check_host_by_sock(int sock, char **hostname, char **ip) 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) diff --git a/lib/silcutil/silcnet.h b/lib/silcutil/silcnet.h index 8445d141..7522e5a1 100644 --- a/lib/silcutil/silcnet.h +++ b/lib/silcutil/silcnet.h @@ -32,6 +32,7 @@ int silc_net_set_socket_nonblock(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(); -- 2.24.0