Merged from silc_1_0_branch (second merge).
authorPekka Riikonen <priikone@silcnet.org>
Thu, 20 Feb 2003 15:27:21 +0000 (15:27 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Thu, 20 Feb 2003 15:27:21 +0000 (15:27 +0000)
56 files changed:
CHANGES
CREDITS
INSTALL
TODO
apps/irssi/docs/help/in/cmode.in
apps/irssi/docs/help/in/kill.in
apps/irssi/src/core/network.c
apps/irssi/src/core/session.c
apps/irssi/src/fe-common/core/fe-common-core.c
apps/irssi/src/fe-text/gui-readline.c
apps/irssi/src/fe-text/silc.c
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-core.c
apps/silcd/command.c
apps/silcd/idlist.c
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/server_backup.c
apps/silcd/server_util.c
apps/silcd/server_util.h
apps/silcd/serverconfig.c
apps/silcd/serverconfig.h
apps/silcd/serverid.c
apps/silcd/silcd.c
configure.in.pre
doc/silcd.conf.yo
lib/doc/LIBINDEX
lib/doc/command_reply_args.html [new file with mode: 0644]
lib/doc/notifyargs.html [new file with mode: 0644]
lib/doc/platforms.html [new file with mode: 0644]
lib/silcclient/DIRECTORY
lib/silcclient/client_notify.c
lib/silcclient/command.c
lib/silcclient/protocol.c
lib/silcclient/silcclient.h
lib/silccore/Makefile.am
lib/silccore/silcauth.c
lib/silccrypt/pkcs1.c
lib/silccrypt/rsa.c
lib/silccrypt/silcpkcs.c
lib/silccrypt/silcrng.c
lib/silcmath/silcmp.h
lib/silcske/silcske.c
lib/silcutil/silcbuffer.h
lib/silcutil/silcbuffmt.c
lib/silcutil/silcconfig.c
lib/silcutil/silcconfig.h
lib/silcutil/silclog.c
lib/silcutil/silclog.h
lib/silcutil/silcschedule.c
lib/silcutil/silctypes.h
lib/silcutil/unix/silcunixsockconn.c
prepare
scripts/stripspaces.tcl
tutorial/Makefile.defines_int.in

diff --git a/CHANGES b/CHANGES
index 40e281ac905e35aadc754d78f077345796baa8cf..abc7a30abeeec793f0bb5548c472c102b8396886 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,91 @@
+Tue Feb  4 22:53:26 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * NULL terminate allocated string in silc_buffer_strformat.
+         Affected file lib/silcutil/silcbuffmt.c.
+
+       * Rewrote the invite/ban list string handling in server to
+         use SilcBuffer instead.  Affected files are silcd/command.c
+         and silcd/server_util.c.
+
+Mon Feb  3 14:43:52 CET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed double free in CMODE command when setting new HMAC
+         for channel.  Affected file silcd/command.c.
+
+       * Added couple of missing memset's to zero sensitive memory.
+         Affected files silcd/command.c, lib/silcclient/command.c.
+
+Sun Jan 26 12:20:30 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed a double free in INVITE command error handling in
+         server.  Affected file silcd/command.c.
+
+       * Added macros SILC_SWAB_[16|32] to swab byte order of
+         16-bit and 32-bit unsigned integers.  Affected file
+         lib/silcutil/silctypes.h.
+
+       * Use the SILC_SWAB_16 instead of htons() in server when
+         handling ports since the ports in structures are always
+         in little-endian order (regardless of platform).  Affected
+         file silcd/serverid.c and silcd/server_backup.c.
+
+Tue Jan 21 17:18:04 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Send DISCONNECT in close admin command in server.  Affected
+         file silcd/command.c.
+
+       * Check whether we are already connecting to a remote router
+         (in addition of checking whether we are already connected)
+         before creating new connection.  Affected file silcd/server.c.
+
+Thu Jan 16 18:47:00 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added better compiler and compiler flags checking in
+         configure.
+
+       * Check that socket is valid after QoS is applied to data.
+         Affected file lib/silcutil/unix/silcunixsockconn.c.
+
+       * Make sure the socket connecetion is not closed to early
+         when closing connection in server.  Also make sure the
+         connection is always closed after error in a protocol.
+         Affected file silcd/server.c.
+
+Wed Jan 15 11:03:36 CET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Removed --session and --dummy options from Irssi SILC Client.
+         -d option is available only if --enable-debug was given.
+         Affected files are irssi/src/silc/core/silc-core,
+         irssi/src/core/session.c and irssi/src/fe-text/silc.c.
+
+Tue Jan 14 12:25:09 CET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Added silc_buffer_steal to steal the data from the buffer.
+         Affected file lib/silcutil/silcbuffer.h.
+
+Sat Jan 11 18:16:29 CET 2003  Giovanni Giacobbi <giovanni@giacobbi.net>
+
+       * Fixed server crash with double Primary block in config file.
+
+         Fixed also various memory leaks around the config file
+         parser.  Affected files lib/silcutil/silcconfig.c,
+         silcd/serverconfig.c.
+
+       * Changed my nickname (Johnny Mnemonic) to my real name, this
+         means that bugs introduced by him were actually introduced
+         by me!
+
+Tue Jan  7 21:58:53 CET 2003  Jochen Eisinger <c0ffee@penguin-breeder.org>
+
+       * Don't display "foo appears as foo\nYou're now known as foo"
+         messages.  Affected file irssi/src/silc/core/client_ops.c
+
+Tue Jan  7 20:08:15 EET 2003  Pekka Riikonen <priikone@silcnet.org>
+
+       * Fixed error handling of invalid client entry when calling
+         commands in server.  Fixes a crash.  Affected file
+         silcd/command.c.
+
 Thu Dec 26 14:19:29 EET 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Added some sanity checks in server for correctness of the
diff --git a/CREDITS b/CREDITS
index 63ec9f6af6d0d2371c902b285477444fe4e77057..950df4ab24aa10282d2339a559a254564637a40c 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -33,12 +33,12 @@ S: Skinnarilankatu 28 E 2
 S: 53850 Lappeenranta
 S: Finland
 
-N: Johnny Mnemonic
+N: Giovanni Giacobbi
+E: giovanni@giacobbi.net
 E: johnny@themnemonic.org
-W: http://www.themnemonic.org/
-P: 1024D/34E2AB40 9AC6 1460 A5D0 4DB7 70D0  5DA5 C17F 50CD 34E2 AB40
+P: 1024D/B2D79FC1 6247 640C 1C90 1EE4 D800  E4E2 2D58 3DF1 B2D7 9FC1
+D: silcconfig, silclog, various patches around
 D: RPM packages
-D: silclog, misc bugfixes
 S: 35100 Padova
 S: Italy
 
diff --git a/INSTALL b/INSTALL
index 9871e92e93a7683fa78bfb5fd16f22f55455ce5c..bca665aa58c77dc22198c5c71ae7ba7b89d038a3 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
 Quick Installation
 ==================
 
-   To configure and compile SILC package give the comands:
+   To configure and compile SILC package give the commands:
 
        ./configure
        make (or gmake)
@@ -11,6 +11,9 @@ Quick Installation
 /usr/local/silc/ directory.  System wide configuration files are installed
 into the /etc/silc/ directory.
 
+You may need to add the /usr/local/silc path to your PATH environment
+variable after the installation.
+
 Some Configuration Options
 ==========================
 
diff --git a/TODO b/TODO
index 1d5f3a69a4ed8b2250c102941de176f167e1489e..fb406ebf08244fe59856794c6d19d51355ec9b14 100644 (file)
--- a/TODO
+++ b/TODO
@@ -9,6 +9,11 @@ TODO for Irssi SILC Client 1.0
 TODO for SILC Server 1.0
 ========================
 
+ o INVITE and BAN notifys send the entire list as notify, but only the
+   added/removed info should be sent.
+
+ o The CMODE cipher & hmac change problem (#101).
+
  o Fix CUMODE_CHANGE and CMODE_CHANGE for founder key things.
 
  o 1.2 backup router support
@@ -32,18 +37,11 @@ TODO in Toolkit Documentation
 Stuff that needs to be done in order to complete the Tooolkit Reference
 Manual (Do these to 0.9.x).
 
- o Document the "notify" and "command_reply" client operations variable 
-   argument lists for all possible notify types and command replys.
-
  o Write "Programming with Toolkit" document, describing how to build
    Toolkit, how the build system works, where is everything, how
    new (external) projects can be glued into Toolkit (use irssi as an
    example), and how external projects can use Toolkit without gluing into
    it (how to link etc), debugging, architecture, types, etc.
 
- o Write "Platform Implementations" document to describe what platforms
-   Toolkit support, what has been implemented, what has not been, what
-   works differently etc.
-
  o Searching of predefined keywords, exact and partial matches (would be 
    nice).
index 6806bea14b562dc4f760e9d2dc2b843fb9d0bdd5..e4cf6b4cddf93df9b84ef12a1d8d41a09205a664 100644 (file)
@@ -5,27 +5,28 @@ This command is used to manage the modes of the channel.  Most
 of the modes require special privileges, such as channel operator
 or channel founder privileges to work.  The mode is added by
 adding + before the option(s) and removed by adding - before the
-option(s).  The following modes are available:
+option(s).  The (*) mark below means that only founder may set/unset
+that mode.  Other modes both channel operator and founder may manage.
+
+The following modes are available:
 
     p               Set/unset channel as private channel
     s               Set/unset channel as secret channel
-    k               Set/unset that channel uses private channel key
+    k               Enable/disable channel private key usage (*)
     i               Set/unset channel as invite only channel
     t               Set/unset that only channel operator or 
                     founder may set channel topic
     m               Set/unset user silencing.  Normal users
-                    are not able to talk on channel.  Only
-                    channel founder may set this mode
+                    are not able to talk on channel. (*)
     M               Set/unset operator silencing.  Operators
-                    are not able to talk on channel.  Only
-                    channel founder may set this mode
+                    are not able to talk on channel. (*)
     l <limit>       Set/unset channel's user limit
     a <passphrase>  Set/unset passphrase for channel that must
-                    be provided when joining to the channel.
-    c <cipher>      Set/unset channel's cipher
-    h <hmac>        Set/unset channel's hmac
+                    be provided when joining to the channel. (*)
+    c <cipher>      Set/unset channel's cipher (*)
+    h <hmac>        Set/unset channel's hmac (*)
     f [<pubkeyfile> <privkeyfile> [<privkey passphrase>]]
-                    Set/unset channel founder authentication.
+                    Set/unset channel founder authentication. (*)
                     Channel founder may set this mode so that
                     if the client leaves the channel it can
                     claim the founder rights when it returns
@@ -45,4 +46,10 @@ Multiple modes can be set/unset at once if the modes does not
 require any arguments.  If mode requires an argument then only
 one mode can be set at once.
 
-See also: CUMODE, UMODE, JOIN
+When the +k (channel private key mode) mode is set the channel's
+default cipher and HMAC are not used.  The private key (see /HELP KEY
+for help how to set the private key) defines the cipher and HMAC for
+the channel while +k mode is set.  Also the +c and +h modes are ignored
+when channel private key is set.
+
+See also: CUMODE, UMODE, JOIN, KEY
index 96b6b6cafc6f9a60842cdea6b801853cdce83e1b..aa274c98bd7965be95bf303891422f7c2582ff99 100644 (file)
@@ -16,15 +16,15 @@ SILC operator -pubkey has no effect.
 
 Examples:
 
-       /KILL myself -pubkey
+        /KILL myself -pubkey
 
-               Kill yourself with nickname "myself" from network.
+            Kill yourself with nickname "myself" from network.
 
-       /SILCOPER user
-       /KILL someclient You have been killed
+        /SILCOPER user
+        /KILL someclient You have been killed
 
-               Become SILC operator and kill client named
-                "someclient", with comment "You have been killed".
+            Become SILC operator and kill client named
+            "someclient", with comment "You have been killed".
 
 See also: OPER, SILCOPER
 
index bb46dd54fcd9f0e5ee51aac3507f571acffb89e6..5892ac6998bb6713562945ef3259dfa099a2060f 100644 (file)
@@ -27,7 +27,7 @@
 #  define INADDR_NONE INADDR_BROADCAST
 #endif
 
-union sockaddr_union {
+union irssi_sockaddr_union {
        struct sockaddr sa;
        struct sockaddr_in sin;
 #ifdef HAVE_IPV6
@@ -71,7 +71,7 @@ G_INLINE_FUNC
 #else
 static
 #endif
-void sin_set_ip(union sockaddr_union *so, const IPADDR *ip)
+void sin_set_ip(union irssi_sockaddr_union *so, const IPADDR *ip)
 {
        if (ip == NULL) {
 #ifdef HAVE_IPV6
@@ -93,7 +93,7 @@ void sin_set_ip(union sockaddr_union *so, const IPADDR *ip)
                memcpy(&so->sin.sin_addr, &ip->ip, 4);
 }
 
-void sin_get_ip(const union sockaddr_union *so, IPADDR *ip)
+void sin_get_ip(const union irssi_sockaddr_union *so, IPADDR *ip)
 {
        ip->family = so->sin.sin_family;
 
@@ -110,7 +110,7 @@ G_INLINE_FUNC
 #else
 static
 #endif
-void sin_set_port(union sockaddr_union *so, int port)
+void sin_set_port(union irssi_sockaddr_union *so, int port)
 {
 #ifdef HAVE_IPV6
        if (so->sin.sin_family == AF_INET6)
@@ -125,7 +125,7 @@ G_INLINE_FUNC
 #else
 static
 #endif
-int sin_get_port(union sockaddr_union *so)
+int sin_get_port(union irssi_sockaddr_union *so)
 {
 #ifdef HAVE_IPV6
        if (so->sin.sin_family == AF_INET6)
@@ -173,7 +173,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
 /* Connect to socket with ip address */
 GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
 {
-       union sockaddr_union so;
+       union irssi_sockaddr_union so;
        int handle, ret, opt = 1;
 
        if (my_ip != NULL && ip->family != my_ip->family) {
@@ -274,7 +274,7 @@ void net_disconnect(GIOChannel *handle)
    address. */
 GIOChannel *net_listen(IPADDR *my_ip, int *port)
 {
-       union sockaddr_union so;
+       union irssi_sockaddr_union so;
        int ret, handle, opt = 1;
        socklen_t len;
 
@@ -331,7 +331,7 @@ GIOChannel *net_listen(IPADDR *my_ip, int *port)
 /* Accept a connection on a socket */
 GIOChannel *net_accept(GIOChannel *handle, IPADDR *addr, int *port)
 {
-       union sockaddr_union so;
+       union irssi_sockaddr_union so;
        int ret;
        socklen_t addrlen;
 
@@ -391,7 +391,7 @@ int net_transmit(GIOChannel *handle, const char *data, int len)
 /* Get socket address/port */
 int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
 {
-       union sockaddr_union so;
+       union irssi_sockaddr_union so;
        socklen_t addrlen;
 
        g_return_val_if_fail(handle != NULL, -1);
@@ -414,7 +414,7 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
 int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
 {
 #ifdef HAVE_IPV6
-       union sockaddr_union *so;
+       union irssi_sockaddr_union *so;
        struct addrinfo hints, *ai, *ailist;
        int ret, count;
 #else
@@ -437,7 +437,7 @@ int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
 
         count = 0;
        for (ai = ailist; ai != NULL && count < 2; ai = ai->ai_next) {
-               so = (union sockaddr_union *) ai->ai_addr;
+               so = (union irssi_sockaddr_union *) ai->ai_addr;
 
                if (ai->ai_family == AF_INET6 && ip6->family == 0) {
                        sin_get_ip(so, ip6);
index 7ebd8f82b956ef60a21bd2eab624d4b42787c1ac..40c4f5474938848d41100f3e2a4f75b8d67afd93 100644 (file)
@@ -350,7 +350,9 @@ static void sig_init_finished(void)
 void session_init(void)
 {
        static struct poptOption options[] = {
+#if 0 /* --session is not available in SILC Client */
                { "session", 0, POPT_ARG_STRING, &session_file, 0, "Used by /UPGRADE command", "PATH" },
+#endif
                { NULL, '\0', 0, NULL }
        };
 
index aa83035053d74a0ada6921beb8e20808e5c799e6..bc556a6a5db81fc1b2fc208e0757e69c84a4a810 100644 (file)
@@ -132,7 +132,7 @@ void fe_common_core_init(void)
        static struct poptOption options[] = {
                { NULL, '\0', POPT_ARG_INCLUDE_TABLE, version_options, 0, NULL, NULL },
                POPT_AUTOHELP
-               { "connect", 'c', POPT_ARG_STRING, &autocon_server, 0, "Automatically connect to server/ircnet", "SERVER" },
+               { "connect", 'c', POPT_ARG_STRING, &autocon_server, 0, "Automatically connect to server", "SERVER" },
                { "password", 'w', POPT_ARG_STRING, &autocon_password, 0, "Autoconnect password", "PASSWORD" },
                { "port", 'p', POPT_ARG_INT, &autocon_port, 0, "Autoconnect port", "PORT" },
                { "noconnect", '!', POPT_ARG_NONE, &no_autoconnect, 0, "Disable autoconnecting", NULL },
index 66867ffb7de0924074087efaf629eacbe806e4ab..4de1936e3adc52b853ab2dbb6498172eea1a42cb 100644 (file)
@@ -182,6 +182,7 @@ static void key_send_line(void)
 {
        HISTORY_REC *history;
         char *str, *add_history;
+       gint flags = (redir ? redir->flags : 0);
 
        str = gui_entry_get_text(active_entry);
 
@@ -197,9 +198,13 @@ static void key_send_line(void)
                            active_win->active_server,
                            active_win->active);
        } else {
-               if (redir->flags & ENTRY_REDIRECT_FLAG_HIDDEN)
+               if (flags & ENTRY_REDIRECT_FLAG_HIDDEN && add_history) {
+                       memset(add_history, 0, strlen(add_history));
                         g_free_and_null(add_history);
+               }
                handle_entry_redirect(str);
+               if (flags & ENTRY_REDIRECT_FLAG_HIDDEN && str)
+                       memset(str, 0, strlen(str));
        }
 
        if (add_history != NULL) {
index 452fa009b5fbfb2eb4528f82700d3b670997c838..1591e601cf767622f0652bad1d721f43a3909cc8 100644 (file)
@@ -310,7 +310,9 @@ static void winsock_init(void)
 int main(int argc, char **argv)
 {
        static struct poptOption options[] = {
+#if 0 /* --dummy is not available in SILC Client */
                { "dummy", 'd', POPT_ARG_NONE, &dummy, 0, "Use the dummy terminal mode", NULL },
+#endif
                { NULL, '\0', 0, NULL }
        };
 
index b55b0d31a7c859a9aa96d21fb73d0cdce191311c..2f9c7541ca5382d9976b8b6a2896b2e86f861640 100644 (file)
@@ -1688,7 +1688,8 @@ silc_command_reply(SilcClient client, SilcClientConnection conn,
        return;
 
       nicks = nicklist_get_same(SERVER(server), client_entry->nickname);
-      if (nicks != NULL) {
+      if ((nicks != NULL) && 
+        (strcmp(SERVER(server)->nick, client_entry->nickname))) {
        char buf[512];
        SilcClientEntry collider, old;
 
index eeea2685303e9ffbbe7e6f804c490d114d8c6fb0..bf572810b301fbd6dd4d3dbdc54a2d3f114693a2 100644 (file)
@@ -360,8 +360,10 @@ void silc_core_init(void)
       "List supported HMACs", NULL },
     { "list-pkcs", 0, POPT_ARG_NONE, NULL, 0,
       "List supported PKCSs", NULL },
+#ifdef SILC_DEBUG
     { "debug", 'd', POPT_ARG_STRING, NULL, 0,
       "Enable debugging", "STRING" },
+#endif /* SILC_DEBUG */
     { "create-key-pair", 'C', POPT_ARG_NONE, NULL, 0,
       "Create new public key pair", NULL },
     { "pkcs", 0, POPT_ARG_STRING, &opt_pkcs, 0,
index 78beef6f58c38c90c71ae045894c8c16000351e1..f5fcb1b4846bf6d5dc3e1bcb6741268decb8ace7 100644 (file)
@@ -160,6 +160,7 @@ SILC_TASK_CALLBACK(silc_server_command_process_timeout)
     SILC_LOG_DEBUG(("Client entry is invalid"));
     silc_server_command_free(timeout->ctx);
     silc_free(timeout);
+    return;
   }
 
   /* Update access time */
@@ -239,6 +240,7 @@ void silc_server_command_process(SilcServer server,
     if (!client) {
       SILC_LOG_DEBUG(("Client entry is invalid"));
       silc_server_command_free(ctx);
+      return;
     }
 
     timeout = silc_calloc(1, sizeof(*timeout));
@@ -1106,8 +1108,6 @@ SILC_SERVER_CMD_FUNC(invite)
                                  silc_server_command_invite, 
                                  silc_server_command_dup(cmd));
       cmd->pending = TRUE;
-      silc_free(channel_id);
-      silc_free(dest_id);
       goto out;
     }
 
@@ -1222,14 +1222,9 @@ SILC_SERVER_CMD_FUNC(invite)
                                          channel->invite_list)),
                       SILC_STR_END);
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
-      if (type == 1)
-       list = silc_argument_payload_encode_one(list, (char *)tmp2,
-                                               strlen((char *)tmp2), type);
-      else
-       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
-                                               type);
-    }
+    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+      list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+                                             type);
     silc_hash_table_list_reset(&htl);
   }
 
@@ -2050,17 +2045,10 @@ static void silc_server_command_join_channel(SilcServer server,
                       SILC_STR_END);
 
     silc_hash_table_list(channel->invite_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
-      if (tmp_len == 1)
-       invite_list = silc_argument_payload_encode_one(invite_list,
-                                                      (char *)reply,
-                                                      strlen((char *)reply),
-                                                      tmp_len);
-      else
-       invite_list = silc_argument_payload_encode_one(invite_list,
-                                                      reply->data,
-                                                      reply->len, tmp_len);
-    }
+    while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
+      invite_list = silc_argument_payload_encode_one(invite_list,
+                                                    reply->data,
+                                                    reply->len, tmp_len);
     silc_hash_table_list_reset(&htl);
   }
 
@@ -2076,17 +2064,10 @@ static void silc_server_command_join_channel(SilcServer server,
                       SILC_STR_END);
 
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply)) {
-      if (tmp_len == 1)
-       ban_list = silc_argument_payload_encode_one(ban_list,
-                                                   (char *)reply,
-                                                   strlen((char *)reply),
-                                                   tmp_len);
-      else
-       ban_list = silc_argument_payload_encode_one(ban_list,
-                                                   reply->data,
-                                                   reply->len, tmp_len);
-    }
+    while (silc_hash_table_get(&htl, (void **)&tmp_len, (void **)&reply))
+      ban_list = silc_argument_payload_encode_one(ban_list,
+                                                 reply->data,
+                                                 reply->len, tmp_len);
     silc_hash_table_list_reset(&htl);
   }
 
@@ -2184,6 +2165,8 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_buffer_free(ban_list);
 
  out:
+  if (passphrase)
+    memset(passphrase, 0, strlen(passphrase));
   silc_free(passphrase);
 }
 
@@ -2939,7 +2922,6 @@ SILC_SERVER_CMD_FUNC(cmode)
       hmac = channel->hmac_name;
 
       /* Delete old hmac and allocate default one */
-      silc_hmac_free(channel->hmac);
       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
                                       SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
@@ -4214,14 +4196,9 @@ SILC_SERVER_CMD_FUNC(ban)
                                          channel->ban_list)),
                       SILC_STR_END);
     silc_hash_table_list(channel->ban_list, &htl);
-    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2)) {
-      if (type == 1)
-       list = silc_argument_payload_encode_one(list, (char *)tmp2,
-                                               strlen((char *)tmp2), type);
-      else
-       list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
-                                               type);
-    }
+    while (silc_hash_table_get(&htl, (void **)&type, (void **)&tmp2))
+      list = silc_argument_payload_encode_one(list, tmp2->data, tmp2->len,
+                                             type);
     silc_hash_table_list_reset(&htl);
   }
 
@@ -4770,17 +4747,19 @@ SILC_SERVER_CMD_FUNC(close)
   /* Close the connection to the server */
   sock = (SilcSocketConnection)server_entry->connection;
 
-  /* If we shutdown primary router connection manually then don't trigger
-     any reconnect or backup router connections, by setting the router
-     to NULL here. */
+  server->backup_noswitch = TRUE;
   if (server->router == server_entry) {
     server->id_entry->router = NULL;
     server->router = NULL;
     server->standalone = TRUE;
   }
-  silc_server_free_sock_user_data(server, sock, NULL);
-  silc_server_close_connection(server, sock);
-  
+  silc_server_disconnect_remote(server, sock,
+                               SILC_STATUS_ERR_BANNED_FROM_SERVER,
+                               "Closed by administrator");
+  if (sock->user_data)
+    silc_server_free_sock_user_data(server, sock, NULL);
+  server->backup_noswitch = FALSE;
+
  out:
   silc_server_command_free(cmd);
 }
