Added support for the identifier strings and their validity
authorPekka Riikonen <priikone@silcnet.org>
Tue, 29 Mar 2005 14:14:55 +0000 (14:14 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Tue, 29 Mar 2005 14:14:55 +0000 (14:14 +0000)
checking into the server.
Added silc_identifier_check for applications to easy check
for validity of identifier strings.

16 files changed:
CHANGES
TODO
apps/silcd/command.c
apps/silcd/command_reply.c
apps/silcd/idlist.c
apps/silcd/packet_receive.c
apps/silcd/server.c
apps/silcd/server_query.c
apps/silcd/server_util.c
apps/silcd/serverid.c
apps/silcd/serverid.h
lib/silccore/silcidcache.c
lib/silccore/silcstatus.h
lib/silcutil/silcstrutil.c
lib/silcutil/silcstrutil.h
lib/silcutil/silcutil.c

diff --git a/CHANGES b/CHANGES
index 5ad094486b62658dc09c92b3fb6d1298d605299b..0b3d0474feb8f3ed8b3bfe8c26222af7996a1a30 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,18 @@
+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
@@ -91,8 +106,8 @@ Tue Nov 23 16:54:35 CET 2004  Pekka Riikonen <priikone@silcnet.org>
 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>
@@ -108,7 +123,7 @@ Sat May  1 13:55:54 CEST 2004  Patrik Weiskircher <pat@icore.at>
 
 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
 
diff --git a/TODO b/TODO
index 8a86a6fe814e29d627eff6cd92076dbd3167d079..1884155580a07de5f956bca86927d09aaad96a95 100644 (file)
--- a/TODO
+++ b/TODO
@@ -28,8 +28,6 @@ TODO for SILC Server 1.0
  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
@@ -38,6 +36,8 @@ TODO for SILC Server 1.0
 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:
 
index d0f4d3e811565d6feba99ed6b38ea5d623836b87..340100406efb871bd8af3591064f1a7e461ba2f7 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -626,7 +626,7 @@ SILC_SERVER_CMD_FUNC(nick)
   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;
 
@@ -635,31 +635,42 @@ SILC_SERVER_CMD_FUNC(nick)
 
   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) {
@@ -667,7 +678,17 @@ SILC_SERVER_CMD_FUNC(nick)
                                            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
@@ -691,7 +712,7 @@ SILC_SERVER_CMD_FUNC(nick)
   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,
@@ -717,7 +738,7 @@ SILC_SERVER_CMD_FUNC(nick)
   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);
 
@@ -1540,7 +1561,7 @@ SILC_SERVER_CMD_FUNC(info)
   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;
@@ -1549,6 +1570,16 @@ SILC_SERVER_CMD_FUNC(info)
 
   /* 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);
@@ -1691,6 +1722,7 @@ SILC_SERVER_CMD_FUNC(info)
   silc_buffer_free(idp);
 
  out:
+  silc_free(dest_server);
   silc_server_command_free(cmd);
 }
 
@@ -2326,12 +2358,17 @@ SILC_SERVER_CMD_FUNC(join)
                                          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;
@@ -2551,7 +2588,7 @@ SILC_SERVER_CMD_FUNC(motd)
   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);
 
@@ -2566,7 +2603,17 @@ SILC_SERVER_CMD_FUNC(motd)
     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);
@@ -2682,6 +2729,7 @@ SILC_SERVER_CMD_FUNC(motd)
   }
 
  out:
+  silc_free(dest_server);
   silc_server_command_free(cmd);
 }
 
@@ -3824,7 +3872,7 @@ SILC_SERVER_CMD_FUNC(oper)
   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;
@@ -3845,6 +3893,16 @@ SILC_SERVER_CMD_FUNC(oper)
     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);
@@ -3917,6 +3975,7 @@ SILC_SERVER_CMD_FUNC(oper)
                                        SILC_STATUS_OK, 0);
 
  out:
+  silc_free(username);
   silc_server_command_free(cmd);
 }
 
@@ -4040,8 +4099,7 @@ SILC_SERVER_CMD_FUNC(watch)
   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;
 
@@ -4126,16 +4184,20 @@ SILC_SERVER_CMD_FUNC(watch)
     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;
@@ -4143,8 +4205,7 @@ SILC_SERVER_CMD_FUNC(watch)
 
     /* 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,
@@ -4153,6 +4214,7 @@ SILC_SERVER_CMD_FUNC(watch)
       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
                                            SILC_STATUS_ERR_NICKNAME_IN_USE,
                                            0);
+      silc_free(nick);
       goto out;
     }
 
@@ -4163,11 +4225,14 @@ SILC_SERVER_CMD_FUNC(watch)
 
     /* 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;
@@ -4175,8 +4240,7 @@ SILC_SERVER_CMD_FUNC(watch)
 
     /* 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,
@@ -4184,7 +4248,8 @@ SILC_SERVER_CMD_FUNC(watch)
       /* 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;
     }
 
@@ -4195,6 +4260,7 @@ SILC_SERVER_CMD_FUNC(watch)
        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 */
