[go: up one dir, main page]

File: link_auth.c

package info (click to toggle)
cctools 9.9-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 44,624 kB
  • sloc: ansic: 192,539; python: 20,827; cpp: 20,199; sh: 11,719; perl: 4,106; xml: 3,688; makefile: 1,224
file content (112 lines) | stat: -rw-r--r-- 3,530 bytes parent folder | download | duplicates (3)
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
Copyright (C) 2013- The University of Notre Dame
This software is distributed under the GNU General Public License.
See the file COPYING for details.
*/

#include "link_auth.h"
#include "link.h"
#include "debug.h"
#include "stringtools.h"
#include "sha1.h"
#include "full_io.h"

#include <string.h>

/*
This function performs a simple hash-based verification
that the other side is holding the same password without
transmitting it in the clear.

server:           generate random key SK
server -> client: SK
client:           generate random key CK
client -> server: CK
server -> client: SHA1(P+CK)
client:           verify SHA1(P+CK) is correct.
client -> server  SHA1(P+SK)
server:           verify SHA(P+SK) is correct.

Note that the protocol is symmetric, so the same code
works for either side.
*/

#define RANDOM_KEY_LENGTH 64
#define LINK_AUTH_LINE_MAX 1024

static const char *auth_password_ident = "auth password sha1";

int link_auth_password( struct link *link, const char *password, time_t stoptime )
{
	int peer_authenticated = 0;
	int self_authenticated = 0;

	// Verify we are using the same procedure.
	char line[LINK_AUTH_LINE_MAX];
	link_putfstring(link,"%s\n",stoptime,auth_password_ident);
	link_readline(link,line,sizeof(line),stoptime);
	if(strcmp(line,auth_password_ident)) {
		debug(D_AUTH,"peer is not using password authentication.\n");
		return 0;
	}

	// Generate and send my challenge string
	debug(D_AUTH,"sending challenge data");
	char my_random_key[LINK_AUTH_LINE_MAX];
	string_cookie(my_random_key,RANDOM_KEY_LENGTH);
	link_putfstring(link,"%s\n",stoptime,my_random_key);

	// Read and parse the peer's random key.
	debug(D_AUTH,"receiving peer's challenge data");
	char peer_random_key[LINK_AUTH_LINE_MAX];
	if(!link_readline(link,peer_random_key,sizeof(peer_random_key),stoptime)) goto failure;

	// Compute and send SHA1( password + peer_random_key )
	debug(D_AUTH,"sending my response");
	char my_response[LINK_AUTH_LINE_MAX*2+1];
	unsigned char digest[SHA1_DIGEST_LENGTH];
	sprintf(my_response,"%s %s",password,peer_random_key);
	sha1_buffer(my_response,strlen(my_response),digest);
	link_putfstring(link,"%s\n",stoptime,sha1_string(digest));

	// Compute the expected value of SHA1( password + my_random_key )
	char expected_response[LINK_AUTH_LINE_MAX*2+1];
	sprintf(expected_response,"%s %s",password,my_random_key);
	sha1_buffer(expected_response,strlen(expected_response),digest);
	strcpy(expected_response,sha1_string(digest));

	// Get the peer's actual response.
	debug(D_AUTH,"getting peer's response");
	char actual_response[LINK_AUTH_LINE_MAX];
	if(!link_readline(link,actual_response,sizeof(actual_response),stoptime)) goto failure;

	// Send back whether we accept it or not, for troubleshooting
	if(!strcmp(expected_response,actual_response)) {
		debug(D_AUTH,"peer sent correct response");
		link_putstring(link,"ok\n",stoptime);
		peer_authenticated = 1;
	} else {
		debug(D_AUTH,"peer did not send correct response");
		link_putstring(link,"failure\n",stoptime);
		peer_authenticated = 0;
	}

	// Read back whether the peer accepted ours or not.
	if(!link_readline(link,line,sizeof(line),stoptime)) goto failure;
	if(!strcmp(line,"ok")) {
		debug(D_AUTH,"peer accepted my response");
		self_authenticated = 1;
	} else {
		debug(D_AUTH,"peer did not accept my response");
		self_authenticated = 0;
	}

	return (peer_authenticated && self_authenticated);

	failure:
	debug(D_AUTH,"failed to read response from peer");
	return 0;
}


/* vim: set noexpandtab tabstop=4: */