X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=lib%2Fsilcutil%2Fsilcutil.c;h=75e85f933fbecc049e1251b132f6b338714590d2;hb=e0fee2ed75e024dc18f60e6404489db3d6eadad4;hp=0333e6302e2cb9fe545d4bad226490d1edc997de;hpb=341fcb5192bf89436681566074087a4b25bafadb;p=crypto.git diff --git a/lib/silcutil/silcutil.c b/lib/silcutil/silcutil.c index 0333e630..75e85f93 100644 --- a/lib/silcutil/silcutil.c +++ b/lib/silcutil/silcutil.c @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 1997 - 2007 Pekka Riikonen + Copyright (C) 1997 - 2008 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 @@ -40,13 +40,17 @@ int silc_gets(char *dest, int destlen, const char *src, int srclen, int begin) i = 0; for ( ; start <= srclen; i++, start++) { - if (i > destlen) + if (i > destlen) { + silc_set_errno(SILC_ERR_OVERFLOW); return -1; + } dest[i] = src[start]; - if (dest[i] == EOF) + if (dest[i] == EOF) { + silc_set_errno(SILC_ERR_EOF); return EOF; + } if (dest[i] == '\n') break; @@ -56,36 +60,16 @@ int silc_gets(char *dest, int destlen, const char *src, int srclen, int begin) return start; } -/* Checks line for illegal characters. Return -1 when illegal character - were found. This is used to check for bad lines when reading data from - for example a configuration file. */ - -int silc_check_line(char *buf) -{ - /* Illegal characters in line */ - if (strchr(buf, '#')) return -1; - if (strchr(buf, '\'')) return -1; - if (strchr(buf, '\\')) return -1; - if (strchr(buf, '\r')) return -1; - if (strchr(buf, '\a')) return -1; - if (strchr(buf, '\b')) return -1; - if (strchr(buf, '\f')) return -1; - - /* Empty line */ - if (buf[0] == '\n') - return -1; - - return 0; -} - /* Converts string to capital characters. */ SilcBool silc_to_upper(const char *string, char *dest, SilcUInt32 dest_size) { int i; - if (strlen(string) > dest_size) + if (strlen(string) > dest_size) { + silc_set_errno(SILC_ERR_OVERFLOW); return FALSE; + } for (i = 0; i < strlen(string); i++) dest[i] = (char)toupper((int)string[i]); @@ -99,8 +83,10 @@ SilcBool silc_to_lower(const char *string, char *dest, SilcUInt32 dest_size) { int i; - if (strlen(string) > dest_size) + if (strlen(string) > dest_size) { + silc_set_errno(SILC_ERR_OVERFLOW); return FALSE; + } for (i = 0; i < strlen(string); i++) dest[i] = (char)tolower((int)string[i]); @@ -116,14 +102,18 @@ int silc_parse_userfqdn(const char *string, { SilcUInt32 tlen; - if (!user && !fqdn) + if (!user && !fqdn) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return 0; + } memset(user, 0, user_size); memset(fqdn, 0, fqdn_size); - if (!string) + if (!string) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); return 0; + } if (string[0] == '@') { if (user) @@ -165,7 +155,7 @@ void silc_parse_command_line(unsigned char *buffer, { int i, len = 0; int argc = 0; - const char *cp = buffer; + const char *cp = (const char *)buffer; char *tmp; *parsed = silc_calloc(1, sizeof(**parsed)); @@ -234,233 +224,54 @@ char *silc_format(char *fmt, ...) va_list args; char buf[8192]; - memset(buf, 0, sizeof(buf)); va_start(args, fmt); - silc_vsnprintf(buf, sizeof(buf) - 1, fmt, args); + silc_vsnprintf(buf, sizeof(buf), fmt, args); va_end(args); - return strdup(buf); + return silc_strdup(buf); } -/* Basic has function to hash strings. May be used with the SilcHashTable. - Note that this lowers the characters of the string (with tolower()) so - this is used usually with nicknames, channel and server names to provide - case insensitive keys. */ - -SilcUInt32 silc_hash_string(void *key, void *user_context) -{ - char *s = (char *)key; - SilcUInt32 h = 0, g; - - while (*s != '\0') { - h = (h << 4) + tolower((int)*s); - if ((g = h & 0xf0000000)) { - h = h ^ (g >> 24); - h = h ^ g; - } - s++; - } - - return h; -} - -/* Hash UTF-8 string */ - -SilcUInt32 silc_hash_utf8_string(void *key, void *user_context) -{ - unsigned char *s = (unsigned char *)key; - SilcUInt32 h = 0, g; - - while (*s != '\0') { - h = (h << 4) + *s; - if ((g = h & 0xf0000000)) { - h = h ^ (g >> 24); - h = h ^ g; - } - s++; - } - - return h; -} - -/* Basic hash function to hash integers. May be used with the SilcHashTable. */ - -SilcUInt32 silc_hash_uint(void *key, void *user_context) -{ - return SILC_PTR_TO_32(key); -} - -/* Basic hash funtion to hash pointers. May be used with the SilcHashTable. */ - -SilcUInt32 silc_hash_ptr(void *key, void *user_context) -{ - return SILC_PTR_TO_32(key); -} - -/* Hash a ID. The `user_context' is the ID type. */ +/* Creates fingerprint from data, usually used with SHA1 digests */ -SilcUInt32 silc_hash_id(void *key, void *user_context) +char *silc_fingerprint(const unsigned char *data, SilcUInt32 data_len) { - SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context); - SilcUInt32 h = 0; - int i; - - switch (id_type) { - case SILC_ID_CLIENT: - { - SilcClientID *id = (SilcClientID *)key; - - /* The client ID is hashed by hashing the hash of the ID - (which is a truncated MD5 hash of the nickname) so that we - can access the entry from the cache with both Client ID but - with just a hash from the ID as well. */ - return silc_hash_client_id_hash(id->hash, NULL); - } - break; - case SILC_ID_SERVER: - { - SilcServerID *id = (SilcServerID *)key; - - h = id->port * id->rnd; - for (i = 0; i < id->ip.data_len; i++) - h ^= id->ip.data[i]; - - return h; - } - break; - case SILC_ID_CHANNEL: - { - SilcChannelID *id = (SilcChannelID *)key; - - h = id->port * id->rnd; - for (i = 0; i < id->ip.data_len; i++) - h ^= id->ip.data[i]; + unsigned char *fingerprint, *cp; + unsigned int len, blocks, i; - return h; - } - break; - default: - break; + if (!data || !data_len) { + silc_set_errno(SILC_ERR_INVALID_ARGUMENT); + return NULL; } - return h; -} + if (data_len >= 256) + data_len = 255; -/* Hash Client ID's hash. */ + /* Align and calculate total length */ + len = ((data_len + 19) / 20) * 20; + blocks = (len / 10); + len = (len * 2) + ((blocks - 1) * 2) + (4 * blocks) + 2 + 1; -SilcUInt32 silc_hash_client_id_hash(void *key, void *user_context) -{ - int i; - unsigned char *hash = key; - SilcUInt32 h = 0, g; - - for (i = 0; i < CLIENTID_HASH_LEN; i++) { - h = (h << 4) + hash[i]; - if ((g = h & 0xf0000000)) { - h = h ^ (g >> 24); - h = h ^ g; - } - } + cp = fingerprint = silc_calloc(len, sizeof(*fingerprint)); + if (!cp) + return NULL; - return h; -} - -/* Hash binary data. The `user_context' is the data length. */ - -SilcUInt32 silc_hash_data(void *key, void *user_context) -{ - SilcUInt32 len = SILC_PTR_TO_32(user_context), h = 0; - unsigned char *data = (unsigned char *)key; - int i; - - h = (data[0] * data[len - 1] + 1) * len; - for (i = 0; i < len; i++) - h ^= data[i]; - - return h; -} - -/* Compares two strings. It may be used as SilcHashTable comparison - function. */ - -SilcBool silc_hash_string_compare(void *key1, void *key2, void *user_context) -{ - return !strcasecmp((char *)key1, (char *)key2); -} - -/* Compares two ID's. May be used as SilcHashTable comparison function. - The Client ID's compares only the hash of the Client ID not any other - part of the Client ID. Other ID's are fully compared. */ - -SilcBool silc_hash_id_compare(void *key1, void *key2, void *user_context) -{ - SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context); - return (id_type == SILC_ID_CLIENT ? - SILC_ID_COMPARE_HASH((SilcClientID *)key1, (SilcClientID *)key2) : - SILC_ID_COMPARE_TYPE(key1, key2, id_type)); -} - -/* Compares two ID's. Compares full IDs. */ - -SilcBool silc_hash_id_compare_full(void *key1, void *key2, void *user_context) -{ - SilcIdType id_type = (SilcIdType)SILC_PTR_TO_32(user_context); - return SILC_ID_COMPARE_TYPE(key1, key2, id_type); -} - -/* Compare two Client ID's entirely and not just the hash from the ID. */ - -SilcBool silc_hash_client_id_compare(void *key1, void *key2, - void *user_context) -{ - return SILC_ID_COMPARE_TYPE(key1, key2, SILC_ID_CLIENT); -} - -/* Compares binary data. May be used as SilcHashTable comparison function. */ - -SilcBool silc_hash_data_compare(void *key1, void *key2, void *user_context) -{ - SilcUInt32 len = SILC_PTR_TO_32(user_context); - return !memcmp(key1, key2, len); -} - -/* Compares UTF-8 string. */ - -SilcBool silc_hash_utf8_compare(void *key1, void *key2, void *user_context) -{ - int l1 = strlen((char *)key1); - int l2 = strlen((char *)key2); - if (l1 != l2) - return FALSE; - return !memcmp(key1, key2, l2); -} - -/* Creates fingerprint from data, usually used with SHA1 digests */ - -char *silc_fingerprint(const unsigned char *data, SilcUInt32 data_len) -{ - char fingerprint[64], *cp; - int i; - - memset(fingerprint, 0, sizeof(fingerprint)); - cp = fingerprint; for (i = 0; i < data_len; i++) { - silc_snprintf(cp, sizeof(fingerprint), "%02X", data[i]); + silc_snprintf(cp, len, "%02X", data[i]); cp += 2; + len -= 2; if ((i + 1) % 2 == 0) - silc_snprintf(cp++, sizeof(fingerprint), " "); - + silc_snprintf(cp++, len--, " "); if ((i + 1) % 10 == 0) - silc_snprintf(cp++, sizeof(fingerprint), " "); + silc_snprintf(cp++, len--, " "); } i--; - if ((i + 1) % 2 == 0) - cp[-2] = 0; if ((i + 1) % 10 == 0) - cp[-1] = 0; + *(--cp) = '\0'; + if ((i + 1) % 2 == 0) + *(--cp) = '\0'; - return strdup(fingerprint); + return fingerprint; } /* Return TRUE if the `data' is ASCII string. */ @@ -493,7 +304,7 @@ char *silc_get_input(const char *prompt, SilcBool echo_off) fd = open("/dev/tty", O_RDONLY); if (fd < 0) { - fprintf(stderr, "silc: %s\n", strerror(errno)); + silc_set_errno_posix(errno); return NULL; } @@ -515,13 +326,14 @@ char *silc_get_input(const char *prompt, SilcBool echo_off) fflush(stdout); if ((read(fd, input, sizeof(input))) < 0) { - fprintf(stderr, "silc: %s\n", strerror(errno)); + silc_set_errno_posix(errno); tcsetattr(fd, TCSANOW, &to_old); return NULL; } if (strlen(input) <= 1) { tcsetattr(fd, TCSANOW, &to_old); + silc_set_errno(SILC_ERR_EOF); return NULL; } @@ -539,7 +351,7 @@ char *silc_get_input(const char *prompt, SilcBool echo_off) } else { fd = open("/dev/tty", O_RDONLY); if (fd < 0) { - fprintf(stderr, "silc: %s\n", strerror(errno)); + silc_set_errno_posix(errno); return NULL; } @@ -549,17 +361,19 @@ char *silc_get_input(const char *prompt, SilcBool echo_off) fflush(stdout); if ((read(fd, input, sizeof(input))) < 0) { - fprintf(stderr, "silc: %s\n", strerror(errno)); + silc_set_errno_posix(errno); return NULL; } - if (strlen(input) <= 1) + if (strlen(input) <= 1) { + silc_set_errno(SILC_ERR_EOF); return NULL; + } if (strchr(input, '\n')) *strchr(input, '\n') = '\0'; - return strdup(input); + return silc_strdup(input); } #else return NULL; @@ -640,8 +454,10 @@ SilcBool silc_hex2data(const char *hex, unsigned char *data, unsigned char l, h; int i; - if (data_size < strlen(hex) / 2) + if (data_size < strlen(hex) / 2) { + silc_set_errno(SILC_ERR_OVERFLOW); return FALSE; + } for (i = 0; i < strlen(hex) / 2; i++) { h = *cp++; @@ -656,8 +472,6 @@ SilcBool silc_hex2data(const char *hex, unsigned char *data, if (ret_data_len) *ret_data_len = i; - SILC_LOG_HEXDUMP(("len %d", i), data, i); - return TRUE; } @@ -670,8 +484,10 @@ SilcBool silc_data2hex(const unsigned char *data, SilcUInt32 data_len, char *cp = hex; int i; - if (hex_size - 1 < data_len * 2) + if (hex_size - 1 < data_len * 2) { + silc_set_errno(SILC_ERR_OVERFLOW); return FALSE; + } memset(hex, 0, hex_size); @@ -684,7 +500,5 @@ SilcBool silc_data2hex(const unsigned char *data, SilcUInt32 data_len, *cp++ = l + (l > 9 ? 'A' - 10 : '0'); } - SILC_LOG_DEBUG(("HEX string: '%s'", hex)); - return TRUE; }