@@ -4310,7 +4376,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   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;
@@ -4337,6 +4403,16 @@ SILC_SERVER_CMD_FUNC(silcoper)
     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);
@@ -4407,6 +4483,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
                                        SILC_STATUS_OK, 0);
 
  out:
+  silc_free(username);
   silc_server_command_free(cmd);
 }
 
@@ -4671,7 +4748,7 @@ SILC_SERVER_CMD_FUNC(users)
   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);
 
@@ -4687,6 +4764,18 @@ SILC_SERVER_CMD_FUNC(users)
     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) {
@@ -4805,6 +4894,7 @@ SILC_SERVER_CMD_FUNC(users)
   silc_free(id);
 
  out:
+  silc_free(channel_name);
   silc_server_command_free(cmd);
 }
 
index 9acb1ed8f49cc788ea9d7f15346b3016df3f27de..99f459550d32c41ee06f82d21c47b96b09f24bf7 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -197,6 +197,14 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
 
   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,
@@ -210,21 +218,35 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
   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;
     }
 
@@ -241,6 +263,17 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     /* 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);
@@ -251,7 +284,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     silc_free(client->servername);
 
     client->nickname = nick;
-    client->username = strdup(username);
+    client->username = username;
     client->userinfo = strdup(realname);
     client->servername = servername;
     client->mode = mode;
@@ -364,6 +397,7 @@ silc_server_command_reply_whois_save(SilcServerCommandReplyContext cmd)
     }
   }
 
+  silc_free(username);
   return TRUE;
 }
 
@@ -455,6 +489,14 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
   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,
@@ -468,22 +510,37 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
   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;
     }
 
@@ -497,12 +554,23 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
     /* 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;
@@ -527,6 +595,7 @@ silc_server_command_reply_whowas_save(SilcServerCommandReplyContext cmd)
   }
 
   silc_free(client_id);
+  silc_free(username);
 
   return TRUE;
 }
@@ -617,9 +686,20 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
        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. */
@@ -629,6 +709,7 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
                                      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;
@@ -643,6 +724,16 @@ silc_server_command_reply_identify_save(SilcServerCommandReplyContext cmd)
       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);
@@ -809,7 +900,7 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
   SilcServerEntry entry;
   SilcServerID *server_id;
   SilcUInt32 tmp_len;
-  unsigned char *tmp, *name;
+  unsigned char *tmp, *name = NULL;
 
   COMMAND_CHECK_STATUS;
 
