]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/auth/as.c
ndb/dns: remove single-ip-address assuptions
[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 <authsrv.h>
12 #include "authcmdlib.h"
13
14 extern int newnsdebug;
15
16 char    *defargv[] = { "/bin/rc", "-i", nil };
17 char    *namespace = nil;
18
19 int     becomeuser(char*);
20
21 void
22 usage(void)
23 {
24         fprint(2, "usage: %s [-d] [-n namespace] user [cmd [args...]]\n", argv0);
25         exits("usage");
26 }
27
28 void
29 run(char **a)
30 {
31         exec(a[0], a);
32
33         if(a[0][0] != '/' && a[0][0] != '#' &&
34           (a[0][0] != '.' || (a[0][1] != '/' &&
35                              (a[0][1] != '.' ||  a[0][2] != '/'))))
36                 exec(smprint("/bin/%s", a[0]), a);
37
38         sysfatal("exec: %s: %r", a[0]);
39 }
40
41 void
42 main(int argc, char *argv[])
43 {
44         ARGBEGIN{
45         case 'd':
46                 newnsdebug = 1;
47                 break;
48         case 'n':
49                 namespace = EARGF(usage());
50                 break;
51         default:
52                 usage();
53         }ARGEND
54
55         if(argc == 0)
56                 usage();
57
58         if(becomeuser(argv[0]) < 0)
59                 sysfatal("can't change uid for %s: %r", argv[0]);
60         if(newns(argv[0], namespace) < 0)
61                 sysfatal("can't build namespace: %r");
62
63         argv++;
64         if(--argc == 0)
65                 argv = defargv;
66
67         run(argv);
68 }
69
70 /*
71  *  create a change uid capability 
72  */
73 char*
74 mkcap(char *from, char *to)
75 {
76         uchar rand[20];
77         char *cap;
78         char *key;
79         int nfrom, nto;
80         uchar hash[SHA1dlen];
81         int fd;
82
83         fd = open("#¤/caphash", OCEXEC|OWRITE);
84         if(fd < 0)
85                 return nil;
86
87         /* create the capability */
88         nto = strlen(to);
89         nfrom = strlen(from);
90         cap = malloc(nfrom+1+nto+1+sizeof(rand)*3+1);
91         if(cap == nil)
92                 sysfatal("malloc: %r");
93         sprint(cap, "%s@%s", from, to);
94         genrandom(rand, sizeof(rand));
95         key = cap+nfrom+1+nto+1;
96         enc64(key, sizeof(rand)*3, rand, sizeof(rand));
97
98         /* hash the capability */
99         hmac_sha1((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil);
100
101         /* give the kernel the hash */
102         key[-1] = '@';
103         if(write(fd, hash, SHA1dlen) < 0){
104                 close(fd);
105                 free(cap);
106                 return nil;
107         }
108         close(fd);
109
110         return cap;
111 }
112
113 int
114 usecap(char *cap)
115 {
116         int fd, rv;
117
118         fd = open("#¤/capuse", OWRITE);
119         if(fd < 0)
120                 return -1;
121         rv = write(fd, cap, strlen(cap));
122         close(fd);
123         return rv;
124 }
125
126 int
127 becomeuser(char *new)
128 {
129         char *cap;
130         int rv;
131
132         cap = mkcap(getuser(), new);
133         if(cap == nil)
134                 return -1;
135         rv = usecap(cap);
136         free(cap);
137         return rv;
138 }