checking into the server.
Added silc_identifier_check for applications to easy check
for validity of identifier strings.
+Tue Mar 29 16:51:35 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
+
+ * Added support for the new identifier strings and their
+ validity checking. Nicknames, channel names and usernames
+ can now include practically any kind of letters and various
+ other characters. Affected files in silcd/ and in libraries.
+
+ NOTE: comparing these strings should now be done with memcmp()
+ to check binary compatibility. All these strings are normalized
+ and casing is irrelevant.
+
+ * Added silc_identifier_check to lib/silcutil/silcstrutil.[ch]
+ as easy function for applications to check whether identifier
+ strings are valid.
+
Tue Mar 29 00:45:11 EEST 2005 Pekka Riikonen <priikone@silcnet.org>
* Fixed SILC_STRING_LDAP_DN encoding and decoding. Affected
Wed Sep 22 19:46:32 CEST 2004 Patrik Weiskircher <pat@icore.at>
* When using silc_net_create_connection[_async], and your system can
- create IPv6 sockets, it will try to connect to the IPv6 host.
- Now it tries to connect to an IPv4 host if IPv6 fails. Affected
+ create IPv6 sockets, it will try to connect to the IPv6 host.
+ Now it tries to connect to an IPv4 host if IPv6 fails. Affected
file lib/silcutil/unix/silcunixnet.c
Fri Jun 18 19:26:58 CEST 2004 Pekka Riikonen <priikone@silcnet.org>
Fri Apr 30 19:40:28 CEST 2004 Patrik Weiskircher <pat@icore.at>
- * Added check to ignore Port value if Initiator is FALSE.
+ * Added check to ignore Port value if Initiator is FALSE.
Remote router coudln't connect if Port was set. Affected file
silcd/serverconfig.c
o Basic UTF-8 stringprep profile that makes sure UTF-8 strings are
as defined in spec-08 section 3.13.
- o Start using the stringprep for identifier strings.
-
o Check that founder key is distributed ok during backup resuming.
o Testing
TODO/bugs In SILC Libraries
===========================
+ o Stringprep checks to the Client Library.
+
o Add following defines in silcincludes.h and silcclient.h for
third-party software:
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
SilcBuffer packet, nidp, oidp = NULL;
SilcClientID *new_id;
SilcUInt32 nick_len;
- char *nick;
+ unsigned char *nick = NULL;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
int nickfail = 0;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
- /* Check nickname */
+ /* Get nickname */
nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
if (!nick) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
SILC_STATUS_ERR_BAD_NICKNAME, 0);
goto out;
}
- if (nick_len > 128)
+
+ /* Truncate over long nicks */
+ if (nick_len > 128) {
nick[128] = '\0';
- if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
+ nick_len = 128;
+ }
+
+ /* Check for valid nickname string */
+ nick = silc_identifier_check(nick, nick_len, SILC_STRING_UTF8, 128,
+ &nick_len);
+ if (!nick) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
SILC_STATUS_ERR_BAD_NICKNAME, 0);
+ silc_free(nick);
goto out;
}
/* Check for same nickname */
- if (!strcmp(client->nickname, nick)) {
+ if (!memcmp(client->nickname, nick, nick_len)) {
nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
+ silc_free(nick);
+ nick = client->nickname;
goto send_reply;
}
/* Create new Client ID */
while (!silc_id_create_client_id(cmd->server, cmd->server->id,
cmd->server->rng,
- cmd->server->md5hash, nick,
+ cmd->server->md5hash, nick, nick_len,
&new_id)) {
nickfail++;
if (nickfail > 9) {
SILC_STATUS_ERR_BAD_NICKNAME, 0);
goto out;
}
- snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
+ if (nickfail < 2) {
+ nick = silc_realloc(nick, sizeof(*nick) * (nick_len + 2));
+ if (!nick) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
+ SILC_STATUS_ERR_BAD_NICKNAME, 0);
+ goto out;
+ }
+ nick_len += 2;
+ nick[nick_len - 1] = '\0';
+ }
+ snprintf(&nick[nick_len - 2], 1, "%d", nickfail);
}
/* Send notify about nickname change to our router. We send the new
client->id = new_id;
silc_free(client->nickname);
- client->nickname = strdup(nick);
+ client->nickname = nick;
/* Update client cache */
silc_idcache_add(server->local_list->clients, client->nickname,
packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
SILC_STATUS_OK, 0, ident, 2,
2, nidp->data, nidp->len,
- 3, nick, strlen(nick));
+ 3, nick, nick_len);
silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
0, packet->data, packet->len, FALSE);
SilcBuffer packet, idp;
unsigned char *tmp;
SilcUInt32 tmp_len;
- char *dest_server, *server_info = NULL, *server_name;
+ char *dest_server = NULL, *server_info = NULL, *server_name;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
SilcServerEntry entry = NULL;
SilcServerID *server_id = NULL;
/* Get server name */
dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
+ if (dest_server) {
+ /* Check server name */
+ dest_server = silc_identifier_check(dest_server, strlen(dest_server),
+ SILC_STRING_UTF8, 256, &tmp_len);
+ if (!dest_server) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
+ SILC_STATUS_ERR_BAD_SERVER, 0);
+ goto out;
+ }
+ }
/* Get Server ID */
tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
silc_buffer_free(idp);
out:
+ silc_free(dest_server);
silc_server_command_free(cmd);
}
0);
goto out;
}
- channel_name = tmp;
- if (tmp_len > 256)
- channel_name[255] = '\0';
+ /* Truncate over long channel names */
+ if (tmp_len > 256) {
+ tmp[256] = '\0';
+ tmp_len = 256;
+ }
- if (silc_server_name_bad_chchars(channel_name, tmp_len) == TRUE) {
+ /* Check for valid channel name */
+ channel_name = silc_identifier_check(tmp, tmp_len, SILC_STRING_UTF8, 256,
+ &tmp_len);
+ if (!channel_name) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
SILC_STATUS_ERR_BAD_CHANNEL, 0);
goto out;
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcBuffer packet, idp;
- char *motd, *dest_server;
+ char *motd, *dest_server = NULL;
SilcUInt32 motd_len;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
goto out;
}
- if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
+ /* Check server name */
+ dest_server = silc_identifier_check(dest_server, strlen(dest_server),
+ SILC_STRING_UTF8, 256, NULL);
+ if (!dest_server) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
+ SILC_STATUS_ERR_BAD_SERVER,
+ 0);
+ goto out;
+ }
+
+ if (!memcmp(dest_server, server->server_name, strlen(dest_server))) {
/* Send our MOTD */
idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
}
out:
+ silc_free(dest_server);
silc_server_command_free(cmd);
}
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
- unsigned char *username, *auth;
+ unsigned char *username = NULL, *auth;
SilcUInt32 tmp_len;
SilcServerConfigAdmin *admin;
SilcIDListData idata = (SilcIDListData)client;
goto out;
}
+ /* Check username */
+ username = silc_identifier_check(username, strlen(username),
+ SILC_STRING_UTF8, 128, &tmp_len);
+ if (!username) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
+ SILC_STATUS_ERR_BAD_USERNAME,
+ 0);
+ goto out;
+ }
+
/* Get the admin configuration */
admin = silc_server_config_find_admin(server, cmd->sock->ip,
username, client->nickname);
SILC_STATUS_OK, 0);
out:
+ silc_free(username);
silc_server_command_free(cmd);
}
SilcServer server = cmd->server;
char *add_nick, *del_nick;
SilcUInt32 add_nick_len, del_nick_len, tmp_len, pk_len;
- char nick[128 + 1];
- unsigned char hash[16], *tmp, *pk;
+ unsigned char hash[16], *tmp, *pk, *nick;
SilcClientEntry client;
SilcClientID *client_id = NULL;
goto out;
}
- if (add_nick && add_nick_len > 128)
+ if (add_nick && add_nick_len > 128) {
add_nick[128] = '\0';
- if (del_nick && del_nick_len > 128)
+ add_nick_len = 128;
+ }
+ if (del_nick && del_nick_len > 128) {
del_nick[128] = '\0';
-
- memset(nick, 0, sizeof(nick));
+ del_nick_len = 128;
+ }
/* Add new nickname to be watched in our cell */
if (add_nick) {
- if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
+ nick = silc_identifier_check(add_nick, add_nick_len, SILC_STRING_UTF8, 128,
+ &add_nick_len);
+ if (!nick) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
SILC_STATUS_ERR_BAD_NICKNAME, 0);
goto out;
/* Hash the nick, we have the hash saved, not nicks because we can
do one to one mapping to the nick from Client ID hash this way. */
- silc_to_lower(add_nick, nick, sizeof(nick) - 1);
- silc_hash_make(server->md5hash, nick, strlen(nick), hash);
+ silc_hash_make(server->md5hash, nick, add_nick_len, hash);
/* Check whether this client is already watching this nickname */
if (silc_hash_table_find_by_context(server->watcher_list, hash,
silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
SILC_STATUS_ERR_NICKNAME_IN_USE,
0);
+ silc_free(nick);
goto out;
}
/* Add the client to the watcher list with the specified nickname hash. */
silc_hash_table_add(server->watcher_list, tmp, client);
+ silc_free(nick);
}
/* Delete nickname from watch list */
if (del_nick) {
- if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
+ nick = silc_identifier_check(del_nick, del_nick_len, SILC_STRING_UTF8, 128,
+ &del_nick_len);
+ if (!nick) {
silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
SILC_STATUS_ERR_BAD_NICKNAME, 0);
goto out;
/* Hash the nick, we have the hash saved, not nicks because we can
do one to one mapping to the nick from Client ID hash this way. */
- silc_to_lower(del_nick, nick, sizeof(nick) - 1);
- silc_hash_make(server->md5hash, nick, strlen(nick), hash);
+ silc_hash_make(server->md5hash, nick, del_nick_len, hash);
/* Check that this client is watching for this nickname */
if (!silc_hash_table_find_by_context(server->watcher_list, hash,
/* Nickname is alredy being watched for this client */
silc_server_command_send_status_data(cmd, SILC_COMMAND_WATCH,
SILC_STATUS_ERR_NO_SUCH_NICK, 0,
- 2, nick, strlen(nick));
+ 2, nick, del_nick_len);
+ silc_free(nick);
goto out;
}
then free the key to not leak memory. */
if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
silc_free(tmp);
+ silc_free(nick);
}
/* Add/del public key */
SilcServerCommandContext cmd = (SilcServerCommandContext)context;
SilcServer server = cmd->server;
SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
- unsigned char *username, *auth;
+ unsigned char *username = NULL, *auth;
SilcUInt32 tmp_len;
SilcServerConfigAdmin *admin;
SilcIDListData idata = (SilcIDListData)client;
goto out;
}
+ /* Check username */
+ username = silc_identifier_check(username, tmp_len, SILC_STRING_UTF8, 128,
+ &tmp_len);
+ if (!username) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
+ SILC_STATUS_ERR_BAD_USERNAME,
+ 0);
+ goto out;
+ }
+
/* Get the admin configuration */
admin = silc_server_config_find_admin(server, cmd->sock->ip,
username, client->nickname);
SILC_STATUS_OK, 0);
out:
+ silc_free(username);
silc_server_command_free(cmd);
}
unsigned char lc[4];
SilcUInt32 list_count = 0;
SilcUInt16 ident = silc_command_get_ident(cmd->payload);
- char *channel_name;
+ char *channel_name = NULL;
SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
goto out;
}
+ /* Check channel name */
+ if (channel_name) {
+ channel_name = silc_identifier_check(channel_name, strlen(channel_name),
+ SILC_STRING_UTF8, 256, NULL);
+ if (!channel_name) {
+ silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
+ SILC_STATUS_ERR_BAD_CHANNEL, 0);
+ goto out;
+ }
+ }
+
+ /* Check Channel ID */
if (channel_id) {
id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
if (!id) {
silc_free(id);
out:
+ silc_free(channel_name);
silc_server_command_free(cmd);
}
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
fingerprint = silc_argument_get_arg_type(cmd->args, 9, &flen);
+ /* Check for valid username */
+ username = silc_identifier_check(username, strlen(username),
+ SILC_STRING_UTF8, 128, NULL);
+ if (!username) {
+ SILC_LOG_ERROR(("Malformed username received in WHOIS reply"));
+ return FALSE;
+ }
+
/* Check if we have this client cached already. */
client = silc_idlist_find_client_by_id(server->local_list, client_id,
if (!client) {
/* If router did not find such Client ID in its lists then this must
be bogus client or some router in the net is buggy. */
- if (server->server_type != SILC_SERVER)
+ if (server->server_type != SILC_SERVER) {
+ silc_free(username);
return FALSE;
+ }
/* Take hostname out of nick string if it includes it. */
silc_parse_userfqdn(nickname, &nick, &servername);
+ /* Check nickname */
+ nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+ 128, NULL);
+ if (!nickname) {
+ SILC_LOG_ERROR(("Malformed nickname received in WHOIS reply"));
+ silc_free(username);
+ return FALSE;
+ }
+ silc_free(nick);
+ nick = nickname;
+
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, nick,
- strdup(username),
+ client = silc_idlist_add_client(server->global_list, nick, username,
strdup(realname), client_id,
cmd->sock->user_data, NULL, 0);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+ silc_free(nick);
+ silc_free(username);
return FALSE;
}
/* Take hostname out of nick string if it includes it. */
silc_parse_userfqdn(nickname, &nick, &servername);
+ /* Check nickname */
+ nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+ 128, NULL);
+ if (!nickname) {
+ SILC_LOG_ERROR(("Malformed nickname received in WHOIS reply"));
+ silc_free(username);
+ return FALSE;
+ }
+ silc_free(nick);
+ nick = nickname;
+
/* Remove the old cache entry */
silc_idcache_del_by_context(global ? server->global_list->clients :
server->local_list->clients, client);
silc_free(client->servername);
client->nickname = nick;
- client->username = strdup(username);
+ client->username = username;
client->userinfo = strdup(realname);
client->servername = servername;
client->mode = mode;
}
}
+ silc_free(username);
return TRUE;
}
if (!client_id)
return FALSE;
+ /* Check for valid username */
+ username = silc_identifier_check(username, strlen(username),
+ SILC_STRING_UTF8, 128, NULL);
+ if (!username) {
+ SILC_LOG_ERROR(("Malformed username received in WHOWAS reply"));
+ return FALSE;
+ }
+
/* Check if we have this client cached already. */
client = silc_idlist_find_client_by_id(server->local_list, client_id,
if (!client) {
/* If router did not find such Client ID in its lists then this must
be bogus client or some router in the net is buggy. */
- if (server->server_type != SILC_SERVER)
+ if (server->server_type != SILC_SERVER) {
+ silc_free(username);
return FALSE;
+ }
/* Take hostname out of nick string if it includes it. */
silc_parse_userfqdn(nickname, &nick, &servername);
+ /* Check nickname */
+ nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+ 128, NULL);
+ if (!nickname) {
+ SILC_LOG_ERROR(("Malformed nickname received in WHOWAS reply"));
+ silc_free(username);
+ return FALSE;
+ }
+ silc_free(nick);
+ nick = nickname;
+
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
- client = silc_idlist_add_client(server->global_list, nick,
- strdup(username), strdup(realname),
+ client = silc_idlist_add_client(server->global_list, nick, username,
+ strdup(realname),
silc_id_dup(client_id, SILC_ID_CLIENT),
cmd->sock->user_data, NULL,
SILC_ID_CACHE_EXPIRE_DEF);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+ silc_free(nick);
+ silc_free(username);
return FALSE;
}
/* Take hostname out of nick string if it includes it. */
silc_parse_userfqdn(nickname, &nick, &servername);
+ /* Check nickname */
+ nickname = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+ 128, NULL);
+ if (!nickname) {
+ SILC_LOG_ERROR(("Malformed nickname received in WHOWAS reply"));
+ silc_free(username);
+ return FALSE;
+ }
+ silc_free(nick);
+ nick = nickname;
+
silc_free(client->nickname);
silc_free(client->username);
silc_free(client->servername);
client->nickname = nick;
- client->username = strdup(username);
+ client->username = username;
client->servername = servername;
client->data.status |= SILC_IDLIST_STATUS_RESOLVED;
client->data.status &= ~SILC_IDLIST_STATUS_RESOLVING;
}
silc_free(client_id);
+ silc_free(username);
return TRUE;
}
goto error;
/* Take nickname */
- if (name)
+ if (name) {
silc_parse_userfqdn(name, &nick, NULL);
+ /* Check nickname */
+ name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+ 128, NULL);
+ if (!name) {
+ SILC_LOG_ERROR(("Malformed nickname received in IDENTIFY reply"));
+ return FALSE;
+ }
+ silc_free(nick);
+ nick = name;
+ }
+
/* We don't have that client anywhere, add it. The client is added
to global list since server didn't have it in the lists so it must be
global. */
NULL, time(NULL) + 300);
if (!client) {
SILC_LOG_ERROR(("Could not add new client to the ID Cache"));
+ silc_free(nick);
goto error;
}
client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
if (name) {
silc_parse_userfqdn(name, &nick, NULL);
+ /* Check nickname */
+ name = silc_identifier_check(nick, strlen(nick), SILC_STRING_UTF8,
+ 128, NULL);
+ if (!name) {
+ SILC_LOG_ERROR(("Malformed nickname received in IDENTIFY reply"));
+ return FALSE;
+ }
+ silc_free(nick);
+ nick = name;
+
/* Remove the old cache entry */
silc_idcache_del_by_context(global ? server->global_list->clients :
server->local_list->clients, client);
SilcServerEntry entry;
SilcServerID *server_id;
SilcUInt32 tmp_len;
- unsigned char *tmp, *name;
+ unsigned char *tmp, *name = NULL;
COMMAND_CHECK_STATUS;
/* Get the name */
name = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
- if (tmp_len > 256)
+ if (!name)
+ goto out;
+
+ /* Check server name */
+ name = silc_identifier_check(name, tmp_len, SILC_STRING_UTF8,
+ 256, NULL);
+ if (!name)
goto out;
entry = silc_idlist_find_server_by_id(server->local_list, server_id,
cmd->sock);
if (!entry) {
silc_free(server_id);
+ silc_free(name);
goto out;
}
entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
entry->server_info = tmp ? strdup(tmp) : NULL;
+ silc_free(name);
+
out:
SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
err:
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2003 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
while (silc_idcache_list_next(list, &id_cache))
(*clients)[(*clients_count)++] = (SilcClientEntry)id_cache->context;
-
silc_idcache_list_free(list);
SILC_LOG_DEBUG(("Found total %d clients", *clients_count));
SilcIDCacheEntry id_cache = NULL;
unsigned char hash[32];
SilcClientID client_id;
- char nick[128 + 1];
SILC_LOG_DEBUG(("Start"));
- memset(nick, 0, sizeof(nick));
- silc_to_lower(nickname, nick, sizeof(nick) - 1);
- silc_hash_make(md5hash, nick, strlen(nick), hash);
+ silc_hash_make(md5hash, nickname, strlen(nickname), hash);
/* As the Client ID is hashed in the ID cache by hashing only the hash
from the Client ID, we can do a lookup with only the hash not the
silc_free(client->id);
silc_free(client->nickname);
client->id = new_id;
- client->nickname = nickname ? strdup(nickname) : NULL;
+ client->nickname = nickname ? silc_memdup(nickname, strlen(nickname)) : NULL;
/* Check if anyone is watching new nickname */
if (server->server_type == SILC_ROUTER)
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
SilcIDListData idata;
char *username = NULL, *realname = NULL;
SilcUInt16 username_len;
- SilcUInt32 id_len;
+ SilcUInt32 id_len, tmp_len;
int ret;
- char *hostname, *nickname;
+ char *hostname, *nickname, *tmp;
int nickfail = 0;
SILC_LOG_DEBUG(("Creating new client"));
return NULL;
}
- if (username_len > 128)
+ if (username_len > 128) {
username[128] = '\0';
+ username_len = 128;
+ }
- /* Check for bad characters for nickname, and modify the nickname if
- it includes those. */
- if (silc_server_name_bad_chars(username, username_len)) {
- nickname = silc_server_name_modify_bad(username, username_len);
- } else {
- nickname = strdup(username);
+ /* Check for valid username string */
+ tmp = silc_identifier_check(username, username_len, SILC_STRING_UTF8, 128,
+ &tmp_len);
+ if (!tmp) {
+ silc_free(username);
+ silc_free(realname);
+ SILC_LOG_ERROR(("Client %s (%s) sent bad username string, closing "
+ "connection", sock->hostname, sock->ip));
+ silc_server_disconnect_remote(server, sock,
+ SILC_STATUS_ERR_INCOMPLETE_INFORMATION,
+ NULL);
+ if (sock->user_data)
+ silc_server_free_sock_user_data(server, sock, NULL);
+ return NULL;
}
+ silc_free(username);
+ username = tmp;
+ username_len = tmp_len;
+
+ /* Nickname is initially same as username */
+ nickname = silc_memdup(username, username_len);
/* Make sanity checks for the hostname of the client. If the hostname
is provided in the `username' check that it is the same than the
/* Create Client ID */
while (!silc_id_create_client_id(server, server->id, server->rng,
- server->md5hash, nickname, &client_id)) {
+ server->md5hash, nickname,
+ strlen(nickname), &client_id)) {
nickfail++;
if (nickfail > 9) {
silc_server_disconnect_remote(server, sock,
}
/* If the ID is not based in our ID then change it */
- if (!SILC_ID_COMPARE(detached_client->id, server->id,
+ if (!SILC_ID_COMPARE(detached_client->id, server->id,
server->id->ip.data_len)) {
silc_free(client_id);
while (!silc_id_create_client_id(server, server->id, server->rng,
server->md5hash,
detached_client->nickname,
+ strlen(detached_client->nickname),
&client_id)) {
nickfail++;
if (nickfail > 9) {
silc_server_free_sock_user_data(server, sock, NULL);
return;
}
+ if (nickfail < 2) {
+ detached_client->nickname =
+ silc_realloc(detached_client->nickname,
+ sizeof(*detached_client->nickname) *
+ (strlen(detached_client->nickname) + 2));
+ detached_client->
+ nickname[strlen(detached_client->nickname) - 1] = '\0';
+ }
snprintf(&detached_client->
- nickname[strlen(detached_client->nickname) - 1], 1,
+ nickname[strlen(detached_client->nickname) - 2], 1,
"%d", nickfail);
}
nick_change = TRUE;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
if (!id)
goto err;
+ /* Check server name */
+ server->server_name =
+ silc_identifier_check(server->config->server_info->server_name,
+ strlen(server->config->server_info->server_name),
+ SILC_STRING_LOCALE, 256, NULL);
+ if (!server->server_name) {
+ SILC_LOG_ERROR(("Malformed server name string '%s'",
+ server->config->server_info->server_name));
+ goto err;
+ }
+
server->id = id;
server->id_string = silc_id_id2str(id, SILC_ID_SERVER);
server->id_string_len = silc_id_get_len(id, SILC_ID_SERVER);
- server->server_name = server->config->server_info->server_name;
- server->config->server_info->server_name = NULL;
/* Add ourselves to the server list. We don't have a router yet
beacuse we haven't established a route yet. It will be done later.
/* Fix the server_name field */
if (strcmp(server->server_name, newconfig->server_info->server_name)) {
silc_free(server->server_name);
- server->server_name = newconfig->server_info->server_name;
- newconfig->server_info->server_name = NULL;
+
+ /* Check server name */
+ server->server_name =
+ silc_identifier_check(newconfig->server_info->server_name,
+ strlen(newconfig->server_info->server_name),
+ SILC_STRING_LOCALE, 256, NULL);
+ if (!server->server_name) {
+ SILC_LOG_ERROR(("Malformed server name string '%s'",
+ server->config->server_info->server_name));
+ return FALSE;
+ }
/* Update the idcache list with a fresh pointer */
silc_free(server->id_entry->server_name);
}
/* Callback for async connection to remote router */
-
+
SILC_TASK_CALLBACK(silc_server_connection_established)
-{
+{
SilcServer server = app_context;
SilcServerConnection sconn = (SilcServerConnection)context;
int sock = fd;
}
return;
}
-
+
SILC_LOG_DEBUG(("Connection to router %s:%d established", sconn->remote_host,
sconn->remote_port));
-
+
/* Continue with key exchange protocol */
silc_server_start_key_exchange(server, sconn, sock);
-}
-
+}
+
/* Generic routine to use connect to a router. */
SILC_TASK_CALLBACK(silc_server_connect_router)
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 - 2003 Pekka Riikonen
+ Copyright (C) 2002 - 2005 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
return;
}
+ /* Check nickname */
+ tmp = silc_identifier_check(query->nickname, strlen(query->nickname),
+ SILC_STRING_UTF8, 128, &tmp_len);
+ if (!tmp) {
+ silc_server_query_send_error(server, query,
+ SILC_STATUS_ERR_BAD_NICKNAME, 0);
+ silc_server_query_free(query);
+ }
+ silc_free(query->nickname);
+ query->nickname = tmp;
+
} else {
/* Parse the IDs included in the query */
query->ids = silc_calloc(argc, sizeof(*query->ids));
return;
}
+ /* Check nickname */
+ tmp = silc_identifier_check(query->nickname, strlen(query->nickname),
+ SILC_STRING_UTF8, 128, &tmp_len);
+ if (!tmp) {
+ silc_server_query_send_error(server, query,
+ SILC_STATUS_ERR_BAD_NICKNAME, 0);
+ silc_server_query_free(query);
+ }
+ silc_free(query->nickname);
+ query->nickname = tmp;
+
/* Get the max count of reply messages allowed */
tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
if (tmp && tmp_len == sizeof(SilcUInt32))
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
/* Make hash from the nick, or take it from Client ID */
if (client->nickname) {
- char nick[128 + 1];
- memset(nick, 0, sizeof(nick));
- silc_to_lower(client->nickname, nick, sizeof(nick) - 1);
- silc_hash_make(server->md5hash, nick, strlen(nick), hash);
+ silc_hash_make(server->md5hash, client->nickname,
+ strlen(client->nickname), hash);
} else {
memset(hash, 0, sizeof(hash));
memcpy(hash, client->id->hash, sizeof(client->id->hash));
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
bool silc_id_create_client_id(SilcServer server,
SilcServerID *server_id, SilcRng rng,
- SilcHash md5hash, char *nickname,
+ SilcHash md5hash,
+ unsigned char *nickname, SilcUInt32 nick_len,
SilcClientID **new_id)
{
unsigned char hash[16];
bool finding = FALSE;
- char nick[128 + 1];
SILC_LOG_DEBUG(("Creating new Client ID"));
*new_id = silc_calloc(1, sizeof(**new_id));
/* Create hash of the nickanem */
- memset(nick, 0, sizeof(nick));
- silc_to_lower(nickname, nick, sizeof(nick) - 1);
- silc_hash_make(md5hash, nick, strlen(nick), hash);
+ silc_hash_make(md5hash, nickname, nick_len, hash);
/* Create the ID */
memcpy((*new_id)->ip.data, server_id->ip.data, server_id->ip.data_len);
/* Assure that the ID does not exist already */
while (1) {
- if (!silc_idlist_find_client_by_id(server->local_list,
+ if (!silc_idlist_find_client_by_id(server->local_list,
*new_id, FALSE, NULL))
- if (!silc_idlist_find_client_by_id(server->global_list,
+ if (!silc_idlist_find_client_by_id(server->global_list,
*new_id, FALSE, NULL))
break;
/* Assure that the ID does not exist already */
while (1) {
- if (!silc_idlist_find_channel_by_id(server->local_list,
+ if (!silc_idlist_find_channel_by_id(server->local_list,
*new_id, NULL))
break;
(*new_id)->rnd++;
-
+
if (finding && (*new_id)->rnd == 0)
return FALSE;
-
+
if (!finding) {
(*new_id)->rnd = 0;
finding = TRUE;
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2002 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#define SERVERID_H
/* Prototypes */
-void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
+void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
SilcServerID **new_id);
bool silc_id_create_client_id(SilcServer server,
SilcServerID *server_id, SilcRng rng,
- SilcHash md5hash, char *nickname,
+ SilcHash md5hash, unsigned char *nickname,
+ SilcUInt32 nick_len,
SilcClientID **new_id);
bool silc_id_create_channel_id(SilcServer server,
SilcServerID *router_id, SilcRng rng,
Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
- Copyright (C) 2000 - 2004 Pekka Riikonen
+ Copyright (C) 2000 - 2005 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
SILC_32_TO_PTR(id_type),
silc_idcache_destructor, NULL, TRUE);
cache->name_table = silc_hash_table_alloc(count, silc_hash_string, NULL,
- silc_hash_string_compare, NULL,
+ silc_hash_data_compare, NULL,
NULL, NULL, TRUE);
cache->context_table = silc_hash_table_alloc(count, silc_hash_ptr, NULL,
NULL, NULL, NULL, NULL, TRUE);
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 - 2003 Pekka Riikonen
+ Copyright (C) 2002 - 2005 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
#define SILC_STATUS_ERR_TIMEDOUT 54
#define SILC_STATUS_ERR_UNSUPPORTED_PUBLIC_KEY 55
#define SILC_STATUS_ERR_OPERATION_ALLOWED 56
+#define SILC_STATUS_ERR_BAD_SERVER 57
+#define SILC_STATUS_ERR_BAD_USERNAME 58
/***/
#define SILC_STATUS_IS_ERROR(status) (status >= SILC_STATUS_ERR_NO_SUCH_NICK)
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 2002 - 2004 Pekka Riikonen
+ Copyright (C) 2002 - 2005 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
return dest;
}
+
+/* Checks that the 'identifier' string is valid identifier string
+ and does not contain any unassigned or prohibited character. This
+ function is used to check for valid nicknames, channel names,
+ server names, usernames, hostnames, service names, algorithm names,
+ other security property names, and SILC Public Key name. */
+
+unsigned char *silc_identifier_check(const unsigned char *identifier,
+ SilcUInt32 identifier_len,
+ SilcStringEncoding identifier_encoding,
+ SilcUInt32 max_allowed_length,
+ SilcUInt32 *out_len)
+{
+ unsigned char *utf8s;
+ SilcUInt32 utf8s_len;
+ SilcStringprepStatus status;
+
+ if (!identifier || !identifier_len)
+ return NULL;
+
+ if (max_allowed_length && identifier_len > max_allowed_length)
+ return NULL;
+
+ status = silc_stringprep(identifier, identifier_len,
+ identifier_encoding, SILC_IDENTIFIER_PREP, 0,
+ &utf8s, &utf8s_len, SILC_STRING_UTF8);
+ if (status != SILC_STRINGPREP_OK) {
+ SILC_LOG_DEBUG(("silc_stringprep() status error %d", status));
+ return NULL;
+ }
+
+ if (out_len)
+ *out_len = utf8s_len;
+
+ return utf8s;
+}
char *silc_strncat(char *dest, SilcUInt32 dest_size,
const char *src, SilcUInt32 src_len);
+/****f* silcutil/SilcStrUtilAPI/silc_identifier_check
+ *
+ * SYNOPSIS
+ *
+ * unsigned char *
+ * silc_identifier_check(const unsigned char *identifier,
+ * SilcUInt32 identifier_len,
+ * SilcStringEncoding identifier_encoding,
+ * SilcUInt32 max_allowed_length,
+ * SilcUInt32 *out_len);
+ *
+ * DESCRIPTION
+ *
+ * Checks that the 'identifier' string is valid identifier string
+ * and does not contain any unassigned or prohibited character. This
+ * function is used to check for valid nicknames, channel names,
+ * server names, usernames, hostnames, service names, algorithm names,
+ * other security property names, and SILC Public Key name.
+ *
+ * If the 'max_allowed_length' is non-zero the identifier cannot be
+ * longer than that, and NULL is returned if it is. If zero (0), no
+ * length limit exist. For nicknames the max length must be 128 bytes
+ * and for channel names 256 bytes. Other identifiers has no default
+ * limit, but application may choose one anyway.
+ *
+ * Returns the validated string, that the caller must free. Returns
+ * NULL if the identifier string is not valid or contain unassigned or
+ * prohibited characters. Such identifier strings must not be used
+ * SILC protocol. The returned string is always in UTF-8 encoding.
+ * The length of the returned string is in 'out_len'.
+ *
+ * NOTES
+ *
+ * In addition of validating the identifier string, this function
+ * may map characters to other characters or remove characters from the
+ * original string. This is done as defined in the SILC protocol. Error
+ * is returned only if the string contains unassigned or prohibited
+ * characters. The original 'identifier' is not modified at any point.
+ *
+ ***/
+unsigned char *silc_identifier_check(const unsigned char *identifier,
+ SilcUInt32 identifier_len,
+ SilcStringEncoding identifier_encoding,
+ SilcUInt32 max_allowed_length,
+ SilcUInt32 *out_len);
+
#endif /* SILCSTRUTIL_H */
Author: Pekka Riikonen <priikone@silcnet.org>
- Copyright (C) 1997 - 2004 Pekka Riikonen
+ Copyright (C) 1997 - 2005 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
}
} else {
if (left)
- *left = strdup(string);
+ *left = silc_memdup(string, strlen(string));
}
return TRUE;
{ STAT(TIMEDOUT), "Service timed out" },
{ STAT(UNSUPPORTED_PUBLIC_KEY), "Unsupported public key type" },
{ STAT(OPERATION_ALLOWED), "Operation is not allowed" },
+ { STAT(BAD_SERVER), "Bad server name" },
+ { STAT(BAD_USERNAME), "Bad user name" },
{ 0, NULL }
};