xref: /plan9/sys/src/cmd/ssh1/util.c (revision 63afb9a5d3f910047231762bcce0ee49fed3d07c)
1*63afb9a5SDavid du Colombier #include "ssh.h"
2*63afb9a5SDavid du Colombier #include <bio.h>
3*63afb9a5SDavid du Colombier #include <ndb.h>
4*63afb9a5SDavid du Colombier 
5*63afb9a5SDavid du Colombier char Edecode[] = "error decoding input packet";
6*63afb9a5SDavid du Colombier char Eencode[] = "out of space encoding output packet (BUG)";
7*63afb9a5SDavid du Colombier char Ehangup[] = "hungup connection";
8*63afb9a5SDavid du Colombier char Ememory[] = "out of memory";
9*63afb9a5SDavid du Colombier 
10*63afb9a5SDavid du Colombier int debuglevel;
11*63afb9a5SDavid du Colombier int doabort;
12*63afb9a5SDavid du Colombier 
13*63afb9a5SDavid du Colombier void
error(char * fmt,...)14*63afb9a5SDavid du Colombier error(char *fmt, ...)
15*63afb9a5SDavid du Colombier {
16*63afb9a5SDavid du Colombier 	va_list arg;
17*63afb9a5SDavid du Colombier 	char buf[2048];
18*63afb9a5SDavid du Colombier 
19*63afb9a5SDavid du Colombier 	va_start(arg, fmt);
20*63afb9a5SDavid du Colombier 	vseprint(buf, buf+sizeof(buf), fmt, arg);
21*63afb9a5SDavid du Colombier 	va_end(arg);
22*63afb9a5SDavid du Colombier 	fprint(2, "%s: %s\n", argv0, buf);
23*63afb9a5SDavid du Colombier 	if(doabort)
24*63afb9a5SDavid du Colombier 		abort();
25*63afb9a5SDavid du Colombier 	exits(buf);
26*63afb9a5SDavid du Colombier }
27*63afb9a5SDavid du Colombier 
28*63afb9a5SDavid du Colombier void
debug(int level,char * fmt,...)29*63afb9a5SDavid du Colombier debug(int level, char *fmt, ...)
30*63afb9a5SDavid du Colombier {
31*63afb9a5SDavid du Colombier 	va_list arg;
32*63afb9a5SDavid du Colombier 
33*63afb9a5SDavid du Colombier 	if((level&debuglevel) == 0)
34*63afb9a5SDavid du Colombier 		return;
35*63afb9a5SDavid du Colombier 	va_start(arg, fmt);
36*63afb9a5SDavid du Colombier 	vfprint(2, fmt, arg);
37*63afb9a5SDavid du Colombier 	va_end(arg);
38*63afb9a5SDavid du Colombier }
39*63afb9a5SDavid du Colombier 
40*63afb9a5SDavid du Colombier void*
emalloc(long n)41*63afb9a5SDavid du Colombier emalloc(long n)
42*63afb9a5SDavid du Colombier {
43*63afb9a5SDavid du Colombier 	void *a;
44*63afb9a5SDavid du Colombier 
45*63afb9a5SDavid du Colombier 	a = mallocz(n, 1);
46*63afb9a5SDavid du Colombier 	if(a == nil)
47*63afb9a5SDavid du Colombier 		error(Ememory);
48*63afb9a5SDavid du Colombier 	setmalloctag(a, getcallerpc(&n));
49*63afb9a5SDavid du Colombier 	return a;
50*63afb9a5SDavid du Colombier }
51*63afb9a5SDavid du Colombier 
52*63afb9a5SDavid du Colombier void*
erealloc(void * v,long n)53*63afb9a5SDavid du Colombier erealloc(void *v, long n)
54*63afb9a5SDavid du Colombier {
55*63afb9a5SDavid du Colombier 	v = realloc(v, n);
56*63afb9a5SDavid du Colombier 	if(v == nil)
57*63afb9a5SDavid du Colombier 		error(Ememory);
58*63afb9a5SDavid du Colombier 	setrealloctag(v, getcallerpc(&v));
59*63afb9a5SDavid du Colombier 	return v;
60*63afb9a5SDavid du Colombier }
61*63afb9a5SDavid du Colombier 
62*63afb9a5SDavid du Colombier 
63*63afb9a5SDavid du Colombier static int killpid[32];
64*63afb9a5SDavid du Colombier static int nkillpid;
65*63afb9a5SDavid du Colombier void
atexitkiller(void)66*63afb9a5SDavid du Colombier atexitkiller(void)
67*63afb9a5SDavid du Colombier {
68*63afb9a5SDavid du Colombier 	int i, pid;
69*63afb9a5SDavid du Colombier 
70*63afb9a5SDavid du Colombier 	pid = getpid();
71*63afb9a5SDavid du Colombier 	debug(DBG, "atexitkiller: nkillpid=%d mypid=%d\n", nkillpid, pid);
72*63afb9a5SDavid du Colombier 	for(i=0; i<nkillpid; i++)
73*63afb9a5SDavid du Colombier 		if(pid != killpid[i]){
74*63afb9a5SDavid du Colombier 			debug(DBG, "killing %d\n", killpid[i]);
75*63afb9a5SDavid du Colombier 			postnote(PNPROC, killpid[i], "kill");
76*63afb9a5SDavid du Colombier 		}
77*63afb9a5SDavid du Colombier }
78*63afb9a5SDavid du Colombier void
atexitkill(int pid)79*63afb9a5SDavid du Colombier atexitkill(int pid)
80*63afb9a5SDavid du Colombier {
81*63afb9a5SDavid du Colombier 	killpid[nkillpid++] = pid;
82*63afb9a5SDavid du Colombier }
83*63afb9a5SDavid du Colombier 
84*63afb9a5SDavid du Colombier int
readstrnl(int fd,char * buf,int nbuf)85*63afb9a5SDavid du Colombier readstrnl(int fd, char *buf, int nbuf)
86*63afb9a5SDavid du Colombier {
87*63afb9a5SDavid du Colombier 	int i;
88*63afb9a5SDavid du Colombier 
89*63afb9a5SDavid du Colombier 	for(i=0; i<nbuf; i++){
90*63afb9a5SDavid du Colombier 		switch(read(fd, buf+i, 1)){
91*63afb9a5SDavid du Colombier 		case -1:
92*63afb9a5SDavid du Colombier 			return -1;
93*63afb9a5SDavid du Colombier 		case 0:
94*63afb9a5SDavid du Colombier 			werrstr("unexpected EOF");
95*63afb9a5SDavid du Colombier 			return -1;
96*63afb9a5SDavid du Colombier 		default:
97*63afb9a5SDavid du Colombier 			if(buf[i]=='\n'){
98*63afb9a5SDavid du Colombier 				buf[i] = '\0';
99*63afb9a5SDavid du Colombier 				return 0;
100*63afb9a5SDavid du Colombier 			}
101*63afb9a5SDavid du Colombier 			break;
102*63afb9a5SDavid du Colombier 		}
103*63afb9a5SDavid du Colombier 	}
104*63afb9a5SDavid du Colombier 	werrstr("line too long");
105*63afb9a5SDavid du Colombier 	return -1;
106*63afb9a5SDavid du Colombier }
107*63afb9a5SDavid du Colombier 
108*63afb9a5SDavid du Colombier void
calcsessid(Conn * c)109*63afb9a5SDavid du Colombier calcsessid(Conn *c)
110*63afb9a5SDavid du Colombier {
111*63afb9a5SDavid du Colombier 	int n;
112*63afb9a5SDavid du Colombier 	uchar buf[1024];
113*63afb9a5SDavid du Colombier 
114*63afb9a5SDavid du Colombier 	n = mptobe(c->hostkey->n, buf, sizeof buf, nil);
115*63afb9a5SDavid du Colombier 	n += mptobe(c->serverkey->n, buf+n, sizeof buf-n, nil);
116*63afb9a5SDavid du Colombier 	memmove(buf+n, c->cookie, COOKIELEN);
117*63afb9a5SDavid du Colombier 	n += COOKIELEN;
118*63afb9a5SDavid du Colombier 	md5(buf, n, c->sessid, nil);
119*63afb9a5SDavid du Colombier }
120*63afb9a5SDavid du Colombier 
121*63afb9a5SDavid du Colombier void
sshlog(char * f,...)122*63afb9a5SDavid du Colombier sshlog(char *f, ...)
123*63afb9a5SDavid du Colombier {
124*63afb9a5SDavid du Colombier 	char *s;
125*63afb9a5SDavid du Colombier 	va_list arg;
126*63afb9a5SDavid du Colombier 	Fmt fmt;
127*63afb9a5SDavid du Colombier 	static int pid;
128*63afb9a5SDavid du Colombier 
129*63afb9a5SDavid du Colombier 	if(pid == 0)
130*63afb9a5SDavid du Colombier 		pid = getpid();
131*63afb9a5SDavid du Colombier 
132*63afb9a5SDavid du Colombier 	va_start(arg, f);
133*63afb9a5SDavid du Colombier 	va_end(arg);
134*63afb9a5SDavid du Colombier 
135*63afb9a5SDavid du Colombier 	if(fmtstrinit(&fmt) < 0)
136*63afb9a5SDavid du Colombier 		sysfatal("fmtstrinit: %r");
137*63afb9a5SDavid du Colombier 
138*63afb9a5SDavid du Colombier 	fmtprint(&fmt, "[%d] ", pid);
139*63afb9a5SDavid du Colombier 	fmtvprint(&fmt, f, arg);
140*63afb9a5SDavid du Colombier 
141*63afb9a5SDavid du Colombier 	s = fmtstrflush(&fmt);
142*63afb9a5SDavid du Colombier 	if(s == nil)
143*63afb9a5SDavid du Colombier 		sysfatal("fmtstrflush: %r");
144*63afb9a5SDavid du Colombier 	syslog(0, "ssh", "%s", s);
145*63afb9a5SDavid du Colombier 	free(s);
146*63afb9a5SDavid du Colombier }
147*63afb9a5SDavid du Colombier 
148*63afb9a5SDavid du Colombier /*
149*63afb9a5SDavid du Colombier  * this is far too smart.
150*63afb9a5SDavid du Colombier  */
151*63afb9a5SDavid du Colombier static int
pstrcmp(const void * a,const void * b)152*63afb9a5SDavid du Colombier pstrcmp(const void *a, const void *b)
153*63afb9a5SDavid du Colombier {
154*63afb9a5SDavid du Colombier 	return strcmp(*(char**)a, *(char**)b);
155*63afb9a5SDavid du Colombier }
156*63afb9a5SDavid du Colombier 
157*63afb9a5SDavid du Colombier static char*
trim(char * s)158*63afb9a5SDavid du Colombier trim(char *s)
159*63afb9a5SDavid du Colombier {
160*63afb9a5SDavid du Colombier 	char *t;
161*63afb9a5SDavid du Colombier 	int i, last, n, nf;
162*63afb9a5SDavid du Colombier 	char **f;
163*63afb9a5SDavid du Colombier 	char *p;
164*63afb9a5SDavid du Colombier 
165*63afb9a5SDavid du Colombier 	t = emalloc(strlen(s)+1);
166*63afb9a5SDavid du Colombier 	t[0] = '\0';
167*63afb9a5SDavid du Colombier 	n = 1;
168*63afb9a5SDavid du Colombier 	for(p=s; *p; p++)
169*63afb9a5SDavid du Colombier 		if(*p == ' ')
170*63afb9a5SDavid du Colombier 			n++;
171*63afb9a5SDavid du Colombier 	f = emalloc((n+1)*sizeof(f[0]));
172*63afb9a5SDavid du Colombier 	nf = tokenize(s, f, n+1);
173*63afb9a5SDavid du Colombier 	qsort(f, nf, sizeof(f[0]), pstrcmp);
174*63afb9a5SDavid du Colombier 	last=-1;
175*63afb9a5SDavid du Colombier 	for(i=0; i<nf; i++){
176*63afb9a5SDavid du Colombier 		if(last==-1 || strcmp(f[last], f[i])!=0){
177*63afb9a5SDavid du Colombier 			if(last >= 0)
178*63afb9a5SDavid du Colombier 				strcat(t, ",");
179*63afb9a5SDavid du Colombier 			strcat(t, f[i]);
180*63afb9a5SDavid du Colombier 			last = i;
181*63afb9a5SDavid du Colombier 		}
182*63afb9a5SDavid du Colombier 	}
183*63afb9a5SDavid du Colombier 	return t;
184*63afb9a5SDavid du Colombier }
185*63afb9a5SDavid du Colombier 
186*63afb9a5SDavid du Colombier static void
usetuple(Conn * c,Ndbtuple * t,int scanentries)187*63afb9a5SDavid du Colombier usetuple(Conn *c, Ndbtuple *t, int scanentries)
188*63afb9a5SDavid du Colombier {
189*63afb9a5SDavid du Colombier 	int first;
190*63afb9a5SDavid du Colombier 	Ndbtuple *l, *e;
191*63afb9a5SDavid du Colombier 	char *s;
192*63afb9a5SDavid du Colombier 
193*63afb9a5SDavid du Colombier 	first=1;
194*63afb9a5SDavid du Colombier 	s = c->host;
195*63afb9a5SDavid du Colombier 	for(l=t; first||l!=t; l=l->line, first=0){
196*63afb9a5SDavid du Colombier 		if(scanentries){
197*63afb9a5SDavid du Colombier 			for(e=l; e; e=e->entry){
198*63afb9a5SDavid du Colombier 				if(strcmp(e->val, c->host) != 0 &&
199*63afb9a5SDavid du Colombier 				  (strcmp(e->attr, "ip")==0 || strcmp(e->attr, "dom")==0 || strcmp(e->attr, "sys")==0)){
200*63afb9a5SDavid du Colombier 					s = smprint("%s %s", s, e->val);
201*63afb9a5SDavid du Colombier 					if(s == nil)
202*63afb9a5SDavid du Colombier 						error("out of memory");
203*63afb9a5SDavid du Colombier 				}
204*63afb9a5SDavid du Colombier 			}
205*63afb9a5SDavid du Colombier 		}
206*63afb9a5SDavid du Colombier 		if(strcmp(l->val, c->host) != 0 &&
207*63afb9a5SDavid du Colombier 		  (strcmp(l->attr, "ip")==0 || strcmp(l->attr, "dom")==0 || strcmp(l->attr, "sys")==0)){
208*63afb9a5SDavid du Colombier 			s = smprint("%s %s", s, l->val);
209*63afb9a5SDavid du Colombier 			if(s == nil)
210*63afb9a5SDavid du Colombier 				error("out of memory");
211*63afb9a5SDavid du Colombier 		}
212*63afb9a5SDavid du Colombier 	}
213*63afb9a5SDavid du Colombier 	s = trim(s);
214*63afb9a5SDavid du Colombier 	c->aliases = s;
215*63afb9a5SDavid du Colombier }
216*63afb9a5SDavid du Colombier 
217*63afb9a5SDavid du Colombier void
setaliases(Conn * c,char * name)218*63afb9a5SDavid du Colombier setaliases(Conn *c, char *name)
219*63afb9a5SDavid du Colombier {
220*63afb9a5SDavid du Colombier 	char *p, *net;
221*63afb9a5SDavid du Colombier 	char *attr[2];
222*63afb9a5SDavid du Colombier 	Ndbtuple *t;
223*63afb9a5SDavid du Colombier 
224*63afb9a5SDavid du Colombier 	net = "/net";
225*63afb9a5SDavid du Colombier 	if(name[0]=='/'){
226*63afb9a5SDavid du Colombier 		p = strchr(name+1, '/');
227*63afb9a5SDavid du Colombier 		if(p){
228*63afb9a5SDavid du Colombier 			net = emalloc(p-name+1);
229*63afb9a5SDavid du Colombier 			memmove(net, name, p-name);
230*63afb9a5SDavid du Colombier 		}
231*63afb9a5SDavid du Colombier 	}
232*63afb9a5SDavid du Colombier 	if(p = strchr(name, '!'))
233*63afb9a5SDavid du Colombier 		name = p+1;
234*63afb9a5SDavid du Colombier 
235*63afb9a5SDavid du Colombier 	c->host = emalloc(strlen(name)+1);
236*63afb9a5SDavid du Colombier 	strcpy(c->host, name);
237*63afb9a5SDavid du Colombier 
238*63afb9a5SDavid du Colombier 	c->aliases = c->host;
239*63afb9a5SDavid du Colombier 	attr[0] = "dom";
240*63afb9a5SDavid du Colombier 	attr[1] = "ip";
241*63afb9a5SDavid du Colombier 	t = csipinfo(nil, ipattr(name), name, attr, 2);
242*63afb9a5SDavid du Colombier 	if(t != nil){
243*63afb9a5SDavid du Colombier 		usetuple(c, t, 0);
244*63afb9a5SDavid du Colombier 		ndbfree(t);
245*63afb9a5SDavid du Colombier 	}else{
246*63afb9a5SDavid du Colombier 		t = dnsquery(net, name, "ip");
247*63afb9a5SDavid du Colombier 		if(t != nil){
248*63afb9a5SDavid du Colombier 			usetuple(c, t, 1);
249*63afb9a5SDavid du Colombier 			ndbfree(t);
250*63afb9a5SDavid du Colombier 		}
251*63afb9a5SDavid du Colombier 	}
252*63afb9a5SDavid du Colombier }
253*63afb9a5SDavid du Colombier 
254*63afb9a5SDavid du Colombier void
privatefactotum(void)255*63afb9a5SDavid du Colombier privatefactotum(void)
256*63afb9a5SDavid du Colombier {
257*63afb9a5SDavid du Colombier 	char *user;
258*63afb9a5SDavid du Colombier 	Dir *d;
259*63afb9a5SDavid du Colombier 
260*63afb9a5SDavid du Colombier 	if((user=getuser()) && (d=dirstat("/mnt/factotum/rpc")) && strcmp(user, d->uid)!=0){
261*63afb9a5SDavid du Colombier 		/* grab the terminal's factotum */
262*63afb9a5SDavid du Colombier 		rfork(RFNAMEG);	/* was RFNOTEG, which makes little sense */
263*63afb9a5SDavid du Colombier 		if(access("/mnt/term/mnt/factotum", AEXIST) >= 0){
264*63afb9a5SDavid du Colombier //			fprint(2, "binding terminal's factotum\n");
265*63afb9a5SDavid du Colombier 			if(bind("/mnt/term/mnt/factotum", "/mnt/factotum", MREPL) < 0)
266*63afb9a5SDavid du Colombier 				sysfatal("cannot find factotum");
267*63afb9a5SDavid du Colombier 		}
268*63afb9a5SDavid du Colombier 	}
269*63afb9a5SDavid du Colombier }
270