]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/auth/as.c
9bootfat: rename open() to fileinit and make it static as its really a internal funct...
[plan9front.git] / sys / src / cmd / auth / as.c
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;
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         cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1);
136         sprint(cap, "%s@%s", from, to);
137         memrandom(rand, sizeof(rand));
138         key = cap+nfrom+1+nto+1;
139         enc64(key, sizeof(rand)*3, rand, sizeof(rand));
140
141         /* hash the capability */
142         hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil);
143
144         /* give the kernel the hash */
145         key[-1] = '@';
146         if(write(caphashfd, hash, SHA1dlen) < 0){
147                 free(cap);
148                 return nil;
149         }
150
151         return cap;
152 }
153
154 int
155 usecap(char *cap)
156 {
157         int fd, rv;
158
159         fd = open("#¤/capuse", OWRITE);
160         if(fd < 0)
161                 return -1;
162         rv = write(fd, cap, strlen(cap));
163         close(fd);
164         return rv;
165 }
166
167 int
168 becomeuser(char *new)
169 {
170         char *cap;
171         int rv;
172
173         cap = mkcap(getuser(), new);
174         if(cap == nil)
175                 return -1;
176         rv = usecap(cap);
177         free(cap);
178
179         newns(new, nil);
180         return rv;
181 }