2018-01-06 01:08:25 +01:00
|
|
|
/*
|
|
|
|
* This file is part of the UCB release of Plan 9. It is subject to the license
|
|
|
|
* terms in the LICENSE file found in the top-level directory of this
|
|
|
|
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
|
|
|
|
* part of the UCB release of Plan 9, including this file, may be copied,
|
|
|
|
* modified, propagated, or distributed except according to the terms contained
|
|
|
|
* in the LICENSE file.
|
|
|
|
*/
|
|
|
|
/* Portions of this file are Copyright (C) 2015-2018 Giacomo Tesio <giacomo@tesio.it>
|
|
|
|
* See /doc/license/gpl-2.0.txt for details about the licensing.
|
|
|
|
*/
|
|
|
|
|
2016-11-25 17:18:40 +01:00
|
|
|
#include <u.h>
|
2017-04-19 23:33:14 +02:00
|
|
|
#include <lib9.h>
|
2017-10-20 00:55:05 +02:00
|
|
|
#include <envvars.h>
|
2016-11-25 17:18:40 +01:00
|
|
|
#include <auth.h>
|
|
|
|
#include <authsrv.h>
|
|
|
|
#include <bio.h>
|
|
|
|
#include <ndb.h>
|
|
|
|
|
|
|
|
char *authdom;
|
|
|
|
|
|
|
|
void
|
|
|
|
readln(char *prompt, char *line, int len, int raw)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
int fdin, fdout, ctl, n, nr;
|
|
|
|
|
|
|
|
fdin = open("/dev/cons", OREAD);
|
|
|
|
fdout = open("/dev/cons", OWRITE);
|
|
|
|
fprint(fdout, "%s", prompt);
|
|
|
|
if(raw){
|
|
|
|
ctl = open("/dev/consctl", OWRITE);
|
|
|
|
if(ctl < 0){
|
|
|
|
fprint(2, "login: couldn't set raw mode");
|
|
|
|
exits("readln");
|
|
|
|
}
|
|
|
|
write(ctl, "rawon", 5);
|
|
|
|
} else
|
|
|
|
ctl = -1;
|
|
|
|
nr = 0;
|
|
|
|
p = line;
|
|
|
|
for(;;){
|
|
|
|
n = read(fdin, p, 1);
|
|
|
|
if(n < 0){
|
|
|
|
close(ctl);
|
|
|
|
close(fdin);
|
|
|
|
close(fdout);
|
|
|
|
fprint(2, "login: can't read cons");
|
|
|
|
exits("readln");
|
|
|
|
}
|
|
|
|
if(*p == 0x7f)
|
|
|
|
exits(0);
|
|
|
|
if(n == 0 || *p == '\n' || *p == '\r'){
|
|
|
|
*p = '\0';
|
|
|
|
if(raw){
|
|
|
|
write(ctl, "rawoff", 6);
|
|
|
|
write(fdout, "\n", 1);
|
|
|
|
}
|
|
|
|
close(ctl);
|
|
|
|
close(fdin);
|
|
|
|
close(fdout);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(*p == '\b'){
|
|
|
|
if(nr > 0){
|
|
|
|
nr--;
|
|
|
|
p--;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
nr++;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if(nr == len){
|
|
|
|
fprint(fdout, "line too int32_t; try again\n");
|
|
|
|
nr = 0;
|
|
|
|
p = line;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setenv(char *var, char *val)
|
|
|
|
{
|
|
|
|
int fd;
|
2017-10-20 00:55:05 +02:00
|
|
|
char buf[128+4];
|
2016-11-25 17:18:40 +01:00
|
|
|
|
2017-10-20 00:55:05 +02:00
|
|
|
snprint(buf, sizeof(buf), "#e/%s", var);
|
|
|
|
fd = ocreate(buf, OWRITE, 0644);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(fd < 0)
|
2017-10-20 00:55:05 +02:00
|
|
|
print("init: can't open %s\n", buf);
|
2016-11-25 17:18:40 +01:00
|
|
|
else{
|
|
|
|
fprint(fd, val);
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* become the authenticated user
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
chuid(AuthInfo *ai)
|
|
|
|
{
|
|
|
|
int rv, fd;
|
|
|
|
|
|
|
|
/* change uid */
|
|
|
|
fd = open("#¤/capuse", OWRITE);
|
|
|
|
if(fd < 0)
|
|
|
|
sysfatal("can't change uid: %r");
|
|
|
|
rv = write(fd, ai->cap, strlen(ai->cap));
|
|
|
|
close(fd);
|
|
|
|
if(rv < 0)
|
|
|
|
sysfatal("can't change uid: %r");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* mount a factotum
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
mountfactotum(char *srvname)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
/* mount it */
|
|
|
|
fd = open(srvname, ORDWR);
|
|
|
|
if(fd < 0)
|
|
|
|
sysfatal("opening factotum: %r");
|
2016-12-01 00:09:42 +01:00
|
|
|
mount(fd, -1, "/mnt", MBEFORE, "", '9');
|
2016-11-25 17:18:40 +01:00
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* find authdom
|
|
|
|
*/
|
|
|
|
char*
|
|
|
|
getauthdom(void)
|
|
|
|
{
|
|
|
|
char *sysname, *s;
|
|
|
|
Ndbtuple *t, *p;
|
|
|
|
|
|
|
|
if(authdom != nil)
|
|
|
|
return authdom;
|
|
|
|
|
2017-10-20 00:55:05 +02:00
|
|
|
sysname = getenv(ENV_SYSNAME);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(sysname == nil)
|
|
|
|
return strdup("cs.bell-labs.com");
|
|
|
|
|
|
|
|
s = "authdom";
|
|
|
|
t = csipinfo(nil, "sys", sysname, &s, 1);
|
|
|
|
free(sysname);
|
|
|
|
for(p = t; p != nil; p = p->entry)
|
|
|
|
if(strcmp(p->attr, s) == 0){
|
|
|
|
authdom = strdup(p->val);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ndbfree(t);
|
|
|
|
fprint(2, "authdom=%s\n", authdom);
|
|
|
|
return authdom;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* start a new factotum and pass it the username and password
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
startfactotum(char *user, char *password, char *srvname)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
strcpy(srvname, "/srv/factotum.XXXXXXXXXXX");
|
|
|
|
mktemp(srvname);
|
|
|
|
|
|
|
|
switch(fork()){
|
|
|
|
case -1:
|
|
|
|
sysfatal("can't start factotum: %r");
|
|
|
|
case 0:
|
|
|
|
execl("/boot/factotum", "loginfactotum", "-ns", srvname+5, nil);
|
|
|
|
sysfatal("starting factotum: %r");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* wait for agent to really be there */
|
2016-12-01 00:09:42 +01:00
|
|
|
while(access(srvname, AEXIST) < 0)
|
2016-11-25 17:18:40 +01:00
|
|
|
sleep(250);
|
|
|
|
|
|
|
|
/* mount it */
|
|
|
|
mountfactotum(srvname);
|
|
|
|
|
|
|
|
/* write in new key */
|
|
|
|
fd = open("/mnt/factotum/ctl", ORDWR);
|
|
|
|
if(fd < 0)
|
|
|
|
sysfatal("opening factotum: %r");
|
|
|
|
fprint(fd, "key proto=p9sk1 dom=%s user=%q !password=%q", getauthdom(), user, password);
|
|
|
|
close(fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
usage(void)
|
|
|
|
{
|
|
|
|
fprint(2, "usage: %s [-a authdom] user\n", argv0);
|
|
|
|
exits("");
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
char pass[ANAMELEN];
|
|
|
|
char buf[2*ANAMELEN];
|
|
|
|
char home[2*ANAMELEN];
|
|
|
|
char srvname[2*ANAMELEN];
|
|
|
|
char *user, *sysname, *tz, *cputype, *service;
|
|
|
|
AuthInfo *ai;
|
|
|
|
|
|
|
|
ARGBEGIN{
|
|
|
|
case 'a':
|
|
|
|
authdom = EARGF(usage());
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
usage();
|
|
|
|
break;
|
|
|
|
}ARGEND;
|
|
|
|
|
|
|
|
if(argc != 1)
|
|
|
|
usage();
|
|
|
|
|
|
|
|
rfork(RFENVG|RFNAMEG);
|
|
|
|
|
2017-10-20 00:55:05 +02:00
|
|
|
service = getenv(ENV_SERVICE);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(strcmp(service, "cpu") == 0)
|
|
|
|
fprint(2, "login: warning: running on a cpu server!\n");
|
|
|
|
if(argc != 1){
|
|
|
|
fprint(2, "usage: login username\n");
|
|
|
|
exits("usage");
|
|
|
|
}
|
|
|
|
user = argv[0];
|
|
|
|
memset(pass, 0, sizeof(pass));
|
|
|
|
readln("Password: ", pass, sizeof(pass), 1);
|
|
|
|
|
|
|
|
/* authenticate */
|
|
|
|
ai = auth_userpasswd(user, pass);
|
|
|
|
if(ai == nil || ai->cap == nil)
|
|
|
|
sysfatal("login incorrect");
|
|
|
|
|
|
|
|
/* change uid */
|
|
|
|
chuid(ai);
|
|
|
|
|
|
|
|
/* start a new factotum and hand it a new key */
|
|
|
|
startfactotum(user, pass, srvname);
|
|
|
|
|
|
|
|
/* set up new namespace */
|
|
|
|
newns(ai->cuid, nil);
|
|
|
|
auth_freeAI(ai);
|
|
|
|
|
|
|
|
/* remount the factotum */
|
|
|
|
mountfactotum(srvname);
|
|
|
|
|
|
|
|
/* set up a new environment */
|
2017-10-20 00:55:05 +02:00
|
|
|
cputype = getenv(ENV_CPUTYPE);
|
|
|
|
sysname = getenv(ENV_SYSNAME);
|
2016-11-25 17:18:40 +01:00
|
|
|
tz = getenv("timezone");
|
|
|
|
rfork(RFCENVG);
|
2017-10-20 00:55:05 +02:00
|
|
|
setenv(ENV_SERVICE, "con");
|
|
|
|
setenv(ENV_USER, user);
|
2016-11-25 17:18:40 +01:00
|
|
|
snprint(home, sizeof(home), "/usr/%s", user);
|
2017-10-20 00:55:05 +02:00
|
|
|
setenv(ENV_HOME, home);
|
|
|
|
setenv(ENV_CPUTYPE, cputype);
|
|
|
|
setenv(ENV_OBJTYPE, cputype);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(sysname != nil)
|
2017-10-20 00:55:05 +02:00
|
|
|
setenv(ENV_SYSNAME, sysname);
|
2016-11-25 17:18:40 +01:00
|
|
|
if(tz != nil)
|
2017-10-20 00:55:05 +02:00
|
|
|
setenv("timezone", tz);
|
2016-11-25 17:18:40 +01:00
|
|
|
|
|
|
|
/* go to new home directory */
|
2017-10-20 00:55:05 +02:00
|
|
|
if(chdir(home) < 0)
|
2016-11-25 17:18:40 +01:00
|
|
|
chdir("/");
|
|
|
|
|
|
|
|
/* read profile and start interactive rc */
|
|
|
|
execl("/bin/rc", "rc", "-li", nil);
|
|
|
|
exits(0);
|
|
|
|
}
|