index 9acdd06844330fd6b2e7f93baaa55d344aa68687..fb457b6c44335fe596b732bccd50aed9d8f0b605 100644 (file)
@@ -227,7 +227,7 @@ silc_idlist_find_server_by_conn(SilcIDList id_list, char *hostname,
     
     if (sock && ((sock->hostname && !strcasecmp(sock->hostname, hostname)) ||
                 (sock->ip && !strcasecmp(sock->ip, hostname)))
-       && server->id->port == htons(port))
+       && server->id->port == SILC_SWAB_16(port))
       break;
 
     id_cache = NULL;
index e49fafb59e7fb9a6d34595eff5748831a191b5a3..ee45290f0b1b779625c1142f201f2f8bc126f9e7 100644 (file)
@@ -2164,6 +2164,16 @@ SilcClientEntry silc_server_new_client(SilcServer server,
     return NULL;
   }
 
+  /* Make sure this client hasn't registered already */
+  if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+    silc_server_disconnect_remote(server, sock, 
+                                 SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                 "Too many registrations");
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    return NULL;
+  }
+
   /* Parse incoming packet */
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING_ALLOC(&username, 
@@ -2413,6 +2423,16 @@ SilcServerEntry silc_server_new_server(SilcServer server,
     local = FALSE;
   }
 
+  /* Make sure this server hasn't registered already */
+  if (idata->status & SILC_IDLIST_STATUS_REGISTERED) {
+    silc_server_disconnect_remote(server, sock, 
+                                 SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                 "Too many registrations");
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    return NULL;
+  }
+
   /* Parse the incoming packet */
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING_ALLOC(&id_string, &id_len),
@@ -2474,19 +2494,38 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                               server_id, TRUE, NULL);
   if (server_entry) {
-    silc_idcache_del_by_context(server->local_list->servers, server_entry);
+    if (SILC_IS_LOCAL(server_entry)) {
+      silc_server_disconnect_remote(server, server_entry->connection, 
+                                   SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                   "Too many registrations");
+      if (((SilcSocketConnection)server_entry->connection)->user_data)
+       silc_server_free_sock_user_data(server, sock, NULL);
+    } else {
+      silc_idcache_del_by_context(server->local_list->servers, server_entry);
+    }
   } else {
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
-    if (server_entry) 
-      silc_idcache_del_by_context(server->global_list->servers, server_entry);
+    if (server_entry) {
+      if (SILC_IS_LOCAL(server_entry)) {
+       silc_server_disconnect_remote(server, server_entry->connection, 
+                                     SILC_STATUS_ERR_OPERATION_ALLOWED,
+                                     "Too many registrations");
+       if (((SilcSocketConnection)server_entry->connection)->user_data)
+         silc_server_free_sock_user_data(server, server_entry->connection,
+                                         NULL);
+      } else {
+       silc_idcache_del_by_context(server->global_list->servers,
+                                   server_entry);
+      }
+    }
   }
 
   /* Update server entry */
   idata->status |= SILC_IDLIST_STATUS_REGISTERED;
   new_server->server_name = server_name;
   new_server->id = server_id;
-  
+
   SILC_LOG_DEBUG(("New server id(%s)",
                  silc_id_render(server_id, SILC_ID_SERVER)));
 
index 8e3ab0f248742ce3a308a3074059467eb3aec13b..80d2d71bfc73cc91b48ddaeb8a40a13fb39f8d00 100644 (file)
@@ -2005,6 +2005,7 @@ void silc_server_packet_queue_purge(SilcServer server,
 {
   if (sock && SILC_IS_OUTBUF_PENDING(sock) && 
       (SILC_IS_DISCONNECTED(sock) == FALSE)) {
+    SILC_LOG_DEBUG(("Purging ourgoing queue"));
     server->stat.packets_sent++;
     silc_packet_send(sock, TRUE);
     SILC_UNSET_OUTBUF_PENDING(sock);
index c3359196fe887f7dfc30da1aeed9c6a8b751f15c..0c55b28d0e87f5c411bfdfe62069e4b15dd0deba 100644 (file)
@@ -430,11 +430,7 @@ bool silc_server_init(SilcServer server)
      timeout. It expires as soon as the caller calls silc_server_run. This
      task performs authentication protocol and key exchange with our
      primary router. */
-  silc_schedule_task_add(server->schedule, 0,
-                        silc_server_connect_to_router,
-                        (void *)server, 0, 1,
-                        SILC_TASK_TIMEOUT,
-                        SILC_TASK_PRI_NORMAL);
+  silc_server_create_connections(server);
 
   /* Add listener task to the scheduler. This task receives new connections
      to the server. This task remains on the queue until the end of the
@@ -695,12 +691,8 @@ bool silc_server_rehash(SilcServer server)
     }
   }
 
-  /* Go through all configured routers after rehash */
-  silc_schedule_task_add(server->schedule, 0,
-                        silc_server_connect_to_router,
-                        (void *)server, 0, 1,
-                        SILC_TASK_TIMEOUT,
-                        SILC_TASK_PRI_NORMAL);
+  /* Create connections after rehash */
+  silc_server_create_connections(server);
 
   /* Check whether our router status has changed */
   if (newconfig->servers) {
@@ -1047,7 +1039,7 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_connect_to_router)
       server->wait_backup = TRUE;
 
     if (ptr->initiator) {
-      /* Check whether we are connected to this host already */
+      /* Check whether we are connecting or connected to this host already */
       if (silc_server_num_sockets_by_remote(server, 
                                            silc_net_is_ip(ptr->host) ?
                                            ptr->host : NULL,
@@ -1057,6 +1049,15 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_connect_to_router)
        SILC_LOG_DEBUG(("We are already connected to this router"));
        continue;
       }
+      if (silc_server_num_sockets_by_remote(server, 
+                                           silc_net_is_ip(ptr->host) ?
+                                           ptr->host : NULL,
+                                           silc_net_is_ip(ptr->host) ?
+                                           NULL : ptr->host, ptr->port,
+                                           SILC_SOCKET_TYPE_UNKNOWN)) {
+       SILC_LOG_DEBUG(("We are already connecting to this router"));
+       continue;
+      }
 
       /* Allocate connection object for hold connection specific stuff. */
       sconn = silc_calloc(1, sizeof(*sconn));
@@ -2239,12 +2240,9 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
       else
        silc_server_free_sock_user_data(server, sock, NULL);
     } else if (server->router_conn && server->router_conn->sock == sock &&
-              !server->router && server->standalone)
-      silc_schedule_task_add(server->schedule, 0,
-                            silc_server_connect_to_router,
-                            server, 1, 0,
-                            SILC_TASK_TIMEOUT,
-                            SILC_TASK_PRI_NORMAL);
+              !server->router && server->standalone) {
+      silc_server_create_connections(server);
+    }
 
     silc_server_close_connection(server, sock);
     return;
@@ -2289,6 +2287,7 @@ SILC_TASK_CALLBACK(silc_server_packet_process)
     if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router)
       server->backup_noswitch = TRUE;
 
+    SILC_SET_DISCONNECTING(sock);
     if (sock->user_data)
       silc_server_free_sock_user_data(server, sock, NULL);
     silc_server_close_connection(server, sock);
@@ -2433,6 +2432,7 @@ bool silc_server_packet_parse(SilcPacketParserContext *parser_context,
       if (SILC_PRIMARY_ROUTE(server) == sock && server->backup_router)
        server->backup_noswitch = TRUE;
 
+      SILC_SET_DISCONNECTING(sock);
       if (sock->user_data)
        silc_server_free_sock_user_data(server, sock, NULL);
       silc_server_close_connection(server, sock);
@@ -2501,10 +2501,15 @@ void silc_server_packet_parse_type(SilcServer server,
                     message ? message : ""));
       silc_free(message);
 
+      /* Do not switch to backup in case of error */
+      server->backup_noswitch = (status == SILC_STATUS_OK ? FALSE : TRUE);
+
       /* Handle the disconnection from our end too */
+      SILC_SET_DISCONNECTING(sock);
       if (sock->user_data && SILC_IS_LOCAL(sock->user_data))
        silc_server_free_sock_user_data(server, sock, NULL);
       silc_server_close_connection(server, sock);
+      server->backup_noswitch = FALSE;
     }
     break;
 
