updates.
authorPekka Riikonen <priikone@silcnet.org>
Fri, 5 Apr 2002 17:36:12 +0000 (17:36 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Fri, 5 Apr 2002 17:36:12 +0000 (17:36 +0000)
29 files changed:
CHANGES
TODO
apps/irssi/src/silc/core/client_ops.c
apps/irssi/src/silc/core/silc-servers.c
apps/silcd/command.c
apps/silcd/packet_receive.c
apps/silcd/protocol.c
apps/silcd/serverconfig.c
doc/draft-riikonen-silc-commands-03.nroff
doc/draft-riikonen-silc-ke-auth-05.nroff
doc/draft-riikonen-silc-pp-05.nroff
doc/draft-riikonen-silc-spec-05.nroff
includes/silcincludes.h
lib/silcclient/client.c
lib/silcclient/client_ftp.c
lib/silcclient/client_internal.h
lib/silcclient/client_ops_example.c
lib/silcclient/command.c
lib/silcclient/protocol.c
lib/silcclient/silcclient.h
lib/silccore/silcauth.c
lib/silccore/silcauth.h
lib/silccrypt/silcpkcs.c
lib/silcutil/DIRECTORY
lib/silcutil/Makefile.am
lib/silcutil/silcstrutil.c
lib/silcutil/silcstrutil.h [new file with mode: 0644]
lib/silcutil/silcutil.c
lib/silcutil/silcutil.h

diff --git a/CHANGES b/CHANGES
index da17f33e55c353fbffe4771eaea58dfe2c8677c2..fc475d7047f607fda2d2c1ebae4ac0ae1af1cff6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -18,6 +18,14 @@ Fri Apr  5 16:03:03 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
          lib/silcclient/protocol.c, silcd/protocol.c, 
          silcd/serverconfig.c, and lib/silccore/silcauth.c.
 
+       * Changed the silc_client_close_connection interface to not
+         need the SilcSocketConnection which should not be visible
+         to application.  Affected files are lib/silcclient/client.c
+         and lib/silcclient/silcclient.h.
+
+       * Rewrote the text for Private Message Key Payload in the
+         protocol specification.  Protocol TODO #11.
+
 Wed Apr  3 16:24:51 EEST 2002  Pekka Riikonen <priikone@silcnet.org>
 
        * Upgraded the protocol version to 1.1, updated protocol specs
diff --git a/TODO b/TODO
index 2f49dc644c2b308f7a8bbba1c9a30fe944d5083e..17012127fad146ee612928824033a495914264fb 100644 (file)
--- a/TODO
+++ b/TODO
@@ -145,11 +145,6 @@ describe new stuff to be added to protocol versions 1.x.
     payload MAC and not alone by packet MAC.  To be included in protocol 
     version 1.1.
 
- 11. Change the wording in Private Message Key Payload definition to
-     describe the problems of trusting the payload, and to indicate that
-     the receiver may not accept the key in the payload, and to describe
-     other means of distributing a key.
-
  16. Add STATS command after all to the protocol for providing practically
      same information client gets when connects to a server.  Normal
      server would send this to router always when received from client.
index a4008b78c8882fa13f610e7f8adee69dfe35e743..b76c467d59f7b936f904d2ed59c8f9ea20568586 100644 (file)
@@ -601,7 +601,7 @@ void silc_connect(SilcClient client, SilcClientConnection conn, int success)
   SILC_SERVER_REC *server = conn->context;
 
   if (!server && !success) {
-    silc_client_close_connection(client, NULL, conn);
+    silc_client_close_connection(client, conn);
     return;
   }
 
index 7c3a69184d55f2e87f06a363bb0b7a7277491eca..f24ba50828474763a75479740c7b2ab8de05fe34 100644 (file)
@@ -221,7 +221,7 @@ static void sig_disconnected(SILC_SERVER_REC *server)
   silc_dlist_uninit(server->ftp_sessions);
 
   if (server->conn && server->conn->sock != NULL) {
-    silc_client_close_connection(silc_client, NULL, server->conn);
+    silc_client_close_connection(silc_client, server->conn);
     
     /* SILC closes the handle */
     g_io_channel_unref(net_sendbuffer_handle(server->handle));
index ba345af6c5490c57d617570b90149cd90c2a78b2..98f1a29cbf73b1f609a36ff9455296a28e0b7756 100644 (file)
@@ -3825,15 +3825,13 @@ SILC_SERVER_CMD_FUNC(cmode)
       }
 
       /* Save the passphrase */
-      passphrase = channel->passphrase = strdup(tmp);
+      passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
     }
   } else {
     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
       /* Passphrase mode is unset. remove the passphrase */
-      if (channel->passphrase) {
-       silc_free(channel->passphrase);
-       channel->passphrase = NULL;
-      }
+      silc_free(channel->passphrase);
+      channel->passphrase = NULL;
     }
   }
 
