X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcstrutil.c;h=fadd31174069a4c6eb49adbb51c45d52e01f6ceb;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=de215d60bb6957aa744536acd020efb59922750b;hpb=413da0f8686910f5e627393157566ae729ca99c4;p=silc.git diff --git a/lib/silcutil/silcstrutil.c b/lib/silcutil/silcstrutil.c index de215d60..fadd3117 100644 --- a/lib/silcutil/silcstrutil.c +++ b/lib/silcutil/silcstrutil.c @@ -1,10 +1,10 @@ /* - silcstrutil.c + silcstrutil.c Author: Pekka Riikonen - Copyright (C) 2002 - 2003 Pekka Riikonen + Copyright (C) 2002 - 2005 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.h" #include "silcstrutil.h" static unsigned char pem_enc[64] = @@ -170,450 +170,144 @@ unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len, 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. */ +/* Concatenates the `src' into `dest'. If `src_len' is more than the + size of the `dest' (minus NULL at the end) the `src' will be + truncated to fit. */ -SilcUInt32 silc_utf8_encode(const unsigned char *bin, SilcUInt32 bin_len, - SilcStringEncoding bin_encoding, - unsigned char *utf8, SilcUInt32 utf8_size) +char *silc_strncat(char *dest, SilcUInt32 dest_size, + const char *src, SilcUInt32 src_len) { - SilcUInt32 enclen = 0, i, charval = 0; + int len; - if (!bin || !bin_len) - return 0; + dest[dest_size - 1] = '\0'; - if (silc_utf8_valid(bin, bin_len) && bin_len <= utf8_size) { - memcpy(utf8, bin, bin_len); - return bin_len; + len = dest_size - 1 - strlen(dest); + if (len < src_len) { + if (len > 0) + strncat(dest, src, len); + } else { + strncat(dest, src, src_len); } - if (bin_encoding == SILC_STRING_LANGUAGE) { -#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET) - char *fromconv, *icp, *ocp; - iconv_t icd; - size_t inlen, outlen; - - setlocale(LC_CTYPE, ""); - fromconv = nl_langinfo(CODESET); - if (fromconv && strlen(fromconv)) { - icd = iconv_open("UTF-8", fromconv); - icp = (char *)bin; - ocp = (char *)utf8; - inlen = bin_len; - outlen = utf8_size; - if (icp && ocp && icd != (iconv_t)-1) { - if (iconv(icd, &icp, &inlen, &ocp, &outlen) != -1) { - utf8_size -= outlen; - iconv_close(icd); - return utf8_size; - } - } - if (icd != (iconv_t)-1) - iconv_close(icd); - } -#endif + return dest; +} - /* Fallback to 8-bit ASCII */ - bin_encoding = SILC_STRING_ASCII; - } +/* Checks that the 'identifier' string is valid identifier string + and does not contain any unassigned or prohibited character. This + function is used to check for valid nicknames, channel names, + server names, usernames, hostnames, service names, algorithm names, + other security property names, and SILC Public Key name. */ + +unsigned char *silc_identifier_check(const unsigned char *identifier, + SilcUInt32 identifier_len, + SilcStringEncoding identifier_encoding, + SilcUInt32 max_allowed_length, + SilcUInt32 *out_len) +{ + unsigned char *utf8s; + SilcUInt32 utf8s_len; + SilcStringprepStatus status; - for (i = 0; i < bin_len; i++) { - switch (bin_encoding) { - case SILC_STRING_ASCII: - charval = bin[i]; - break; - case SILC_STRING_ASCII_ESC: - SILC_NOT_IMPLEMENTED("SILC_STRING_ASCII_ESC"); - return 0; - break; - case SILC_STRING_BMP: - if (i + 1 >= bin_len) - return 0; - SILC_GET16_MSB(charval, bin + i); - i += 1; - break; - case SILC_STRING_BMP_LSB: - if (i + 1 >= bin_len) - return 0; - SILC_GET16_LSB(charval, bin + i); - i += 1; - break; - case SILC_STRING_UNIVERSAL: - if (i + 3 >= bin_len) - return 0; - SILC_GET32_MSB(charval, bin + i); - i += 3; - break; - case SILC_STRING_UNIVERSAL_LSB: - if (i + 3 >= bin_len) - return 0; - SILC_GET32_LSB(charval, bin + i); - i += 3; - break; - default: - return 0; - break; - } + if (!identifier || !identifier_len) + return NULL; - 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; - } + if (max_allowed_length && identifier_len > max_allowed_length) + return NULL; + + status = silc_stringprep(identifier, identifier_len, + identifier_encoding, SILC_IDENTIFIER_PREP, 0, + &utf8s, &utf8s_len, SILC_STRING_UTF8); + if (status != SILC_STRINGPREP_OK) { + SILC_LOG_DEBUG(("silc_stringprep() status error %d", status)); + return NULL; } - return enclen; + if (out_len) + *out_len = utf8s_len; + + return utf8s; } -/* 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. */ +/* Same as above but does not allocate memory, just checks the + validity of the string. */ -SilcUInt32 silc_utf8_decode(const unsigned char *utf8, SilcUInt32 utf8_len, - SilcStringEncoding bin_encoding, - unsigned char *bin, SilcUInt32 bin_size) +SilcBool silc_identifier_verify(const unsigned char *identifier, + SilcUInt32 identifier_len, + SilcStringEncoding identifier_encoding, + SilcUInt32 max_allowed_length) { - SilcUInt32 enclen = 0, i, charval; - - if (!utf8 || !utf8_len) - return 0; - - if (bin_encoding == SILC_STRING_LANGUAGE) { -#if defined(HAVE_ICONV) && defined(HAVE_NL_LANGINFO) && defined(CODESET) - char *toconv, *icp, *ocp; - iconv_t icd; - size_t inlen, outlen; - - setlocale(LC_CTYPE, ""); - toconv = nl_langinfo(CODESET); - if (toconv && strlen(toconv)) { - icd = iconv_open(toconv, "UTF-8"); - icp = (char *)utf8; - ocp = (char *)bin; - inlen = utf8_len; - outlen = bin_size; - if (icp && ocp && icd != (iconv_t)-1) { - if (iconv(icd, &icp, &inlen, &ocp, &outlen) != -1) { - bin_size -= outlen; - iconv_close(icd); - return bin_size; - } - } - if (icd != (iconv_t)-1) - iconv_close(icd); - } -#endif + SilcStringprepStatus status; - /* Fallback to 8-bit ASCII */ - bin_encoding = SILC_STRING_ASCII; - } - - for (i = 0; i < utf8_len; i++) { - if ((utf8[i] & 0x80) == 0x00) { - charval = utf8[i] & 0x7f; - } else if ((utf8[i] & 0xe0) == 0xc0) { - if (i + 1 >= utf8_len) - 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 (i + 2 >= utf8_len) - 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 (i + 3 >= utf8_len) - 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 (i + 4 >= utf8_len) - 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 (i + 5 >= utf8_len) - 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; - } + if (!identifier || !identifier_len) + return FALSE; - switch (bin_encoding) { - case SILC_STRING_ASCII: - if (bin) { - if (enclen + 1 > bin_size) - return 0; + if (max_allowed_length && identifier_len > max_allowed_length) + return FALSE; - bin[enclen] = (unsigned char)charval; - } - enclen++; - break; - case SILC_STRING_ASCII_ESC: - SILC_NOT_IMPLEMENTED("SILC_STRING_ASCII_ESC"); - return 0; - break; - case SILC_STRING_BMP: - if (bin) - SILC_PUT16_MSB(charval, bin + enclen); - enclen += 2; - break; - case SILC_STRING_BMP_LSB: - if (bin) - SILC_PUT16_LSB(charval, bin + enclen); - enclen += 2; - break; - case SILC_STRING_UNIVERSAL: - if (bin) - SILC_PUT32_MSB(charval, bin + enclen); - enclen += 4; - break; - case SILC_STRING_UNIVERSAL_LSB: - if (bin) - SILC_PUT32_LSB(charval, bin + enclen); - enclen += 4; - break; - default: - return 0; - break; - } + status = silc_stringprep(identifier, identifier_len, + identifier_encoding, SILC_IDENTIFIER_PREP, 0, + NULL, NULL, SILC_STRING_UTF8); + if (status != SILC_STRINGPREP_OK) { + SILC_LOG_DEBUG(("silc_stringprep() status error %d", status)); + return FALSE; } - 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); + return TRUE; } -/* Returns the length of decoded string if the `bin' of encoding of - `bin_encoding' is decoded with silc_utf8_decode. */ - -SilcUInt32 silc_utf8_decoded_len(const unsigned char *bin, SilcUInt32 bin_len, - SilcStringEncoding bin_encoding) +unsigned char *silc_channel_name_check(const unsigned char *identifier, + SilcUInt32 identifier_len, + SilcStringEncoding identifier_encoding, + SilcUInt32 max_allowed_length, + SilcUInt32 *out_len) { - return silc_utf8_decode(bin, bin_len, bin_encoding, NULL, 0); -} + unsigned char *utf8s; + SilcUInt32 utf8s_len; + SilcStringprepStatus status; -/* 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. */ + if (!identifier || !identifier_len) + return NULL; -bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len) -{ - return silc_utf8_decode(utf8, utf8_len, 0, NULL, 0) != 0; -} + if (max_allowed_length && identifier_len > max_allowed_length) + return NULL; -/* Mime constants and macros */ -#define MIME_VERSION "MIME-Version: " -#define MIME_VERSION_LEN 14 -#define MIME_CONTENT_TYPE "Content-Type: " -#define MIME_CONTENT_TYPE_LEN 14 -#define MIME_TRANSFER_ENCODING "Content-Transfer-Encoding: " -#define MIME_TRANSFER_ENCODING_LEN 27 - -#define MIME_GET_FIELD(header, mime, mime_len, field, field_len, \ - dest, dest_size) \ -do { \ - if (dest) { \ - char *f = strstr(header, field); \ - if (f) { \ - f = (char *)mime + (f - header) + field_len; \ - for (i = 0; i < (mime_len - (f - (char *)mime)); i++) { \ - if (f[i] == '\r' || f[i] == '\n' || i == dest_size) \ - break; \ - dest[i] = f[i]; \ - } \ - } \ - } \ -} while(0) - -/* Parses MIME object and MIME header in it. */ - -bool -silc_mime_parse(const unsigned char *mime, SilcUInt32 mime_len, - char *version, SilcUInt32 version_size, - char *content_type, SilcUInt32 content_type_size, - char *transfer_encoding, SilcUInt32 transfer_encoding_size, - unsigned char **mime_data_ptr, SilcUInt32 *mime_data_len) -{ - int i; - char header[256]; - - memcpy(header, mime, 256 > mime_len ? mime_len : 256); - header[sizeof(header) - 1] = '\0'; - - /* Check for mandatory Content-Type field */ - if (!strstr(header, MIME_CONTENT_TYPE)) - return FALSE; - - /* Get the pointer to the data area in the object */ - for (i = 0; i < mime_len; i++) { - if (mime_len >= i + 4 && - mime[i ] == '\r' && mime[i + 1] == '\n' && - mime[i + 2] == '\r' && mime[i + 3] == '\n') - break; + status = silc_stringprep(identifier, identifier_len, + identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0, + &utf8s, &utf8s_len, SILC_STRING_UTF8); + if (status != SILC_STRINGPREP_OK) { + SILC_LOG_DEBUG(("silc_stringprep() status error %d", status)); + return NULL; } - if (i >= mime_len) - return FALSE; - if (mime_data_ptr) - *mime_data_ptr = (unsigned char *)mime + i + 4; - if (mime_data_len) - *mime_data_len = mime_len - ((mime + i + 4) - mime); - - /* Get MIME version, Content-Type and Transfer Encoding fields */ - MIME_GET_FIELD(header, mime, mime_len, - MIME_VERSION, MIME_VERSION_LEN, - version, version_size); - MIME_GET_FIELD(header, mime, mime_len, - MIME_CONTENT_TYPE, MIME_CONTENT_TYPE_LEN, - content_type, content_type_size); - MIME_GET_FIELD(header, mime, mime_len, - MIME_TRANSFER_ENCODING, MIME_TRANSFER_ENCODING_LEN, - transfer_encoding, transfer_encoding_size); + if (out_len) + *out_len = utf8s_len; - return TRUE; + return utf8s; } -/* Concatenates the `src' into `dest'. If `src_len' is more than the - size of the `dest' (minus NULL at the end) the `src' will be - truncated to fit. */ +/* Same as above but does not allocate memory, just checks the + validity of the string. */ -char *silc_strncat(char *dest, SilcUInt32 dest_size, - const char *src, SilcUInt32 src_len) +SilcBool silc_channel_name_verify(const unsigned char *identifier, + SilcUInt32 identifier_len, + SilcStringEncoding identifier_encoding, + SilcUInt32 max_allowed_length) { - int len; + SilcStringprepStatus status; - dest[dest_size - 1] = '\0'; + if (!identifier || !identifier_len) + return FALSE; - len = dest_size - 1 - strlen(dest); - if (len < src_len) { - if (len > 0) - strncat(dest, src, len); - } else { - strncat(dest, src, src_len); + if (max_allowed_length && identifier_len > max_allowed_length) + return FALSE; + + status = silc_stringprep(identifier, identifier_len, + identifier_encoding, SILC_IDENTIFIER_CH_PREP, 0, + NULL, NULL, SILC_STRING_UTF8); + if (status != SILC_STRINGPREP_OK) { + SILC_LOG_DEBUG(("silc_stringprep() status error %d", status)); + return FALSE; } - return dest; + return TRUE; }