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
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.
SILC_SERVER_REC *server = conn->context;
if (!server && !success) {
- silc_client_close_connection(client, NULL, conn);
+ silc_client_close_connection(client, conn);
return;
}
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));
}
/* 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;
}
}
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;
*/
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)))
{
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;
}
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
(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:
[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.
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.
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
[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
.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
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
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
.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:
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
[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.
#include "silcbuffmt.h"
#include "silcnet.h"
#include "silcfileutil.h"
+#include "silcstrutil.h"
#include "silcutil.h"
#include "silcconfig.h"
#include "silcprotocol.h"
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;
}
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;
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. */
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
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);
}
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);
/* 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,
/* 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);
}
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));
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;
/* 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);
* 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);
{
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),
SILC_STR_UI_XNSTRING(auth_data, auth_len),
SILC_STR_END);
+ silc_free(autf8);
return buffer;
}
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)
/* 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)
*
* 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,
*
* 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,
* 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,
* 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);
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;
}
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;
}
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;
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;
}
@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
silcnet.c \
silcschedule.c \
silcfileutil.c \
+ silcstrutil.c \
silcutil.c \
silchashtable.c \
silcsockconn.c \
silcdlist.h \
silcfileutil.h \
silcutil.h \
+ silcstrutil.h \
silctypes.h
endif
GNU General Public License for more details.
*/
+/* $Id$ */
#include "silcincludes.h"
#include "silcstrutil.h"
--- /dev/null
+/*
+
+ 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 */
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)
*
* DESCRIPTION
*
- * XXX
+ * Utility functions.
*
***/
***/
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