index f0c3616da003fd8061cd92cc3000ec7032e41c8a..56f015696817a1290285cb917453799a6934157f 100644 (file)
@@ -595,7 +595,7 @@ void silc_server_notify(SilcServer server,
     tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
     if (tmp) {
       silc_free(channel->passphrase);
-      channel->passphrase = strdup(tmp);
+      channel->passphrase = silc_memdup(tmp, tmp_len);
     }
 
     break;
index eb7b3013a01e2f5cdf6c0777ca54fdb4793209e0..6aa3ac93b54cb432493347297b4c5d26aab35340 100644 (file)
@@ -690,10 +690,10 @@ SILC_TASK_CALLBACK(silc_server_protocol_key_exchange)
  */
 
 static int 
-silc_server_password_authentication(SilcServer server, char *remote_auth, 
-                                   char *local_auth)
+silc_server_password_authentication(SilcServer server, char *local_auth, 
+                                   char *remote_auth)
 {
-  if (!remote_auth || !local_auth)
+  if (!remote_auth || !local_auth || strlen(local_auth) != strlen(remote_auth))
     return FALSE;
 
   if (!memcmp(remote_auth, local_auth, strlen(local_auth)))
index b5dbc04ce5a90ba6c885c9202719d725d270f96f..cd5a0d3749365fd362d8fefb6d00810fe2395ca9 100644 (file)
@@ -113,18 +113,26 @@ static bool my_parse_authdata(SilcAuthMethod auth_meth, char *p,
 {
   if (auth_meth == SILC_AUTH_PASSWORD) {
     /* p is a plain text password */
-    if (auth_data)
-      *auth_data = (void *) strdup(p);
-    if (auth_data_len)
-      *auth_data_len = (SilcUInt32) strlen(p);
+    if (auth_data && auth_data_len) {
+      if (!silc_utf8_valid(p, strlen(p))) {
+       *auth_data_len = silc_utf8_encoded_len(p, strlen(p), 0);
+       *auth_data = silc_calloc(*auth_data_len, sizeof(unsigned char));
+       silc_utf8_encode(p, strlen(p), SILC_STRING_ASCII, *auth_data,
+                        *auth_data_len);
+      } else {
+       *auth_data = (void *) strdup(p);
+       *auth_data_len = (SilcUInt32) strlen(p);
+      }
+    }
   } else if (auth_meth == SILC_AUTH_PUBLIC_KEY) {
     /* p is a public key file name */
     SilcPublicKey public_key;
 
     if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_PEM))
       if (!silc_pkcs_load_public_key(p, &public_key, SILC_PKCS_FILE_BIN)) {
-       SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line %lu: "
-                              "Could not load public key file!\n", line));
+       SILC_SERVER_LOG_ERROR(("\nError while parsing config file at line "
+                              "%lu: Could not load public key file!\n", 
+                              line));
        return FALSE;
       }
 
index d0dcd698c4f9e8f1a50f9ea3ded730ba289bf12c..b5d038771e695ddac2e6304fb7200fae90d7e919 100644 (file)
@@ -202,7 +202,9 @@ are defined in the section 2.3 SILC Command Status Types.
 Every command that has some kind of ID as argument (for example
 <Client ID>) are actually ID Payloads, defined in [SILC2] that includes
 the type of the ID, length of the ID and the actual ID data.  This
-way variable length ID's can be sent as arguments.
+way variable length ID's can be sent as arguments.  Also note that
+all passphrases that may be sent in commands MUST be UTF-8 [RFC2279]
+encoded.
 
 
 .ti 0
@@ -603,8 +605,7 @@ List of all defined commands in SILC follows.
                         (3) [<invite list>]
 
        This command replies with the invite list of the channel if it
-       exists.  The <invite list> may be omitted if the list was not
-        altered.
+       exists.
 
         Status messages:
 
@@ -1896,8 +1897,8 @@ security of this protocol.
 [RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.
 
-
-
+[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 2279, January 1998.
 
 
 
index 4e207e4fa08d4390b3cc5dc3e51c32ed5d7c7782..495647ba38b7f90872aa7cfd65226bdda718047b 100644 (file)
@@ -200,7 +200,9 @@ whether it supports the security properties.
 
 It then sends a Key Exchange Start Payload to the initiator filled with
 security properties it selected from the original payload.  The payload
-sent by responder MUST include only one chosen property per list.
+sent by responder MUST include only one chosen property per list.  The
+character encoding for the security property values as defined in [SILC1] 
+SHOULD be UTF-8 [RFC2279].
 
 The Key Exchange Start Payload is used to tell connecting entities what
 security properties and algorithms should be used in the communication.
@@ -958,7 +960,13 @@ for defined numerical authentication method types.
 Passphrase authentication or pre-shared-key based authentication is 
 simply an authentication where the party that wants to authenticate 
 itself to the other end sends the passphrase that is required by
-the other end, for example server.
+the other end, for example server.  The plaintext passphrase is put
+to the payload, that is then encrypted.  The plaintext passphrase
+MUST be in UTF-8 [RFC2279] encoding.  If the passphrase is in the
+sender's system in some other encoding it MUST be UTF-8 encoded 
+before transmitted.  The receiver MAY change the encoding of the
+passphrase to its system's default character encoding before verifying
+the passphrase.
 
 If the passphrase matches with the one in the server's end the
 authentication is successful.  Otherwise SILC_PACKET_FAILURE MUST be
@@ -1101,6 +1109,9 @@ security of this protocol.
 [RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.
 
+[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 2279, January 1998.
+
 
 .ti 0
 6 Author's Address
index 36dee34b6c08bc6de5424358f65d7b9ce270297f..9c8a5cc6ac89d1c367592899c7e2ce7020640d5c 100644 (file)
@@ -1839,11 +1839,18 @@ o Padding (variable length) - This field is present only
 .ti 0
 2.3.12 Private Message Key Payload
 
-This payload is used to send key from client to another client that
-is going to be used to protect the private messages between these
-two clients.  If this payload is not sent normal session key 
-established by the SILC Key Exchange Protocol is used to protect
-the private messages.
+This payload is optional and can be used to send private message
+key between two clients in the network.  The packet is secured with
+normal session keys.  By default private messages are encrypted
+with session keys, and with this payload it is possible to set
+private key for private message encryption between two clients.
+
+The receiver of this payload SHOULD verify for example from user
+whether user wants to receive private message key.  Note that there
+are other, more secure ways of exchanging private message keys in
+the SILC network.  Instead of sending this payload it is possible to
+negotiate the private message key with SKE protocol using the Key
+Agreement payload directly peer to peer.
 
 This payload may only be sent by client to another client.  Server
 MUST NOT send this payload at any time.  After sending this payload
index 1841178da9e62a9ee8c068df3aac04b728218a47..72369b8def050fc6e12d0344f96442d492d2fa16 100644 (file)
@@ -1047,8 +1047,9 @@ completed.  The purpose of authentication is to authenticate for example
 client connecting to the server.  However, usually clients are accepted
 to connect to server without explicit authentication.  Servers are
 required use authentication protocol when connecting.  The authentication
-may be based on passphrase (pre-shared-secret) or public key.  The
-connection authentication protocol is described in detail in [SILC3].
+may be based on passphrase (pre-shared-secret) or public key.  All
+passphrases sent in SILC protocol MUST be UTF-8 [RFC2279] encoded.
+The connection authentication protocol is described in detail in [SILC3].
 
 
 .ti 0
@@ -1118,9 +1119,9 @@ o Authentication Data (variable length) - Authentication
 
 
 If the authentication method is password based, the Authentication
-Data field includes the plaintext password.  It is safe to send
-plaintext password since the entire payload is encrypted.  In this
-case the Public Data Length is set to zero (0), but MAY also include
+Data field includes the plaintext UTF-8 encoded password.  It is safe
+to send plaintext password since the entire payload is encrypted.  In
+this case the Public Data Length is set to zero (0), but MAY also include
 random data for padding purposes.  It is also RECOMMENDED that maximum
 amount of padding is applied to SILC packet when using password based
 authentication.  This way it is not possible to approximate the length
@@ -1421,14 +1422,15 @@ software version = <major>[.<minor>[.<build or vendor string>]]
 .in 3
 
 Protocol version MAY provide both major and minor version.  Currently
-implementations MUST set the protocol version and accept the protocol
-version as SILC-1.1-<software version>.  If new protocol version causes
-in compatibilities with older version the the <minor> versio number MUST
-be incremented.  The <major> is incremented if new protocol version is
-fully incompatible.
+implementations MUST set the protocol version and accept at least the 
+protocol version as SILC-1.1-<software version>.  If new protocol version 
+causes in compatibilities with older version the the <minor> versio number 
+MUST be incremented.  The <major> is incremented if new protocol version 
+is fully incompatible.
 
-Software version MAY provide major, minor and build version.  The
-software version MAY be freely set and accepted.
+Software version MAY provide major, minor and build (vendor) version.
+The software version MAY be freely set and accepted.  The version string 
+MUST consist of printable US-ASCII characters.
 
 
 Thus, the version strings could be, for example:
@@ -1437,6 +1439,7 @@ Thus, the version strings could be, for example:
 SILC-1.1-2.0.2
 SILC-1.0-1.2
 SILC-1.1-1.0.VendorXYZ
+SILC-1.1-2.4.5 Vendor Limited
 .in 3
 
 
@@ -2220,8 +2223,8 @@ should have a forum to discuss the cell management issues.
 [RFC2119]    Bradner, S., "Key Words for use in RFCs to Indicate
              Requirement Levels", BCP 14, RFC 2119, March 1997.
 
-
-
+[RFC2279]    Yergeau, F., "UTF-8, a transformation format of ISO
+             10646", RFC 2279, January 1998.
 
 
 
index 0c72f406c9d326154a8623470fc1c02750a07517..a74228dc6b0fabccf2c77d63781229fad19c8020 100644 (file)
@@ -230,6 +230,7 @@ extern "C" {
 #include "silcbuffmt.h"
 #include "silcnet.h"
 #include "silcfileutil.h"
+#include "silcstrutil.h"
 #include "silcutil.h"
 #include "silcconfig.h"
 #include "silcprotocol.h"
index 64ecee8873b7e3d860c84280c2863bfdb9f63fe1..4875e8e24d09901ece369ff18c6c3231b2e0c047 100644 (file)
@@ -806,14 +806,14 @@ SILC_TASK_CALLBACK_GLOBAL(silc_client_packet_process)
       if (SILC_IS_DISCONNECTING(sock)) {
        if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
          client->internal->ops->disconnect(client, conn);
-       silc_client_close_connection(client, sock, conn);
+       silc_client_close_connection_real(client, sock, conn);
        return;
       }
       
       SILC_LOG_DEBUG(("EOF from connection %d", sock->sock));
       if (sock == conn->sock && sock->type != SILC_SOCKET_TYPE_CLIENT)
        client->internal->ops->disconnect(client, conn);
-      silc_client_close_connection(client, sock, conn);
+      silc_client_close_connection_real(client, sock, conn);
       return;
     }
 
@@ -1278,9 +1278,9 @@ void silc_client_packet_queue_purge(SilcClient client,
    connection but `conn->sock' might be actually a different connection
    than the `sock'). */
 
-void silc_client_close_connection(SilcClient client,
-                                 SilcSocketConnection sock,
-                                 SilcClientConnection conn)
+void silc_client_close_connection_real(SilcClient client,
+                                      SilcSocketConnection sock,
+                                      SilcClientConnection conn)
 {
   int del = FALSE;
 
@@ -1395,6 +1395,14 @@ void silc_client_close_connection(SilcClient client,
   silc_socket_free(sock);
 }
 
+/* Closes the connection to the remote end */
+
+void silc_client_close_connection(SilcClient client,
+                                 SilcClientConnection conn)
+{
+  silc_client_close_connection_real(client, NULL, conn);
+}
+
 /* Called when we receive disconnection packet from server. This 
    closes our end properly and displays the reason of the disconnection
    on the screen. */
@@ -1408,7 +1416,7 @@ SILC_TASK_CALLBACK(silc_client_disconnected_by_server_later)
   if (sock == NULL)
     return;
 
-  silc_client_close_connection(client, sock, sock->user_data);
+  silc_client_close_connection_real(client, sock, sock->user_data);
 }
 
 /* Called when we receive disconnection packet from server. This 
index a67267098ea5121ff2db44b57092b66a88cc1182..6d63544d07835427e4e471142cfd540d5456a218 100644 (file)
@@ -754,7 +754,7 @@ void silc_client_ftp_session_free(SilcClientFtpSession session)
       if (conn->active_session == session)
        conn->active_session = NULL;
 
-      silc_client_close_connection(session->client, session->sock, conn);
+      silc_client_close_connection_real(session->client, session->sock, conn);
     } else {
       silc_socket_free(session->sock);
     }
index 294e003a165ce76048daabc25a3fd4920fc76ec5..7de59e7f76df2679ee0f8cd8acb593a2beb735e9 100644 (file)
@@ -155,6 +155,9 @@ void silc_client_packet_send(SilcClient client,
                             unsigned char *data, 
                             SilcUInt32 data_len, 
                             int force_send);
+void silc_client_close_connection_real(SilcClient client,
+                                      SilcSocketConnection sock,
+                                      SilcClientConnection conn);
 void silc_client_disconnected_by_server(SilcClient client,
                                        SilcSocketConnection sock,
                                        SilcBuffer message);
index 7ecb981b7d899b19d1cde5fe7d751384e3aee872..e35a56e6bd80fbdb265a57107ce0169700a23871 100644 (file)
@@ -164,7 +164,8 @@ silc_verify_public_key(SilcClient client, SilcClientConnection conn,
 
 /* Ask (interact, that is) a passphrase from user. The passphrase is
    returned to the library by calling the `completion' callback with
-   the `context'. */
+   the `context'. The returned passphrase SHOULD be in UTF-8 encoded,
+   if not then the library will attempt to encode. */
 
 static void 
 silc_ask_passphrase(SilcClient client, SilcClientConnection conn, 
index f6813f34b236c935a2fee66cb3acfeafa7dbd0a8..48b7cd276bc3138c3be0bf210297764e5b906335 100644 (file)
@@ -663,7 +663,7 @@ SILC_TASK_CALLBACK(silc_client_command_quit_cb)
 
   /* Close connection */
   q->client->internal->ops->disconnect(q->client, q->conn);
-  silc_client_close_connection(q->client, NULL, q->conn->sock->user_data);
+  silc_client_close_connection(q->client, q->conn->sock->user_data);
 
   silc_free(q);
 }
index 3c66d905817a8ccc36a2ae6c74f65c7c4c43cb06..6ab25d6806b4d7a7fbb8050961be574bb91abc34 100644 (file)
@@ -572,9 +572,21 @@ silc_client_conn_auth_continue(unsigned char *auth_data,
   SilcClient client = (SilcClient)ctx->client;
   SilcBuffer packet;
   int payload_len = 0;
+  unsigned char *autf8 = NULL;
 
   SILC_LOG_DEBUG(("Start"));
 
+  /* Passphrase must be UTF-8 encoded, if it isn't encode it */
+  if (ctx->auth_meth == SILC_AUTH_PASSWORD && 
+      !silc_utf8_valid(auth_data, auth_data_len)) {
+    payload_len = silc_utf8_encoded_len(auth_data, auth_data_len, 
+                                       SILC_STRING_ASCII);
+    autf8 = silc_calloc(payload_len, sizeof(*autf8));
+    auth_data_len = silc_utf8_encode(auth_data, auth_data_len, 
+                                    SILC_STRING_ASCII, autf8, payload_len);
+    auth_data = autf8;
+  }
+
   payload_len = 4 + auth_data_len;
   packet = silc_buffer_alloc(payload_len);
   silc_buffer_pull_tail(packet, SILC_BUFFER_END(packet));
@@ -590,6 +602,7 @@ silc_client_conn_auth_continue(unsigned char *auth_data,
                          NULL, 0, NULL, NULL,
                          packet->data, packet->len, TRUE);
   silc_buffer_free(packet);
+  silc_free(autf8);
       
   /* Next state is end of protocol */
   protocol->state = SILC_PROTOCOL_STATE_END;
index b9647bdf08bb705e159f6c947a9fc6a3ffb51e27..a1f8e48b87005a187c04321e5c385df244b60697 100644 (file)
@@ -345,7 +345,7 @@ typedef struct {
 
   /* Called to indicate that connection was either successfully established
      or connecting failed.  This is also the first time application receives
-     the SilcClientConnection objecet which it should save somewhere.
+     the SilcClientConnection object which it should save somewhere.
      If the `success' is FALSE the application must always call the function
      silc_client_close_connection. */
   void (*connect)(SilcClient client, SilcClientConnection conn, int success);
@@ -745,22 +745,15 @@ void silc_client_start_key_exchange(SilcClient client,
  * SYNOPSIS
  *
  *    void silc_client_close_connection(SilcClient client,
- *                                      SilcSocketConnection sock,
  *                                      SilcClientConnection conn);
  *
  * DESCRIPTION
  *
  *    Closes connection to remote end. Free's all allocated data except
  *    for some information such as nickname etc. that are valid at all time. 
- *    If the `sock' is NULL then the conn->sock will be used.  If `sock' is
- *    provided it will be checked whether the sock and `conn->sock' are the
- *    same (they can be different, ie. a socket can use `conn' as its
- *    connection but `conn->sock' might be actually a different connection
- *    than the `sock'). 
  *
  ***/
 void silc_client_close_connection(SilcClient client,
-                                 SilcSocketConnection sock,
                                  SilcClientConnection conn);
 
 
index 6e73a9f468bff84c7d84f0ee993e1bc32c613d22..e38eff0b3b5171e918271e8fbb8c5963fc083d40 100644 (file)
@@ -92,13 +92,28 @@ SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
 {
   SilcBuffer buffer;
   SilcUInt32 len;
+  unsigned char *autf8 = NULL;
+  SilcUInt32 autf8_len;
 
   SILC_LOG_DEBUG(("Encoding Authentication Payload"));
 
+  /* Passphrase MUST be UTF-8 encoded, encode if it is not */
+  if (method == SILC_AUTH_PASSWORD && !silc_utf8_valid(auth_data, auth_len)) {
+    autf8_len = silc_utf8_encoded_len(auth_data, auth_len, 0);
+    if (!autf8_len)
+      return NULL;
+    autf8 = silc_calloc(autf8_len, sizeof(*autf8));
+    auth_len = silc_utf8_encode(auth_data, auth_len, 0, autf8, autf8_len);
+    auth_data = (const unsigned char *)autf8;
+  }
+
   len = 2 + 2 + 2 + random_len + 2 + auth_len;
   buffer = silc_buffer_alloc_size(len);
-  if (!buffer)
+  if (!buffer) {
+    silc_free(autf8);
     return NULL;
+  }
+
   silc_buffer_format(buffer,
                     SILC_STR_UI_SHORT(len),
                     SILC_STR_UI_SHORT(method),
@@ -108,6 +123,7 @@ SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
                     SILC_STR_UI_XNSTRING(auth_data, auth_len),
                     SILC_STR_END);
 
+  silc_free(autf8);
   return buffer;
 }
 
@@ -135,7 +151,7 @@ SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload)
   return payload->auth_method;
 }
 
-/* Get the authentication data */
+/* Get the authentication data. If this is passphrase it is UTF-8 encoded. */
 
 unsigned char *silc_auth_get_data(SilcAuthPayload payload,
                                  SilcUInt32 *auth_len)
@@ -392,7 +408,8 @@ bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method,
 
 /* Same as above but parses the authentication payload before verify. */
 
-bool silc_auth_verify_data(const unsigned char *payload, SilcUInt32 payload_len,
+bool silc_auth_verify_data(const unsigned char *payload, 
+                          SilcUInt32 payload_len,
                           SilcAuthMethod auth_method, const void *auth_data,
                           SilcUInt32 auth_data_len, SilcHash hash, 
                           const void *id, SilcIdType type)
index 38a0a418b3938aa1b00b8c244547c78dee667ad0..f66621324107bbc403b2c85a45f4b05b270b920c 100644 (file)
@@ -129,7 +129,10 @@ SilcAuthPayload silc_auth_payload_parse(const unsigned char *data,
  *
  *    Encodes authentication payload into buffer and returns it.
  *    The `random_data' is provided only if doing public key authentication.
- *    The `auth_data' is the actual authentication data.
+ *    The `auth_data' is the actual authentication data.  If the
+ *    `method' is SILC_AUTH_PASSWORD the passphase in `auth_data' sent as
+ *    argument SHOULD be UTF-8 encoded, if not library will attempt to
+ *    encode it.
  *
  ***/
 SilcBuffer silc_auth_payload_encode(SilcAuthMethod method,
@@ -173,7 +176,9 @@ SilcAuthMethod silc_auth_get_method(SilcAuthPayload payload);
  *
  * DESCRIPTION
  *
- *    Get the authentication data. The caller must not free the data.
+ *    Get the authentication data. The caller must not free the data.  If
+ *    the authentication method is passphrase, then the returned string
+ *    is UTF-8 encoded passphrase.
  *
  ***/
 unsigned char *silc_auth_get_data(SilcAuthPayload payload,
@@ -266,9 +271,9 @@ bool silc_auth_public_key_auth_verify_data(const unsigned char *payload,
  *    Verifies the authentication data directly from the Authentication 
  *    Payload. Supports all authentication methods. If the authentication
  *    method is passphrase based then the `auth_data' and `auth_data_len'
- *    are the passphrase and its length. If the method is public key
- *    authentication then the `auth_data' is the SilcPublicKey and the
- *    `auth_data_len' is ignored.
+ *    are the passphrase and its length.  The passphrase MUST be UTF-8
+ *    encoded.  If the method is public key authentication then the
+ *    `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored.
  *
  ***/
 bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method,
@@ -292,12 +297,13 @@ bool silc_auth_verify(SilcAuthPayload payload, SilcAuthMethod auth_method,
  *    Verifies the authentication data directly from the Authentication 
  *    Payload. Supports all authentication methods. If the authentication
  *    method is passphrase based then the `auth_data' and `auth_data_len'
- *    are the passphrase and its length. If the method is public key
- *    authentication then the `auth_data' is the SilcPublicKey and the
- *    `auth_data_len' is ignored.
+ *    are the passphrase and its length.  The passphrase MUST be UTF-8
+ *    encoded.  If the method is public key authentication then the
+ *    `auth_data' is the SilcPublicKey and the `auth_data_len' is ignored.
  *
  ***/
-bool silc_auth_verify_data(const unsigned char *payload, SilcUInt32 payload_len,
+bool silc_auth_verify_data(const unsigned char *payload, 
+                          SilcUInt32 payload_len,
                           SilcAuthMethod auth_method, const void *auth_data,
                           SilcUInt32 auth_data_len, SilcHash hash, 
                           const void *id, SilcIdType type);
index 4e7cdcfe6e76a55c5b997415dc8d4a2361e93c97..db3a8e2581ef882d32032b6c3140adc3f2a762e0 100644 (file)
@@ -945,7 +945,7 @@ static int silc_pkcs_save_public_key_internal(char *filename,
   case SILC_PKCS_FILE_BIN:
     break;
   case SILC_PKCS_FILE_PEM:
-    data = silc_encode_pem_file(data, data_len);
+    data = silc_pem_encode_file(data, data_len);
     data_len = strlen(data);
     break;
   }
@@ -1008,7 +1008,7 @@ static int silc_pkcs_save_private_key_internal(char *filename,
   case SILC_PKCS_FILE_BIN:
     break;
   case SILC_PKCS_FILE_PEM:
-    data = silc_encode_pem_file(data, data_len);
+    data = silc_pem_encode_file(data, data_len);
     data_len = strlen(data);
     break;
   }
@@ -1097,7 +1097,7 @@ int silc_pkcs_load_public_key(char *filename, SilcPublicKey *public_key,
     case SILC_PKCS_FILE_BIN:
       break;
     case SILC_PKCS_FILE_PEM:
-      data = silc_decode_pem(data, len, &len);
+      data = silc_pem_decode(data, len, &len);
       memset(old, 0, data_len);
       silc_free(old);
       old = data; 
@@ -1154,7 +1154,7 @@ int silc_pkcs_load_private_key(char *filename, SilcPrivateKey *private_key,
     case SILC_PKCS_FILE_BIN:
       break;
     case SILC_PKCS_FILE_PEM:
-      data = silc_decode_pem(data, len, &len);
+      data = silc_pem_decode(data, len, &len);
       break;
     }
 
index 66e1d3a6933cb5ecb30fc5463c98de01218439f4..37b0a95e1f205c2170efc2be506658b13f59d93b 100644 (file)
@@ -15,6 +15,7 @@
 @LINK=silcprotocol.html:SILC Protocol Interface
 @LINK=silcconfig.html:SILC Config Interface
 @LINK=silcfileutil.html:SILC File Util Interface
+@LINK=silcstrutil.html:SILC String Util Interface
 @LINK=silcutil.html:SILC Util Interface
 @LINK=silclist.html:SILC List Interface
 @LINK=silcdlist.html:SILC Dynamic List Interface
index 5b7f020e0d5aef7749c220f1dfdc74769d2222c2..2b65ce0f3360726fcbf8ac52e3050f4f7a0d57d2 100644 (file)
@@ -45,6 +45,7 @@ libsilcutil_a_SOURCES = \
        silcnet.c \
        silcschedule.c \
        silcfileutil.c \
+       silcstrutil.c \
        silcutil.c \
        silchashtable.c \
        silcsockconn.c  \
@@ -68,6 +69,7 @@ include_HEADERS =     \
        silcdlist.h     \
        silcfileutil.h  \
        silcutil.h      \
+       silcstrutil.h   \
        silctypes.h
 endif
 
index fa598945be4948372649434fb61e3c8d0ef711f1..d1f04883d69d99818031a839b35feda68cc30f8c 100644 (file)
@@ -16,6 +16,7 @@
   GNU General Public License for more details.
 
 */
+/* $Id$ */
 
 #include "silcincludes.h"
 #include "silcstrutil.h"
diff --git a/lib/silcutil/silcstrutil.h b/lib/silcutil/silcstrutil.h
new file mode 100644 (file)
index 0000000..746d0ad
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+
+  silcstrutil.h 
+
+  Author: Pekka Riikonen <priikone@silcnet.org>
+
+  Copyright (C) 2002 Pekka Riikonen
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; version 2 of the License.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+*/
+
+/****h* silcutil/SILC String Utilities
+ *
+ * DESCRIPTION
+ *
+ *    String manipulation utility routines.  These routines provides
+ *    various helper functions for encoding, decoding and otherwise
+ *    managing strings.
+ *
+ ***/
+
+#ifndef SILCSTRUTIL_H
+#define SILCSTRUTIL_H
+
+/****f* silcutil/SilcStrUtilAPI/silc_pem_encode
+ *
+ * SYNOPSIS
+ *
+ *    char *silc_pem_encode(unsigned char *data, SilcUInt32 len);
+ *
+ * DESCRIPTION
+ *
+ *    Encodes data into PEM encoding. Returns NULL terminated PEM encoded
+ *    data string. Note: This is originally public domain code and is
+ *    still PD.
+ *
+ ***/
+char *silc_pem_encode(unsigned char *data, SilcUInt32 len);
+
+/****f* silcutil/SilcStrUtilAPI/silc_pem_encode_file
+ *
+ * SYNOPSIS
+ *
+ *    char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len);
+ *
+ * DESCRIPTION
+ *
+ *    Same as silc_pem_encode() but puts newline ('\n') every 72 characters.
+ *
+ ***/
+char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len);
+
+/****f* silcutil/SilcStrUtilAPI/silc_pem_decode
+ *
+ * SYNOPSIS
+ *
+ *    unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len,
+ *                                   SilcUInt32 *ret_len);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes PEM into data. Returns the decoded data. Note: This is
+ *    originally public domain code and is still PD.
+ *
+ ***/
+unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len,
+                              SilcUInt32 *ret_len);
+
+/****d* silcutil/SilcStrUtilAPI/SilcStringEncoding
+ *
+ * NAME
+ * 
+ *    typedef enum { ... } SilcStringEncoding;
+ *
+ * DESCRIPTION
+ *
+ *    String encoding definitions used with the UTF-8 encoding and the
+ *    decoding functions.
+ *
+ * SOURCE
+ */
+typedef enum {
+  SILC_STRING_ASCII     = 0,   /* Any 8 bit ASCII encoding (default) */
+
+  /* Rest are not implemented yet */
+  SILC_STRING_ASCII_ESC = 1,   /* 7 bit ASCII (>0x7f escaped) */
+  SILC_STRING_BMP       = 2,   /* 16 bit, UCS-2, BMP, ISO/IEC 10646 */
+  SILC_STRING_UNIVERSAL = 3,   /* 32 bit, UCS-4, Universal, ISO/IEC 10646 */
+} SilcStringEncoding;
+/***/
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_encode
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
+ *                                SilcStringEncoding bin_encoding,
+ *                                unsigned char *utf8, SilcUInt32 utf8_size);
+ *
+ * DESCRIPTION
+ *
+ *    Encodes the string `bin' of which encoding is `bin_encoding' to the
+ *    UTF-8 encoding into the buffer `utf8' which is of size of `utf8_size'.
+ *    Returns the length of the UTF-8 encoded string, or zero (0) on error.
+ *    By default `bin_encoding' is ASCII, and the caller needs to know the
+ *    encoding of the input string if it is anything else.
+ *
+ ***/
+SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len,
+                           SilcStringEncoding bin_encoding,
+                           unsigned char *utf8, SilcUInt32 utf8_size);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_decode
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_utf8_decode(const unsigned char *utf8, 
+ *                                SilcUInt32 utf8_len,
+ *                                SilcStringEncoding bin_encoding,
+ *                                unsigned char *bin, SilcUInt32 bin_size);
+ *
+ * DESCRIPTION
+ *
+ *    Decodes UTF-8 encoded string `utf8' to string of which encoding is
+ *    to be `bin_encoding', into the `bin' buffer of size of `bin_size'.
+ *    Returns the length of the decoded buffer, or zero (0) on error.
+ *    By default `bin_encoding' is ASCII, and the caller needs to know to
+ *    which encoding the output string is to be encoded if ASCII is not
+ *    desired. 
+ *
+ ***/
+SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len,
+                           SilcStringEncoding bin_encoding,
+                           unsigned char *bin, SilcUInt32 bin_size);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_encoded_len
+ *
+ * SYNOPSIS
+ *
+ *    SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, 
+ *                                     SilcUInt32 bin_len,
+ *                                     SilcStringEncoding bin_encoding);
+ *
+ * DESCRIPTION
+ *
+ *    Returns the length of UTF-8 encoded string if the `bin' of
+ *    encoding of `bin_encoding' is encoded with silc_utf8_encode.
+ *
+ ***/
+SilcUInt32 silc_utf8_encoded_len(const unsigned char *bin, SilcUInt32 bin_len,
+                                SilcStringEncoding bin_encoding);
+
+/****f* silcutil/SilcStrUtilAPI/silc_utf8_valid
+ *
+ * SYNOPSIS
+ *
+ *    bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len);
+ *
+ * DESCRIPTION
+ *
+ *    Returns TRUE if the `utf8' string of length of `utf8_len' is valid
+ *    UTF-8 encoded string, FALSE if it is not UTF-8 encoded string.
+ *
+ ***/
+bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len);
+
+
+#endif /* SILCSTRUTIL_H */
index f0c0e7b6a1d429cd2e31f1b940504a64b018ef3c..e322c2af84fae0b936e459c7ce2b2402424ae9f2 100644 (file)
@@ -105,157 +105,6 @@ char *silc_to_upper(char *string)
   return ret;
 }
 
-static unsigned char pem_enc[64] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-/* Encodes data into PEM encoding. Returns NULL terminated PEM encoded
-   data string. Note: This is originally public domain code and is
-   still PD. */
-
-char *silc_encode_pem(unsigned char *data, SilcUInt32 len)
-{
-  int i, j;
-  SilcUInt32 bits, c, char_count;
-  char *pem;
-
-  char_count = 0;
-  bits = 0;
-  j = 0;
-
-  pem = silc_calloc(((len * 8 + 5) / 6) + 5, sizeof(*pem));
-
-  for (i = 0; i < len; i++) {
-    c = data[i];
-    bits += c;
-    char_count++;
-
-    if (char_count == 3) {
-      pem[j++] = pem_enc[bits  >> 18];
-      pem[j++] = pem_enc[(bits >> 12) & 0x3f];
-      pem[j++] = pem_enc[(bits >> 6)  & 0x3f];
-      pem[j++] = pem_enc[bits & 0x3f];
-      bits = 0;
-      char_count = 0;
-    } else {
-      bits <<= 8;
-    }
-  }
-
-  if (char_count != 0) {
-    bits <<= 16 - (8 * char_count);
-    pem[j++] = pem_enc[bits >> 18];
-    pem[j++] = pem_enc[(bits >> 12) & 0x3f];
-
-    if (char_count == 1) {
-      pem[j++] = '=';
-      pem[j] = '=';
-    } else {
-      pem[j++] = pem_enc[(bits >> 6) & 0x3f];
-      pem[j] = '=';
-    }
-  }
-
-  return pem;
-}
-
-/* Same as above but puts newline ('\n') every 72 characters. */
-
-char *silc_encode_pem_file(unsigned char *data, SilcUInt32 data_len)
-{
-  int i, j;
-  SilcUInt32 len, cols;
-  char *pem, *pem2;
-
-  pem = silc_encode_pem(data, data_len);
-  len = strlen(pem);
-
-  pem2 = silc_calloc(len + (len / 72) + 1, sizeof(*pem2));
-
-  for (i = 0, j = 0, cols = 1; i < len; i++, cols++) {
-    if (cols == 72) {
-      pem2[i] = '\n';
-      cols = 0;
-      len++;
-      continue;
-    }
-
-    pem2[i] = pem[j++];
-  }
-
-  silc_free(pem);
-  return pem2;
-}
-
-/* Decodes PEM into data. Returns the decoded data. Note: This is
-   originally public domain code and is still PD. */
-
-unsigned char *silc_decode_pem(unsigned char *pem, SilcUInt32 pem_len,
-                              SilcUInt32 *ret_len)
-{
-  int i, j;
-  SilcUInt32 len, c, char_count, bits;
-  unsigned char *data;
-  static char ialpha[256], decoder[256];
-
-  for (i = 64 - 1; i >= 0; i--) {
-    ialpha[pem_enc[i]] = 1;
-    decoder[pem_enc[i]] = i;
-  }
-
-  char_count = 0;
-  bits = 0;
-  j = 0;
-
-  if (!pem_len)
-    len = strlen(pem);
-  else
-    len = pem_len;
-
-  data = silc_calloc(((len * 6) / 8), sizeof(*data));
-
-  for (i = 0; i < len; i++) {
-    c = pem[i];
-
-    if (c == '=')
-      break;
-
-    if (c > 127 || !ialpha[c])
-      continue;
-
-    bits += decoder[c];
-    char_count++;
-
-    if (char_count == 4) {
-      data[j++] = bits >> 16;
-      data[j++] = (bits >> 8) & 0xff;
-      data[j++] = bits & 0xff;
-      bits = 0;
-      char_count = 0;
-    } else {
-      bits <<= 6;
-    }
-  }
-
-  switch(char_count) {
-  case 1:
-    silc_free(data);
-    return NULL;
-    break;
-  case 2:
-    data[j++] = bits >> 10;
-    break;
-  case 3:
-    data[j++] = bits >> 16;
-    data[j++] = (bits >> 8) & 0xff;
-    break;
-  }
-
-  if (ret_len)
-    *ret_len = j;
-
-  return data;
-}
-
 /* Parse userfqdn string which is in user@fqdn format. */
 
 bool silc_parse_userfqdn(const char *string, char **left, char **right)
index 156d86661a528919ed64ce5f8f7b1def16c65a94..1618b4ff1893f6ab43596f404e6c38cc57557a87 100644 (file)
@@ -21,7 +21,7 @@
  *
  * DESCRIPTION
  *
- *    XXX
+ *    Utility functions.
  *
  ***/
 
@@ -85,50 +85,6 @@ char *silc_get_time();
  ***/
 char *silc_to_upper(char *string);
 
-/****f* silcutil/SilcUtilAPI/silc_encode_pem
- *
- * SYNOPSIS
- *
- *    char *silc_encode_pem(unsigned char *data, SilcUInt32 len);
- *
- * DESCRIPTION
- *
- *    Encodes data into PEM encoding. Returns NULL terminated PEM encoded
- *    data string. Note: This is originally public domain code and is
- *    still PD.
- *
- ***/
-char *silc_encode_pem(unsigned char *data, SilcUInt32 len);
-
-/****f* silcutil/SilcUtilAPI/silc_encode_pem_file
- *
- * SYNOPSIS
- *
- *    char *silc_encode_pem_file(unsigned char *data, SilcUInt32 data_len);
- *
- * DESCRIPTION
- *
- *    Same as silc_encode_pem() but puts newline ('\n') every 72 characters.
- *
- ***/
-char *silc_encode_pem_file(unsigned char *data, SilcUInt32 data_len);
-
-/****f* silcutil/SilcUtilAPI/silc_decode_pem
- *
- * SYNOPSIS
- *
- *    unsigned char *silc_decode_pem(unsigned char *pem, SilcUInt32 pem_len,
- *                                   SilcUInt32 *ret_len);
- *
- * DESCRIPTION
- *
- *    Decodes PEM into data. Returns the decoded data. Note: This is
- *    originally public domain code and is still PD.
- *
- ***/
-unsigned char *silc_decode_pem(unsigned char *pem, SilcUInt32 pem_len,
-                              SilcUInt32 *ret_len);
-
 /****f* silcutil/SilcUtilAPI/silc_parse_userfqdn
  *
  * SYNOPSIS