@@ -2931,6 +2936,7 @@ void silc_server_close_connection(SilcServer server,
   if (!server->sockets[sock->sock] && SILC_IS_DISCONNECTED(sock)) {
     silc_schedule_unset_listen_fd(server->schedule, sock->sock);
     silc_schedule_task_del_by_fd(server->schedule, sock->sock);
+    silc_net_close_connection(sock->sock);
     silc_schedule_task_add(server->schedule, sock->sock,
                           silc_server_close_connection_final,
                           (void *)sock, 0, 1, SILC_TASK_TIMEOUT,
@@ -2950,8 +2956,6 @@ void silc_server_close_connection(SilcServer server,
   /* Unregister all tasks */
   silc_schedule_task_del_by_fd(server->schedule, sock->sock);
 
-  /* Close the actual connection */
-  silc_net_close_connection(sock->sock);
   server->sockets[sock->sock] = NULL;
 
   /* If sock->user_data is NULL then we'll check for active protocols
@@ -2971,6 +2975,9 @@ void silc_server_close_connection(SilcServer server,
     }
   }
 
+  /* Close the actual connection */
+  silc_net_close_connection(sock->sock);
+
   /* We won't listen for this connection anymore */
   silc_schedule_unset_listen_fd(server->schedule, sock->sock);
 
@@ -2993,8 +3000,13 @@ void silc_server_disconnect_remote(SilcServer server,
   char *cp;
   int len;
 
-  if (!sock || SILC_IS_DISCONNECTED(sock))
+  if (!sock)
+    return;
+
+  if (SILC_IS_DISCONNECTED(sock)) {
+    silc_server_close_connection(server, sock);
     return;
+  }
 
   memset(buf, 0, sizeof(buf));
   va_start(ap, status);
@@ -3152,12 +3164,7 @@ void silc_server_free_sock_user_data(SilcServer server,
       if (server->router == user_data) {
        /* Check whether we have a backup router connection */
        if (!backup_router || backup_router == user_data) {
-         silc_schedule_task_add(server->schedule, 0,
-                                silc_server_connect_to_router,
-                                server, 1, 0,
-                                SILC_TASK_TIMEOUT,
-                                SILC_TASK_PRI_NORMAL);
-
+         silc_server_create_connections(server);
          server->id_entry->router = NULL;
          server->router = NULL;
          server->standalone = TRUE;
@@ -3205,15 +3212,12 @@ void silc_server_free_sock_user_data(SilcServer server,
       } else if (server->server_type == SILC_SERVER &&
                 sock->type == SILC_SOCKET_TYPE_ROUTER) {
        /* Reconnect to the router (backup) */
-       silc_schedule_task_add(server->schedule, 0,
-                              silc_server_connect_to_router,
-                              server, 1, 0,
-                              SILC_TASK_TIMEOUT,
-                              SILC_TASK_PRI_NORMAL);
+       silc_server_create_connections(server);
       }
 
-      SILC_SERVER_SEND_OPERS(server, FALSE, TRUE, SILC_NOTIFY_TYPE_NONE,
-                            ("Server %s signoff", user_data->server_name));
+      if (user_data->server_name)
+       SILC_SERVER_SEND_OPERS(server, FALSE, TRUE, SILC_NOTIFY_TYPE_NONE,
+                              ("Server %s signoff", user_data->server_name));
 
       if (!backup_router) {
        /* Remove all servers that are originated from this server, and
@@ -3851,7 +3855,12 @@ bool silc_server_create_channel_key(SilcServer server,
 
   /* Generate HMAC key from the channel key data and set it */
   if (!channel->hmac)
-    silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
+    if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) {
+      memset(channel->key, 0, channel->key_len / 8);
+      silc_free(channel->key);
+      channel->channel_key = NULL;
+      return FALSE;
+    }
   silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, len, hash);
   silc_hmac_set_key(channel->hmac, hash,
                    silc_hash_len(silc_hmac_get_hash(channel->hmac)));
@@ -3962,7 +3971,12 @@ SilcChannelEntry silc_server_save_channel_key(SilcServer server,
 
   /* Generate HMAC key from the channel key data and set it */
   if (!channel->hmac)
-    silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac);
+    if (!silc_hmac_alloc(SILC_DEFAULT_HMAC, NULL, &channel->hmac)) {
+      memset(channel->key, 0, channel->key_len / 8);
+      silc_free(channel->key);
+      channel->channel_key = NULL;
+      return FALSE;
+    }
   silc_hash_make(silc_hmac_get_hash(channel->hmac), tmp, tmp_len, hash);
   silc_hmac_set_key(channel->hmac, hash,
                    silc_hash_len(silc_hmac_get_hash(channel->hmac)));
@@ -5062,8 +5076,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
   if (protocol->state == SILC_PROTOCOL_STATE_ERROR ||
       protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
     /* Error occured during protocol */
-    SILC_LOG_ERROR(("Error occurred during rekey protocol with
-                  %s (%s)", sock->hostname, sock->ip));
+    SILC_LOG_ERROR(("Error occurred during rekey protocol with "
+                   "%s (%s)", sock->hostname, sock->ip));
     silc_protocol_cancel(protocol, server->schedule);
     silc_protocol_free(protocol);
     sock->protocol = NULL;
@@ -5072,6 +5086,14 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_rekey_final)
     if (ctx->ske)
       silc_ske_free(ctx->ske);
     silc_free(ctx);
+
+    /* Reconnect */
+    SILC_SET_DISCONNECTING(sock);
+    server->backup_noswitch = TRUE;
+    if (sock->user_data)
+      silc_server_free_sock_user_data(server, sock, NULL);
+    silc_server_close_connection(server, sock);
+    silc_server_create_connections(server);
     return;
   }
 
index 78634fe2e02fcc35a8b58da88df56808590256ce..757f5177a17d0e812a64f01521870d0cc3ddf256 100644 (file)
@@ -96,7 +96,7 @@ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
     if (!server->backup->servers[i].server) {
       server->backup->servers[i].server = backup_server;
       server->backup->servers[i].local = local;
-      server->backup->servers[i].port = htons(port);
+      server->backup->servers[i].port = SILC_SWAB_16(port);
       memset(server->backup->servers[i].ip.data, 0,
             sizeof(server->backup->servers[i].ip.data));
       silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
@@ -111,7 +111,7 @@ void silc_server_backup_add(SilcServer server, SilcServerEntry backup_server,
                                         (i + 1));
   server->backup->servers[i].server = backup_server;
   server->backup->servers[i].local = local;
-  server->backup->servers[i].port = htons(port);
+  server->backup->servers[i].port = SILC_SWAB_16(port);
   memset(server->backup->servers[i].ip.data, 0,
         sizeof(server->backup->servers[i].ip.data));
   silc_net_addr2bin(ip, server->backup->servers[i].ip.data,
@@ -1054,6 +1054,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
            SILC_LOG_DEBUG(("Sending RESUMED to %s",
                            server_entry->server_name));
+           SILC_LOG_INFO(("Sending RESUMED to %s",
+                          server_entry->server_name));
 
            server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
 
@@ -1091,6 +1093,8 @@ SILC_TASK_CALLBACK_GLOBAL(silc_server_protocol_backup)
 
            SILC_LOG_DEBUG(("Sending RESUMED to %s",
                            server_entry->server_name));
+           SILC_LOG_INFO(("Sending RESUMED to %s",
+                          server_entry->server_name));
 
            server_entry->data.status &= ~SILC_IDLIST_STATUS_DISABLED;
 
@@ -1257,16 +1261,13 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
                protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
              server->backup_noswitch = TRUE;
              server->server_type = SILC_BACKUP_ROUTER;
+             if (ctx->sock == sock)
+               ctx->sock = NULL;
 
              if (sock->user_data)
                silc_server_free_sock_user_data(server, sock, NULL);
              silc_server_close_connection(server, sock);
-
-             silc_schedule_task_add(server->schedule, 0,
-                                    silc_server_connect_to_router,
-                                    server, 1, 0,
-                                    SILC_TASK_TIMEOUT,
-                                    SILC_TASK_PRI_NORMAL);
+             silc_server_create_connections(server);
 
              if (!silc_idcache_list_next(list, &id_cache))
                break;
@@ -1300,16 +1301,13 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
                protocol->state == SILC_PROTOCOL_STATE_FAILURE) {
              server->backup_noswitch = TRUE;
              server->server_type = SILC_BACKUP_ROUTER;
+             if (ctx->sock == sock)
+               ctx->sock = NULL;
 
              if (sock->user_data)
                silc_server_free_sock_user_data(server, sock, NULL);
              silc_server_close_connection(server, sock);
-
-             silc_schedule_task_add(server->schedule, 0,
-                                    silc_server_connect_to_router,
-                                    server, 1, 0,
-                                    SILC_TASK_TIMEOUT,
-                                    SILC_TASK_PRI_NORMAL);
+             silc_server_create_connections(server);
 
              if (!silc_idcache_list_next(list, &id_cache))
                break;
@@ -1332,7 +1330,7 @@ SILC_TASK_CALLBACK(silc_server_protocol_backup_done)
       protocol->state != SILC_PROTOCOL_STATE_FAILURE)
     SILC_LOG_INFO(("Backup resuming protocol ended successfully"));
 
-  if (ctx->sock->protocol)
+  if (ctx->sock && ctx->sock->protocol)
     ctx->sock->protocol = NULL;
   silc_protocol_free(protocol);
   silc_free(ctx->sessions);
index dead873a6d250037bff3b3c9a91a585e9a4acc0a..839599d2cfde0b1f166e504c4c4c5d3014319a6e 100644 (file)
@@ -1754,7 +1754,7 @@ bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
   while (silc_hash_table_get(&htl, (void **)&t, (void **)&entry)) {
     if (type == t) {
       if (type == 1) {
-       if (silc_string_match((char *)entry, tmp)) {
+       if (silc_string_match(entry->data, tmp)) {
          ret = TRUE;
          break;
        }
@@ -1772,12 +1772,6 @@ bool silc_server_inviteban_match(SilcServer server, SilcHashTable list,
   return ret;
 }
 
-static void silc_server_inviteban_dummy_dest(void *key, void *context,
-                                            void *user_context)
-{
-  /* Nothing */
-}
-
 /* Process invite or ban information */
 
 void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
@@ -1800,24 +1794,16 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
       if (type == 1) {
        /* Invite string.  Get the old invite string from hash table
           and append this at the end of the existing one. */
-       char *string = NULL;
-       silc_hash_table_find(list, (void *)1,
-                            NULL, (void **)&string);
-       silc_hash_table_del_ext(list, (void *)1, NULL, NULL, NULL, NULL,
-                               silc_server_inviteban_dummy_dest, NULL);
-       if (!string)
-         string = silc_calloc(len + 2, sizeof(*string));
-       else
-         string = silc_realloc(string, sizeof(*string) *
-                               (strlen(string) + len + 2));
-       memset(string + strlen(string), 0, len + 2);
+       if (!silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
+         tmp2 = silc_calloc(1, sizeof(*tmp2));
+         silc_hash_table_add(list, (void *)1, tmp2);
+       }
        if (tmp[len - 1] == ',')
          tmp[len - 1] = '\0';
-       strncat(string, tmp, len);
-       strncat(string, ",", 1);
-
-       /* Add new invite string to invite list */
-       silc_hash_table_add(list, (void *)1, string);
+       if (len) {
+         silc_buffer_strformat(tmp2, tmp, SILC_STR_END);
+         silc_buffer_strformat(tmp2, ",", SILC_STR_END);
+       }
 
       } else if (type == 2) {
        /* Public key.  Check first if the public key is already on the
@@ -1875,25 +1861,23 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
           the requested string. */
        char *string = NULL, *start, *end, *n;
 
-       if (silc_hash_table_find(list, (void *)1, NULL, (void **)&string)) {
-         if (!strncmp(string, tmp, strlen(string) - 1)) {
+       if (silc_hash_table_find(list, (void *)1, NULL, (void **)&tmp2)) {
+         string = tmp2->head;
+         if (tmp2->truelen && !strncmp(string, tmp, tmp2->truelen - 1)) {
+           /* Delete entire string */
            silc_hash_table_del(list, (void *)1);
-           string = NULL;
-         } else {
+         } else if (tmp2->truelen) {
+           /* Delete part of the string */
            start = strstr(string, tmp);
            if (start && strlen(start) >= len) {
              end = start + len;
              n = silc_calloc(strlen(string) - len, sizeof(*n));
              strncat(n, string, start - string);
              strncat(n, end + 1, ((string + strlen(string)) - end) - 1);
-             silc_hash_table_del(list, (void *)1);
-             string = n;
+             silc_free(tmp2->head);
+             silc_buffer_set(tmp2, n, strlen(n));
            }
          }
-
-         /* Add new invite string to invite list */
-         if (string)
-           silc_hash_table_add(list, (void *)1, string);
        }
 
       } else if (type == 2) {
@@ -1928,22 +1912,21 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
   }
 }
 
-/* Destructor for invite or ban list entrys */
+/* Destructor for invite and ban list entrys */
 
 void silc_server_inviteban_destruct(void *key, void *context,
                                    void *user_context)
 {
-  switch ((SilcUInt32)key) {
-  case 1:
-    /* Invite string */
-    silc_free(context);
-    break;
-  case 2:
-  case 3:
-    /* Public key/Channel ID SilcBuffer */
-    silc_buffer_free(context);
-    break;
-  default:
-    break;
-  }
+  silc_buffer_free(context);
+}
+
+/* Creates connections accoring to configuration. */
+
+void silc_server_create_connections(SilcServer server)
+{
+  silc_schedule_task_del_by_callback(server->schedule,
+                                    silc_server_connect_to_router);
+  silc_schedule_task_add(server->schedule, 0,
+                        silc_server_connect_to_router, server, 0, 1,
+                        SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
 }
index 393f09003e6f558b70cdfefe8be4c5956104e912..489abf8781633deda10323812360d2bf4b199866 100644 (file)
@@ -207,4 +207,7 @@ void silc_server_inviteban_process(SilcServer server, SilcHashTable list,
 void silc_server_inviteban_destruct(void *key, void *context,
                                    void *user_context);
 
+/* Creates connections accoring to configuration. */
+void silc_server_create_connections(SilcServer server);
+
 #endif /* SERVER_UTIL_H */
index 911caff0dde735085b13ccc4fa628097740cbe6e..2121264101e7665917e15b7519a0166af7f7642a 100644 (file)
@@ -2,7 +2,7 @@
 
   serverconfig.c
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
   Copyright (C) 1997 - 2002 Pekka Riikonen
 
@@ -495,22 +495,40 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   SILC_SERVER_CONFIG_SECTION_INIT(SilcServerConfigServerInfoInterface);
   SilcServerConfigServerInfo *server_info = config->server_info;
 
-  /* if there isn't the struct alloc it */
+  SERVER_CONFIG_DEBUG(("Received SERVERINFO type=%d name=\"%s\" (val=%x)",
+                      type, name, context));
+
+  /* if there isn't the main struct alloc it */
   if (!server_info)
     config->server_info = server_info = (SilcServerConfigServerInfo *)
                silc_calloc(1, sizeof(*server_info));
 
   if (type == SILC_CONFIG_ARG_BLOCK) {
     if (!strcmp(name, "primary")) {
+      if (server_info->primary) {
+       SILC_SERVER_LOG_ERROR(("Error while parsing config file: "
+                              "Double primary specification."));
+       got_errno = SILC_CONFIG_EPRINTLINE;
+       goto got_err;
+      }
       CONFIG_IS_DOUBLE(server_info->primary);
-      if (!tmp)
-       return SILC_CONFIG_OK;
+
+      /* now check the temporary struct, don't accept empty block and
+         make sure all fields are there */
+      if (!tmp || !tmp->server_ip || !tmp->port) {
+       got_errno = SILC_CONFIG_EMISSFIELDS;
+       goto got_err;
+      }
       server_info->primary = tmp;
       config->tmp = NULL;
       return SILC_CONFIG_OK;
     } else if (!strcmp(name, "secondary")) {
       if (!tmp)
        return SILC_CONFIG_OK;
+      if (!tmp || !tmp->server_ip || !tmp->port) {
+       got_errno = SILC_CONFIG_EMISSFIELDS;
+       goto got_err;
+      }
       SILC_SERVER_CONFIG_LIST_APPENDTMP(server_info->secondary);
       config->tmp = NULL;
       return SILC_CONFIG_OK;
@@ -603,9 +621,13 @@ SILC_CONFIG_CALLBACK(fetch_serverinfo)
   return SILC_CONFIG_OK;
 
  got_err:
-  silc_free(tmp);
-  silc_free(config->tmp);
-  config->tmp = NULL;
+  /* here we need to check if tmp exists because this function handles
+   * misc data (multiple fields and single-only fields) */
+  if (tmp) {
+    silc_free(tmp->server_ip);
+    silc_free(tmp);
+    config->tmp = NULL;
+  }
   return got_errno;
 }
 
@@ -1438,6 +1460,7 @@ SilcServerConfig silc_server_config_alloc(const char *filename)
       }
     }
     silc_server_config_destroy(config_new);
+    silc_config_close(file);
     return NULL;
   }
 
index 164647d8262664e3fc4830a6c14f5936c102a327..03cb63a0d89b57304e2508dd961e9216d55c0ecb 100644 (file)
@@ -2,7 +2,7 @@
 
   serverconfig.h
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
   Copyright (C) 1997 - 2002 Pekka Riikonen
 
index d9e39bb5350c35d0b5eacbbf346d82580297c231..7d8fdea5c1f059e28cf8ffd9d779677c8d2c75f4 100644 (file)
@@ -42,7 +42,7 @@ void silc_id_create_server_id(const char *ip, SilcUInt16 port, SilcRng rng,
   }
 
   (*new_id)->ip.data_len = silc_net_is_ip4(ip) ? 4 : 16;
-  (*new_id)->port = htons(port);
+  (*new_id)->port = SILC_SWAB_16(port);
   (*new_id)->rnd = silc_rng_get_rn16(rng);
 
   SILC_LOG_DEBUG(("New ID (%s)", silc_id_render(*new_id, SILC_ID_SERVER)));
index 33a5043cc7ca12475dc117c538a5930024e62773..d7e276a6175e65325f9ba997766ca3bbdeb73666 100644 (file)
@@ -306,6 +306,37 @@ SILC_TASK_CALLBACK(dump_stats)
 #undef STAT_OUTPUT
 
 #ifdef SILC_DEBUG
+  /* Dump internal flags */
+  fprintf(fdd, "\nDumping internal flags\n");
+  fprintf(fdd, "  server_type            : %d\n", silcd->server_type);
+  fprintf(fdd, "  standalone             : %d\n", silcd->standalone);
+  fprintf(fdd, "  listenning             : %d\n", silcd->listenning);
+  fprintf(fdd, "  background             : %d\n", silcd->background);
+  fprintf(fdd, "  backup_router          : %d\n", silcd->backup_router);
+  fprintf(fdd, "  backup_primary         : %d\n", silcd->backup_primary);
+  fprintf(fdd, "  backup_noswitch        : %d\n", silcd->backup_noswitch);
+  fprintf(fdd, "  wait_backup            : %d\n", silcd->wait_backup);
+  if (silcd->router)
+    fprintf(fdd, "  primary router         : %s\n", 
+      silcd->router->server_name ? silcd->router->server_name : "");
+
+  /* Dump socket connections */
+  {
+    int i;
+    SilcSocketConnection s;
+
+    fprintf(fdd, "\nDumping socket connections\n");
+    for (i = 0; i < silcd->config->param.connections_max; i++) {
+      s = silcd->sockets[i];
+      if (!s)
+        continue;
+      fprintf(fdd, "  %d: host %s ip %s port %d type %d flags 0x%x\n",
+             s->sock, s->hostname ? s->hostname : "N/A",
+             s->ip ? s->ip : "N/A", s->port, s->type,
+             (unsigned int)s->flags);
+    }
+  }
+
   /* Dump lists */
   {
     SilcIDCacheList list = NULL;
index 671dac894b0f2fabe6e7c1f8ce2c30b203f3873e..1fb1bdefbbcb1169acfa66370de4fc18816ea6b8 100644 (file)
@@ -39,6 +39,7 @@ AM_INIT_AUTOMAKE(SILC_PACKAGE, SILC_VERSION)
 AC_PREREQ(2.52)
 AC_CONFIG_HEADERS(includes/silcdefs.h)
 
+CFLAGS=
 AC_PROG_CC
 AC_C_INLINE
 AC_C_CONST
@@ -46,23 +47,18 @@ AC_C_CONST
 AC_PROG_LN_S
 AC_SUBST(LN_S)
 
-# Distribution definition. ./prepare will automatically add here a correct
-# value. Do not edit!
-#
+##
+## Distribution definition. ./prepare will automatically add here a correct
+## value. Do not edit!
+##
 silc_dist=SILC_PACKAGE
 SILC_DIST_SUBDIRS="SILC_DISTRIBUTION_SUBDIRS"
 AC_DEFINE(SILC_DIST_DEFINE)
 
-# XXX
-# Compiler flags
-#
-if test "$GCC"; then
-  CFLAGS="-Wall -finline-functions $CFLAGS"
-fi
 
-#
-# Library versioning.
-#
+##
+## Library versioning.
+##
 # Do the releases and library versioning according to following rules:
 #
 #  - If any code has changed in library, increment [LIB]_REVISION
@@ -205,7 +201,6 @@ AM_CONDITIONAL(HAVE_REGEX, test x$have_regex = x1)
 AC_CHECK_FUNC(getopt_long, have_getopt_long=1, have_getopt_long=0)
 AM_CONDITIONAL(HAVE_GETOPT_LONG, test x$have_getopt_long = x1)
 
-
 ##
 ##  Enable/disable checking
 ##
@@ -277,17 +272,14 @@ AC_ARG_ENABLE(debug,
       yes)
         AC_MSG_RESULT(yes)
         AC_DEFINE(SILC_DEBUG)
-        CFLAGS="-O -g $CFLAGS"
        summary_debug="yes"
         ;;
       *)
         AC_MSG_RESULT(no)
-        CFLAGS="-O2 -g $CFLAGS"
         ;;
     esac
   ],
   [
-    CFLAGS="-O2 -g $CFLAGS"
     AC_MSG_RESULT(no)
   ])
 
@@ -327,6 +319,49 @@ AC_ARG_ENABLE(asm,
   ])
 
 
+##
+## Compiler and compiler flag checks
+##
+
+# Function to check if compiler flag works
+# Usage: SILC_ADD_CFLAGS(FLAGS, [ACTION-IF-FAILED])
+AC_DEFUN(SILC_ADD_CFLAGS,
+[ tmp_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS $1"
+  AC_MSG_CHECKING(whether $CC accepts $1 flag)
+  AC_TRY_LINK(, , AC_MSG_RESULT(yes), [AC_MSG_RESULT(no)
+                                      CFLAGS="$tmp_CFLAGS"
+                                      $2])
+  unset tmp_CFLAGS
+])
+
+if test "$GCC"; then
+  # GCC specific options
+  if test "x$summary_debug" = "xyes"; then
+    SILC_ADD_CFLAGS(-g -O)
+  else
+    SILC_ADD_CFLAGS(-g -O2)
+  fi
+  SILC_ADD_CFLAGS(-Wall -finline-functions)
+else
+  # Other compilers
+  case "$target" in
+    alpha*-dec-osf*)
+      SILC_ADD_CFLAGS(-g3 -O2, SILC_ADD_CFLAGS(-g3 -O, SILC_ADD_CFLAGS(-O)))
+      ;;
+    *)
+      SILC_ADD_CFLAGS(-g)
+      SILC_ADD_CFLAGS(-O2, SILC_ADD_CFLAGS(-O))
+      ;;
+  esac
+
+  # Intel C++ Compiler needs -restrict
+  if test "x$CC" = "xicc"; then
+    SILC_ADD_CFLAGS(-restrict)
+  fi
+fi
+
+
 ##
 ##  Installation
 ##
@@ -1141,6 +1176,7 @@ echo ""
 echo " Installation prefix ...........: $prefix"
 echo " bin directory .................: $s_bindir"
 echo " sbin directory ................: $s_sbindir"
+echo " etc directory .................: $ETCDIR"
 echo " man directory .................: $s_mandir"
 echo " help directory ................: $HELPDIR"
 echo " doc directory .................: $DOCDIR"
@@ -1174,8 +1210,14 @@ if test x$sim_support = xfalse; then
 else
   sim_support="yes"
 fi
+if test x$has_iconv = xfalse; then
+  iconv_support="no"
+else
+  iconv_support="yes"
+fi
 echo " SIM support ...................: $sim_support"
 echo " IPv6 support ..................: $summary_ipv6"
+echo " Iconv support .................: $iconv_support"
 echo " Assembler optimizations .......: $summary_asm"
 
 mp="MPI"
index 9eab20c4ca3b15e415d6a879847cdfa08d894210..a78ed96437614084655bf2967ccc93290651dc51 100644 (file)
@@ -455,7 +455,8 @@ manpageauthor()
 SILC is designed and written by Pekka Riikonen <priikone@iki.fi> and rest
 of the SILC Project.
 
-Configuration file format and parser is by Johnny Mnemonic.
+Configuration file format and parser is by Giovanni Giacobbi
+<giovanni@giacobbi.net>.
 
 This manpage was written by Mika 'Bostik' Boström <bostik@lut.fi>
 
index 59524bfbc86b68710506151684783d1a9d4bcb0f..b10c4bb5ef7ce72d3ce9540c860fa004d7a84c3e 100644 (file)
@@ -28,6 +28,13 @@ of the Toolkit always delivers the latest version of this reference manual.
 <li><a href="intro_reference.html">Introduction to the Manual</a><br />
 <li><a href="programming_conv.html">Programming Conventions</a><br />
 <li><a href="building.html">Building the Toolkit</a>
+<li><a href="platforms.html">Platform Implementations</a>
+
+<br /><br />
+<b>Guides & Tutorials</b>
+<br /><br />
+<li><a href="silcclientlib.html">Client Library Guides & Reference</a>
+<li><a href="silcrng_intro.html">Introduction to SILC Random Number Generator</a>
 
 <br /><br />
 <b>Toolkit Reference</b>
diff --git a/lib/doc/command_reply_args.html b/lib/doc/command_reply_args.html
new file mode 100644 (file)
index 0000000..5a96427
--- /dev/null
@@ -0,0 +1,373 @@
+<big><b>Command Reply Arguments</b></big>
+
+<br />&nbsp;<br />
+The SILC Client Library 'command_reply client operation (which is part of the
+<a href="silcclient-SilcClientOperations.html">
+SilcClientOperation</a> callback functions) returns command replies
+from the SILC Server for commands that the client has earlier sent to the
+server.  The 'command_reply' client operation implementation has a variable
+argument list to deliver <a href="silccommand-SilcCommand.html">SilcCommand</a>
+specific arguments to the application.  This document describes these
+arguments for all command replies to help SILC client software developers
+to process them.
+
+<br />&nbsp;<br />&nbsp;<br />
+<b>command_reply Client Library operation</b>
+
+<br />&nbsp;<br />
+The 'command_reply' client operation callback function prototype is as follows:
+
+<br />&nbsp;<br />
+<tt>
+&nbsp;&nbsp;
+void (*command_reply)(SilcClient client, SilcClientConnection conn,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+SilcCommandPayload cmd_payload, bool success, SilcCommand command,<br />
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+SilcStatus status, ...);
+</tt>
+
+<br />&nbsp;<br />
+The first argument 'client' is the SILC Client Library context, the 'conn' 
+is the context for the connection to the remote server, the 'cmd_payload'
+is the raw SilcCommandPayload and application usually ignores it, the
+'success' boolean value indicates whether the earlier command was a success
+or not, the 'command' is the command reply enumeration, and the 'status'
+indicates the status of the command reply.  If 'success' is FALSE then
+'status' includes error status.
+
+<br />&nbsp;<br />
+Rest of the arguments are 'command' specific and implementation should
+handle them by the SilcCommand for example in a <tt>switch</tt> statement.
+The commands are defined in lib/silccore/silccomand.h header file.  A short 
+example:
+
+<br />&nbsp;<br />
+<tt>
+&nbsp;&nbsp;switch(type)<br />
+&nbsp;&nbsp;&nbsp;&nbsp;{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;case SILC_COMMAND_WHOIS:<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
+&nbsp;&nbsp;&nbsp;&nbsp;case SILC_COMMAND_WHOWAS:<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
+&nbsp;&nbsp;&nbsp;&nbsp;case SILC_COMMAND_NICK:<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;}
+</tt>
+
+<br />&nbsp;<br />&nbsp;<br />
+<b>Arguments</b>
+
+<br />&nbsp;<br />
+The following table describes all commands and arguments that the client
+library sends in the 'command_reply' client operation to the application.  
+By default all arguments that the library sends to application are valid 
+pointers.  However, it is possible that some pointers may be NULL.  If 
+this is the case it is separately mentioned that the argument may be NULL.  
+In this case application must ignore that argument.  The 'command_reply'
+arguments per SilcCommand is as follows:
+
+<br />&nbsp;<br />
+<table border="1" width="100%" cellpadding="3" cellspacing="0">
+
+<tr>
+<td><small>Name</td>
+<td><small>Description</td>
+<td width="50%"><small>Variable Arguments</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_WHOIS</td>
+<td><small>
+Returns information about user. The following pointers may be NULL: 'channels',
+'fingerprint', 'channel_usermodes' and 'attrs'.  If 'fingerprint' is valid its
+length is 20 bytes. If 'channels' is valid it can be parsed with
+silc_channel_payload_parse_list function. It is the list of channels user
+has joined. If the 'channel_usermodes' is valid it can be parsed with
+silc_get_mode_list function. It is the list of the user's modes on the
+joined channels. The 'attr' is the Requested Attributes that may have been
+returned by the client and it can be parsed by traversing the SilcDList
+and using silc_attribute_get_attribute function.
+</td>
+<td width="50%"><small>SilcClientEntry client_entry, char *nickname,
+char *username, char *realname, SilcBuffer channels, SilcUInt32 usermode,
+SilcUInt32 idletime, unsigned char *fingerprint, SilcBuffer channel_usermodes,
+SilcDList attrs
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_WHOWAS</td>
+<td><small>
+Returns history information about user. The 'client_entry' and 'realname'
+may be NULL.
+</td>
+<td width="50%"><small>SilcClientEntry client_entry, char *nickname,
+char *username, char *realname
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_IDENTIFY</td>
+<td><small>
+Returns information about user, channel or server.  This is similar to
+WHOIS command but does not return so much information and can be used to
+get information about channels and servers too.  Application should ignore
+this command reply.  The 'name' and 'info' may be NULL.
+</td>
+<td width="50%"><small>void *entry, char *name, char *info
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_NICK</td>
+<td><small>
+Returns the new Client ID after user has changed nickname.
+</td>
+<td width="50%"><small>SilcClientEntry local_entry, char *nickname
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_LIST</td>
+<td><small>
+Returns the list of channel in the SILC network. Each call of command reply
+returns one channel. This means that the command reply is called multiple
+times to return list of channels.  The 'channel_topic' may be NULL.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, char *channel_name,
+char *channel_topic, SilcUInt32 user_count
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_TOPIC</td>
+<td><small>
+Returns the topic of the channel.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, char *topic
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_INVITE</td>
+<td><small>
+Returns the invite list of the channel.  Called also even if invite list
+was not modified but SILC_COMMAND_INVITE command was used to invite a user
+into a channel.  In this case the invite list is not returned by the
+server and 'invite_list' is NULL.  The 'invite_list' is list of
+SilcArgumentPayloads.  The first 2 bytes are the number of arguments in
+the list and can be parsed with SILC_GET16_MSB macro.  The list can be
+parsed with silc_argument_payload_parse function.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcBuffer invite_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_KILL</td>
+<td><small>
+Called after killing a client.  There is no arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_INFO</td>
+<td><small>
+Returns information about the server user is connected to.
+</td>
+<td width="50%"><small>SilcServerEntry server, char *server_name,
+char *server_info
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_STATS</td>
+<td><small>
+Returns network statistics from the server.  The 'stats_buffer' of length of
+'buffer_length' bytes includes 32-bit integers one after the other each
+representing some statistics.  The integers can be parsed for example with
+SILC_GET32_MSB macro.  The integers in the buffer are: starttime, uptime,
+local_clients, local_channels, local_serverops, local_routerops, cell_clients,
+cell_channels, cell_servers, all_clients, all_channel, all_servers,
+all_routers, all_serverops, all_routerops.  All integers are always present.
+</td>
+<td width="50%"><small>unsigned char *stats_buffer, SilcUInt32 buffer_length
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_PING</td>
+<td><small>
+Returns reply to earlier ping.  There is no arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_OPER</td>
+<td><small>
+Returns reply to earlier SILC_COMMAND_OPER command.  There is no arguments
+to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_JOIN</td>
+<td><small>
+Reply received when user joined a channel.  The 'ignored' argument can
+be ignored by the application.  The 'topic' and 'hmac_name' may be NULL.
+The 'key_payload' is usually ignored by the application.  The 'list_count'
+is the number of entries in both 'client_id_list' and 'client_mode_list'.
+The 'client_id_list' is a list of clients on the channel and 'client_mode_list'
+includes those clients' modes on the channel.  If application likes to
+resolve information about the clients on the channel it may call
+silc_client_get_clients_by_list function and pass the 'client_id_list' as
+argument to it.  The 'client_mode_list' includes 32-bit integers one after
+the other and they are in same order as clients in 'client_mode_list'.
+If application resolves the information with silc_client_get_clients_by_list
+parsing the 'client_mode_list' is not necessary.
+</td>
+<td width="50%"><small>char *channel_name, SilcChannelEntry channel,
+SilcUInt32 channel_mode, int ignored, SilcBuffer key_payload, NULL, NULL,
+char *topic, char *hmac_name, SilcUInt32 list_count, SilcBuffer client_id_list,
+SilcBuffer client_mode_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_MOTD</td>
+<td><small>
+Returns the Message of the Day from the server.  The 'motd' may be NULL.
+</td>
+<td width="50%"><small>char *motd
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_UMODE</td>
+<td><small>
+Returns the user mode after changing it.
+</td>
+<td width="50%"><small>SilcUInt32 user_mode
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_CMODE</td>
+<td><small>
+Returns channel's mode after changing it.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcUInt32 mode
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_CUMODE</td>
+<td><small>
+Returns user's mode on channel after changing it.
+</td>
+<td width="50%"><small>SilcUInt32 mode, SilcChannelEntry channel,
+SilcClientEntry target_client
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_KICK</td>
+<td><small>
+Called after kicking a client.  There is no arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_BAN</td>
+<td><small>
+Returns channel's ban list.  The 'ban_list' may be NULL.  The construction
+of that list is equivalent to invite list.  See description of
+SILC_COMMAND_INVITE command reply.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcBuffer ban_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_DETACH</td>
+<td><small>
+Called after being detached from the SILC network. There is no arguments
+to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_WATCH</td>
+<td><small>
+Called after modifying the watch list in the server.  There is no arguments
+to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_SILCOPER</td>
+<td><small>
+Returns reply to earlier SILC_COMMAND_SILCOPER command.  There is no
+arguments to this reply.
+</td>
+<td width="50%"><small>none
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_LEAVE</td>
+<td><small>
+Called after leaving the channel.
+</td>
+<td width="50%"><small>SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_USERS</td>
+<td><small>
+Returns list of users in channel.  If application wishes not to parse
+the raw lists the channel->user_list hash table is updated before calling
+this command reply and application may traverse that table instead of
+parssing the raw lists.
+</td>
+<td width="50%"><small>SilcChannelEntry channel, SilcUInt32 list_count,
+SilcBuffer client_id_list, SilcBuffer client_mode_list
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_COMMAND_GETKEY</td>
+<td><small>
+Returns public key of client or server.  The 'public_key' may be NULL.
+The 'entry_type' is used to check what type of pointer the entry' is.  For 
+SILC_ID_CLIENT SilcClientEntry and for SILC_ID_SERVER SilcServerEntry.
+</td>
+<td width="50%"><small>SilcIdType entry_type, void *entry,
+SilcPublicKey public_key
+</td>
+</tr>
+
+</table>
+
+<br />&nbsp;<br />
+SILC protocol defines some additional commands but command replies to 
+those commands are not delivered to the application.  Only the command
+replies listed above are delivered to application.
diff --git a/lib/doc/notifyargs.html b/lib/doc/notifyargs.html
new file mode 100644 (file)
index 0000000..ebe124a
--- /dev/null
@@ -0,0 +1,269 @@
+<big><b>SilcNotifyType Arguments</b></big>
+
+<br />&nbsp;<br />
+The SILC Client Library 'notify' client operation (which is part of the
+<a href="silcclient-SilcClientOperations.html">
+SilcClientOperation</a> callback functions) returns different kind of
+notifications from the SILC server to the SILC client.  The 'notify'
+client operation implementation has a variable argument list to deliver
+<a href="silcnotify-SilcNotifyType.html">SilcNotifyType</a> type specific arguments to the application.  This document
+describes these arguments for all notify types to help SILC client
+software developers to handle the incoming notifications.
+
+<br />&nbsp;<br />&nbsp;<br />
+<b>notify Client Library operation</b>
+
+<br />&nbsp;<br />
+The 'notify' client operation callback function prototype is as follows:
+
+<br />&nbsp;<br />
+<tt>
+&nbsp;&nbsp;void (*notify)(SilcClient client, SilcClientConnection conn,
+SilcNotifyType type, ...);
+</tt>
+
+<br />&nbsp;<br />
+The first argument 'client' is the SILC Client Library context, the `conn' 
+is the context for the connection to the remote server, and the `type' is 
+the notify type enumeration sent by the server.  Rest of the arguments are 
+`type' specific and implementation should handle them by the 
+SilcNotifyType for example in a <tt>switch</tt> statement.  The notify 
+types are defined in lib/silccore/silcnotify.h header file.  A short 
+example:
+
+<br />&nbsp;<br />
+<tt>
+&nbsp;&nbsp;switch(type)<br />
+&nbsp;&nbsp;&nbsp;&nbsp;{<br />
+&nbsp;&nbsp;&nbsp;&nbsp;case SILC_NOTIFY_TYPE_NONE:<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
+&nbsp;&nbsp;&nbsp;&nbsp;case SILC_NOTIFY_TYPE_INVITE:<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
+&nbsp;&nbsp;&nbsp;&nbsp;case SILC_NOTIFY_TYPE_JOIN:<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
+&nbsp;&nbsp;&nbsp;&nbsp;...<br />
+&nbsp;&nbsp;&nbsp;&nbsp;}
+</tt>
+
+<br />&nbsp;<br />&nbsp;<br />
+<b>Arguments</b>
+
+<br />&nbsp;<br />
+The following table describes all notify types and arguments that the 
+client library sends in the 'notify' client operation to the application.  
+By default all arguments that the library sends to application are valid 
+pointers.  However, it is possible that some pointers may be NULL.  If 
+this is the case it is separately mentioned that the argument may be NULL.  
+In this case application must ignore that argument.  The SilcNotifyType 
+arguments per notify type is as follows:
+
+<br />&nbsp;<br />
+<table border="1" width="100%" cellpadding="3" cellspacing="0">
+
+<tr>
+<td><small>Name</td>
+<td><small>Description</td>
+<td width="50%"><small>Variable Arguments</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_NONE</td>
+<td><small>
+A message from server that usually does not include any critical
+information.  Application may ignore this or display it for the user.
+The 'message' argument may be NULL.
+</td>
+<td width="50%"><small>char *message</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_INVITE</td>
+<td><small>
+Sent to the client if the user is invited on a channel. The 'channel_name' 
+argument may be NULL.
+</td>
+<td width="50%"><small>SilcClientChannel channel, char *channel_name,
+SilcClientEntry inviter
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_JOIN</td>
+<td><small>
+Sent when someone joins to a channel.
+</td>
+<td width="50%"><small>SilcClientEntry joining_client, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_LEAVE</td>
+<td><small>
+Sent when someone leaves (parts) the channel.
+</td>
+<td width="50%"><small>SilcClientEntry leaving_client, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_SIGNOFF</td>
+<td><small>
+Sent when someone signoff the SILC network.  The 'signoff_message' may be 
+NULL.  The 'leaving_client' SilcClientEntry may be incomplete and contain 
+NULL pointers, application must check it's pointers before attempting to 
+display for example nickname information.
+</td>
+<td width="50%"><small>SilcClientEntry signoff_client, char *signoff_message
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_TOPIC_SET</td>
+<td><small>
+Sent when the topic of a channel is set/changed.  The 'setter_id_type'
+is used to check what type of pointer the 'setter_entry' is.  For 
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for 
+SILC_ID_CHANNEL SilcChannelEntry.
+</td>
+<td width="50%"><small>SilcIdType setter_id_type, void *setter_entry,
+char *topic, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_NICK_CHANGE</td>
+<td><small>
+Sent when someone changes their nickname.  The 'old_client_entry' includes 
+the old nickname and the 'new_client_entry' includes the new nickname.  
+Application must understand that the 'old_client_entry' pointer becomes 
+invalid after returning from the function.
+</td>
+<td width="50%"><small>SilcClientEntry old_client_entry,
+SilcClientEntry new_client_entry
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_CMODE_CHANGE</td>
+<td><small>
+Sent when channel's mode has changed. The 'changer_id_type'
+is used to check what type of pointer the 'changer_entry' is.  For 
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for 
+SILC_ID_CHANNEL SilcChannelEntry.  The 'mode' is the mode mask after the 
+change.  The 'hmac_name' argument may be NULL.
+</td>
+<td width="50%"><small>SilcIdType changer_id_type, void *changer_entry,
+SilcUInt32 mode, NULL, char *hmac_name, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_CUMODE_CHANGE</td>
+<td><small>
+Sent when a users mode on a channel has changed. The 'changer_id_type'
+is used to check what type of pointer the 'changer_entry' is.  For 
+SILC_ID_CLIENT SilcClientEntry, for SILC_ID_SERVER SilcServerEntry and for 
+SILC_ID_CHANNEL SilcChannelEntry.  The 'mode' is the mode mask after the
+change.  The 'target_client' is the client whose mode was changed.
+</td>
+<td width="50%"><small>SilcIdType changer_id_type, void *changer_entry,
+SilcUInt32 mode, SilcClientEntry target_client, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_MOTD</td>
+<td><small>
+Message of the Day from the server.
+</td>
+<td width="50%"><small>char *motd
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_CHANNEL_CHANGE</td>
+<td><small>
+Sent when a channel's Channel ID changes.  It is possible that channel's 
+ID changes and this notify is sent by the server when this happens.  
+Usually application does not need to handle this notify type and may 
+safely ignore it when received.
+</td>
+<td width="50%"><small>SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_SERVER_SIGNOFF</td>
+<td><small>
+Sent when a server quits the network.  The 'clients' is an array 
+SilcClientEntry pointers of size of 'clients_count'.  Each client in the 
+entry is one client signing off from the SILC network.
+</td>
+<td width="50%"><small>NULL, SilcClientEntry *clients, SilcUInt32 clients_count
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_KICKED</td>
+<td><small>
+Sent when a client (possibly our client) is kicked from a channel.  The 
+'kick_message' may be NULL.  If our client was kicked then 'kicked' is our 
+local SilcClientEntry pointer.
+</td>
+<td width="50%"><small>SilcClientEntry kicked, char *kick_message,
+SilcClientEntry kicker, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_KILLED</td>
+<td><small>
+Sent when a client (possibly our client) is killed from the network.  The 
+'kill_message' may be NULL.  If our client was killed then 'killed' is our 
+local SilcClientEntry pointer.  The 'killer_type' is used to check what 
+type of pointer the 'killer' is.  For SILC_ID_CLIENT SilcClientEntry, for 
+SILC_ID_SERVER SilcServerEntry and for SILC_ID_CHANNEL SilcChannelEntry.
+</td>
+<td width="50%"><small>SilcClientEntry killed, char *kill_message,
+SilcIdType killer_type, void *killer, SilcChannelEntry channel
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_ERROR</td>
+<td><small>
+Sent when an error occurs while handling some operation (except command)
+from the client.  Application usually cannot handle this notify type and 
+may safely ignore it.
+</td>
+<td width="50%"><small>SilcStatus error
+</td>
+</tr>
+
+<tr>
+<td><small>SILC_NOTIFY_TYPE_WATCH</td>
+<td><small>
+Sent to notify some status change of a client we are wathing.  The 
+SILC_COMMAND_WATCH is used to manage clients we are wathing and this 
+notify type is used to deliver information about that client.  If the 
+client just changed nickname the 'new_nickname' includes the new nickname.  
+Otherwise this pointer is NULL.  The 'user_mode' is the client's mode in 
+the SILC network.  The 'notification' contains the notify type that 
+happened for the 'watched_client' (for example 
+SILC_NOTIFY_TYPE_NICK_CHANGE if the client changed their nickname).
+</td>
+<td width="50%"><small>SilcClientEntry watched_client, char *new_nickname,
+SilcUInt32 user_mode, SilcNotifyType notification
+</td>
+</tr>
+
+</table>
+
+<br />&nbsp;<br />
+SILC protocol defines some additional notify types but those notify types 
+are not delivered to the application.  Some of those notify types are only 
+delivered between servers and routers and clients never receive them.  
+Only the notify types listed above are delivered to application.
diff --git a/lib/doc/platforms.html b/lib/doc/platforms.html
new file mode 100644 (file)
index 0000000..fa873d9
--- /dev/null
@@ -0,0 +1,60 @@
+<big><b>Platform Implementations</b></big>
+
+<br />&nbsp;<br />
+This document describes the implementation issues with different platforms
+that the SILC Toolkit support.  Some of the supported platforms does not
+support all the features delivered with the Toolkit or they may behave
+differently from other platforms.  This document descibres these
+differences between platforms.
+
+<br />&nbsp;<br />
+<li><a href="#unix">Unix & Linux Implementation</a><br />
+<li><a href="#windows">Windows Implementation</a><br />
+<li><a href="#macosx">Mac OS X Implementation</a>
+
+<br />&nbsp;<br />&nbsp;<br />
+<b>Supported Platforms</b>
+
+<br />&nbsp;<br />
+SILC Toolkit supports by default all Unix and Linux platforms, Windows 
+platforms from Windows 98 and newer, and Mac OS X.  In the future there is
+also plans to add support for other platforms such as Symbian OS (EPOC).
+
+<br />&nbsp;<br />&nbsp;<br />
+<b><a name="unix"></a>Unix Implementation</b>
+
+<br />&nbsp;<br />
+All features and components delivered with the SILC Toolkit work on all
+Unix and Linux platforms.  There are no special Unix platform related
+implementation issues with current version of SILC Toolkit.
+
+
+<br />&nbsp;<br />&nbsp;<br />
+<b><a name="windows"></a>Windows Implementation</b>
+
+<br />&nbsp;<br />
+By default all features and components delivered with SILC Toolkit are
+supported on Windows.  However, there are some certain issues with the
+Windows version of the SILC Toolkit.
+
+<br />&nbsp;<br />
+<li>Toolkit users should not use <tt>silc_client_run</tt> function to
+execute the Client Library.  Instead the <tt>silc_client_run_one</tt> should
+be used, for example as an timer task and the Windows application's own
+message loop should be used as the main message loop.
+
+<li>The function <tt>silc_net_create_connection_async</tt> is not actually
+asynchronous on Windows, but synchronous and it will block the process
+while the connection is created.  This means also that the function
+<tt>silc_client_connect_to_server</tt> is not asynchronous but
+synchronous.
+
+
+<br />&nbsp;<br />&nbsp;<br />
+<b><a name="macosx"></a>Mac OS X Implementation</b>
+
+<br />&nbsp;<br />
+All features and components delivered with the SILC Toolkit work on Mac
+OS X platform.  There are no special Mac OS X platform related
+implementation issues with current version of SILC Toolkit.
+
index 7fa78c18b5835f2e62fb4ae9d88bfe3e440f4cc5..84267123723b35e68aa08f8620114dbae708a2d8 100644 (file)
@@ -1,8 +1,10 @@
 <!--
 @LIBRARY=SILC Client Library
 @FILENAME=silcclientlib.html
-@LINK=silcclient_using.html:Using SILC Client Library
-@LINK=silcclient.html:Client Library Interface
+@LINK=silcclient_using.html:Using SILC Client Library Tutorial
+@LINK=command_reply_args.html:Arguments for <b>command_reply</b> Client Operation
+@LINK=notifyargs.html:Arguments for <b>notify</b> Client Operation
+@LINK=silcclient.html:Client Library Interface Reference
 -->
 
 <big><b>SILC Client Library</b></big>
index f42ebaa6482bc21f6cd9d16e86df364b0d426847..b6df9915e7f8456013721d71034863759d9b893b 100644 (file)
@@ -639,7 +639,7 @@ void silc_client_notify_by_server(SilcClient client,
     client_entry2->fingerprint = client_entry->fingerprint;
     client_entry2->fingerprint_len = client_entry->fingerprint_len;
     client_entry->fingerprint = NULL;
-    client_entry->fingerprint_len = NULL;
+    client_entry->fingerprint_len = 0;
     silc_client_update_client(client, conn, client_entry2, tmp, NULL, NULL,
                              client_entry->mode);
 
index 3131900efdc680fb6379fb6dafc5765c79639bef..40e1d2566f0eb7c3dbbc510ee7d56e026a5e1e00 100644 (file)
@@ -1175,6 +1175,8 @@ SILC_CLIENT_CMD_FUNC(join)
   silc_buffer_free(idp);
   if (auth)
     silc_buffer_free(auth);
+  if (passphrase)
+    memset(passphrase, 0, strlen(passphrase));
   silc_free(passphrase);
 
   /* Notify application */
@@ -1935,6 +1937,7 @@ static void silc_client_command_oper_send(unsigned char *data,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
 
   silc_buffer_free(buffer);
+  silc_buffer_clear(auth);
   silc_buffer_free(auth);
 
   /* Notify application */
@@ -2006,6 +2009,7 @@ static void silc_client_command_silcoper_send(unsigned char *data,
                          0, NULL, NULL, buffer->data, buffer->len, TRUE);
 
   silc_buffer_free(buffer);
+  silc_buffer_clear(auth);
   silc_buffer_free(auth);
 
   /* Notify application */
index fb834aa07be300ebfa2f12aa4c1a3863e9247ad8..0c68045a362318fc521a1cac211a0a357c16adeb 100644 (file)
@@ -249,7 +249,7 @@ static void silc_client_protocol_ke_continue(SilcSKE ske,
      function. */
   if (ctx->responder == TRUE) {
     protocol->state++;
-    silc_protocol_execute(protocol, client->schedule, 0, 100000);
+    silc_protocol_execute(protocol, client->schedule, 0, 1);
   }
 }
 
@@ -327,7 +327,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
       /* Advance protocol state and call the next state if we are responder */
       protocol->state++;
       if (ctx->responder == TRUE)
-       silc_protocol_execute(protocol, client->schedule, 0, 100000);
+       silc_protocol_execute(protocol, client->schedule, 0, 1);
     }
     break;
   case 2:
@@ -360,7 +360,7 @@ SILC_TASK_CALLBACK(silc_client_protocol_key_exchange)
       /* Advance protocol state and call next state if we are initiator */
       protocol->state++;
       if (ctx->responder == FALSE)
-       silc_protocol_execute(protocol, client->schedule, 0, 100000);
+       silc_protocol_execute(protocol, client->schedule, 0, 1);
     }
     break;
   case 3:
index d87dff84b92f2054edc34d15498df2fa459195e0..5750bb203c4239aee49d1e6f6becab9333080e2b 100644 (file)
@@ -527,7 +527,8 @@ typedef struct {
      message to a specific connection.  `conn', however, may be NULL. 
      The `type' indicates the type of the message sent by the library.
      The application can for example filter the message according the
-     type. */
+     type.  The variable argument list is arguments to the formatted
+     message that `msg' may be. */
   void (*say)(SilcClient client, SilcClientConnection conn, 
              SilcClientMessageType type, char *msg, ...);
 
index afefc36241ce936b576e47f879c2acb549789f9e..f01af8d6ab336ec8e790f399304df7eb42569ed0 100644 (file)
@@ -47,6 +47,6 @@ include_HEADERS =     \
        silcattrs.h
 endif
 
-EXTRA_DIST = *.h
+EXTRA_DIST = *.h tests
 
 include $(top_srcdir)/Makefile.defines.in
index 38a1a961392e87fe668cd7110f48dc0418990780..d42dd66fb0ba747268f7a25cc28e46e11b541f2f 100644 (file)
@@ -216,14 +216,8 @@ silc_auth_public_key_encode_data(SilcPublicKey public_key,
                     SILC_STR_UI_XNSTRING(pk, pk_len),
                     SILC_STR_END);
 
-  ret = silc_memdup(buf->data, buf->len);
-  if (!ret)
-    return NULL;
-
-  if (ret_len)
-    *ret_len = buf->len;
+  ret = silc_buffer_steal(buf, ret_len);
 
-  silc_buffer_clear(buf);
   silc_buffer_free(buf);
   silc_free(id_data);
   silc_free(pk);
index 6e5a6a4a560b181774b0ab82364fb5e5503458dd..9b596d9b93203616280a11db6a26dfd85eceb209 100644 (file)
@@ -317,7 +317,7 @@ SILC_PKCS_API_ENCRYPT(pkcs1)
   SilcMPInt mp_tmp;
   SilcMPInt mp_dst;
   unsigned char *padded;
-  SilcUInt32 padded_len, len = key->bits / 8;
+  SilcUInt32 padded_len, len = (key->bits + 7) / 8;
 
   /* Pad data */
   if (!RSA_FormatBlock(&padded, &padded_len, len,
@@ -326,8 +326,6 @@ SILC_PKCS_API_ENCRYPT(pkcs1)
 
   silc_mp_init(&mp_tmp);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Data to MP */
   silc_mp_bin2mp(padded, padded_len, &mp_tmp);
@@ -357,8 +355,6 @@ SILC_PKCS_API_DECRYPT(pkcs1)
 
   silc_mp_init(&mp_tmp);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Data to MP */
   silc_mp_bin2mp(src, src_len, &mp_tmp);
@@ -367,7 +363,7 @@ SILC_PKCS_API_DECRYPT(pkcs1)
   rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
 
   /* MP to data */
-  padded = silc_mp_mp2bin(&mp_dst, key->bits / 8, &padded_len);
+  padded = silc_mp_mp2bin(&mp_dst, (key->bits + 7) / 8, &padded_len);
 
   /* Unpad data */
   unpadded = RSA_DecodeOneBlock(padded, padded_len, 0, 
@@ -401,7 +397,7 @@ SILC_PKCS_API_SIGN(pkcs1)
   SilcMPInt mp_dst;
   unsigned char *padded;
   SilcUInt32 padded_len;
-  SilcUInt32 len = key->bits / 8;
+  SilcUInt32 len = (key->bits + 7) / 8;
 
   /* Pad data */
   if (!RSA_FormatBlock(&padded, &padded_len, len, RSA_BlockPrivate, 
@@ -410,8 +406,6 @@ SILC_PKCS_API_SIGN(pkcs1)
 
   silc_mp_init(&mp_tmp);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Data to MP */
   silc_mp_bin2mp(padded, len, &mp_tmp);
@@ -438,12 +432,10 @@ SILC_PKCS_API_VERIFY(pkcs1)
   SilcMPInt mp_tmp2;
   SilcMPInt mp_dst;
   unsigned char *verify, *unpadded;
-  SilcUInt32 verify_len, len = key->bits / 8;
+  SilcUInt32 verify_len, len = (key->bits + 7) / 8;
 
   silc_mp_init(&mp_tmp2);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp2, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Format the signature into MP int */
   silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
index 202ccf3ffd16759079a849d6bc9e3803d3a3dfa8..5172593256ceae73a24e755d4d677355ff802b9a 100644 (file)
@@ -146,7 +146,7 @@ SILC_PKCS_API_GET_PUBLIC_KEY(rsa)
   unsigned char tmp[4];
 
   e = silc_mp_mp2bin(&key->e, 0, &e_len);
-  n = silc_mp_mp2bin(&key->n, key->bits / 8, &n_len);
+  n = silc_mp_mp2bin(&key->n, (key->bits + 7) / 8, &n_len);
 
   *ret_len = e_len + 4 + n_len + 4;
   ret = silc_calloc(*ret_len, sizeof(unsigned char));
@@ -185,7 +185,7 @@ SILC_PKCS_API_GET_PRIVATE_KEY(rsa)
   unsigned char tmp[4];
 
   e = silc_mp_mp2bin(&key->e, 0, &e_len);
-  n = silc_mp_mp2bin(&key->n, key->bits / 8, &n_len);
+  n = silc_mp_mp2bin(&key->n, (key->bits + 7) / 8, &n_len);
   d = silc_mp_mp2bin(&key->d, 0, &d_len);
 
   *ret_len = e_len + 4 + n_len + 4 + d_len + 4;
@@ -259,7 +259,7 @@ SILC_PKCS_API_SET_PUBLIC_KEY(rsa)
 
   silc_mp_bin2mp(key_data + 4 + e_len + 4, n_len, &key->n);
 
-  key->bits = n_len * 8;
+  key->bits = silc_mp_sizeinbase(&key->n, 2);
   key->pub_set = TRUE;
 
   return key->bits;
@@ -323,7 +323,7 @@ SILC_PKCS_API_SET_PRIVATE_KEY(rsa)
 
   silc_mp_bin2mp(key_data + 4 + e_len + 4 + n_len + 4, d_len, &key->d);
 
-  key->bits = n_len * 8;
+  key->bits = silc_mp_sizeinbase(&key->n, 2);
   key->prv_set = TRUE;
   key->pub_set = TRUE;
 
@@ -338,20 +338,15 @@ SILC_PKCS_API_CONTEXT_LEN(rsa)
 SILC_PKCS_API_ENCRYPT(rsa)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, tmplen;
+  int tmplen;
   SilcMPInt mp_tmp;
   SilcMPInt mp_dst;
 
   silc_mp_init(&mp_tmp);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Format the data into MP int */
-  for (i = 0; i < src_len; i++) {
-    silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
-    silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
-  }
+  silc_mp_bin2mp(src, src_len, &mp_tmp);
 
   /* Encrypt */
   rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->e, &key->n);
@@ -359,10 +354,7 @@ SILC_PKCS_API_ENCRYPT(rsa)
   tmplen = (key->bits + 7) / 8;
 
   /* Format the MP int back into data */
-  for (i = tmplen; i > 0; i--) {
-    dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
-    silc_mp_div_2exp(&mp_dst, &mp_dst, 8);
-  }
+  silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
   *dst_len = tmplen;
 
   silc_mp_uninit(&mp_tmp);
@@ -374,20 +366,15 @@ SILC_PKCS_API_ENCRYPT(rsa)
 SILC_PKCS_API_DECRYPT(rsa)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, tmplen;
+  int tmplen;
   SilcMPInt mp_tmp;
   SilcMPInt mp_dst;
 
   silc_mp_init(&mp_tmp);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Format the data into MP int */
-  for (i = 0; i < src_len; i++) {
-    silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
-    silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
-  }
+  silc_mp_bin2mp(src, src_len, &mp_tmp);
 
   /* Decrypt */
   rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
@@ -395,10 +382,7 @@ SILC_PKCS_API_DECRYPT(rsa)
   tmplen = (key->bits + 7) / 8;
 
   /* Format the MP int back into data */
-  for (i = tmplen; i > 0; i--) {
-    dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
-    silc_mp_div_2exp(&mp_dst, &mp_dst, 8);
-  }
+  silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
   *dst_len = tmplen;
 
   silc_mp_uninit(&mp_tmp);
@@ -410,20 +394,15 @@ SILC_PKCS_API_DECRYPT(rsa)
 SILC_PKCS_API_SIGN(rsa)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, tmplen;
+  int tmplen;
   SilcMPInt mp_tmp;
   SilcMPInt mp_dst;
 
   silc_mp_init(&mp_tmp);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Format the data into MP int */
-  for (i = 0; i < src_len; i++) {
-    silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
-    silc_mp_add_ui(&mp_tmp, &mp_tmp, src[i]);
-  }
+  silc_mp_bin2mp(src, src_len, &mp_tmp);
 
   /* Sign */
   rsa_en_de_crypt(&mp_dst, &mp_tmp, &key->d, &key->n);
@@ -431,10 +410,7 @@ SILC_PKCS_API_SIGN(rsa)
   tmplen = (key->bits + 7) / 8;
 
   /* Format the MP int back into data */
-  for (i = tmplen; i > 0; i--) {
-    dst[i - 1] = (unsigned char)(silc_mp_get_ui(&mp_dst) & 0xff);
-    silc_mp_div_2exp(&mp_dst, &mp_dst, 8);
-  }
+  silc_mp_mp2bin_noalloc(&mp_dst, dst, tmplen);
   *dst_len = tmplen;
 
   silc_mp_uninit(&mp_tmp);
@@ -446,31 +422,22 @@ SILC_PKCS_API_SIGN(rsa)
 SILC_PKCS_API_VERIFY(rsa)
 {
   RsaKey *key = (RsaKey *)context;
-  int i, ret;
+  int ret;
   SilcMPInt mp_tmp, mp_tmp2;
   SilcMPInt mp_dst;
 
   silc_mp_init(&mp_tmp);
   silc_mp_init(&mp_tmp2);
   silc_mp_init(&mp_dst);
-  silc_mp_set_ui(&mp_tmp, 0);
-  silc_mp_set_ui(&mp_tmp2, 0);
-  silc_mp_set_ui(&mp_dst, 0);
 
   /* Format the signature into MP int */
-  for (i = 0; i < signature_len; i++) {
-    silc_mp_mul_2exp(&mp_tmp2, &mp_tmp2, 8);
-    silc_mp_add_ui(&mp_tmp2, &mp_tmp2, signature[i]);
-  }
+  silc_mp_bin2mp(signature, signature_len, &mp_tmp2);
 
   /* Verify */
   rsa_en_de_crypt(&mp_dst, &mp_tmp2, &key->e, &key->n);
 
   /* Format the data into MP int */
-  for (i = 0; i < data_len; i++) {
-    silc_mp_mul_2exp(&mp_tmp, &mp_tmp, 8);
-    silc_mp_add_ui(&mp_tmp, &mp_tmp, data[i]);
-  }
+  silc_mp_bin2mp(data, data_len, &mp_tmp);
 
   ret = TRUE;
 
index 4deddfd96f33b063277784024cd7f1861b4bb98d..83a16d005e4bb6073164dfbc77d171d21c95e274 100644 (file)
@@ -687,8 +687,9 @@ silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
   SilcBuffer buf;
   unsigned char *ret;
 
-  buf = silc_buffer_alloc(public_key->len + 4);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(public_key->len + 4);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_INT(public_key->len),
@@ -699,13 +700,9 @@ silc_pkcs_public_key_encode(SilcPublicKey public_key, SilcUInt32 *len)
                     SILC_STR_UI_XNSTRING(public_key->pk, 
                                          public_key->pk_len),
                     SILC_STR_END);
-  if (len)
-    *len = public_key->len + 4;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -721,8 +718,9 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
   SilcUInt32 totlen;
 
   totlen = 2 + strlen(pkcs) + 2 + strlen(identifier) + pk_len;
-  buf = silc_buffer_alloc(totlen + 4);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(totlen + 4);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_INT(totlen),
@@ -732,13 +730,9 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
                     SILC_STR_UI32_STRING(identifier),
                     SILC_STR_UI_XNSTRING(pk, pk_len),
                     SILC_STR_END);
-  if (len)
-    *len = totlen + 4;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -748,40 +742,34 @@ silc_pkcs_public_key_data_encode(unsigned char *pk, SilcUInt32 pk_len,
 bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
                                 SilcPublicKey *public_key)
 {
-  SilcBuffer buf;
+  SilcBufferStruct buf;
   SilcPKCS alg;
   SilcUInt16 pkcs_len, identifier_len;
   SilcUInt32 totlen, key_len;
   unsigned char *pkcs_name = NULL, *ident = NULL, *key_data = NULL;
   int ret;
 
-  buf = silc_buffer_alloc(data_len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
-  silc_buffer_put(buf, data, data_len);
+  silc_buffer_set(&buf, data, data_len);
 
   /* Get length */
-  ret = silc_buffer_unformat(buf,
+  ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_INT(&totlen),
                             SILC_STR_END);
-  if (ret == -1) {
-    silc_buffer_free(buf);
+  if (ret == -1)
     return FALSE;
-  }
 
 #if 1 /* Backwards support, remove! */
   if (totlen == data_len)
     totlen -= 4;
 #endif
 
-  if (totlen + 4 != data_len) {
-    silc_buffer_free(buf);
+  if (totlen + 4 != data_len)
     return FALSE;
-  }
 
   /* Get algorithm name and identifier */
-  silc_buffer_pull(buf, 4);
+  silc_buffer_pull(&buf, 4);
   ret =
-    silc_buffer_unformat(buf,
+    silc_buffer_unformat(&buf,
                         SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
                         SILC_STR_UI16_NSTRING_ALLOC(&ident, &identifier_len),
                         SILC_STR_END);
@@ -807,9 +795,9 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
   }
 
   /* Get key data. We assume that rest of the buffer is key data. */
-  silc_buffer_pull(buf, 2 + pkcs_len + 2 + identifier_len);
-  key_len = buf->len;
-  ret = silc_buffer_unformat(buf,
+  silc_buffer_pull(&buf, 2 + pkcs_len + 2 + identifier_len);
+  key_len = buf.len;
+  ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
                             SILC_STR_END);
   if (ret == -1)
@@ -835,17 +823,12 @@ bool silc_pkcs_public_key_decode(unsigned char *data, SilcUInt32 data_len,
     (*public_key)->pk_type = SILC_SKE_PK_TYPE_SILC;
   }
 
-  silc_buffer_free(buf);
   return TRUE;
 
  err:
-  if (pkcs_name)
-    silc_free(pkcs_name);
-  if (ident)
-    silc_free(ident);
-  if (key_data)
-    silc_free(key_data);
-  silc_buffer_free(buf);
+  silc_free(pkcs_name);
+  silc_free(ident);
+  silc_free(key_data);
   return FALSE;
 }
 
@@ -971,8 +954,9 @@ silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
   SilcUInt32 totlen;
 
   totlen = 2 + strlen(private_key->name) + private_key->prv_len;
-  buf = silc_buffer_alloc(totlen);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(totlen);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_SHORT(strlen(private_key->name)),
@@ -980,14 +964,9 @@ silc_pkcs_private_key_encode(SilcPrivateKey private_key, SilcUInt32 *len)
                     SILC_STR_UI_XNSTRING(private_key->prv, 
                                          private_key->prv_len),
                     SILC_STR_END);
-  if (len)
-    *len = totlen;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
-  silc_buffer_clear(buf);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -1002,22 +981,18 @@ silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
   SilcUInt32 totlen;
 
   totlen = 2 + strlen(pkcs) + prv_len;
-  buf = silc_buffer_alloc(totlen);
-  silc_buffer_pull_tail(buf, totlen);
+  buf = silc_buffer_alloc_size(totlen);
+  if (!buf)
+    return NULL;
 
   silc_buffer_format(buf,
                     SILC_STR_UI_SHORT(strlen(pkcs)),
                     SILC_STR_UI32_STRING(pkcs),
                     SILC_STR_UI_XNSTRING(prv, prv_len),
                     SILC_STR_END);
-  if (len)
-    *len = totlen;
 
-  ret = silc_calloc(buf->len, sizeof(*ret));
-  memcpy(ret, buf->data, buf->len);
-  silc_buffer_clear(buf);
+  ret = silc_buffer_steal(buf, len);
   silc_buffer_free(buf);
-
   return ret;
 }
 
@@ -1027,20 +1002,18 @@ silc_pkcs_private_key_data_encode(unsigned char *prv, SilcUInt32 prv_len,
 bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
                                  SilcPrivateKey *private_key)
 {
-  SilcBuffer buf;
+  SilcBufferStruct buf;
   SilcPKCS alg;
   SilcUInt16 pkcs_len;
   SilcUInt32 key_len;
   unsigned char *pkcs_name = NULL, *key_data = NULL;
   int ret;
 
-  buf = silc_buffer_alloc(data_len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
-  silc_buffer_put(buf, data, data_len);
+  silc_buffer_set(&buf, data, data_len);
 
   /* Get algorithm name and identifier */
   ret = 
-    silc_buffer_unformat(buf,
+    silc_buffer_unformat(&buf,
                         SILC_STR_UI16_NSTRING_ALLOC(&pkcs_name, &pkcs_len),
                         SILC_STR_END);
   if (ret == -1) {
@@ -1048,7 +1021,7 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
     goto err;
   }
 
-  if (pkcs_len < 1 || pkcs_len > buf->truelen) {
+  if (pkcs_len < 1 || pkcs_len > buf.truelen) {
     SILC_LOG_DEBUG(("Malformed private key buffer"));
     goto err;
   }
@@ -1060,9 +1033,9 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
   }
 
   /* Get key data. We assume that rest of the buffer is key data. */
-  silc_buffer_pull(buf, 2 + pkcs_len);
-  key_len = buf->len;
-  ret = silc_buffer_unformat(buf,
+  silc_buffer_pull(&buf, 2 + pkcs_len);
+  key_len = buf.len;
+  ret = silc_buffer_unformat(&buf,
                             SILC_STR_UI_XNSTRING_ALLOC(&key_data, key_len),
                             SILC_STR_END);
   if (ret == -1)
@@ -1087,17 +1060,11 @@ bool silc_pkcs_private_key_decode(unsigned char *data, SilcUInt32 data_len,
     (*private_key)->prv_len = key_len;
   }
 
-  silc_buffer_clear(buf);
-  silc_buffer_free(buf);
   return TRUE;
 
  err:
-  if (pkcs_name)
-    silc_free(pkcs_name);
-  if (key_data)
-    silc_free(key_data);
-  silc_buffer_clear(buf);
-  silc_buffer_free(buf);
+  silc_free(pkcs_name);
+  silc_free(key_data);
   return FALSE;
 }
 
@@ -1110,20 +1077,24 @@ static bool silc_pkcs_save_public_key_internal(const char *filename,
 {
   SilcBuffer buf;
   SilcUInt32 len;
+  unsigned char *tmp = NULL;
 
   switch(encoding) {
   case SILC_PKCS_FILE_BIN:
     break;
   case SILC_PKCS_FILE_PEM:
-    data = silc_pem_encode_file(data, data_len);
+    tmp = data = silc_pem_encode_file(data, data_len);
     data_len = strlen(data);
     break;
   }
 
   len = data_len + (strlen(SILC_PKCS_PUBLIC_KEYFILE_BEGIN) +
                    strlen(SILC_PKCS_PUBLIC_KEYFILE_END));
-  buf = silc_buffer_alloc(len);
-  silc_buffer_pull_tail(buf, SILC_BUFFER_END(buf));
+  buf = silc_buffer_alloc_size(len);
+  if (!buf) {
+    silc_free(tmp);
+    return FALSE;
+  }
 
   silc_buffer_format(buf,
                     SILC_STR_UI32_STRING(SILC_PKCS_PUBLIC_KEYFILE_BEGIN),
@@ -1133,10 +1104,12 @@ static bool silc_pkcs_save_public_key_internal(const char *filename,
 
   /* Save into file */
   if (silc_file_writefile(filename, buf->data, buf->len)) {
+    silc_free(tmp);
     silc_buffer_free(buf);
     return FALSE;
   }
 
+  silc_free(tmp);
   silc_buffer_free(buf);
   return TRUE;
 }
index 2686c74a55378739aa636d7afb13b36d069df612..48a3e0011ff755dc13dec26cb033f3ffe8164011 100644 (file)
@@ -554,7 +554,7 @@ SilcUInt16 silc_rng_get_rn16(SilcRng rng)
 SilcUInt32 silc_rng_get_rn32(SilcRng rng)
 {
   unsigned char rn[4];
-  SilcUInt16 num;
+  SilcUInt32 num;
 
   rn[0] = silc_rng_get_byte(rng);
   rn[1] = silc_rng_get_byte(rng);
index da72aa9129a5dac36d62d2cae239f37382178828..ba18ae35bfe1f2d01af2fa818aba398614f0660b 100644 (file)
@@ -106,10 +106,16 @@ size_t silc_mp_size(SilcMPInt *mp);
  *
  * DESCRIPTION
  *
- *    Return the size of the integer in base `base'. Note that this size
- *    is probably only an approximation.  However, it is guaranteed that
- *    the returned size is always at least the size of the integer, however,
- *    it may be larger.
+ *    Return the size of the integer in base `base'.
+ *
+ * NOTES
+ *
+ *    For any other base but 2 this function usually returns only an
+ *    approximated size in the base.  It is however guaranteed that the
+ *    the returned size is always at least the size of the integer or
+ *    larger.
+ *
+ *    For base 2 this returns the exact bit-size of the integer.
  *
  ***/
 size_t silc_mp_sizeinbase(SilcMPInt *mp, int base);
@@ -167,6 +173,11 @@ void silc_mp_set_si(SilcMPInt *dst, SilcInt32 si);
  *    Set `dst' integer from string `str' of base `base'. The `dst' must
  *    already be initialized.
  *
+ * NOTES
+ *
+ *    For base 2 the string must be in ASCII bit presentation, not in
+ *    binary.  Use the silc_mp_bin2mp to decode binary into integer.
+ *
  ***/
 void silc_mp_set_str(SilcMPInt *dst, const char *str, int base);
 
@@ -195,6 +206,11 @@ SilcUInt32 silc_mp_get_ui(SilcMPInt *mp);
  *    must already have space allocated. The function returns the same
  *    as `str' or NULL on error.
  *
+ * NOTES
+ *
+ *    For base 2 the returned string is in ASCII bit presentation, not
+ *    in binary.  Use the silc_mp_mp2bin to encode integer into binary.
+ *
  ***/
 char *silc_mp_get_str(char *str, SilcMPInt *mp, int base);
 
index 2fd4e0107ea646bea7f2fe87dabc7d29830a80a6..e00121210a4b767ab89a295318768d8251f189e3 100644 (file)
@@ -201,17 +201,15 @@ SilcSKEStatus silc_ske_initiator_start(SilcSKE ske, SilcRng rng,
   if (status != SILC_SKE_STATUS_OK)
     return status;
 
-  /* Take a copy of the payload buffer for future use. It is used to
-     compute the HASH value. */
-  ske->start_payload_copy = silc_buffer_copy(payload_buf);
-  ske->start_payload = start_payload;
-
   /* Send the packet. */
   if (ske->callbacks->send_packet)
     (*ske->callbacks->send_packet)(ske, payload_buf, SILC_PACKET_KEY_EXCHANGE, 
                                   ske->callbacks->context);
 
-  silc_buffer_free(payload_buf);
+  /* Save the the payload buffer for future use. It is later used to 
+     compute the HASH value. */
+  ske->start_payload_copy = payload_buf;
+  ske->start_payload = start_payload;
 
   return status;
 }
@@ -427,10 +425,9 @@ SilcSKEStatus silc_ske_initiator_phase_2(SilcSKE ske,
       ske->status = SILC_SKE_STATUS_SIGNATURE_ERROR;
       return ske->status;
     }
-    payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
-    memcpy(payload->sign_data, sign, sign_len);
-    memset(sign, 0, sizeof(sign));
+    payload->sign_data = silc_memdup(sign, sign_len);
     payload->sign_len = sign_len;
+    memset(sign, 0, sizeof(sign));
   }
 
   status = silc_ske_payload_ke_encode(ske, payload, &payload_buf);
@@ -514,8 +511,7 @@ static void silc_ske_initiator_finish_final(SilcSKE ske,
     if (status != SILC_SKE_STATUS_OK)
       goto err;
 
-    ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
-    memcpy(ske->hash, hash, hash_len);
+    ske->hash = silc_memdup(hash, hash_len);
     ske->hash_len = hash_len;
 
     SILC_LOG_DEBUG(("Verifying signature (HASH)"));
@@ -627,8 +623,8 @@ SilcSKEStatus silc_ske_initiator_finish(SilcSKE ske,
     
     ske->users++;
     (*ske->callbacks->verify_key)(ske, payload->pk_data, payload->pk_len,
-                                payload->pk_type, ske->callbacks->context,
-                                silc_ske_initiator_finish_final, NULL);
+                                 payload->pk_type, ske->callbacks->context,
+                                 silc_ske_initiator_finish_final, NULL);
     
     /* We will continue to the final state after the public key has
        been verified by the caller. */
@@ -726,8 +722,7 @@ SilcSKEStatus silc_ske_responder_start(SilcSKE ske, SilcRng rng,
  err:
   if (remote_payload)
     silc_ske_payload_start_free(remote_payload);
-  if (payload)
-    silc_free(payload);
+  silc_free(payload);
 
   if (status == SILC_SKE_STATUS_OK)
     return SILC_SKE_STATUS_ERROR;
@@ -1056,8 +1051,7 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
     if (status != SILC_SKE_STATUS_OK)
       goto err;
 
-    ske->hash = silc_calloc(hash_len, sizeof(unsigned char));
-    memcpy(ske->hash, hash, hash_len);
+    ske->hash = silc_memdup(hash, hash_len);
     ske->hash_len = hash_len;
     
     SILC_LOG_DEBUG(("Signing HASH value"));
@@ -1070,10 +1064,9 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
       status = SILC_SKE_STATUS_SIGNATURE_ERROR;
       goto err;
     }
-    ske->ke2_payload->sign_data = silc_calloc(sign_len, sizeof(unsigned char));
-    memcpy(ske->ke2_payload->sign_data, sign, sign_len);
-    memset(sign, 0, sizeof(sign));
+    ske->ke2_payload->sign_data = silc_memdup(sign, sign_len);
     ske->ke2_payload->sign_len = sign_len;
+    memset(sign, 0, sizeof(sign));
   }
   ske->ke2_payload->pk_type = pk_type;
 
@@ -1112,23 +1105,18 @@ SilcSKEStatus silc_ske_responder_finish(SilcSKE ske,
 
 SilcSKEStatus silc_ske_end(SilcSKE ske)
 {
-  SilcBuffer packet;
+  SilcBufferStruct packet;
+  unsigned char data[4];
 
   SILC_LOG_DEBUG(("Start"));
 
-  packet = silc_buffer_alloc_size(4);
-  if (!packet)
-    return SILC_SKE_STATUS_OUT_OF_MEMORY;
-  silc_buffer_format(packet,
-                    SILC_STR_UI_INT((SilcUInt32)SILC_SKE_STATUS_OK),
-                    SILC_STR_END);
+  SILC_PUT32_MSB((SilcUInt32)SILC_SKE_STATUS_OK, data);
+  silc_buffer_set(&packet, data, 4);
 
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_SUCCESS, 
+    (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_SUCCESS, 
                                   ske->callbacks->context);
 
-  silc_buffer_free(packet);
-
   return SILC_SKE_STATUS_OK;
 }
 
@@ -1138,26 +1126,21 @@ SilcSKEStatus silc_ske_end(SilcSKE ske)
 
 SilcSKEStatus silc_ske_abort(SilcSKE ske, SilcSKEStatus status)
 {
-  SilcBuffer packet;
+  SilcBufferStruct packet;
+  unsigned char data[4];
 
   SILC_LOG_DEBUG(("Start"));
 
   if (status > SILC_SKE_STATUS_INVALID_COOKIE)
     status = SILC_SKE_STATUS_BAD_PAYLOAD;
 
-  packet = silc_buffer_alloc_size(4);
-  if (!packet)
-    return SILC_SKE_STATUS_OUT_OF_MEMORY;
-  silc_buffer_format(packet,
-                    SILC_STR_UI_INT((SilcUInt32)status),
-                    SILC_STR_END);
+  SILC_PUT32_MSB((SilcUInt32)status, data);
+  silc_buffer_set(&packet, data, 4);
 
   if (ske->callbacks->send_packet)
-    (*ske->callbacks->send_packet)(ske, packet, SILC_PACKET_FAILURE, 
+    (*ske->callbacks->send_packet)(ske, &packet, SILC_PACKET_FAILURE, 
                                   ske->callbacks->context);
 
-  silc_buffer_free(packet);
-
   return SILC_SKE_STATUS_OK;
 }
 
index b84630446ee9b9924d007b12c04bb2159c068dfc..149adc1dffd6a2c587278c10a34654827dd62bd7 100644 (file)
@@ -210,13 +210,43 @@ void silc_buffer_free(SilcBuffer sb)
 {
   if (sb) {
 #if defined(SILC_DEBUG)
-    memset(sb->head, 'F', sb->truelen);
+    if (sb->head)
+      memset(sb->head, 'F', sb->truelen);
 #endif
     silc_free(sb->head);
     silc_free(sb);
   }
 }
 
+/****f* silcutil/SilcBufferAPI/silc_buffer_steal
+ *
+ * SYNOPSIS
+ *
+ *    static inline
+ *    unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len);
+ *
+ * DESCRIPTION
+ *
+ *    Steals the data from the buffer `sb'.  This returns pointer to the
+ *    start of the buffer and the true length of that buffer.  The `sb'
+ *    cannot be used anymore after calling this function because the
+ *    data buffer was stolen.  The `sb' must be freed with silc_buffer_free.
+ *    The caller is responsible of freeing the stolen data buffer with
+ *    silc_free.
+ *
+ ***/
+
+static inline
+unsigned char *silc_buffer_steal(SilcBuffer sb, SilcUInt32 *data_len)
+{
+  unsigned char *buf = sb->head;
+  if (data_len)
+    *data_len = sb->truelen;
+  sb->head = sb->data = sb->tail = sb->end = NULL;
+  sb->len = sb->truelen = 0;
+  return buf;
+}
+
 /****f* silcutil/SilcBufferAPI/silc_buffer_set
  *
  * SYNOPSIS
index 4fffb7c34d87b7144f9007c921453c97b9e2dfe0..a189c2903a7e145fb6ccc88ee9fbd31e4b4d298a 100644 (file)
@@ -532,9 +532,12 @@ int silc_buffer_strformat(SilcBuffer dst, ...)
       goto ok;
 
     dst->head = silc_realloc(dst->head, sizeof(*dst->head) *
-                            (strlen(string) + len));
+                            (strlen(string) + len + 1));
+    if (!dst->head)
+      return -1;
     memcpy(dst->head + len, string, strlen(string));
     len += strlen(string);
+    dst->head[len] = '\0';
   }
 
   SILC_LOG_DEBUG(("Error occured while formatting buffer"));
@@ -543,9 +546,9 @@ int silc_buffer_strformat(SilcBuffer dst, ...)
 
  ok:
   dst->end = dst->head + len;
-  dst->tail = dst->data = dst->end;
-  dst->len = 0;
-  dst->truelen = len;
+  dst->data = dst->head;
+  dst->tail = dst->end;
+  dst->len = dst->truelen = len;
 
   va_end(va);
   return len;
index 1f3e4699fdf79d20891961d4463f4b507dd69a73..2066f95719ed0531315ffaebdc7bb2e9d8c36346 100644 (file)
@@ -2,9 +2,9 @@
 
   silcconfig.c
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2003 Giovanni Giacobbi
 
   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
@@ -172,7 +172,8 @@ static SilcConfigOption *silc_config_find_option(SilcConfigEntity ent,
   }
   return NULL;
 }
-/* ... */
+/* Converts a string in the type specified. returns a dynamically
+ * allocated pointer. */
 static void *silc_config_marshall(SilcConfigType type, const char *val)
 {
   void *pt;
@@ -578,7 +579,7 @@ static int silc_config_main_internal(SilcConfigEntity ent)
     }
     else {
       void *pt;
-      int ret;
+      int ret = 0;     /* very important in case of no cb */
 
       if (*(*p)++ != '=')
        return SILC_CONFIG_EEXPECTEDEQUAL;
@@ -594,15 +595,17 @@ static int silc_config_main_internal(SilcConfigEntity ent)
       pt = silc_config_marshall(thisopt->type, buf);
       if (!pt)
        return SILC_CONFIG_EINVALIDTEXT;
-      if (thisopt->cb) {
+      if (thisopt->cb)
        ret = thisopt->cb(thisopt->type, thisopt->name, file->line,
                          pt, thisopt->context);
-       if (ret) {
-         SILC_CONFIG_DEBUG(("Callback refused the value [ret=%d]", ret));
-         return ret;
-       }
-      }
+
+      /* since we have to free "pt" both on failure and on success, we
+         assume that ret == 0 if we didn't actually call any cb. */
       silc_free(pt);
+      if (ret) {
+       SILC_CONFIG_DEBUG(("Callback refused the value [ret=%d]", ret));
+       return ret;
+      }
     }
     continue;
 
index 91225867c716fd5c34a01ba053b39d61a6e6e6de..4d45aa86f1e2f2f37bde8231dd3bbd24dd724715 100644 (file)
@@ -2,9 +2,9 @@
 
   silcconfig.h
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
-  Copyright (C) 1997 - 2002 Pekka Riikonen
+  Copyright (C) 2002 - 2003 Giovanni Giacobbi
 
   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
index 14d31d545f519ca0caa9e7423b9094fdc7f16393..736edb03f4daa8b671ef8a6183797dfec908b93d 100644 (file)
@@ -2,7 +2,7 @@
 
   silclog.c
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
   Copyright (C) 1997 - 2002 Pekka Riikonen
 
index 60b2f637432af626e5022b72278b9a2be57eac3f..337c882e252fe3067b2ed61a00edb17f198455b4 100644 (file)
@@ -2,7 +2,7 @@
 
   silclog.h
 
-  Author: Johnny Mnemonic <johnny@themnemonic.org>
+  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 
   Copyright (C) 1997 - 2002 Pekka Riikonen
 
index e0f658b08f52807e42fa93107a14f107155bbf59..a474d1651ce4c4b2cad15636a62b8b46d4462456 100644 (file)
@@ -399,12 +399,13 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
 
       task = schedule->generic_queue->task;
       while(1) {
-       /* Validity of the task is checked always before and after
+       /* Validity of the task and fd is checked always before and after
           execution beacuse the task might have been unregistered
           in the callback function, ie. it is not valid anymore. */
 
        /* Is the task ready for reading */                             
-       if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ) {
+       if (task->valid && schedule->fd_list[i].revents & SILC_TASK_READ &&
+           fd == schedule->fd_list[i].fd) {
          silc_mutex_unlock(schedule->generic_queue->lock);
          SILC_SCHEDULE_UNLOCK(schedule);
          task->callback(schedule, schedule->app_context,
@@ -414,7 +415,8 @@ static void silc_schedule_dispatch_nontimeout(SilcSchedule schedule)
        }
 
        /* Is the task ready for writing */                             
-       if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE) {
+       if (task->valid && schedule->fd_list[i].revents & SILC_TASK_WRITE &&
+           fd == schedule->fd_list[i].fd) {
          silc_mutex_unlock(schedule->generic_queue->lock);
          SILC_SCHEDULE_UNLOCK(schedule);
          task->callback(schedule, schedule->app_context,
@@ -718,9 +720,6 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
   if (!schedule->valid)
     return NULL;
 
-  SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd, 
-                 type, priority));
-
   queue = SILC_SCHEDULE_GET_QUEUE(type);
     
   /* If the task is generic task, we check whether this task has already
@@ -729,6 +728,9 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
   if (type == SILC_TASK_GENERIC) {
     silc_mutex_lock(queue->lock);
 
+    SILC_LOG_DEBUG(("Registering new task, fd=%d type=%d priority=%d", fd, 
+                   type, priority));
+
     if (queue->task) {
       SilcTask task = queue->task;
       while(1) {
@@ -754,6 +756,12 @@ SilcTask silc_schedule_task_add(SilcSchedule schedule, SilcUInt32 fd,
   }
 
   newtask = silc_calloc(1, sizeof(*newtask));
+  if (!newtask)
+    return NULL;
+
+  SILC_LOG_DEBUG(("Registering new task %p, fd=%d type=%d priority=%d",
+                 newtask, fd, type, priority));
+
   newtask->fd = fd;
   newtask->context = context;
   newtask->callback = callback;
@@ -1223,7 +1231,7 @@ static int silc_schedule_task_remove(SilcTaskQueue queue, SilcTask task)
     return TRUE;
   }
 
-  SILC_LOG_DEBUG(("Removing task"));
+  SILC_LOG_DEBUG(("Removing task %p", task));
 
   /* Unregister the task */
   old = first;
index b123cea8173e664a19eda7deaf4bb5708ff8b3bf..c763f8fa3b6be5fa1b6f613bbc0a926cdd6d2354 100644 (file)
@@ -216,8 +216,8 @@ typedef signed long SilcInt64;
 typedef unsigned long long SilcUInt64;
 typedef signed long long SilcInt64;
 #else
-typedef SilcUInt32 SilcUInt64; /* XXX Use Windows's own 64 bit types */
-typedef SilcInt32 SilcInt64;
+typedef unsigned __int64 SilcUInt64;
+typedef signed __int64 SilcInt64;
 #endif
 #else
 typedef SilcUInt32 SilcUInt64;
@@ -245,9 +245,9 @@ typedef SilcUInt32 * void *;
 
 /* Macros */
 
-#define GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24    \
-                   | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)    \
-                   | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)     \
+#define SILC_GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24       \
+                   | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
+                   | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
                    | ((SilcUInt32)(SilcUInt8)(cp)[3])
 
 /****d* silcutil/SILCTypes/SILC_GET16_MSB
@@ -302,10 +302,10 @@ do {                                                      \
  *
  * SOURCE
  */
-#define SILC_GET64_MSB(l, cp)                          \
-do {                                                   \
-       (l) = ((((SilcUInt64)GET_WORD((cp))) << 32) |   \
-             ((SilcUInt64)GET_WORD((cp) + 4)));        \
+#define SILC_GET64_MSB(l, cp)                                  \
+do {                                                           \
+       (l) = ((((SilcUInt64)SILC_GET_WORD((cp))) << 32) |      \
+             ((SilcUInt64)SILC_GET_WORD((cp) + 4)));           \
 } while(0)
 /***/
 
@@ -455,4 +455,40 @@ do {                                               \
 } while(0)
 /***/
 
+/****d* silcutil/SILCTypes/SILC_SWAB_16
+ *
+ * NAME
+ *
+ *    #define SILC_SWAB_16 ...
+ *
+ * DESCRIPTION
+ *
+ *    Swabs 16-bit unsigned integer byte order.
+ *
+ * SOURCE
+ */
+#define SILC_SWAB_16(l)                                                \
+  ((SilcUInt16)(((SilcUInt16)(l) & (SilcUInt16)0x00FFU) << 8) |        \
+               (((SilcUInt16)(l) & (SilcUInt16)0xFF00U) >> 8))
+/***/
+
+/****d* silcutil/SILCTypes/SILC_SWAB_32
+ *
+ * NAME
+ *
+ *    #define SILC_SWAB_32 ...
+ *
+ * DESCRIPTION
+ *
+ *    Swabs 32-bit unsigned integer byte order.
+ *
+ * SOURCE
+ */
+#define SILC_SWAB_32(l)                                                        \
+  ((SilcUInt32)(((SilcUInt32)(l) & (SilcUInt32)0x000000FFUL) << 24) |  \
+               (((SilcUInt32)(l) & (SilcUInt32)0x0000FF00UL) << 8)  |  \
+               (((SilcUInt32)(l) & (SilcUInt32)0x00FF0000UL) >> 8)  |  \
+               (((SilcUInt32)(l) & (SilcUInt32)0xFF000000UL) >> 24))
+/***/
+
 #endif /* SILCTYPES_H */
index 4d14ac5fc323626aa037aeff5eabedeca60441da..26d9dd73a15e362f138f25281288c11f059ae815 100644 (file)
@@ -74,8 +74,9 @@ SILC_TASK_CALLBACK(silc_socket_read_qos)
 {
   SilcSocketConnection sock = context;
   sock->qos->applied = TRUE;
-  silc_schedule_set_listen_fd(sock->qos->schedule, sock->sock,
-                             (SILC_TASK_READ | SILC_TASK_WRITE), TRUE);
+  if (sock->users > 1)
+    silc_schedule_set_listen_fd(sock->qos->schedule, sock->sock,
+                               (SILC_TASK_READ | SILC_TASK_WRITE), TRUE);
   sock->qos->applied = FALSE;
   silc_socket_free(sock);
 }
diff --git a/prepare b/prepare
index e0ba0efe7f5abf09487201abd5b2dd366aacb94e..e126805b4cda661156787e9adcc3929b75d8bbdc 100755 (executable)
--- a/prepare
+++ b/prepare
@@ -37,7 +37,7 @@
 # SILC Distribution versions. Set here or give the version on the command
 # line as argument.
 #
-SILC_VERSION=0.9.7                     # Base version
+SILC_VERSION=0.9.8                     # Base version
 
 #############################################################################
 
index 0e629665aed837c2c417d499ce19deb4ec89bec5..01bac3200ce2a6f43996b0c28b7a4f7edf2090cf 100755 (executable)
@@ -2,9 +2,9 @@
 #
 #  stripspaces.tcl - strip trailing spaces from source files
 #
-#  Author: Johnny Mnemonic <johnny@themnemonic.org>
+#  Author: Giovanni Giacobbi <giovanni@giacobbi.net>
 #
-#  Copyright (C) 2002 Johnny Mnemonic
+#  Copyright (C) 2002 - 2003 Giovanni Giacobbi
 #
 #  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
index 03ee3ff370e1351621025c5a1986c1275907c974..252e825a09ced90ca4a0f55983066ed185f7b62f 100644 (file)
@@ -17,7 +17,7 @@
 
 silc_install_prefix=@prefix@
 SILC_COMMON_LIBS= @LIBS@ -L$(silc_install_prefix)/lib \
-       -L/usr/local/silc/lib -lsilc -lsilcclient
+       -L/usr/local/silc/lib -lsilc -lsilcclient -lsilc
 SILC_CFLAGS=@CFLAGS@
 CC=@CC@
 LIBTOOL = @LIBTOOL@