SilcClientConnection conn = cmd->conn;
SilcChannelEntry channel;
SilcBuffer buffer, idp, auth = NULL;
- char *name, *passphrase = NULL, *cipher = NULL, *hmac = NULL;
- int i;
+ char *name, *passphrase = NULL, *pu8, *cipher = NULL, *hmac = NULL;
+ int i, passphrase_len = 0;
if (!cmd->conn) {
SILC_NOT_CONNECTED(cmd->client, cmd->conn);
}
i++;
} else {
- passphrase = cmd->argv[i];
+ /* Passphrases must be UTF-8 encoded, so encode if it is not */
+ if (!silc_utf8_valid(cmd->argv[i], cmd->argv_lens[i])) {
+ passphrase_len = silc_utf8_encoded_len(cmd->argv[i],
+ cmd->argv_lens[i], 0);
+ pu8 = silc_calloc(passphrase_len, sizeof(*pu8));
+ passphrase_len = silc_utf8_encode(cmd->argv[i], cmd->argv_lens[i],
+ 0, pu8, passphrase_len);
+ passphrase = pu8;
+ } else {
+ passphrase = strdup(cmd->argv[i]);
+ passphrase_len = cmd->argv_lens[i];
+ }
}
}
silc_command_payload_encode_va(SILC_COMMAND_JOIN, 0, 6,
1, name, strlen(name),
2, idp->data, idp->len,
- 3, passphrase,
- passphrase ? strlen(passphrase) : 0,
+ 3, passphrase, passphrase_len,
4, cipher, cipher ? strlen(cipher) : 0,
5, hmac, hmac ? strlen(hmac) : 0,
6, auth ? auth->data : NULL,
silc_buffer_free(idp);
if (auth)
silc_buffer_free(auth);
+ silc_free(passphrase);
/* Notify application */
COMMAND;
}
static void silc_client_command_silcoper_send(unsigned char *data,
- SilcUInt32 data_len, void *context)
+ SilcUInt32 data_len,
+ void *context)
{
SilcClientCommandContext cmd = (SilcClientCommandContext)context;
SilcClientConnection conn = cmd->conn;
--- /dev/null
+/*
+
+ silcstrutil.c
+
+ 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.
+
+*/
+
+#include "silcincludes.h"
+#include "silcstrutil.h"
+
+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_pem_encode(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_pem_encode_file(unsigned char *data, SilcUInt32 data_len)
+{
+ int i, j;
+ SilcUInt32 len, cols;
+ char *pem, *pem2;
+
+ pem = silc_pem_encode(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_pem_decode(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;
+}
+
+/* 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)
+{
+ SilcUInt32 enclen = 0, i, charval = 0;
+
+ if (!bin || !bin_len)
+ return 0;
+
+ for (i = 0; i < bin_len; i++) {
+ switch (bin_encoding) {
+ case SILC_STRING_ASCII:
+ charval = bin[i];
+ break;
+ case SILC_STRING_ASCII_ESC:
+ break;
+ case SILC_STRING_BMP:
+ break;
+ case SILC_STRING_UNIVERSAL:
+ break;
+ }
+
+ if (charval < 0x80) {
+ if (utf8) {
+ if (enclen > utf8_size)
+ return 0;
+
+ utf8[enclen] = (unsigned char)charval;
+ }
+ enclen++;
+ } else if (charval < 0x800) {
+ if (utf8) {
+ if (enclen + 2 > utf8_size)
+ return 0;
+
+ utf8[enclen ] = (unsigned char )(((charval >> 6) & 0x1f) | 0xc0);
+ utf8[enclen + 1] = (unsigned char )((charval & 0x3f) | 0x80);
+ }
+ enclen += 2;
+ } else if (charval < 0x10000) {
+ if (utf8) {
+ if (enclen + 3 > utf8_size)
+ return 0;
+
+ utf8[enclen ] = (unsigned char )(((charval >> 12) & 0xf) | 0xe0);
+ utf8[enclen + 1] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80);
+ utf8[enclen + 2] = (unsigned char )((charval & 0x3f) | 0x80);
+ }
+ enclen += 3;
+ } else if (charval < 0x200000) {
+ if (utf8) {
+ if (enclen + 4 > utf8_size)
+ return 0;
+
+ utf8[enclen ] = (unsigned char )(((charval >> 18) & 0x7) | 0xf0);
+ utf8[enclen + 1] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
+ utf8[enclen + 2] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80);
+ utf8[enclen + 3] = (unsigned char )((charval & 0x3f) | 0x80);
+ }
+ enclen += 4;
+ } else if (charval < 0x4000000) {
+ if (utf8) {
+ if (enclen + 5 > utf8_size)
+ return 0;
+
+ utf8[enclen ] = (unsigned char )(((charval >> 24) & 0x3) | 0xf8);
+ utf8[enclen + 1] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80);
+ utf8[enclen + 2] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
+ utf8[enclen + 3] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80);
+ utf8[enclen + 4] = (unsigned char )((charval & 0x3f) | 0x80);
+ }
+ enclen += 5;
+ } else {
+ if (utf8) {
+ if (enclen + 6 > utf8_size)
+ return 0;
+
+ utf8[enclen ] = (unsigned char )(((charval >> 30) & 0x1) | 0xfc);
+ utf8[enclen + 1] = (unsigned char )(((charval >> 24) & 0x3f) | 0x80);
+ utf8[enclen + 2] = (unsigned char )(((charval >> 18) & 0x3f) | 0x80);
+ utf8[enclen + 3] = (unsigned char )(((charval >> 12) & 0x3f) | 0x80);
+ utf8[enclen + 4] = (unsigned char )(((charval >> 6) & 0x3f) | 0x80);
+ utf8[enclen + 5] = (unsigned char )((charval & 0x3f) | 0x80);
+ }
+ enclen += 6;
+ }
+ }
+
+ return enclen;
+}
+
+/* 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)
+{
+ SilcUInt32 enclen = 0, i, charval;
+
+ if (!utf8 || !utf8_len)
+ return 0;
+
+ for (i = 0; i < utf8_len; i++) {
+ if ((utf8[i] & 0x80) == 0x00) {
+ charval = utf8[i] & 0x7f;
+ } else if ((utf8[i] & 0xe0) == 0xc0) {
+ if (utf8_len < 2)
+ return 0;
+
+ if ((utf8[i + 1] & 0xc0) != 0x80)
+ return 0;
+
+ charval = (utf8[i++] & 0x1f) << 6;
+ charval |= utf8[i] & 0x3f;
+ if (charval < 0x80)
+ return 0;
+ } else if ((utf8[i] & 0xf0) == 0xe0) {
+ if (utf8_len < 3)
+ return 0;
+
+ if (((utf8[i + 1] & 0xc0) != 0x80) ||
+ ((utf8[i + 2] & 0xc0) != 0x80))
+ return 0;
+
+ charval = (utf8[i++] & 0xf) << 12;
+ charval |= (utf8[i++] & 0x3f) << 6;
+ charval |= utf8[i] & 0x3f;
+ if (charval < 0x800)
+ return 0;
+ } else if ((utf8[i] & 0xf8) == 0xf0) {
+ if (utf8_len < 4)
+ return 0;
+
+ if (((utf8[i + 1] & 0xc0) != 0x80) ||
+ ((utf8[i + 2] & 0xc0) != 0x80) ||
+ ((utf8[i + 3] & 0xc0) != 0x80))
+ return 0;
+
+ charval = ((SilcUInt32)(utf8[i++] & 0x7)) << 18;
+ charval |= (utf8[i++] & 0x3f) << 12;
+ charval |= (utf8[i++] & 0x3f) << 6;
+ charval |= utf8[i] & 0x3f;
+ if (charval < 0x10000)
+ return 0;
+ } else if ((utf8[i] & 0xfc) == 0xf8) {
+ if (utf8_len < 5)
+ return 0;
+
+ if (((utf8[i + 1] & 0xc0) != 0x80) ||
+ ((utf8[i + 2] & 0xc0) != 0x80) ||
+ ((utf8[i + 3] & 0xc0) != 0x80) ||
+ ((utf8[i + 4] & 0xc0) != 0x80))
+ return 0;
+
+ charval = ((SilcUInt32)(utf8[i++] & 0x3)) << 24;
+ charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18;
+ charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12;
+ charval |= (utf8[i++] & 0x3f) << 6;
+ charval |= utf8[i] & 0x3f;
+ if (charval < 0x200000)
+ return 0;
+ } else if ((utf8[i] & 0xfe) == 0xfc) {
+ if (utf8_len < 6)
+ return 0;
+
+ if (((utf8[i + 1] & 0xc0) != 0x80) ||
+ ((utf8[i + 2] & 0xc0) != 0x80) ||
+ ((utf8[i + 3] & 0xc0) != 0x80) ||
+ ((utf8[i + 4] & 0xc0) != 0x80) ||
+ ((utf8[i + 5] & 0xc0) != 0x80))
+ return 0;
+
+ charval = ((SilcUInt32)(utf8[i++] & 0x1)) << 30;
+ charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 24;
+ charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 18;
+ charval |= ((SilcUInt32)(utf8[i++] & 0x3f)) << 12;
+ charval |= (utf8[i++] & 0x3f) << 6;
+ charval |= utf8[i] & 0x3f;
+ if (charval < 0x4000000)
+ return 0;
+ } else {
+ return 0;
+ }
+
+ switch (bin_encoding) {
+ case SILC_STRING_ASCII:
+ if (bin) {
+ if (enclen + 1 > bin_size)
+ return 0;
+
+ bin[enclen] = (unsigned char)charval;
+ }
+ enclen++;
+ break;
+ case SILC_STRING_ASCII_ESC:
+ return 0;
+ break;
+ case SILC_STRING_BMP:
+ return 0;
+ break;
+ case SILC_STRING_UNIVERSAL:
+ return 0;
+ break;
+ }
+ }
+
+ return enclen;
+}
+
+/* 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)
+{
+ return silc_utf8_encode(bin, bin_len, bin_encoding, NULL, 0);
+}
+
+/* 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)
+{
+ return silc_utf8_decode(utf8, utf8_len, 0, NULL, 0) != 0;
+}