/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library 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 Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ #include #include #include #include #include #include #include #include #define RANDOMDEV "/dev/urandom" void get_random_buffer(unsigned char *out, size_t outlen) { int fd, i; ssize_t count = 0; char hostname[512]; struct timeval tv; unsigned char hash[16]; int len = 0; if (out == NULL || outlen < 0) return; fd = open(RANDOMDEV, O_RDONLY); if (fd >= 0) { count = read(fd, out, outlen); close(fd); } if (fd < 0 || count < outlen) { /* if number of bytes read was too small or simply an error occured while reading urandom file use timestamp and hostname both hashed with md5 to simulate random bytes */ if (gethostname(hostname, sizeof(hostname)) == 0) { /* ensure the returned name is no longer than size of the buffer */ hostname[sizeof(hostname) - 1] = '\0'; len = strlen(hostname); md5(hash, (unsigned char*)hostname, len); } if (gettimeofday(&tv, NULL) == 0) { md5(hash, (unsigned char*)&tv, sizeof(tv)); } /* fill the output buffer with 16 bytes chunks, each being a hash of preceding one */ i = 0; do { if (i >= sizeof(hash)) { int j, off; unsigned char in[16]; off = ((i/sizeof(hash))-1)*sizeof(hash); for (j = 0; j < sizeof(hash) && (off + j) < len ; j++) { in[j] = out[off + j]; } md5(hash, in, sizeof(in)); } memcpy((void*)&(out[i]), (void*)hash, ((outlen-i) < sizeof(hash)) ? outlen % sizeof(hash) : sizeof(hash)); i += sizeof(hash); } while (i < outlen); } } static const char randomchar[] = "abcdefghijklmnoprstuvwxyz" "ABCDEFGHIJKLMNOPRSTUVWXYZ" "-+/*,.;:!<=>%'&()0123456789"; void get_random_string(char *out, size_t outsize) { int i = 0; if (out == NULL || outsize == 0) return; get_random_buffer((unsigned char*)out, outsize - 1); if (out[0] == '\0') return; /* replace each byte with its ASCII equivalent */ for (i = 0; i < (outsize - 1); i++) { out[i] = randomchar[out[i] % (sizeof(randomchar)-1)]; } /* terminate the string */ out[outsize - 1] = '\0'; } void get_random_string_w16(wchar16_t *out, size_t outsize) { int i = 0; unsigned char *bytes = NULL; if (out == NULL || outsize == 0) return; bytes = (unsigned char*) malloc(sizeof(unsigned char) * outsize); if (bytes == NULL) { out[0] = '\0'; return; } get_random_buffer((unsigned char*)bytes, outsize - 1); if (bytes[0] == '\0') goto done; /* replace each byte with its alphanum equivalent converted to 2-byte unicode */ for (i = 0; i < (outsize - 1); i++) { out[i] = (wchar16_t)randomchar[bytes[i] % (sizeof(randomchar)-1)]; } /* terminate the string */ out[outsize - 1] = '\0'; done: memset(bytes, 0, sizeof(sizeof(unsigned char) * outsize)); free(bytes); } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */