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 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 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* 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* 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 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 79 atexitkill(int pid) 80 { 81 killpid[nkillpid++] = pid; 82 } 83 84 int 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 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 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 152 pstrcmp(const void *a, const void *b) 153 { 154 return strcmp(*(char**)a, *(char**)b); 155 } 156 157 static char* 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 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 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 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