@@ -823,7 +914,13 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
 
   /* 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,
@@ -839,6 +936,7 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
                                     cmd->sock);
       if (!entry) {
        silc_free(server_id);
+       silc_free(name);
        goto out;
       }
       entry->data.status |= SILC_IDLIST_STATUS_REGISTERED;
@@ -852,6 +950,8 @@ SILC_SERVER_CMD_REPLY_FUNC(info)
 
   entry->server_info = tmp ? strdup(tmp) : NULL;
 
+  silc_free(name);
+
  out:
   SILC_SERVER_PENDING_EXEC(cmd, SILC_COMMAND_INFO);
  err:
index 2562c0f03d39ec1db2f4c252dd78a0fc9d0c0e38..91ac9cf2d8b093a9b449096267ebc630bdf671f9 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -419,7 +419,6 @@ int silc_idlist_get_clients_by_nickname(SilcIDList id_list, char *nickname,
 
   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));
@@ -439,13 +438,10 @@ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
   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
@@ -552,7 +548,7 @@ silc_idlist_replace_client_id(SilcServer server,
   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)
index 1215e604b303f590e6343e8f54b7f8e76802418e..01b072a095b94c2686f5d7d574069696f162904e 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -2256,9 +2256,9 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   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"));
@@ -2322,16 +2322,32 @@ SilcClientEntry silc_server_new_client(SilcServer server,
     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
@@ -2422,7 +2438,8 @@ SilcClientEntry silc_server_new_client(SilcServer server,
 
   /* 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,
@@ -3835,12 +3852,13 @@ void silc_server_resume_client(SilcServer server,
     }
 
     /* 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) {
@@ -3851,8 +3869,16 @@ void silc_server_resume_client(SilcServer server,
            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;
index 05302a7f7c2e4bc2f7912da7c337c217a356392a..7f9dd5d58ba41ce54debeaf4feeef9b6cc53fe29 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -427,11 +427,20 @@ bool silc_server_init(SilcServer server)
   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.
@@ -585,8 +594,17 @@ bool silc_server_rehash(SilcServer server)
   /* 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);
@@ -970,9 +988,9 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router_retry)
 }
 
 /* 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;
@@ -1000,14 +1018,14 @@ SILC_TASK_CALLBACK(silc_server_connection_established)
     }
     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)
index 9e8c7bba234804d21c7ae41ee1658d8d864824d5..48ecd78d56d7b346bf443f953675a39d42ec7f84 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -399,6 +399,17 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
        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));
@@ -466,6 +477,17 @@ void silc_server_query_parse(SilcServer server, SilcServerQuery query)
       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))
index d733f78a699695285914b27b01a2ca5f408b706a..a65a2c1938ad77bdfe4a56c31c5715b365999760 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -1728,10 +1728,8 @@ bool silc_server_check_watcher_list(SilcServer server,
 
   /* 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));
index 7d8fdea5c1f059e28cf8ffd9d779677c8d2c75f4..aa1dee54b32ff51d7a3252b7270302fd79249cf9 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -56,21 +56,19 @@ void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
 
 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);
@@ -80,9 +78,9 @@ bool silc_id_create_client_id(SilcServer server,
 
   /* 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;
 
@@ -126,15 +124,15 @@ bool silc_id_create_channel_id(SilcServer server,
 
   /* 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;
index ce70e7af94c33d29aedd39cd52247c1ba232f1de..4f81aa17ad0421658036e59e0b044abccdbe2983 100644 (file)
@@ -4,13 +4,13 @@
 
   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,
index 9d93db2032ffb14b2c855261abfb119544cfba0a..16e995f877f6a7ce007f1994ccd2db09cbab5509 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -114,7 +114,7 @@ SilcIDCache silc_idcache_alloc(SilcUInt32 count, SilcIdType id_type,
                                          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);
index 3b5c7cd0ec648fd97cee67c6fbfd0cfada70ec17..3f1637b6f07db4e78597fc009ae374f5b4a49abd 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -102,6 +102,8 @@ typedef SilcUInt8 SilcStatus;
 #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)
index d998ebbedc27b6dc005531d54284c52b1ebacad5..e3b75fbffe1887f717418850d636a7635b3c15f3 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -273,3 +273,39 @@ char *silc_strncat(char *dest, SilcUInt32 dest_size,
 
   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;
+}
index fe1243f96ade37d8bce7df0e5c7abe4a4682b04a..98d0e7403f5a090d28d1e199a45a89a11bfa4224 100644 (file)
@@ -167,4 +167,50 @@ silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len,
 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 */
index 4715e926a3c956f760516c4ac90f120399942838..c30024e8bcaef494bc05014a5cac87d7be78d418 100644 (file)
@@ -4,7 +4,7 @@
 
   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
@@ -156,7 +156,7 @@ bool silc_parse_userfqdn(const char *string, char **left, char **right)
     }
   } else {
     if (left)
-      *left = strdup(string);
+      *left = silc_memdup(string, strlen(string));
   }
 
   return TRUE;
@@ -1046,6 +1046,8 @@ static const SilcStatusMessage silc_status_messages[] = {
   { 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 }
 };