]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/auth/login.c
ndb/dns: remove single-ip-address assuptions
[plan9front.git] / sys / src / cmd / auth / login.c
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <authsrv.h>
5 #include <bio.h>
6 #include <ndb.h>
7
8 char *authdom;
9
10 void
11 setenv(char *var, char *val)
12 {
13         int fd;
14
15         fd = create(var, OWRITE, 0644);
16         if(fd < 0)
17                 print("init: can't open %s\n", var);
18         else{
19                 fprint(fd, val);
20                 close(fd);
21         }
22 }
23
24 /*
25  *  become the authenticated user
26  */
27 void
28 chuid(AuthInfo *ai)
29 {
30         int rv, fd;
31
32         /* change uid */
33         fd = open("#ยค/capuse", OWRITE);
34         if(fd < 0)
35                 sysfatal("can't change uid: %r");
36         rv = write(fd, ai->cap, strlen(ai->cap));
37         close(fd);
38         if(rv < 0)
39                 sysfatal("can't change uid: %r");
40 }
41
42 /*
43  *  mount a factotum
44  */
45 void
46 mountfactotum(char *srvname)
47 {
48         int fd;
49
50         /* mount it */
51         fd = open(srvname, ORDWR);
52         if(fd < 0)
53                 sysfatal("opening factotum: %r");
54         mount(fd, -1, "/mnt", MBEFORE, "");
55         close(fd);
56 }
57
58 /*
59  * find authdom
60  */
61 char*
62 getauthdom(void)
63 {
64         char *sysname, *s;
65         Ndbtuple *t, *p;
66
67         if(authdom != nil)
68                 return authdom;
69
70         sysname = getenv("sysname");
71         if(sysname == nil)
72                 return strdup("cs.bell-labs.com");
73
74         s = "authdom";
75         t = csipinfo(nil, "sys", sysname, &s, 1);
76         free(sysname);
77         for(p = t; p != nil; p = p->entry)
78                 if(strcmp(p->attr, s) == 0){
79                         authdom = strdup(p->val);
80                         break;
81                 }
82         ndbfree(t);
83         return authdom;
84 }
85
86 /*
87  *  start a new factotum and pass it the username and password
88  */
89 void
90 startfactotum(char *user, char *password, char *srvname)
91 {
92         int fd;
93
94         strcpy(srvname, "/srv/factotum.XXXXXXXXXXX");
95         mktemp(srvname);
96
97         switch(fork()){
98         case -1:
99                 sysfatal("can't start factotum: %r");
100         case 0:
101                 execl("/boot/factotum", "loginfactotum", "-ns", srvname+5, nil);
102                 sysfatal("starting factotum: %r");
103                 break;
104         }
105         waitpid();
106
107         /* mount it */
108         mountfactotum(srvname);
109
110         /* write in new key */
111         fd = open("/mnt/factotum/ctl", ORDWR);
112         if(fd < 0)
113                 sysfatal("opening factotum: %r");
114         fprint(fd, "key proto=dp9ik dom=%q user=%q !password=%q\n", getauthdom(), user, password);
115         fprint(fd, "key proto=p9sk1 dom=%q user=%q !password=%q\n", getauthdom(), user, password);
116         close(fd);
117 }
118
119 void
120 usage(void)
121 {
122         fprint(2, "usage: %s [-a authdom] user\n", argv0);
123         exits("");
124 }
125
126 void
127 main(int argc, char *argv[])
128 {
129         char buf[2*ANAMELEN];
130         char home[2*ANAMELEN];
131         char srvname[2*ANAMELEN];
132         char *user, *pass, *sysname, *tz, *cputype, *service;
133         AuthInfo *ai;
134
135         quotefmtinstall();
136
137         ARGBEGIN{
138         case 'a':
139                 authdom = EARGF(usage());
140                 break;
141         default:
142                 usage();
143                 break;
144         }ARGEND;
145
146         if(argc != 1)
147                 usage();
148
149         rfork(RFENVG|RFNAMEG);
150
151         service = getenv("service");
152         if(strcmp(service, "cpu") == 0)
153                 fprint(2, "login: warning: running on a cpu server!\n");
154         if(argc != 1){
155                 fprint(2, "usage: login username\n");
156                 exits("usage");
157         }
158         user = argv[0];
159         pass = readcons("Password", nil, 1);
160         if(pass == nil)
161                 exits("no password");
162
163         /* authenticate */
164         ai = auth_userpasswd(user, pass);
165         if(ai == nil || ai->cap == nil)
166                 sysfatal("login incorrect");
167
168         /* change uid */
169         chuid(ai);
170
171         /* start a new factotum and hand it a new key */
172         startfactotum(user, pass, srvname);
173
174         memset(pass, 0, strlen(pass));
175         free(pass);
176
177         /* set up new namespace */
178         newns(ai->cuid, nil);
179         auth_freeAI(ai);
180
181         /* remount the factotum */
182         mountfactotum(srvname);
183
184         /* get rid of srvname */
185         remove(srvname);
186
187         /* set up a new environment */
188         cputype = getenv("cputype");
189         sysname = getenv("sysname");
190         tz = getenv("timezone");
191         rfork(RFCENVG);
192         setenv("#e/service", "con");
193         setenv("#e/user", user);
194         snprint(home, sizeof(home), "/usr/%s", user);
195         setenv("#e/home", home);
196         setenv("#e/cputype", cputype);
197         setenv("#e/objtype", cputype);
198         if(sysname != nil)
199                 setenv("#e/sysname", sysname);
200         if(tz != nil)
201                 setenv("#e/timezone", tz);
202
203         /* go to new home directory */
204         snprint(buf, sizeof(buf), "/usr/%s", user);
205         if(chdir(buf) < 0)
206                 chdir("/");
207
208         /* read profile and start interactive rc */
209         execl("/bin/rc", "rc", "-li", nil);
210         exits(nil);
211 }