1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include "challenge.h"
#include "options.h"
#include "md5.h"
/* generate_challenge: Generates a random challenge, incorporating the current
* local timestamp to avoid replay attacks.
*/
challenge_t* generate_challenge(void) {
struct timeval tt;
challenge_t *c;
int i;
c = (challenge_t *) calloc(1, sizeof(challenge_t));
gettimeofday(&tt, 0);
c->sec = tt.tv_sec;
c->usec_rnd = tt.tv_usec + rand();
for (i=0;i<6;i++)
c->random[i] = rand();
return c;
}
/* generate_response: Generates a response to the given challenge. The response
* is generated by combining the concatenating the challenge data with the
* md5 digest of the password, and then calculating the MD5 digest of the
* entire buffer. The result is stored in the passed-in challenge, overwriting
* the challenge data.
*/
void generate_response(challenge_t *challenge) {
md5_byte_t buf[sizeof(challenge_t)+kMD5_digest_size];
md5_state_t state;
memcpy(buf, challenge, sizeof(challenge_t));
memcpy(&buf[sizeof(challenge_t)], opts.password_digest, kMD5_digest_size);
memset(challenge, 0, sizeof(challenge_t));
md5_init(&state);
md5_append(&state, buf, sizeof(challenge_t)+kMD5_digest_size);
md5_finish(&state, (md5_byte_t*)challenge);
}
/* validate_challenge: Checks whether a given response matches the expected
* response, returning 1 if validation succeeded, and 0 otherwise. Note that
* overwriting the local challenge with the challenge result is not a problem,
* as the data will not be used again anyway (authentication either succeeds,
* or the connection is closed down).
*/
int validate_challenge(challenge_t *local, challenge_t *remote) {
generate_response(local);
if (memcmp(local, remote, sizeof(challenge_t)) == 0)
return 1;
return 0;
}
|