diff options
author | Daniel Stenberg <daniel@haxx.se> | 2007-05-30 21:11:10 +0000 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2007-05-30 21:11:10 +0000 |
commit | 7a77f24d26f755421b91a0ea3852b6348d637861 (patch) | |
tree | 9c844a8c94f38eadb15c554e570db4e0daebf638 /ares_query.c | |
parent | f1440b240528afe3dfc03256d92b49acb4ef8537 (diff) | |
download | c-ares-7a77f24d26f755421b91a0ea3852b6348d637861.tar.gz c-ares-7a77f24d26f755421b91a0ea3852b6348d637861.tar.bz2 c-ares-7a77f24d26f755421b91a0ea3852b6348d637861.zip |
Shmulik Regev brought cryptographically secure transaction IDs
Diffstat (limited to 'ares_query.c')
-rw-r--r-- | ares_query.c | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/ares_query.c b/ares_query.c index 742e873..4ca4cf9 100644 --- a/ares_query.c +++ b/ares_query.c @@ -39,6 +39,64 @@ struct qquery { static void qcallback(void *arg, int status, unsigned char *abuf, int alen); +void ares__rc4(rc4_key* key, unsigned char *buffer_ptr, int buffer_len) +{ + unsigned char x; + unsigned char y; + unsigned char* state; + unsigned char xorIndex; + short counter; + + x = key->x; + y = key->y; + + state = &key->state[0]; + for(counter = 0; counter < buffer_len; counter ++) + { + x = (x + 1) % 256; + y = (state[x] + y) % 256; + ARES_SWAP_BYTE(&state[x], &state[y]); + + xorIndex = (state[x] + state[y]) % 256; + + buffer_ptr[counter] ^= state[xorIndex]; + } + key->x = x; + key->y = y; +} + +static struct query* find_query_by_id(ares_channel channel, int id) +{ + int qid; + struct query* q; + DNS_HEADER_SET_QID(((unsigned char*)&qid), id); + + /* Find the query corresponding to this packet. */ + for (q = channel->queries; q; q = q->next) + { + if (q->qid == qid) + return q; + } + return NULL; +} + + +/* a unique query id is generated using an rc4 key. Since the id may already + be used by a running query (as infrequent as it may be), a lookup is + performed per id generation. In practice this search should happen only + once per newly generated id +*/ +static int generate_unique_id(ares_channel channel) +{ + int id; + + do { + id = ares__generate_new_id(&channel->id_key); + } while (find_query_by_id(channel,id)); + + return id; +} + void ares_query(ares_channel channel, const char *name, int dnsclass, int type, ares_callback callback, void *arg) { @@ -50,7 +108,8 @@ void ares_query(ares_channel channel, const char *name, int dnsclass, rd = !(channel->flags & ARES_FLAG_NORECURSE); status = ares_mkquery(name, dnsclass, type, channel->next_id, rd, &qbuf, &qlen); - channel->next_id++; + channel->next_id = generate_unique_id(channel); + if (status != ARES_SUCCESS) { callback(arg, status, NULL, 0); |