Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_unix/sys/src/cmd/auth/factotum/httpdigest.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * HTTPDIGEST - MD5 challenge/response authentication (RFC 2617)
3
 *
4
 * Client protocol:
5
 *	write challenge: nonce method uri 
6
 *	read response: 2*MD5dlen hex digits
7
 *
8
 * Server protocol:
9
 *	unimplemented
10
 */
11
#include "dat.h"
12
 
13
enum
14
{
15
	CNeedChal,
16
	CHaveResp,
17
 
18
	Maxphase,
19
};
20
 
21
static char *phasenames[Maxphase] = {
22
[CNeedChal]	"CNeedChal",
23
[CHaveResp]	"CHaveResp",
24
};
25
 
26
struct State
27
{
28
	char resp[MD5dlen*2+1];
29
};
30
 
31
static int
32
hdinit(Proto *p, Fsstate *fss)
33
{
34
	int iscli;
35
	State *s;
36
 
37
	if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)
38
		return failure(fss, nil);
39
	if(!iscli)
40
		return failure(fss, "%s server not supported", p->name);
41
 
42
	s = emalloc(sizeof *s);
43
	fss->phasename = phasenames;
44
	fss->maxphase = Maxphase;
45
	fss->phase = CNeedChal;
46
	fss->ps = s;
47
	return RpcOk;
48
}
49
 
50
static void
51
strtolower(char *s)
52
{
53
	while(*s){
54
		*s = tolower(*s);
55
		s++;
56
	}
57
}
58
 
59
static void
60
digest(char *user, char *realm, char *passwd,
61
	char *nonce, char *method, char *uri,
62
	char *dig)
63
{
64
	uchar b[MD5dlen];
65
	char ha1[MD5dlen*2+1];
66
	char ha2[MD5dlen*2+1];
67
	DigestState *s;
68
 
69
	/*
70
	 *  H(A1) = MD5(uid + ":" + realm ":" + passwd)
71
	 */
72
	s = md5((uchar*)user, strlen(user), nil, nil);
73
	md5((uchar*)":", 1, nil, s);
74
	md5((uchar*)realm, strlen(realm), nil, s);
75
	md5((uchar*)":", 1, nil, s);
76
	md5((uchar*)passwd, strlen(passwd), b, s);
77
	enc16(ha1, sizeof(ha1), b, MD5dlen);
78
	strtolower(ha1);
79
 
80
	/*
81
	 *  H(A2) = MD5(method + ":" + uri)
82
	 */
83
	s = md5((uchar*)method, strlen(method), nil, nil);
84
	md5((uchar*)":", 1, nil, s);
85
	md5((uchar*)uri, strlen(uri), b, s);
86
	enc16(ha2, sizeof(ha2), b, MD5dlen);
87
	strtolower(ha2);
88
 
89
	/*
90
	 *  digest = MD5(H(A1) + ":" + nonce + ":" + H(A2))
91
	 */
92
	s = md5((uchar*)ha1, MD5dlen*2, nil, nil);
93
	md5((uchar*)":", 1, nil, s);
94
	md5((uchar*)nonce, strlen(nonce), nil, s);
95
	md5((uchar*)":", 1, nil, s);
96
	md5((uchar*)ha2, MD5dlen*2, b, s);
97
	enc16(dig, MD5dlen*2+1, b, MD5dlen);
98
	strtolower(dig);
99
}
100
 
101
static int
102
hdwrite(Fsstate *fss, void *va, uint n)
103
{
104
	State *s;
105
	int ret;
106
	char *a, *p, *r, *u, *t;
107
	char *tok[4];
108
	Key *k;
109
	Keyinfo ki;
110
	Attr *attr;
111
 
112
	s = fss->ps;
113
	a = va;
114
 
115
	if(fss->phase != CNeedChal)
116
		return phaseerror(fss, "write");
117
 
118
	attr = _delattr(_copyattr(fss->attr), "role");
119
	mkkeyinfo(&ki, fss, attr);
120
	ret = findkey(&k, &ki, "%s", fss->proto->keyprompt);
121
	_freeattr(attr);
122
	if(ret != RpcOk)
123
		return ret;
124
	p = _strfindattr(k->privattr, "!password");
125
	if(p == nil)
126
		return failure(fss, "key has no password");
127
	r = _strfindattr(k->attr, "realm");
128
	if(r == nil)
129
		return failure(fss, "key has no realm");
130
	u = _strfindattr(k->attr, "user");
131
	if(u == nil)
132
		return failure(fss, "key has no user");
133
	setattrs(fss->attr, k->attr);
134
 
135
	/* copy in case a is not null-terminated */
136
	t = emalloc(n+1);
137
	memcpy(t, a, n);
138
	t[n] = 0;
139
 
140
	/* get nonce, method, uri */
141
	if(tokenize(t, tok, 4) != 3)
142
		return failure(fss, "bad challenge");
143
 
144
	digest(u, r, p, tok[0], tok[1], tok[2], s->resp);
145
 
146
	free(t);
147
	closekey(k);
148
	fss->phase = CHaveResp;
149
	return RpcOk;
150
}
151
 
152
static int
153
hdread(Fsstate *fss, void *va, uint *n)
154
{
155
	State *s;
156
 
157
	s = fss->ps;
158
	if(fss->phase != CHaveResp)
159
		return phaseerror(fss, "read");
160
	if(*n > strlen(s->resp))
161
		*n = strlen(s->resp);
162
	memmove(va, s->resp, *n);
163
	fss->phase = Established;
164
	fss->haveai = 0;
165
	return RpcOk;
166
}
167
 
168
static void
169
hdclose(Fsstate *fss)
170
{
171
	State *s;
172
	s = fss->ps;
173
	free(s);
174
}
175
 
176
Proto httpdigest = {
177
.name=		"httpdigest",
178
.init=		hdinit,
179
.write=		hdwrite,
180
.read=		hdread,
181
.close=		hdclose,
182
.addkey=	replacekey,
183
.keyprompt=	"user? realm? !password?"
184
};