Subversion Repositories planix.SVN

Rev

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

Rev Author Line No. Line
2 - 1
/*
2
 * as user cmd [arg...] - run cmd with args as user on this cpu server.
3
 *	must be hostowner for this to work.
4
 *	needs #¤/caphash and #¤/capuse.
5
 */
6
#include <u.h>
7
#include <libc.h>
8
#include <bio.h>
9
#include <libsec.h>
10
#include <auth.h>
11
#include "authcmdlib.h"
12
 
13
int	debug;
14
 
15
int	becomeuser(char*);
16
void	createuser(void);
17
void	*emalloc(ulong);
18
void	*erealloc(void*, ulong);
19
void	initcap(void);
20
int	mkcmd(char*, char*, int);
21
int	myauth(int, char*);
22
int	qidcmp(Qid, Qid);
23
void	runas(char *, char *);
24
void	usage(void);
25
 
26
#pragma varargck	argpos clog 1
27
#pragma varargck	argpos fatal 1
28
 
29
static void
30
fatal(char *fmt, ...)
31
{
32
	char msg[256];
33
	va_list arg;
34
 
35
	va_start(arg, fmt);
36
	vseprint(msg, msg + sizeof msg, fmt, arg);
37
	va_end(arg);
38
	error("%s", msg);
39
}
40
 
41
void
42
main(int argc, char *argv[])
43
{
44
	debug = 0;
45
	ARGBEGIN{
46
	case 'd':
47
		debug = 1;
48
		break;
49
	default:
50
		usage();
51
	}ARGEND
52
 
53
	initcap();
54
	srand(getpid()*time(0));
55
	runas(argv[0], argv[1]);
56
}
57
 
58
void
59
runas(char *user, char *cmd)
60
{
61
	if(becomeuser(user) < 0)
62
		sysfatal("can't change uid for %s: %r", user);
63
	putenv("service", "rx");
64
	execl("/bin/rc", "rc", "-lc", cmd, nil);
65
	sysfatal("exec /bin/rc: %r");
66
}
67
 
68
void *
69
emalloc(ulong n)
70
{
71
	void *p;
72
 
73
	if(p = mallocz(n, 1))
74
		return p;
75
	fatal("out of memory");
76
	return 0;
77
}
78
 
79
void *
80
erealloc(void *p, ulong n)
81
{
82
	if(p = realloc(p, n))
83
		return p;
84
	fatal("out of memory");
85
	return 0;
86
}
87
 
88
void
89
usage(void)
90
{
91
	fprint(2, "usage: %s [-c]\n", argv0);
92
	exits("usage");
93
}
94
 
95
void
96
memrandom(void *p, int n)
97
{
98
	uchar *cp;
99
 
100
	for(cp = (uchar*)p; n > 0; n--)
101
		*cp++ = fastrand();
102
}
103
 
104
/*
105
 *  keep caphash fd open since opens of it could be disabled
106
 */
107
static int caphashfd;
108
 
109
void
110
initcap(void)
111
{
112
	caphashfd = open("#¤/caphash", OCEXEC|OWRITE);
113
	if(caphashfd < 0)
114
		fprint(2, "%s: opening #¤/caphash: %r\n", argv0);
115
}
116
 
117
/*
118
 *  create a change uid capability 
119
 */
120
char*
121
mkcap(char *from, char *to)
122
{
123
	uchar rand[20];
124
	char *cap;
125
	char *key;
126
	int nfrom, nto, ncap;
127
	uchar hash[SHA1dlen];
128
 
129
	if(caphashfd < 0)
130
		return nil;
131
 
132
	/* create the capability */
133
	nto = strlen(to);
134
	nfrom = strlen(from);
135
	ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1;
136
	cap = emalloc(ncap);
137
	snprint(cap, ncap, "%s@%s", from, to);
138
	memrandom(rand, sizeof(rand));
139
	key = cap+nfrom+1+nto+1;
140
	enc64(key, sizeof(rand)*3, rand, sizeof(rand));
141
 
142
	/* hash the capability */
143
	hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil);
144
 
145
	/* give the kernel the hash */
146
	key[-1] = '@';
147
	if(write(caphashfd, hash, SHA1dlen) < 0){
148
		free(cap);
149
		return nil;
150
	}
151
 
152
	return cap;
153
}
154
 
155
int
156
usecap(char *cap)
157
{
158
	int fd, rv;
159
 
160
	fd = open("#¤/capuse", OWRITE);
161
	if(fd < 0)
162
		return -1;
163
	rv = write(fd, cap, strlen(cap));
164
	close(fd);
165
	return rv;
166
}
167
 
168
int
169
becomeuser(char *new)
170
{
171
	char *cap;
172
	int rv;
173
 
174
	cap = mkcap(getuser(), new);
175
	if(cap == nil)
176
		return -1;
177
	rv = usecap(cap);
178
	free(cap);
179
 
180
	newns(new, nil);
181
	return rv;
182
}