File: auth.c

package info (click to toggle)
ddns3-client 1.8-5
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 148 kB
  • ctags: 125
  • sloc: ansic: 926; makefile: 52; sh: 52
file content (143 lines) | stat: -rw-r--r-- 3,200 bytes parent folder | download | duplicates (5)
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 *	DDNS v3 Client
 *
 *		Author:		Alan Yates <alany@ay.com.au>
 *		Version:	$Id: auth.c,v 1.1.1.1 2002/07/19 11:47:20 alany Exp $
 */
#define _XOPEN_SOURCE
#ifdef WIN32
#include <windows.h>
#include <process.h>
#else
#include <unistd.h>
#endif
#include <string.h>
#include "ctx.h"
#include "auth.h"
#include "crypto.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static char *ddns3_auth_salts = 
	"abcdefghijklmnopqrstuzwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890./";

static int
auth_plaintext(struct ddns3_ctx *c, char *user, char *passwd) {
	if(!strstr(c->hello, "plaintext")) return -1;

	sprintf(c->buf, "LOGIN %s %s", user, passwd);
	return 0;
}

#ifndef WIN32
static int
auth_crypt(struct ddns3_ctx *c, char *user, char *passwd) {
	char salt[2];
	char *hash;

	if(!strstr(c->hello, "crypt")) return -1;

	srand(getpid() * time(0));
	salt[0] = ddns3_auth_salts[rand() % strlen(ddns3_auth_salts)];
	salt[1] = ddns3_auth_salts[rand() % strlen(ddns3_auth_salts)];
	hash = ddns3_crypto_crypt(passwd, salt);
	sprintf(c->buf, "LOGIN %s %s", user, hash);
	free(hash);
	return 0;
}
#endif

static int
auth_md5(struct ddns3_ctx *c, char *user, char *passwd) {
	char *hash;

	if(!strstr(c->hello, "md5")) return -1;

	hash = ddns3_crypto_md5hash(passwd, strlen(passwd));
	sprintf(c->buf, "LOGIN %s %s", user, hash);
	free(hash);
	return 0;
}

static int
auth_ddns(struct ddns3_ctx *c, char *user, char *passwd) {
	char *hash, *p;
	char buf[4096];

	if(!strstr(c->hello, "ddns")) return -1;

	strcpy(buf, passwd);
	strcat(buf, ":");
	p = strstr(c->hello, "ddns{");
	strncat(buf, p+5, 32);
	hash = ddns3_crypto_md5hash(buf, strlen(buf));
	sprintf(c->buf, "LOGIN %s %s", user, hash);
	free(hash);
	return 0;
}

/* FIXME: there is no server support for strong auth yet */
static int
auth_strong(struct ddns3_ctx *c, char *user, char *passwd) {
	char *phash, *uhash, *challenge, *p;
	char buf[4096];
	int i;

	if(!strstr(c->hello, "ddns")) return -1;

	/* password hash */
	strcpy(buf, passwd);
	strcat(buf, ":");
	p = strstr(c->hello, "ddns{");
	strncat(buf, p+5, 32);
	phash = ddns3_crypto_md5hash(buf, strlen(buf));

	/* random challenge */
	srand(getpid() * time(0));
	for(i = 0; i < 100; i++) buf[i] = rand();
	challenge = ddns3_crypto_md5hash(buf, 100);

	/* username hash */
	strcpy(buf, user);
	strcat(buf, ":");
	strncat(buf, challenge, 32);
	uhash = ddns3_crypto_md5hash(buf, strlen(buf));

	sprintf(c->buf, "LOGIN %s %s %s", uhash, phash, challenge);

	free(uhash);
	free(phash);
	free(challenge);
	return 0;
}


static struct ddns3_auth known_auths[] = {
	{"plaintext",	auth_plaintext},
#ifndef WIN32
	{"crypt",	auth_crypt},
#endif
	{"md5",		auth_md5},
	{"ddns",	auth_ddns},
	{"strong",	auth_strong},
	{0, 0}
};

int
ddns3_auth_makechallenge(struct ddns3_ctx *c, char *auth, char *user, char *passwd) {
	int i;
	int ret = -2;
	
	for(i = 0; known_auths[i].name; i++)
		if(!strcmp(known_auths[i].name, auth)) {
			ret = known_auths[i].makechallenge(c, user, passwd);
			break;
		}
	if(ret < -1)
		strcpy(c->buf, "client_error: authentication type unknown to client\n");
	else if(ret < 0)
		strcpy(c->buf, "client_error: authentication type not supported by server\n");

	return ret;
}