aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilmer van der Gaast <wilmer@gaast.net>2006-06-28 16:47:05 +0200
committerWilmer van der Gaast <wilmer@gaast.net>2006-06-28 16:47:05 +0200
commit171946457cccb7280f0918201093e79bbc9eac72 (patch)
tree59b41cf763f80bc8800ae183b649e414f7ac2b72
parentb3c467bc312114eb7cdd45e6bc36a3d87bee6064 (diff)
Added random_bytes() function for better/more reliable randomization and
moved set_eval_ops() to a slightly more suitable place.
-rw-r--r--lib/misc.c78
-rw-r--r--lib/misc.h10
-rw-r--r--lib/rc4.c9
-rw-r--r--set.c14
-rw-r--r--set.h4
-rw-r--r--storage_xml.c5
6 files changed, 96 insertions, 24 deletions
diff --git a/lib/misc.c b/lib/misc.c
index 9f592289..784d80d6 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -1,7 +1,7 @@
/********************************************************************\
* BitlBee -- An IRC to other IM-networks gateway *
* *
- * Copyright 2002-2004 Wilmer van der Gaast and others *
+ * Copyright 2002-2006 Wilmer van der Gaast and others *
\********************************************************************/
/*
@@ -10,7 +10,7 @@
*
* Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
* (and possibly other members of the Gaim team)
- * Copyright 2002-2005 Wilmer van der Gaast <wilmer@gaast.net>
+ * Copyright 2002-2006 Wilmer van der Gaast <wilmer@gaast.net>
*/
/*
@@ -421,17 +421,67 @@ signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t si
return( outbuf - dst );
}
-char *set_eval_charset( irc_t *irc, set_t *set, char *value )
+/* A pretty reliable random number generator. Tries to use the /dev/random
+ devices first, and falls back to the random number generator from libc
+ when it fails. Opens randomizer devices with O_NONBLOCK to make sure a
+ lack of entropy won't halt BitlBee. */
+void random_bytes( unsigned char *buf, int count )
{
- GIConv cd;
-
- if ( g_strncasecmp( value, "none", 4 ) == 0 )
- return( value );
-
- cd = g_iconv_open( "UTF-8", value );
- if( cd == (GIConv) -1 )
- return( NULL );
-
- g_iconv_close( cd );
- return( value );
+ static int use_dev = -1;
+
+ /* Actually this probing code isn't really necessary, is it? */
+ if( use_dev == -1 )
+ {
+ if( access( "/dev/random", R_OK ) == 0 || access( "/dev/urandom", R_OK ) == 0 )
+ use_dev = 1;
+ else
+ {
+ use_dev = 0;
+ srand( ( getpid() << 16 ) ^ time( NULL ) );
+ }
+ }
+
+ if( use_dev )
+ {
+ int fd;
+
+ /* At least on Linux, /dev/random can block if there's not
+ enough entropy. We really don't want that, so if it can't
+ give anything, use /dev/urandom instead. */
+ if( ( fd = open( "/dev/random", O_RDONLY | O_NONBLOCK ) ) >= 0 )
+ if( read( fd, buf, count ) == count )
+ {
+ close( fd );
+ return;
+ }
+ close( fd );
+
+ /* urandom isn't supposed to block at all, but just to be
+ sure. If it blocks, we'll disable use_dev and use the libc
+ randomizer instead. */
+ if( ( fd = open( "/dev/urandom", O_RDONLY | O_NONBLOCK ) ) >= 0 )
+ if( read( fd, buf, count ) == count )
+ {
+ close( fd );
+ return;
+ }
+ close( fd );
+
+ /* If /dev/random blocks once, we'll still try to use it
+ again next time. If /dev/urandom also fails for some
+ reason, stick with libc during this session. */
+
+ use_dev = 0;
+ srand( ( getpid() << 16 ) ^ time( NULL ) );
+ }
+
+ if( !use_dev )
+ {
+ int i;
+
+ /* Possibly the LSB of rand() isn't very random on some
+ platforms. Seems okay on at least Linux and OSX though. */
+ for( i = 0; i < count; i ++ )
+ buf[i] = rand() & 0xff;
+ }
}
diff --git a/lib/misc.h b/lib/misc.h
index ed019bd8..57ff3e37 100644
--- a/lib/misc.h
+++ b/lib/misc.h
@@ -23,8 +23,11 @@
Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _UTIL_H
-#define _UTIL_H
+#ifndef _MISC_H
+#define _MISC_H
+
+#include <gmodule.h>
+#include <time.h>
G_MODULE_EXPORT void strip_linefeed( gchar *text );
G_MODULE_EXPORT char *add_cr( char *text );
@@ -44,6 +47,7 @@ G_MODULE_EXPORT char *ipv6_wrap( char *src );
G_MODULE_EXPORT char *ipv6_unwrap( char *src );
G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf );
-char *set_eval_charset( irc_t *irc, set_t *set, char *value );
+
+G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count );
#endif
diff --git a/lib/rc4.c b/lib/rc4.c
index cbe0e2c0..86b74ef5 100644
--- a/lib/rc4.c
+++ b/lib/rc4.c
@@ -38,8 +38,10 @@
#include <glib.h>
+#include <gmodule.h>
#include <stdlib.h>
#include <string.h>
+#include "misc.h"
#include "rc4.h"
/* Add some seed to the password, to make sure we *never* use the same key.
@@ -133,8 +135,11 @@ int rc4_encode( unsigned char *clear, int clear_len, unsigned char **crypt, char
*crypt = g_malloc( clear_len + RC4_IV_LEN );
key = g_malloc( key_len );
strcpy( (char*) key, password );
- for( i = 0; i < RC4_IV_LEN; i ++ )
- key[key_len-RC4_IV_LEN+i] = crypt[0][i] = rand() & 0xff;
+
+ /* Add the salt. Save it for later (when decrypting) and, of course,
+ add it to the encryption key. */
+ random_bytes( crypt[0], RC4_IV_LEN );
+ memcpy( key + key_len - RC4_IV_LEN, crypt[0], RC4_IV_LEN );
/* Generate the initial S[] from the IVed key. */
st = rc4_keymaker( key, key_len, RC4_CYCLES );
diff --git a/set.c b/set.c
index 60912e10..a26bc17b 100644
--- a/set.c
+++ b/set.c
@@ -223,3 +223,17 @@ char *set_eval_ops( irc_t *irc, set_t *set, char *value )
return( NULL );
}
+char *set_eval_charset( irc_t *irc, set_t *set, char *value )
+{
+ GIConv cd;
+
+ if ( g_strncasecmp( value, "none", 4 ) == 0 )
+ return( value );
+
+ cd = g_iconv_open( "UTF-8", value );
+ if( cd == (GIConv) -1 )
+ return( NULL );
+
+ g_iconv_close( cd );
+ return( value );
+}
diff --git a/set.h b/set.h
index ebebf2d0..8a7b6747 100644
--- a/set.h
+++ b/set.h
@@ -46,7 +46,7 @@ void set_del( irc_t *irc, char *key );
char *set_eval_int( irc_t *irc, set_t *set, char *value );
char *set_eval_bool( irc_t *irc, set_t *set, char *value );
+
char *set_eval_to_char( irc_t *irc, set_t *set, char *value );
char *set_eval_ops( irc_t *irc, set_t *set, char *value );
-
-
+char *set_eval_charset( irc_t *irc, set_t *set, char *value );
diff --git a/storage_xml.c b/storage_xml.c
index cc3498af..5a8b51ef 100644
--- a/storage_xml.c
+++ b/storage_xml.c
@@ -370,7 +370,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
set_t *set;
nick_t *nick;
account_t *acc;
- int fd, i;
+ int fd;
md5_byte_t pass_md5[21];
md5_state_t md5_state;
@@ -395,8 +395,7 @@ static storage_status_t xml_save( irc_t *irc, int overwrite )
/* Generate a salted md5sum of the password. Use 5 bytes for the salt
(to prevent dictionary lookups of passwords) to end up with a 21-
byte password hash, more convenient for base64 encoding. */
- for( i = 0; i < 5; i ++ )
- pass_md5[16+i] = rand() & 0xff;
+ random_bytes( pass_md5 + 16, 5 );
md5_init( &md5_state );
md5_append( &md5_state, (md5_byte_t*) irc->password, strlen( irc->password ) );
md5_append( &md5_state, pass_md5 + 16, 5 ); /* Add the salt. */