summaryrefslogtreecommitdiff
path: root/ares_init.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-05-30 21:11:10 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-05-30 21:11:10 +0000
commit7a77f24d26f755421b91a0ea3852b6348d637861 (patch)
tree9c844a8c94f38eadb15c554e570db4e0daebf638 /ares_init.c
parentf1440b240528afe3dfc03256d92b49acb4ef8537 (diff)
downloadc-ares-7a77f24d26f755421b91a0ea3852b6348d637861.tar.gz
c-ares-7a77f24d26f755421b91a0ea3852b6348d637861.tar.bz2
c-ares-7a77f24d26f755421b91a0ea3852b6348d637861.zip
Shmulik Regev brought cryptographically secure transaction IDs
Diffstat (limited to 'ares_init.c')
-rw-r--r--ares_init.c83
1 files changed, 71 insertions, 12 deletions
diff --git a/ares_init.c b/ares_init.c
index d384f94..e86d80c 100644
--- a/ares_init.c
+++ b/ares_init.c
@@ -72,6 +72,8 @@ static int config_nameserver(struct server_state **servers, int *nservers,
static int set_search(ares_channel channel, const char *str);
static int set_options(ares_channel channel, const char *str);
static const char *try_option(const char *p, const char *q, const char *opt);
+static void init_id_key(rc4_key* key,int key_data_len);
+
#ifndef WIN32
static int sortlist_alloc(struct apattern **sortlist, int *nsort, struct apattern *pat);
static int ip_addr(const char *s, int len, struct in_addr *addr);
@@ -85,10 +87,10 @@ static char *try_config(char *s, const char *opt);
#endif
#define ARES_CONFIG_CHECK(x) (x->lookups && x->nsort > -1 && \
- x->nservers > -1 && \
+ x->nservers > -1 && \
x->ndomains > -1 && \
- x->ndots > -1 && x->timeout > -1 && \
- x->tries > -1)
+ x->ndots > -1 && x->timeout > -1 && \
+ x->tries > -1)
int ares_init(ares_channel *channelptr)
{
@@ -102,7 +104,6 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
int i;
int status = ARES_SUCCESS;
struct server_state *server;
- struct timeval tv;
#ifdef CURLDEBUG
const char *env = getenv("CARES_MEMDEBUG");
@@ -203,15 +204,9 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
server->qtail = NULL;
}
- /* Choose a somewhat random query ID. The main point is to avoid
- * collisions with stale queries. An attacker trying to spoof a DNS
- * answer also has to guess the query ID, but it's only a 16-bit
- * field, so there's not much to be done about that.
- */
- gettimeofday(&tv, NULL);
- channel->next_id = (unsigned short)
- ((tv.tv_sec ^ tv.tv_usec ^ getpid()) & 0xffff);
+ init_id_key(&channel->id_key, ARES_ID_KEY_LEN);
+ channel->next_id = ares__generate_new_id(&channel->id_key);
channel->queries = NULL;
*channelptr = channel;
@@ -1271,3 +1266,67 @@ static void natural_mask(struct apattern *pat)
pat->mask.addr.addr4.s_addr = htonl(IN_CLASSC_NET);
}
#endif
+/* initialize an rc4 key. If possible a cryptographically secure random key
+ is generated using a suitable function (for example win32's RtlGenRandom as
+ described in
+ http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
+ otherwise the code defaults to cross-platform albeit less secure mechanism
+ using rand
+*/
+static void randomize_key(unsigned char* key,int key_data_len)
+{
+ int randomized = 0;
+#ifdef WIN32
+ HMODULE lib=LoadLibrary("ADVAPI32.DLL");
+ if (lib) {
+ BOOLEAN (APIENTRY *pfn)(void*, ULONG) =
+ (BOOLEAN (APIENTRY *)(void*,ULONG))GetProcAddress(lib,"SystemFunction036");
+ if (pfn && pfn(key,key_data_len) )
+ randomized = 1;
+
+ FreeLibrary(lib);
+ }
+#endif
+
+ if ( !randomized ) {
+ int counter;
+ for (counter=0;counter<key_data_len;counter++)
+ key[counter]=rand() % 256;
+ }
+}
+
+static void init_id_key(rc4_key* key,int key_data_len)
+{
+ unsigned char index1;
+ unsigned char index2;
+ unsigned char* state;
+ short counter;
+ unsigned char *key_data_ptr = 0;
+
+ key_data_ptr = calloc(1,key_data_len);
+ randomize_key(key->state,key_data_len);
+ state = &key->state[0];
+ for(counter = 0; counter < 256; counter++)
+ state[counter] = counter;
+ key->x = 0;
+ key->y = 0;
+ index1 = 0;
+ index2 = 0;
+ for(counter = 0; counter < 256; counter++)
+ {
+ index2 = (key_data_ptr[index1] + state[counter] +
+ index2) % 256;
+ ARES_SWAP_BYTE(&state[counter], &state[index2]);
+
+ index1 = (index1 + 1) % key_data_len;
+ }
+ free(key_data_ptr);
+
+}
+
+short ares__generate_new_id(rc4_key* key)
+{
+ short r;
+ ares__rc4(key, (unsigned char *)&r, sizeof(r));
+ return r;
+}