Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <auth.h>
4
#include <libsec.h>
5
#include <bio.h>
6
#include "imap4d.h"
7
 
8
/*
9
 * hack to allow smtp forwarding.
10
 * hide the peer IP address under a rock in the ratifier FS.
11
 */
12
void
13
enableForwarding(void)
14
{
15
	char buf[64], peer[64], *p;
16
	static ulong last;
17
	ulong now;
18
	int fd;
19
 
20
	if(remote == nil)
21
		return;
22
 
23
	now = time(0);
24
	if(now < last + 5*60)
25
		return;
26
	last = now;
27
 
28
	fd = open("/srv/ratify", ORDWR);
29
	if(fd < 0)
30
		return;
31
	if(!mount(fd, -1, "/mail/ratify", MBEFORE, "")){
32
		close(fd);
33
		return;
34
	}
35
	close(fd);
36
 
37
	strncpy(peer, remote, sizeof(peer));
38
	peer[sizeof(peer) - 1] = '\0';
39
	p = strchr(peer, '!');
40
	if(p != nil)
41
		*p = '\0';
42
 
43
	snprint(buf, sizeof(buf), "/mail/ratify/trusted/%s#32", peer);
44
 
45
	/*
46
	 * if the address is already there and the user owns it,
47
	 * remove it and recreate it to give him a new time quanta.
48
	 */
49
	if(access(buf, 0) >= 0 && remove(buf) < 0)
50
		return;
51
 
52
	fd = create(buf, OREAD, 0666);
53
	if(fd >= 0)
54
		close(fd);
55
}
56
 
57
void
58
setupuser(AuthInfo *ai)
59
{
60
	Waitmsg *w;
61
	int pid;
62
 
63
	if(ai){
64
		strecpy(username, username+sizeof username, ai->cuid);
65
 
66
		if(auth_chuid(ai, nil) < 0)
67
			bye("user auth failed: %r");
68
		auth_freeAI(ai);
69
	}else
70
		strecpy(username, username+sizeof username, getuser());
71
 
72
	if(newns(username, 0) < 0)
73
		bye("user login failed: %r");
74
 
75
	/*
76
	 * hack to allow access to outgoing smtp forwarding
77
	 */
78
	enableForwarding();
79
 
80
	snprint(mboxDir, MboxNameLen, "/mail/box/%s", username);
81
	if(myChdir(mboxDir) < 0)
82
		bye("can't open user's mailbox");
83
 
84
	switch(pid = fork()){
85
	case -1:
86
		bye("can't initialize mail system");
87
		break;
88
	case 0:
89
		execl("/bin/upas/fs", "upas/fs", "-np", nil);
90
_exits("rob1");
91
		_exits(0);
92
		break;
93
	default:
94
		break;
95
	}
96
	if((w=wait()) == nil || w->pid != pid || w->msg[0] != '\0')
97
		bye("can't initialize mail system");
98
	free(w);
99
}
100
 
101
static char*
102
authresp(void)
103
{
104
	char *s, *t;
105
	int n;
106
 
107
	t = Brdline(&bin, '\n');
108
	n = Blinelen(&bin);
109
	if(n < 2)
110
		return nil;
111
	n--;
112
	if(t[n-1] == '\r')
113
		n--;
114
	t[n] = '\0';
115
	if(n == 0 || strcmp(t, "*") == 0)
116
		return nil;
117
 
118
	s = binalloc(&parseBin, n + 1, 0);
119
	n = dec64((uchar*)s, n, t, n);
120
	s[n] = '\0';
121
	return s;
122
}
123
 
124
/*
125
 * rfc 2195 cram-md5 authentication
126
 */
127
char*
128
cramauth(void)
129
{
130
	AuthInfo *ai;
131
	Chalstate *cs;
132
	char *s, *t;
133
	int n;
134
 
135
	if((cs = auth_challenge("proto=cram role=server")) == nil)
136
		return "couldn't get cram challenge";
137
 
138
	n = cs->nchal;
139
	s = binalloc(&parseBin, n * 2, 0);
140
	n = enc64(s, n * 2, (uchar*)cs->chal, n);
141
	Bprint(&bout, "+ ");
142
	Bwrite(&bout, s, n);
143
	Bprint(&bout, "\r\n");
144
	if(Bflush(&bout) < 0)
145
		writeErr();
146
 
147
	s = authresp();
148
	if(s == nil)
149
		return "client cancelled authentication";
150
 
151
	t = strchr(s, ' ');
152
	if(t == nil)
153
		bye("bad auth response");
154
	*t++ = '\0';
155
	strncpy(username, s, UserNameLen);
156
	username[UserNameLen-1] = '\0';
157
 
158
	cs->user = username;
159
	cs->resp = t;
160
	cs->nresp = strlen(t);
161
	if((ai = auth_response(cs)) == nil)
162
		return "login failed";
163
	auth_freechal(cs);
164
	setupuser(ai);
165
	return nil;
166
}
167
 
168
AuthInfo*
169
passLogin(char *user, char *secret)
170
{
171
	AuthInfo *ai;
172
	Chalstate *cs;
173
	uchar digest[MD5dlen];
174
	char response[2*MD5dlen+1];
175
	int i;
176
 
177
	if((cs = auth_challenge("proto=cram role=server")) == nil)
178
		return nil;
179
 
180
	hmac_md5((uchar*)cs->chal, strlen(cs->chal),
181
		(uchar*)secret, strlen(secret), digest,
182
		nil);
183
	for(i = 0; i < MD5dlen; i++)
184
		snprint(response + 2*i, sizeof(response) - 2*i, "%2.2ux", digest[i]);
185
 
186
	cs->user = user;
187
	cs->resp = response;
188
	cs->nresp = strlen(response);
189
	ai = auth_response(cs);
190
	auth_freechal(cs);
191
	return ai;
192
}