X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcstrutil.c;h=fadd31174069a4c6eb49adbb51c45d52e01f6ceb;hb=40f8443d8d3a6577336ee66d18e04d9ac4d956bb;hp=5e6a592bce8484a37205d71c0379ba098f86217f;hpb=103b560c55e218ad043094bdcb29e709158c3b5b;p=silc.git diff --git a/lib/silcutil/silcstrutil.c b/lib/silcutil/silcstrutil.c index 5e6a592b..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 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,15 +18,14 @@ */ /* $Id$ */ -#include "silcincludes.h" +#include "silc.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. */ + data string. */ char *silc_pem_encode(unsigned char *data, SilcUInt32 len) { @@ -102,8 +101,7 @@ char *silc_pem_encode_file(unsigned char *data, SilcUInt32 data_len) return pem2; } -/* Decodes PEM into data. Returns the decoded data. Note: This is - originally public domain code and is still PD. */ +/* Decodes PEM into data. Returns the decoded data. */ unsigned char *silc_pem_decode(unsigned char *pem, SilcUInt32 pem_len, SilcUInt32 *ret_len) @@ -172,316 +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); } - 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; - } + return dest; +} - 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; - } +/* 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; + + if (!identifier || !identifier_len) + return NULL; + + 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; - - 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; - } + SilcStringprepStatus status; - switch (bin_encoding) { - case SILC_STRING_ASCII: - if (bin) { - if (enclen + 1 > bin_size) - return 0; + if (!identifier || !identifier_len) + return FALSE; - 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; - } + if (max_allowed_length && identifier_len > max_allowed_length) + return FALSE; + + 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; + return TRUE; } -/* 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) +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_encode(bin, bin_len, bin_encoding, NULL, 0); + unsigned char *utf8s; + SilcUInt32 utf8s_len; + SilcStringprepStatus status; + + if (!identifier || !identifier_len) + return NULL; + + if (max_allowed_length && identifier_len > max_allowed_length) + return NULL; + + 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 (out_len) + *out_len = utf8s_len; + + return utf8s; } -/* 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. */ +/* Same as above but does not allocate memory, just checks the + validity of the string. */ -bool silc_utf8_valid(const unsigned char *utf8, SilcUInt32 utf8_len) +SilcBool silc_channel_name_verify(const unsigned char *identifier, + SilcUInt32 identifier_len, + SilcStringEncoding identifier_encoding, + SilcUInt32 max_allowed_length) { - return silc_utf8_decode(utf8, utf8_len, 0, NULL, 0) != 0; -} + SilcStringprepStatus status; -/* 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)) + if (!identifier || !identifier_len) 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; - } - if (i >= mime_len) + + if (max_allowed_length && identifier_len > max_allowed_length) 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); + 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 TRUE; }