mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
basically none of these build
This commit is contained in:
parent
d9c8a7c536
commit
be8b315d15
19 changed files with 1459 additions and 0 deletions
22
src/libauth/amount.c
Normal file
22
src/libauth/amount.c
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
amount(int fd, char *mntpt, int flags, char *aname)
|
||||||
|
{
|
||||||
|
int rv, afd;
|
||||||
|
AuthInfo *ai;
|
||||||
|
|
||||||
|
afd = fauth(fd, aname);
|
||||||
|
if(afd >= 0){
|
||||||
|
ai = auth_proxy(afd, amount_getkey, "proto=p9any role=client");
|
||||||
|
if(ai != nil)
|
||||||
|
auth_freeAI(ai);
|
||||||
|
}
|
||||||
|
rv = mount(fd, afd, mntpt, flags, aname);
|
||||||
|
if(afd >= 0)
|
||||||
|
close(afd);
|
||||||
|
return rv;
|
||||||
|
}
|
5
src/libauth/amount_getkey.c
Normal file
5
src/libauth/amount_getkey.c
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
|
||||||
|
int (*amount_getkey)(char*) = auth_getkey;
|
174
src/libauth/attr.c
Normal file
174
src/libauth/attr.c
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
_attrfmt(Fmt *fmt)
|
||||||
|
{
|
||||||
|
char *b, buf[1024], *ebuf;
|
||||||
|
Attr *a;
|
||||||
|
|
||||||
|
ebuf = buf+sizeof buf;
|
||||||
|
b = buf;
|
||||||
|
strcpy(buf, " ");
|
||||||
|
for(a=va_arg(fmt->args, Attr*); a; a=a->next){
|
||||||
|
if(a->name == nil)
|
||||||
|
continue;
|
||||||
|
switch(a->type){
|
||||||
|
case AttrQuery:
|
||||||
|
b = seprint(b, ebuf, " %q?", a->name);
|
||||||
|
break;
|
||||||
|
case AttrNameval:
|
||||||
|
b = seprint(b, ebuf, " %q=%q", a->name, a->val);
|
||||||
|
break;
|
||||||
|
case AttrDefault:
|
||||||
|
b = seprint(b, ebuf, " %q:=%q", a->name, a->val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fmtstrcpy(fmt, buf+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr*
|
||||||
|
_copyattr(Attr *a)
|
||||||
|
{
|
||||||
|
Attr **la, *na;
|
||||||
|
|
||||||
|
na = nil;
|
||||||
|
la = &na;
|
||||||
|
for(; a; a=a->next){
|
||||||
|
*la = _mkattr(a->type, a->name, a->val, nil);
|
||||||
|
setmalloctag(*la, getcallerpc(&a));
|
||||||
|
la = &(*la)->next;
|
||||||
|
}
|
||||||
|
*la = nil;
|
||||||
|
return na;
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr*
|
||||||
|
_delattr(Attr *a, char *name)
|
||||||
|
{
|
||||||
|
Attr *fa;
|
||||||
|
Attr **la;
|
||||||
|
|
||||||
|
for(la=&a; *la; ){
|
||||||
|
if(strcmp((*la)->name, name) == 0){
|
||||||
|
fa = *la;
|
||||||
|
*la = (*la)->next;
|
||||||
|
fa->next = nil;
|
||||||
|
_freeattr(fa);
|
||||||
|
}else
|
||||||
|
la=&(*la)->next;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr*
|
||||||
|
_findattr(Attr *a, char *n)
|
||||||
|
{
|
||||||
|
for(; a; a=a->next)
|
||||||
|
if(strcmp(a->name, n) == 0 && a->type != AttrQuery)
|
||||||
|
return a;
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_freeattr(Attr *a)
|
||||||
|
{
|
||||||
|
Attr *anext;
|
||||||
|
|
||||||
|
for(; a; a=anext){
|
||||||
|
anext = a->next;
|
||||||
|
free(a->name);
|
||||||
|
free(a->val);
|
||||||
|
a->name = (void*)~0;
|
||||||
|
a->val = (void*)~0;
|
||||||
|
a->next = (void*)~0;
|
||||||
|
free(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr*
|
||||||
|
_mkattr(int type, char *name, char *val, Attr *next)
|
||||||
|
{
|
||||||
|
Attr *a;
|
||||||
|
|
||||||
|
a = malloc(sizeof(*a));
|
||||||
|
if(a==nil)
|
||||||
|
sysfatal("_mkattr malloc: %r");
|
||||||
|
a->type = type;
|
||||||
|
a->name = strdup(name);
|
||||||
|
a->val = strdup(val);
|
||||||
|
if(a->name==nil || a->val==nil)
|
||||||
|
sysfatal("_mkattr malloc: %r");
|
||||||
|
a->next = next;
|
||||||
|
setmalloctag(a, getcallerpc(&type));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Attr*
|
||||||
|
cleanattr(Attr *a)
|
||||||
|
{
|
||||||
|
Attr *fa;
|
||||||
|
Attr **la;
|
||||||
|
|
||||||
|
for(la=&a; *la; ){
|
||||||
|
if((*la)->type==AttrQuery && _findattr(a, (*la)->name)){
|
||||||
|
fa = *la;
|
||||||
|
*la = (*la)->next;
|
||||||
|
fa->next = nil;
|
||||||
|
_freeattr(fa);
|
||||||
|
}else
|
||||||
|
la=&(*la)->next;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Attr*
|
||||||
|
_parseattr(char *s)
|
||||||
|
{
|
||||||
|
char *p, *t, *tok[256];
|
||||||
|
int i, ntok, type;
|
||||||
|
Attr *a;
|
||||||
|
|
||||||
|
s = strdup(s);
|
||||||
|
if(s == nil)
|
||||||
|
sysfatal("_parseattr strdup: %r");
|
||||||
|
|
||||||
|
ntok = tokenize(s, tok, nelem(tok));
|
||||||
|
a = nil;
|
||||||
|
for(i=ntok-1; i>=0; i--){
|
||||||
|
t = tok[i];
|
||||||
|
if(p = strchr(t, '=')){
|
||||||
|
*p++ = '\0';
|
||||||
|
// if(p-2 >= t && p[-2] == ':'){
|
||||||
|
// p[-2] = '\0';
|
||||||
|
// type = AttrDefault;
|
||||||
|
// }else
|
||||||
|
type = AttrNameval;
|
||||||
|
a = _mkattr(type, t, p, a);
|
||||||
|
setmalloctag(a, getcallerpc(&s));
|
||||||
|
}
|
||||||
|
else if(t[strlen(t)-1] == '?'){
|
||||||
|
t[strlen(t)-1] = '\0';
|
||||||
|
a = _mkattr(AttrQuery, t, "", a);
|
||||||
|
setmalloctag(a, getcallerpc(&s));
|
||||||
|
}else{
|
||||||
|
/* really a syntax error, but better to provide some indication */
|
||||||
|
a = _mkattr(AttrNameval, t, "", a);
|
||||||
|
setmalloctag(a, getcallerpc(&s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(s);
|
||||||
|
return cleanattr(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
_strfindattr(Attr *a, char *n)
|
||||||
|
{
|
||||||
|
a = _findattr(a, n);
|
||||||
|
if(a == nil)
|
||||||
|
return nil;
|
||||||
|
return a->val;
|
||||||
|
}
|
||||||
|
|
13
src/libauth/auth_attr.c
Normal file
13
src/libauth/auth_attr.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include <authsrv.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
Attr*
|
||||||
|
auth_attr(AuthRpc *rpc)
|
||||||
|
{
|
||||||
|
if(auth_rpc(rpc, "attr", nil, 0) != ARok)
|
||||||
|
return nil;
|
||||||
|
return _parseattr(rpc->arg);
|
||||||
|
}
|
117
src/libauth/auth_challenge.c
Normal file
117
src/libauth/auth_challenge.c
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include <authsrv.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
Chalstate*
|
||||||
|
auth_challenge(char *fmt, ...)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
va_list arg;
|
||||||
|
Chalstate *c;
|
||||||
|
|
||||||
|
quotefmtinstall(); /* just in case */
|
||||||
|
va_start(arg, fmt);
|
||||||
|
p = vsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
if(p == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
c = mallocz(sizeof(*c), 1);
|
||||||
|
if(c == nil){
|
||||||
|
free(p);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((c->afd = open("/mnt/factotum/rpc", ORDWR)) < 0){
|
||||||
|
Error:
|
||||||
|
auth_freechal(c);
|
||||||
|
free(p);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((c->rpc=auth_allocrpc(c->afd)) == nil
|
||||||
|
|| auth_rpc(c->rpc, "start", p, strlen(p)) != ARok
|
||||||
|
|| auth_rpc(c->rpc, "read", nil, 0) != ARok)
|
||||||
|
goto Error;
|
||||||
|
|
||||||
|
if(c->rpc->narg > sizeof(c->chal)-1){
|
||||||
|
werrstr("buffer too small for challenge");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
memmove(c->chal, c->rpc->arg, c->rpc->narg);
|
||||||
|
c->nchal = c->rpc->narg;
|
||||||
|
free(p);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthInfo*
|
||||||
|
auth_response(Chalstate *c)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
AuthInfo *ai;
|
||||||
|
|
||||||
|
ai = nil;
|
||||||
|
if(c->afd < 0){
|
||||||
|
werrstr("auth_response: connection not open");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if(c->resp == nil){
|
||||||
|
werrstr("auth_response: nil response");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if(c->nresp == 0){
|
||||||
|
werrstr("auth_response: unspecified response length");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c->user){
|
||||||
|
if(auth_rpc(c->rpc, "write", c->user, strlen(c->user)) != ARok){
|
||||||
|
/*
|
||||||
|
* if this fails we're out of phase with factotum.
|
||||||
|
* give up.
|
||||||
|
*/
|
||||||
|
goto Out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(auth_rpc(c->rpc, "write", c->resp, c->nresp) != ARok){
|
||||||
|
/*
|
||||||
|
* don't close the connection -- maybe we'll try again.
|
||||||
|
*/
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ret = auth_rpc(c->rpc, "read", nil, 0)){
|
||||||
|
case ARok:
|
||||||
|
default:
|
||||||
|
werrstr("factotum protocol botch %d %s", ret, c->rpc->ibuf);
|
||||||
|
break;
|
||||||
|
case ARdone:
|
||||||
|
ai = auth_getinfo(c->rpc);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Out:
|
||||||
|
close(c->afd);
|
||||||
|
auth_freerpc(c->rpc);
|
||||||
|
c->afd = -1;
|
||||||
|
c->rpc = nil;
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_freechal(Chalstate *c)
|
||||||
|
{
|
||||||
|
if(c == nil)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(c->afd >= 0)
|
||||||
|
close(c->afd);
|
||||||
|
if(c->rpc != nil)
|
||||||
|
auth_freerpc(c->rpc);
|
||||||
|
|
||||||
|
memset(c, 0xBB, sizeof(*c));
|
||||||
|
free(c);
|
||||||
|
}
|
38
src/libauth/auth_chuid.c
Normal file
38
src/libauth/auth_chuid.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* become the authenticated user
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
auth_chuid(AuthInfo *ai, char *ns)
|
||||||
|
{
|
||||||
|
int rv, fd;
|
||||||
|
|
||||||
|
if(ai == nil || ai->cap == nil){
|
||||||
|
werrstr("no capability");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* change uid */
|
||||||
|
fd = open("#¤/capuse", OWRITE);
|
||||||
|
if(fd < 0){
|
||||||
|
werrstr("opening #¤/capuse: %r");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rv = write(fd, ai->cap, strlen(ai->cap));
|
||||||
|
close(fd);
|
||||||
|
if(rv < 0){
|
||||||
|
werrstr("writing %s to #¤/capuse: %r", ai->cap);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get a link to factotum as new user */
|
||||||
|
fd = open("/srv/factotum", ORDWR);
|
||||||
|
if(fd >= 0)
|
||||||
|
mount(fd, -1, "/mnt", MREPL, "");
|
||||||
|
|
||||||
|
/* set up new namespace */
|
||||||
|
return newns(ai->cuid, ns);
|
||||||
|
}
|
51
src/libauth/auth_getkey.c
Normal file
51
src/libauth/auth_getkey.c
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_getkey(char *params)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
Dir *d;
|
||||||
|
int pid;
|
||||||
|
Waitmsg *w;
|
||||||
|
|
||||||
|
/* start /factotum to query for a key */
|
||||||
|
name = "/factotum";
|
||||||
|
d = dirstat(name);
|
||||||
|
if(d == nil){
|
||||||
|
name = "/boot/factotum";
|
||||||
|
d = dirstat(name);
|
||||||
|
}
|
||||||
|
if(d == nil){
|
||||||
|
werrstr("auth_getkey: no /factotum or /boot/factotum: didn't get key %s", params);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(0) if(d->type != '/'){
|
||||||
|
werrstr("auth_getkey: /factotum may be bad: didn't get key %s", params);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
switch(pid = fork()){
|
||||||
|
case -1:
|
||||||
|
werrstr("can't fork for %s: %r", name);
|
||||||
|
return -1;
|
||||||
|
case 0:
|
||||||
|
execl(name, "getkey", "-g", params, nil);
|
||||||
|
exits(0);
|
||||||
|
default:
|
||||||
|
for(;;){
|
||||||
|
w = wait();
|
||||||
|
if(w == nil)
|
||||||
|
break;
|
||||||
|
if(w->pid == pid){
|
||||||
|
if(w->msg[0] != '\0'){
|
||||||
|
free(w);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(w);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
75
src/libauth/auth_getuserpasswd.c
Normal file
75
src/libauth/auth_getuserpasswd.c
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARgiveup = 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
|
||||||
|
return ret;
|
||||||
|
if(getkey == nil)
|
||||||
|
return ARgiveup; /* don't know how */
|
||||||
|
if((*getkey)(rpc->arg) < 0)
|
||||||
|
return ARgiveup; /* user punted */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserPasswd*
|
||||||
|
auth_getuserpasswd(AuthGetkey *getkey, char *fmt, ...)
|
||||||
|
{
|
||||||
|
AuthRpc *rpc;
|
||||||
|
char *f[3], *p, *params;
|
||||||
|
int fd;
|
||||||
|
va_list arg;
|
||||||
|
UserPasswd *up;
|
||||||
|
|
||||||
|
up = nil;
|
||||||
|
rpc = nil;
|
||||||
|
params = nil;
|
||||||
|
|
||||||
|
fd = open("/mnt/factotum/rpc", ORDWR);
|
||||||
|
if(fd < 0)
|
||||||
|
goto out;
|
||||||
|
rpc = auth_allocrpc(fd);
|
||||||
|
if(rpc == nil)
|
||||||
|
goto out;
|
||||||
|
quotefmtinstall(); /* just in case */
|
||||||
|
va_start(arg, fmt);
|
||||||
|
params = vsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
if(params == nil)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok
|
||||||
|
|| dorpc(rpc, "read", nil, 0, getkey) != ARok)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rpc->arg[rpc->narg] = '\0';
|
||||||
|
if(tokenize(rpc->arg, f, 2) != 2){
|
||||||
|
werrstr("bad answer from factotum");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
up = malloc(sizeof(*up)+rpc->narg+1);
|
||||||
|
if(up == nil)
|
||||||
|
goto out;
|
||||||
|
p = (char*)&up[1];
|
||||||
|
strcpy(p, f[0]);
|
||||||
|
up->user = p;
|
||||||
|
p += strlen(p)+1;
|
||||||
|
strcpy(p, f[1]);
|
||||||
|
up->passwd = p;
|
||||||
|
|
||||||
|
out:
|
||||||
|
free(params);
|
||||||
|
auth_freerpc(rpc);
|
||||||
|
close(fd);
|
||||||
|
return up;
|
||||||
|
}
|
212
src/libauth/auth_proxy.c
Normal file
212
src/libauth/auth_proxy.c
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <fcall.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARgiveup = 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uchar*
|
||||||
|
gstring(uchar *p, uchar *ep, char **s)
|
||||||
|
{
|
||||||
|
uint n;
|
||||||
|
|
||||||
|
if(p == nil)
|
||||||
|
return nil;
|
||||||
|
if(p+BIT16SZ > ep)
|
||||||
|
return nil;
|
||||||
|
n = GBIT16(p);
|
||||||
|
p += BIT16SZ;
|
||||||
|
if(p+n > ep)
|
||||||
|
return nil;
|
||||||
|
*s = malloc(n+1);
|
||||||
|
memmove((*s), p, n);
|
||||||
|
(*s)[n] = '\0';
|
||||||
|
p += n;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar*
|
||||||
|
gcarray(uchar *p, uchar *ep, uchar **s, int *np)
|
||||||
|
{
|
||||||
|
uint n;
|
||||||
|
|
||||||
|
if(p == nil)
|
||||||
|
return nil;
|
||||||
|
if(p+BIT16SZ > ep)
|
||||||
|
return nil;
|
||||||
|
n = GBIT16(p);
|
||||||
|
p += BIT16SZ;
|
||||||
|
if(p+n > ep)
|
||||||
|
return nil;
|
||||||
|
*s = malloc(n);
|
||||||
|
if(*s == nil)
|
||||||
|
return nil;
|
||||||
|
memmove((*s), p, n);
|
||||||
|
*np = n;
|
||||||
|
p += n;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_freeAI(AuthInfo *ai)
|
||||||
|
{
|
||||||
|
if(ai == nil)
|
||||||
|
return;
|
||||||
|
free(ai->cuid);
|
||||||
|
free(ai->suid);
|
||||||
|
free(ai->cap);
|
||||||
|
free(ai->secret);
|
||||||
|
free(ai);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar*
|
||||||
|
convM2AI(uchar *p, int n, AuthInfo **aip)
|
||||||
|
{
|
||||||
|
uchar *e = p+n;
|
||||||
|
AuthInfo *ai;
|
||||||
|
|
||||||
|
ai = mallocz(sizeof(*ai), 1);
|
||||||
|
if(ai == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
p = gstring(p, e, &ai->cuid);
|
||||||
|
p = gstring(p, e, &ai->suid);
|
||||||
|
p = gstring(p, e, &ai->cap);
|
||||||
|
p = gcarray(p, e, &ai->secret, &ai->nsecret);
|
||||||
|
if(p == nil)
|
||||||
|
auth_freeAI(ai);
|
||||||
|
else
|
||||||
|
*aip = ai;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthInfo*
|
||||||
|
auth_getinfo(AuthRpc *rpc)
|
||||||
|
{
|
||||||
|
AuthInfo *a;
|
||||||
|
|
||||||
|
if(auth_rpc(rpc, "authinfo", nil, 0) != ARok)
|
||||||
|
return nil;
|
||||||
|
if(convM2AI((uchar*)rpc->arg, rpc->narg, &a) == nil){
|
||||||
|
werrstr("bad auth info from factotum");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
|
||||||
|
return ret;
|
||||||
|
if(getkey == nil)
|
||||||
|
return ARgiveup; /* don't know how */
|
||||||
|
if((*getkey)(rpc->arg) < 0)
|
||||||
|
return ARgiveup; /* user punted */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this just proxies what the factotum tells it to.
|
||||||
|
*/
|
||||||
|
AuthInfo*
|
||||||
|
fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int m, n, ret;
|
||||||
|
AuthInfo *a;
|
||||||
|
char oerr[ERRMAX];
|
||||||
|
|
||||||
|
rerrstr(oerr, sizeof oerr);
|
||||||
|
werrstr("UNKNOWN AUTH ERROR");
|
||||||
|
|
||||||
|
if(dorpc(rpc, "start", params, strlen(params), getkey) != ARok){
|
||||||
|
werrstr("fauth_proxy start: %r");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = malloc(AuthRpcMax);
|
||||||
|
if(buf == nil)
|
||||||
|
return nil;
|
||||||
|
for(;;){
|
||||||
|
switch(dorpc(rpc, "read", nil, 0, getkey)){
|
||||||
|
case ARdone:
|
||||||
|
free(buf);
|
||||||
|
a = auth_getinfo(rpc);
|
||||||
|
errstr(oerr, sizeof oerr); /* no error, restore whatever was there */
|
||||||
|
return a;
|
||||||
|
case ARok:
|
||||||
|
if(write(fd, rpc->arg, rpc->narg) != rpc->narg){
|
||||||
|
werrstr("auth_proxy write fd: %r");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARphase:
|
||||||
|
n = 0;
|
||||||
|
memset(buf, 0, AuthRpcMax);
|
||||||
|
while((ret = dorpc(rpc, "write", buf, n, getkey)) == ARtoosmall){
|
||||||
|
if(atoi(rpc->arg) > AuthRpcMax)
|
||||||
|
break;
|
||||||
|
m = read(fd, buf+n, atoi(rpc->arg)-n);
|
||||||
|
if(m <= 0){
|
||||||
|
if(m == 0)
|
||||||
|
werrstr("auth_proxy short read: %s", buf);
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
n += m;
|
||||||
|
}
|
||||||
|
if(ret != ARok){
|
||||||
|
werrstr("auth_proxy rpc write: %s: %r", buf);
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
werrstr("auth_proxy rpc: %r");
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Error:
|
||||||
|
free(buf);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthInfo*
|
||||||
|
auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...)
|
||||||
|
{
|
||||||
|
int afd;
|
||||||
|
char *p;
|
||||||
|
va_list arg;
|
||||||
|
AuthInfo *ai;
|
||||||
|
AuthRpc *rpc;
|
||||||
|
|
||||||
|
quotefmtinstall(); /* just in case */
|
||||||
|
va_start(arg, fmt);
|
||||||
|
p = vsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
afd = open("/mnt/factotum/rpc", ORDWR);
|
||||||
|
if(afd < 0){
|
||||||
|
werrstr("opening /mnt/factotum/rpc: %r");
|
||||||
|
free(p);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
rpc = auth_allocrpc(afd);
|
||||||
|
if(rpc == nil){
|
||||||
|
free(p);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
ai = fauth_proxy(fd, rpc, getkey, p);
|
||||||
|
free(p);
|
||||||
|
auth_freerpc(rpc);
|
||||||
|
close(afd);
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
73
src/libauth/auth_respond.c
Normal file
73
src/libauth/auth_respond.c
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include <authsrv.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ARgiveup = 100,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
dorpc(AuthRpc *rpc, char *verb, char *val, int len, AuthGetkey *getkey)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
if((ret = auth_rpc(rpc, verb, val, len)) != ARneedkey && ret != ARbadkey)
|
||||||
|
return ret;
|
||||||
|
if(getkey == nil)
|
||||||
|
return ARgiveup; /* don't know how */
|
||||||
|
if((*getkey)(rpc->arg) < 0)
|
||||||
|
return ARgiveup; /* user punted */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
auth_respond(void *chal, uint nchal, char *user, uint nuser, void *resp, uint nresp, AuthGetkey *getkey, char *fmt, ...)
|
||||||
|
{
|
||||||
|
char *p, *s;
|
||||||
|
va_list arg;
|
||||||
|
int afd;
|
||||||
|
AuthRpc *rpc;
|
||||||
|
Attr *a;
|
||||||
|
|
||||||
|
if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if((rpc = auth_allocrpc(afd)) == nil){
|
||||||
|
close(afd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
quotefmtinstall(); /* just in case */
|
||||||
|
va_start(arg, fmt);
|
||||||
|
p = vsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
if(p==nil
|
||||||
|
|| dorpc(rpc, "start", p, strlen(p), getkey) != ARok
|
||||||
|
|| dorpc(rpc, "write", chal, nchal, getkey) != ARok
|
||||||
|
|| dorpc(rpc, "read", nil, 0, getkey) != ARok){
|
||||||
|
free(p);
|
||||||
|
close(afd);
|
||||||
|
auth_freerpc(rpc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
if(rpc->narg < nresp)
|
||||||
|
nresp = rpc->narg;
|
||||||
|
memmove(resp, rpc->arg, nresp);
|
||||||
|
|
||||||
|
if((a = auth_attr(rpc)) != nil
|
||||||
|
&& (s = _strfindattr(a, "user")) != nil && strlen(s) < nuser)
|
||||||
|
strcpy(user, s);
|
||||||
|
else if(nuser > 0)
|
||||||
|
user[0] = '\0';
|
||||||
|
|
||||||
|
_freeattr(a);
|
||||||
|
close(afd);
|
||||||
|
auth_freerpc(rpc);
|
||||||
|
return nresp;
|
||||||
|
}
|
116
src/libauth/auth_rpc.c
Normal file
116
src/libauth/auth_rpc.c
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
char *verb;
|
||||||
|
int val;
|
||||||
|
} tab[] = {
|
||||||
|
"ok", ARok,
|
||||||
|
"done", ARdone,
|
||||||
|
"error", ARerror,
|
||||||
|
"needkey", ARneedkey,
|
||||||
|
"badkey", ARbadkey,
|
||||||
|
"phase", ARphase,
|
||||||
|
"toosmall", ARtoosmall,
|
||||||
|
"error", ARerror,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
classify(char *buf, uint n, AuthRpc *rpc)
|
||||||
|
{
|
||||||
|
int i, len;
|
||||||
|
|
||||||
|
for(i=0; i<nelem(tab); i++){
|
||||||
|
len = strlen(tab[i].verb);
|
||||||
|
if(n >= len && memcmp(buf, tab[i].verb, len) == 0 && (n==len || buf[len]==' ')){
|
||||||
|
if(n==len){
|
||||||
|
rpc->narg = 0;
|
||||||
|
rpc->arg = "";
|
||||||
|
}else{
|
||||||
|
rpc->narg = n - (len+1);
|
||||||
|
rpc->arg = (char*)buf+len+1;
|
||||||
|
}
|
||||||
|
return tab[i].val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
werrstr("malformed rpc response: %s", buf);
|
||||||
|
return ARrpcfailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthRpc*
|
||||||
|
auth_allocrpc(int afd)
|
||||||
|
{
|
||||||
|
AuthRpc *rpc;
|
||||||
|
|
||||||
|
rpc = mallocz(sizeof(*rpc), 1);
|
||||||
|
if(rpc == nil)
|
||||||
|
return nil;
|
||||||
|
rpc->afd = afd;
|
||||||
|
return rpc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_freerpc(AuthRpc *rpc)
|
||||||
|
{
|
||||||
|
free(rpc);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint
|
||||||
|
auth_rpc(AuthRpc *rpc, char *verb, void *a, int na)
|
||||||
|
{
|
||||||
|
int l, n, type;
|
||||||
|
char *f[4];
|
||||||
|
|
||||||
|
l = strlen(verb);
|
||||||
|
if(na+l+1 > AuthRpcMax){
|
||||||
|
werrstr("rpc too big");
|
||||||
|
return ARtoobig;
|
||||||
|
}
|
||||||
|
|
||||||
|
memmove(rpc->obuf, verb, l);
|
||||||
|
rpc->obuf[l] = ' ';
|
||||||
|
memmove(rpc->obuf+l+1, a, na);
|
||||||
|
if((n=write(rpc->afd, rpc->obuf, l+1+na)) != l+1+na){
|
||||||
|
if(n >= 0)
|
||||||
|
werrstr("auth_rpc short write");
|
||||||
|
return ARrpcfailure;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((n=read(rpc->afd, rpc->ibuf, AuthRpcMax)) < 0)
|
||||||
|
return ARrpcfailure;
|
||||||
|
rpc->ibuf[n] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set error string for good default behavior.
|
||||||
|
*/
|
||||||
|
switch(type = classify(rpc->ibuf, n, rpc)){
|
||||||
|
default:
|
||||||
|
werrstr("unknown rpc type %d (bug in auth_rpc.c)", type);
|
||||||
|
break;
|
||||||
|
case ARok:
|
||||||
|
break;
|
||||||
|
case ARrpcfailure:
|
||||||
|
break;
|
||||||
|
case ARerror:
|
||||||
|
if(rpc->narg == 0)
|
||||||
|
werrstr("unspecified rpc error");
|
||||||
|
else
|
||||||
|
werrstr("%s", rpc->arg);
|
||||||
|
break;
|
||||||
|
case ARneedkey:
|
||||||
|
werrstr("needkey %s", rpc->arg);
|
||||||
|
break;
|
||||||
|
case ARbadkey:
|
||||||
|
if(getfields(rpc->arg, f, nelem(f), 0, "\n") < 2)
|
||||||
|
werrstr("badkey %s", rpc->arg);
|
||||||
|
else
|
||||||
|
werrstr("badkey %s", f[1]);
|
||||||
|
break;
|
||||||
|
case ARphase:
|
||||||
|
werrstr("phase error %s", rpc->arg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
50
src/libauth/auth_userpasswd.c
Normal file
50
src/libauth/auth_userpasswd.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include <authsrv.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compute the proper response. We encrypt the ascii of
|
||||||
|
* challenge number, with trailing binary zero fill.
|
||||||
|
* This process was derived empirically.
|
||||||
|
* this was copied from inet's guard.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
netresp(char *key, long chal, char *answer)
|
||||||
|
{
|
||||||
|
uchar buf[8];
|
||||||
|
|
||||||
|
memset(buf, 0, 8);
|
||||||
|
sprint((char *)buf, "%lud", chal);
|
||||||
|
if(encrypt(key, buf, 8) < 0)
|
||||||
|
abort();
|
||||||
|
chal = (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+buf[3];
|
||||||
|
sprint(answer, "%.8lux", chal);
|
||||||
|
}
|
||||||
|
|
||||||
|
AuthInfo*
|
||||||
|
auth_userpasswd(char *user, char *passwd)
|
||||||
|
{
|
||||||
|
char key[DESKEYLEN], resp[16];
|
||||||
|
AuthInfo *ai;
|
||||||
|
Chalstate *ch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Probably we should have a factotum protocol
|
||||||
|
* to check a raw password. For now, we use
|
||||||
|
* p9cr, which is simplest to speak.
|
||||||
|
*/
|
||||||
|
if((ch = auth_challenge("user=%q proto=p9cr role=server", user)) == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
passtokey(key, passwd);
|
||||||
|
netresp(key, atol(ch->chal), resp);
|
||||||
|
memset(key, 0, sizeof key);
|
||||||
|
|
||||||
|
ch->resp = resp;
|
||||||
|
ch->nresp = strlen(resp);
|
||||||
|
ai = auth_response(ch);
|
||||||
|
auth_freechal(ch);
|
||||||
|
return ai;
|
||||||
|
}
|
50
src/libauth/auth_wep.c
Normal file
50
src/libauth/auth_wep.c
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* make factotum add wep keys to an 802.11 device
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
auth_wep(char *dev, char *fmt, ...)
|
||||||
|
{
|
||||||
|
AuthRpc *rpc;
|
||||||
|
char *params, *p;
|
||||||
|
int fd;
|
||||||
|
va_list arg;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rv = -1;
|
||||||
|
|
||||||
|
if(dev == nil){
|
||||||
|
werrstr("no device specified");
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open("/mnt/factotum/rpc", ORDWR);
|
||||||
|
if(fd < 0)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
rpc = auth_allocrpc(fd);
|
||||||
|
if(rpc != nil){
|
||||||
|
quotefmtinstall(); /* just in case */
|
||||||
|
va_start(arg, fmt);
|
||||||
|
params = vsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
if(params != nil){
|
||||||
|
p = smprint("proto=wep %s", params);
|
||||||
|
if(p != nil){
|
||||||
|
if(auth_rpc(rpc, "start", p, strlen(p)) == ARok
|
||||||
|
&& auth_rpc(rpc, "write", dev, strlen(dev)) == ARok)
|
||||||
|
rv = 0;
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
free(params);
|
||||||
|
}
|
||||||
|
auth_freerpc(rpc);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
1
src/libauth/authlocal.h
Normal file
1
src/libauth/authlocal.h
Normal file
|
@ -0,0 +1 @@
|
||||||
|
extern AuthInfo* _fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params);
|
51
src/libauth/httpauth.c
Normal file
51
src/libauth/httpauth.c
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include <authsrv.h>
|
||||||
|
|
||||||
|
/* deprecated.
|
||||||
|
This is the mechanism that put entries in /sys/lib/httpd.rewrite
|
||||||
|
and passwords on the authserver in /sys/lib/httppasswords, which
|
||||||
|
was awkward to administer. Instead, use local .httplogin files,
|
||||||
|
which are implemented in sys/src/cmd/ip/httpd/authorize.c */
|
||||||
|
|
||||||
|
int
|
||||||
|
httpauth(char *name, char *password)
|
||||||
|
{
|
||||||
|
int afd;
|
||||||
|
Ticketreq tr;
|
||||||
|
Ticket t;
|
||||||
|
char key[DESKEYLEN];
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
|
afd = authdial(nil, nil);
|
||||||
|
if(afd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* send ticket request to AS */
|
||||||
|
memset(&tr, 0, sizeof(tr));
|
||||||
|
strcpy(tr.uid, name);
|
||||||
|
tr.type = AuthHttp;
|
||||||
|
convTR2M(&tr, buf);
|
||||||
|
if(write(afd, buf, TICKREQLEN) != TICKREQLEN){
|
||||||
|
close(afd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(_asrdresp(afd, buf, TICKETLEN) < 0){
|
||||||
|
close(afd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(afd);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* use password and try to decrypt the
|
||||||
|
* ticket. If it doesn't work we've got a bad password,
|
||||||
|
* give up.
|
||||||
|
*/
|
||||||
|
passtokey(key, password);
|
||||||
|
convM2T(buf, &t, key);
|
||||||
|
if(t.num != AuthHr || strcmp(t.cuid, tr.uid))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
17
src/libauth/login.c
Normal file
17
src/libauth/login.c
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <auth.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
login(char *user, char *password, char *namespace)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
AuthInfo *ai;
|
||||||
|
|
||||||
|
if((ai = auth_userpasswd(user, password)) == nil)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
rv = auth_chuid(ai, namespace);
|
||||||
|
auth_freeAI(ai);
|
||||||
|
return rv;
|
||||||
|
}
|
27
src/libauth/mkfile
Normal file
27
src/libauth/mkfile
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
PLAN9=../..
|
||||||
|
<$PLAN9/src/mkhdr
|
||||||
|
|
||||||
|
LIB=libauth.a
|
||||||
|
OFILES=\
|
||||||
|
# amount.$O\
|
||||||
|
# amount_getkey.$O\
|
||||||
|
attr.$O\
|
||||||
|
# auth_attr.$O\
|
||||||
|
# auth_challenge.$O\
|
||||||
|
# auth_chuid.$O\
|
||||||
|
# auth_getkey.$O\
|
||||||
|
# auth_getuserpasswd.$O\
|
||||||
|
# auth_proxy.$O\
|
||||||
|
# auth_respond.$O\
|
||||||
|
# auth_rpc.$O\
|
||||||
|
# auth_userpasswd.$O\
|
||||||
|
# auth_wep.$O\
|
||||||
|
# login.$O\
|
||||||
|
# newns.$O\
|
||||||
|
# noworld.$O\
|
||||||
|
|
||||||
|
HFILES=\
|
||||||
|
$PLAN9/include/auth.h\
|
||||||
|
authlocal.h\
|
||||||
|
|
||||||
|
<$PLAN9/src/mksyslib
|
322
src/libauth/newns.c
Normal file
322
src/libauth/newns.c
Normal file
|
@ -0,0 +1,322 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <auth.h>
|
||||||
|
#include <authsrv.h>
|
||||||
|
#include "authlocal.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
NARG = 15, /* max number of arguments */
|
||||||
|
MAXARG = 10*ANAMELEN, /* max length of an argument */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int setenv(char*, char*);
|
||||||
|
static char *expandarg(char*, char*);
|
||||||
|
static int splitargs(char*, char*[], char*, int);
|
||||||
|
static int nsfile(Biobuf *, AuthRpc *);
|
||||||
|
static int nsop(int, char*[], AuthRpc*);
|
||||||
|
static int callexport(char*, char*);
|
||||||
|
static int catch(void*, char*);
|
||||||
|
|
||||||
|
static int
|
||||||
|
buildns(int newns, char *user, char *file)
|
||||||
|
{
|
||||||
|
Biobuf *b;
|
||||||
|
char home[4*ANAMELEN];
|
||||||
|
int afd;
|
||||||
|
AuthRpc *rpc;
|
||||||
|
int cdroot;
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
rpc = nil;
|
||||||
|
/* try for factotum now because later is impossible */
|
||||||
|
afd = open("/mnt/factotum/rpc", ORDWR);
|
||||||
|
if(afd >= 0){
|
||||||
|
rpc = auth_allocrpc(afd);
|
||||||
|
if(rpc == nil){
|
||||||
|
close(afd);
|
||||||
|
afd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(file == nil){
|
||||||
|
if(!newns){
|
||||||
|
werrstr("no namespace file specified");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
file = "/lib/namespace";
|
||||||
|
}
|
||||||
|
b = Bopen(file, OREAD);
|
||||||
|
if(b == 0){
|
||||||
|
werrstr("can't open %s: %r", file);
|
||||||
|
close(afd);
|
||||||
|
auth_freerpc(rpc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(newns){
|
||||||
|
rfork(RFENVG|RFCNAMEG);
|
||||||
|
setenv("user", user);
|
||||||
|
snprint(home, 2*ANAMELEN, "/usr/%s", user);
|
||||||
|
setenv("home", home);
|
||||||
|
}
|
||||||
|
cdroot = nsfile(b, rpc);
|
||||||
|
Bterm(b);
|
||||||
|
if(rpc){
|
||||||
|
close(rpc->afd);
|
||||||
|
auth_freerpc(rpc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure we managed to cd into the new name space */
|
||||||
|
if(newns && !cdroot){
|
||||||
|
path = malloc(1024);
|
||||||
|
if(path == nil || getwd(path, 1024) == 0 || chdir(path) < 0)
|
||||||
|
chdir("/");
|
||||||
|
if(path != nil)
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nsfile(Biobuf *b, AuthRpc *rpc)
|
||||||
|
{
|
||||||
|
int argc;
|
||||||
|
char *cmd, *argv[NARG+1], argbuf[MAXARG*NARG];
|
||||||
|
int cdroot = 0;
|
||||||
|
|
||||||
|
atnotify(catch, 1);
|
||||||
|
while(cmd = Brdline(b, '\n')){
|
||||||
|
cmd[Blinelen(b)-1] = '\0';
|
||||||
|
while(*cmd==' ' || *cmd=='\t')
|
||||||
|
cmd++;
|
||||||
|
if(*cmd == '#')
|
||||||
|
continue;
|
||||||
|
argc = splitargs(cmd, argv, argbuf, NARG);
|
||||||
|
if(argc)
|
||||||
|
cdroot |= nsop(argc, argv, rpc);
|
||||||
|
}
|
||||||
|
atnotify(catch, 0);
|
||||||
|
return cdroot;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
newns(char *user, char *file)
|
||||||
|
{
|
||||||
|
return buildns(1, user, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
addns(char *user, char *file)
|
||||||
|
{
|
||||||
|
return buildns(0, user, file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
famount(int fd, AuthRpc *rpc, char *mntpt, int flags, char *aname)
|
||||||
|
{
|
||||||
|
int afd;
|
||||||
|
AuthInfo *ai;
|
||||||
|
|
||||||
|
afd = fauth(fd, aname);
|
||||||
|
if(afd >= 0){
|
||||||
|
ai = fauth_proxy(afd, rpc, amount_getkey, "proto=p9any role=client");
|
||||||
|
if(ai != nil)
|
||||||
|
auth_freeAI(ai);
|
||||||
|
}
|
||||||
|
return mount(fd, afd, mntpt, flags, aname);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nsop(int argc, char *argv[], AuthRpc *rpc)
|
||||||
|
{
|
||||||
|
char *argv0;
|
||||||
|
ulong flags;
|
||||||
|
int fd;
|
||||||
|
Biobuf *b;
|
||||||
|
int cdroot = 0;
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
argv0 = 0;
|
||||||
|
ARGBEGIN{
|
||||||
|
case 'a':
|
||||||
|
flags |= MAFTER;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
flags |= MBEFORE;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
flags |= MCREATE;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
flags |= MCACHE;
|
||||||
|
break;
|
||||||
|
}ARGEND
|
||||||
|
|
||||||
|
if(!(flags & (MAFTER|MBEFORE)))
|
||||||
|
flags |= MREPL;
|
||||||
|
|
||||||
|
if(strcmp(argv0, ".") == 0 && argc == 1){
|
||||||
|
b = Bopen(argv[0], OREAD);
|
||||||
|
if(b == nil)
|
||||||
|
return 0;
|
||||||
|
cdroot |= nsfile(b, rpc);
|
||||||
|
Bterm(b);
|
||||||
|
} else if(strcmp(argv0, "clear") == 0 && argc == 0)
|
||||||
|
rfork(RFCNAMEG);
|
||||||
|
else if(strcmp(argv0, "bind") == 0 && argc == 2)
|
||||||
|
bind(argv[0], argv[1], flags);
|
||||||
|
else if(strcmp(argv0, "unmount") == 0){
|
||||||
|
if(argc == 1)
|
||||||
|
unmount(nil, argv[0]);
|
||||||
|
else if(argc == 2)
|
||||||
|
unmount(argv[0], argv[1]);
|
||||||
|
} else if(strcmp(argv0, "mount") == 0){
|
||||||
|
fd = open(argv[0], ORDWR);
|
||||||
|
if(argc == 2)
|
||||||
|
famount(fd, rpc, argv[1], flags, "");
|
||||||
|
else if(argc == 3)
|
||||||
|
famount(fd, rpc, argv[1], flags, argv[2]);
|
||||||
|
close(fd);
|
||||||
|
} else if(strcmp(argv0, "import") == 0){
|
||||||
|
fd = callexport(argv[0], argv[1]);
|
||||||
|
if(argc == 2)
|
||||||
|
famount(fd, rpc, argv[1], flags, "");
|
||||||
|
else if(argc == 3)
|
||||||
|
famount(fd, rpc, argv[2], flags, "");
|
||||||
|
close(fd);
|
||||||
|
} else if(strcmp(argv0, "cd") == 0 && argc == 1)
|
||||||
|
if(chdir(argv[0]) == 0 && *argv[0] == '/')
|
||||||
|
cdroot = 1;
|
||||||
|
return cdroot;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *wocp = "sys: write on closed pipe";
|
||||||
|
|
||||||
|
static int
|
||||||
|
catch(void *x, char *m)
|
||||||
|
{
|
||||||
|
USED(x);
|
||||||
|
return strncmp(m, wocp, strlen(wocp)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
callexport(char *sys, char *tree)
|
||||||
|
{
|
||||||
|
char *na, buf[3];
|
||||||
|
int fd;
|
||||||
|
AuthInfo *ai;
|
||||||
|
|
||||||
|
na = netmkaddr(sys, 0, "exportfs");
|
||||||
|
if((fd = dial(na, 0, 0, 0)) < 0)
|
||||||
|
return -1;
|
||||||
|
if((ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client")) == nil
|
||||||
|
|| write(fd, tree, strlen(tree)) < 0
|
||||||
|
|| read(fd, buf, 3) != 2 || buf[0]!='O' || buf[1]!= 'K'){
|
||||||
|
close(fd);
|
||||||
|
auth_freeAI(ai);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
auth_freeAI(ai);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
splitargs(char *p, char *argv[], char *argbuf, int nargv)
|
||||||
|
{
|
||||||
|
char *q;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
n = gettokens(p, argv, nargv, " \t'\r");
|
||||||
|
if(n == nargv)
|
||||||
|
return 0;
|
||||||
|
for(i = 0; i < n; i++){
|
||||||
|
q = argv[i];
|
||||||
|
argv[i] = argbuf;
|
||||||
|
argbuf = expandarg(q, argbuf);
|
||||||
|
if(!argbuf)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* copy the arg into the buffer,
|
||||||
|
* expanding any environment variables.
|
||||||
|
* environment variables are assumed to be
|
||||||
|
* names (ie. < ANAMELEN long)
|
||||||
|
* the entire argument is expanded to be at
|
||||||
|
* most MAXARG long and null terminated
|
||||||
|
* the address of the byte after the terminating null is returned
|
||||||
|
* any problems cause a 0 return;
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
expandarg(char *arg, char *buf)
|
||||||
|
{
|
||||||
|
char env[3+ANAMELEN], *p, *q, *x;
|
||||||
|
int fd, n, len;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
while(p = utfrune(arg, L'$')){
|
||||||
|
len = p - arg;
|
||||||
|
if(n + len + ANAMELEN >= MAXARG-1)
|
||||||
|
return 0;
|
||||||
|
memmove(&buf[n], arg, len);
|
||||||
|
n += len;
|
||||||
|
p++;
|
||||||
|
arg = utfrune(p, L'\0');
|
||||||
|
q = utfrune(p, L'/');
|
||||||
|
if(q && q < arg)
|
||||||
|
arg = q;
|
||||||
|
q = utfrune(p, L'.');
|
||||||
|
if(q && q < arg)
|
||||||
|
arg = q;
|
||||||
|
q = utfrune(p, L'$');
|
||||||
|
if(q && q < arg)
|
||||||
|
arg = q;
|
||||||
|
len = arg - p;
|
||||||
|
if(len >= ANAMELEN)
|
||||||
|
continue;
|
||||||
|
strcpy(env, "#e/");
|
||||||
|
strncpy(env+3, p, len);
|
||||||
|
env[3+len] = '\0';
|
||||||
|
fd = open(env, OREAD);
|
||||||
|
if(fd >= 0){
|
||||||
|
len = read(fd, &buf[n], ANAMELEN - 1);
|
||||||
|
/* some singleton environment variables have trailing NULs */
|
||||||
|
/* lists separate entries with NULs; we arbitrarily take the first element */
|
||||||
|
if(len > 0){
|
||||||
|
x = memchr(&buf[n], 0, len);
|
||||||
|
if(x != nil)
|
||||||
|
len = x - &buf[n];
|
||||||
|
n += len;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len = strlen(arg);
|
||||||
|
if(n + len >= MAXARG - 1)
|
||||||
|
return 0;
|
||||||
|
strcpy(&buf[n], arg);
|
||||||
|
return &buf[n+len+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
setenv(char *name, char *val)
|
||||||
|
{
|
||||||
|
int f;
|
||||||
|
char ename[ANAMELEN+6];
|
||||||
|
long s;
|
||||||
|
|
||||||
|
sprint(ename, "#e/%s", name);
|
||||||
|
f = create(ename, OWRITE, 0664);
|
||||||
|
if(f < 0)
|
||||||
|
return -1;
|
||||||
|
s = strlen(val);
|
||||||
|
if(write(f, val, s) != s){
|
||||||
|
close(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
close(f);
|
||||||
|
return 0;
|
||||||
|
}
|
45
src/libauth/noworld.c
Normal file
45
src/libauth/noworld.c
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <auth.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see if user is in the group noworld, i.e., has all file
|
||||||
|
* priviledges masked with 770, and all directories with
|
||||||
|
* 771, before checking access rights
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
noworld(char *user)
|
||||||
|
{
|
||||||
|
Biobuf *b;
|
||||||
|
char *p;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
b = Bopen("/adm/users", OREAD);
|
||||||
|
if(b == nil)
|
||||||
|
return 0;
|
||||||
|
while((p = Brdline(b, '\n')) != nil){
|
||||||
|
p[Blinelen(b)-1] = 0;
|
||||||
|
p = strchr(p, ':');
|
||||||
|
if(p == nil)
|
||||||
|
continue;
|
||||||
|
if(strncmp(p, ":noworld:", 9) == 0){
|
||||||
|
p += 9;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n = strlen(user);
|
||||||
|
while(p != nil && *p != 0){
|
||||||
|
p = strstr(p, user);
|
||||||
|
if(p == nil)
|
||||||
|
break;
|
||||||
|
if(*(p-1) == ':' || *(p-1) == ',')
|
||||||
|
if(*(p+n) == ':' || *(p+n) == ',' || *(p+n) == 0){
|
||||||
|
Bterm(b);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
Bterm(b);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue