Add real factotum.
This commit is contained in:
		
							
								
								
									
										21
									
								
								libauth/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								libauth/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
ROOT=..
 | 
			
		||||
include ../Make.config
 | 
			
		||||
 | 
			
		||||
LIB=libauth.a
 | 
			
		||||
OFILES=\
 | 
			
		||||
	attr.$O\
 | 
			
		||||
	auth_attr.$O\
 | 
			
		||||
	auth_challenge.$O\
 | 
			
		||||
	auth_getuserpasswd.$O\
 | 
			
		||||
	auth_proxy.$O\
 | 
			
		||||
	auth_respond.$O\
 | 
			
		||||
	auth_rpc.$O\
 | 
			
		||||
	auth_userpasswd.$O\
 | 
			
		||||
 | 
			
		||||
$(LIB): $(OFILES)
 | 
			
		||||
	$(AR) r $(LIB) $(OFILES)
 | 
			
		||||
	$(RANLIB) $(LIB)
 | 
			
		||||
 | 
			
		||||
%.$O: %.c
 | 
			
		||||
	$(CC) $(CFLAGS) $*.c
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										174
									
								
								libauth/attr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								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
									
								
								libauth/auth_attr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								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
									
								
								libauth/auth_challenge.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								libauth/auth_getuserpasswd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								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
									
								
								libauth/auth_proxy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								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
									
								
								libauth/auth_respond.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								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
									
								
								libauth/auth_rpc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								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
									
								
								libauth/auth_userpasswd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								libauth/authlocal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								libauth/authlocal.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
extern AuthInfo*	_fauth_proxy(int fd, AuthRpc *rpc, AuthGetkey *getkey, char *params);
 | 
			
		||||
							
								
								
									
										51
									
								
								libauth/httpauth.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								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;
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user