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