|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that this notice is preserved and that due credit is given
7: * to the University of California at Berkeley. The name of the University
8: * may not be used to endorse or promote products derived from this
9: * software without specific prior written permission. This software
10: * is provided ``as is'' without express or implied warranty.
11: */
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)system.c 3.3 (Berkeley) 3/28/88";
15: #endif /* not lint */
16:
17: #include <sys/types.h>
18:
19: #if defined(pyr)
20: #define fd_set fdset_t
21: #endif /* defined(pyr) */
22:
23: #if !defined(sun) && !defined(pyr)
24: #include <sys/inode.h>
25: #else /* !defined(sun) */
26: #define IREAD 00400
27: #define IWRITE 00200
28: #endif /* !defined(sun) */
29:
30: #include <sys/file.h>
31: #include <sys/time.h>
32: #include <sys/socket.h>
33: #include <netinet/in.h>
34: #include <sys/wait.h>
35:
36: #include <errno.h>
37: extern int errno;
38:
39: #include <netdb.h>
40: #include <signal.h>
41: #include <stdio.h>
42: #include <pwd.h>
43:
44: #include "../general/general.h"
45: #include "../ctlr/api.h"
46: #include "../api/api_exch.h"
47:
48: #include "../general/globals.h"
49:
50: #ifndef FD_SETSIZE
51: /*
52: * The following is defined just in case someone should want to run
53: * this telnet on a 4.2 system.
54: *
55: */
56:
57: #define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n)))
58: #define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n)))
59: #define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n)))
60: #define FD_ZERO(p) ((p)->fds_bits[0] = 0)
61:
62: #endif
63:
64: static int shell_pid = 0;
65: static char key[50]; /* Actual key */
66: static char *keyname; /* Name of file with key in it */
67:
68: static char *ourENVlist[200]; /* Lots of room */
69:
70: static int
71: sock = -1, /* Connected socket */
72: serversock; /* Server (listening) socket */
73:
74: static enum { DEAD, UNCONNECTED, CONNECTED } state;
75:
76: static int
77: storage_location, /* Address we have */
78: storage_length = 0, /* Length we have */
79: storage_must_send = 0, /* Storage belongs on other side of wire */
80: storage_accessed = 0; /* The storage is accessed (so leave alone)! */
81:
82: static long storage[1000];
83:
84: static union REGS inputRegs;
85: static struct SREGS inputSregs;
86:
87:
88: static void
89: kill_connection()
90: {
91: state = UNCONNECTED;
92: if (sock != -1) {
93: (void) close(sock);
94: sock = -1;
95: }
96: }
97:
98:
99: static int
100: nextstore()
101: {
102: struct storage_descriptor sd;
103:
104: if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
105: storage_length = 0;
106: return -1;
107: }
108: storage_length = sd.length;
109: storage_location = sd.location;
110: if (storage_length > sizeof storage) {
111: fprintf(stderr, "API client tried to send too much storage (%d).\n",
112: storage_length);
113: storage_length = 0;
114: return -1;
115: }
116: if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
117: == -1) {
118: storage_length = 0;
119: return -1;
120: }
121: return 0;
122: }
123:
124:
125: static int
126: doreject(message)
127: char *message;
128: {
129: struct storage_descriptor sd;
130: int length = strlen(message);
131:
132: if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) {
133: return -1;
134: }
135: sd.length = length;
136: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
137: return -1;
138: }
139: if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) {
140: return -1;
141: }
142: return 0;
143: }
144:
145:
146: /*
147: * doassociate()
148: *
149: * Negotiate with the other side and try to do something.
150: *
151: * Returns:
152: *
153: * -1: Error in processing
154: * 0: Invalid password entered
155: * 1: Association OK
156: */
157:
158: static int
159: doassociate()
160: {
161: struct passwd *pwent;
162: char
163: promptbuf[100],
164: buffer[200];
165: int length;
166: int was;
167: struct storage_descriptor sd;
168:
169: if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
170: return -1;
171: }
172: sd.length = sd.length;
173: if (sd.length > sizeof buffer) {
174: doreject("(internal error) Authentication key too long");
175: return -1;
176: }
177: if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
178: return -1;
179: }
180: buffer[sd.length] = 0;
181:
182: if (strcmp(buffer, key) != 0) {
183: if ((pwent = getpwuid(geteuid())) == 0) {
184: return -1;
185: }
186: sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name);
187: if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) {
188: return -1;
189: }
190: sd.length = strlen(promptbuf);
191: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
192: == -1) {
193: return -1;
194: }
195: if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf)
196: == -1) {
197: return -1;
198: }
199: sd.length = strlen(pwent->pw_name);
200: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
201: == -1) {
202: return -1;
203: }
204: if (api_exch_outtype(EXCH_TYPE_BYTES,
205: strlen(pwent->pw_name), pwent->pw_name) == -1) {
206: return -1;
207: }
208: if (api_exch_incommand(EXCH_CMD_AUTH) == -1) {
209: return -1;
210: }
211: if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
212: == -1) {
213: return -1;
214: }
215: sd.length = sd.length;
216: if (sd.length > sizeof buffer) {
217: doreject("Password entered was too long");
218: return -1;
219: }
220: if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
221: return -1;
222: }
223: buffer[sd.length] = 0;
224:
225: /* Is this the correct password? */
226: if (strlen(pwent->pw_name)) {
227: char *ptr;
228: int i;
229:
230: ptr = pwent->pw_name;
231: i = 0;
232: while (i < sd.length) {
233: buffer[i++] ^= *ptr++;
234: if (*ptr == 0) {
235: ptr = pwent->pw_name;
236: }
237: }
238: }
239: if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) {
240: doreject("Invalid password");
241: sleep(10); /* Don't let us do too many of these */
242: return 0;
243: }
244: }
245: if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) {
246: return -1;
247: } else {
248: return 1;
249: }
250: }
251:
252:
253: void
254: freestorage()
255: {
256: char buffer[40];
257: struct storage_descriptor sd;
258:
259: if (storage_accessed) {
260: fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
261: fprintf(stderr, "(Encountered in file %s at line %d.)\n",
262: __FILE__, __LINE__);
263: quit();
264: }
265: if (storage_must_send == 0) {
266: return;
267: }
268: storage_must_send = 0;
269: if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) {
270: kill_connection();
271: return;
272: }
273: sd.length = storage_length;
274: sd.location = storage_location;
275: if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
276: kill_connection();
277: return;
278: }
279: if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
280: == -1) {
281: kill_connection();
282: return;
283: }
284: }
285:
286:
287: static int
288: getstorage(address, length, copyin)
289: int
290: address,
291: length,
292: copyin;
293: {
294: struct storage_descriptor sd;
295: char buffer[40];
296:
297: freestorage();
298: if (storage_accessed) {
299: fprintf(stderr,
300: "Internal error - attempt to get while storage accessed.\n");
301: fprintf(stderr, "(Encountered in file %s at line %d.)\n",
302: __FILE__, __LINE__);
303: quit();
304: }
305: storage_must_send = 0;
306: if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) {
307: kill_connection();
308: return -1;
309: }
310: storage_location = address;
311: storage_length = length;
312: if (copyin) {
313: sd.location = storage_location;
314: sd.length = storage_length;
315: if (api_exch_outtype(EXCH_TYPE_STORE_DESC,
316: sizeof sd, (char *)&sd) == -1) {
317: kill_connection();
318: return -1;
319: }
320: if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) {
321: fprintf(stderr, "Bad data from other side.\n");
322: fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__);
323: return -1;
324: }
325: if (nextstore() == -1) {
326: kill_connection();
327: return -1;
328: }
329: }
330: return 0;
331: }
332:
333: void
334: movetous(local, es, di, length)
335: char
336: *local;
337: int
338: es,
339: di;
340: int
341: length;
342: {
343: if (length > sizeof storage) {
344: fprintf(stderr, "Internal API error - movetous() length too long.\n");
345: fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
346: quit();
347: } else if (length == 0) {
348: return;
349: }
350: getstorage(di, length, 1);
351: memcpy(local, storage+(di-storage_location), length);
352: }
353:
354: void
355: movetothem(es, di, local, length)
356: int
357: es,
358: di;
359: char
360: *local;
361: int
362: length;
363: {
364: if (length > sizeof storage) {
365: fprintf(stderr, "Internal API error - movetothem() length too long.\n");
366: fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
367: quit();
368: } else if (length == 0) {
369: return;
370: }
371: freestorage();
372: memcpy((char *)storage, local, length);
373: storage_length = length;
374: storage_location = di;
375: storage_must_send = 1;
376: }
377:
378:
379: char *
380: access_api(location, length, copyin)
381: int
382: location,
383: length,
384: copyin; /* Do we need to copy in initially? */
385: {
386: if (storage_accessed) {
387: fprintf(stderr, "Internal error - storage accessed twice\n");
388: fprintf(stderr, "(Encountered in file %s, line %d.)\n",
389: __FILE__, __LINE__);
390: quit();
391: } else if (length != 0) {
392: freestorage();
393: getstorage(location, length, copyin);
394: storage_accessed = 1;
395: }
396: return (char *) storage;
397: }
398:
399: unaccess_api(location, local, length, copyout)
400: int location;
401: char *local;
402: int length;
403: {
404: if (storage_accessed == 0) {
405: fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n");
406: fprintf(stderr, "(Encountered in file %s, line %d.)\n",
407: __FILE__, __LINE__);
408: quit();
409: }
410: storage_accessed = 0;
411: storage_must_send = copyout; /* if needs to go back */
412: }
413:
414: /*
415: * Accept a connection from an API client, aborting if the child dies.
416: */
417:
418: static int
419: doconnect()
420: {
421: fd_set fdset;
422: int i;
423:
424: sock = -1;
425: FD_ZERO(&fdset);
426: while (shell_active && (sock == -1)) {
427: FD_SET(serversock, &fdset);
428: if ((i = select(serversock+1, &fdset, 0, 0, 0)) < 0) {
429: if (errno = EINTR) {
430: continue;
431: } else {
432: perror("in select waiting for API connection");
433: return -1;
434: }
435: } else {
436: i = accept(serversock, 0, 0);
437: if (i == -1) {
438: perror("accepting API connection");
439: return -1;
440: }
441: sock = i;
442: }
443: }
444: /* If the process has already exited, we may need to close */
445: if ((shell_active == 0) && (sock != -1)) {
446: (void) close(sock);
447: sock = -1;
448: setcommandmode(); /* In case child_died sneaked in */
449: }
450: }
451:
452: /*
453: * shell_continue() actually runs the command, and looks for API
454: * requests coming back in.
455: *
456: * We are called from the main loop in telnet.c.
457: */
458:
459: int
460: shell_continue()
461: {
462: int i;
463:
464: switch (state) {
465: case DEAD:
466: pause(); /* Nothing to do */
467: break;
468: case UNCONNECTED:
469: if (doconnect() == -1) {
470: kill_connection();
471: return -1;
472: }
473: if (api_exch_init(sock, "server") == -1) {
474: return -1;
475: }
476: while (state == UNCONNECTED) {
477: if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) {
478: kill_connection();
479: return -1;
480: } else {
481: switch (doassociate()) {
482: case -1:
483: kill_connection();
484: return -1;
485: case 0:
486: break;
487: case 1:
488: state = CONNECTED;
489: }
490: }
491: }
492: break;
493: case CONNECTED:
494: switch (i = api_exch_nextcommand()) {
495: case EXCH_CMD_REQUEST:
496: if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs,
497: (char *)&inputRegs) == -1) {
498: kill_connection();
499: } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs,
500: (char *)&inputSregs) == -1) {
501: kill_connection();
502: } else if (nextstore() == -1) {
503: kill_connection();
504: } else {
505: handle_api(&inputRegs, &inputSregs);
506: freestorage(); /* Send any storage back */
507: if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) {
508: kill_connection();
509: } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs,
510: (char *)&inputRegs) == -1) {
511: kill_connection();
512: } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs,
513: (char *)&inputSregs) == -1) {
514: kill_connection();
515: }
516: /* Done, and it all worked! */
517: }
518: break;
519: case EXCH_CMD_DISASSOCIATE:
520: kill_connection();
521: break;
522: default:
523: if (i != -1) {
524: fprintf(stderr,
525: "Looking for a REQUEST or DISASSOCIATE command\n");
526: fprintf(stderr, "\treceived 0x%02x.\n", i);
527: }
528: kill_connection();
529: break;
530: }
531: }
532: return shell_active;
533: }
534:
535:
536: static int
537: child_died()
538: {
539: union wait *status;
540: register int pid;
541:
542: while ((pid = wait3(&status, WNOHANG, 0)) > 0) {
543: if (pid == shell_pid) {
544: char inputbuffer[100];
545:
546: shell_active = 0;
547: if (sock != -1) {
548: (void) close(sock);
549: sock = -1;
550: }
551: printf("[Hit return to continue]");
552: fflush(stdout);
553: (void) gets(inputbuffer);
554: setconnmode();
555: ConnectScreen(); /* Turn screen on (if need be) */
556: (void) close(serversock);
557: (void) unlink(keyname);
558: }
559: }
560: signal(SIGCHLD, child_died);
561: }
562:
563:
564: /*
565: * Called from telnet.c to fork a lower command.com. We
566: * use the spint... routines so that we can pick up
567: * interrupts generated by application programs.
568: */
569:
570:
571: int
572: shell(argc,argv)
573: int argc;
574: char *argv[];
575: {
576: int length;
577: struct sockaddr_in server;
578: char sockNAME[100];
579: static char **whereAPI = 0;
580: int fd;
581: struct timeval tv;
582: long ikey;
583: extern long random();
584: extern char *mktemp();
585:
586: /* First, create verification file. */
587: do {
588: keyname = mktemp("/tmp/apiXXXXXX");
589: fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE);
590: } while ((fd == -1) && (errno == EEXIST));
591:
592: if (fd == -1) {
593: perror("open");
594: return 0;
595: }
596:
597: /* Now, get seed for random */
598:
599: if (gettimeofday(&tv, 0) == -1) {
600: perror("gettimeofday");
601: return 0;
602: }
603: srandom(tv.tv_usec); /* seed random number generator */
604: do {
605: ikey = random();
606: } while (ikey == 0);
607: sprintf(key, "%lu\n", ikey);
608: if (write(fd, key, strlen(key)) != strlen(key)) {
609: perror("write");
610: return 0;
611: }
612: key[strlen(key)-1] = 0; /* Get rid of newline */
613:
614: if (close(fd) == -1) {
615: perror("close");
616: return 0;
617: }
618:
619: /* Next, create the socket which will be connected to */
620: serversock = socket(AF_INET, SOCK_STREAM, 0);
621: if (serversock < 0) {
622: perror("opening API socket");
623: return 0;
624: }
625: server.sin_family = AF_INET;
626: server.sin_addr.s_addr = INADDR_ANY;
627: server.sin_port = 0;
628: if (bind(serversock, &server, sizeof server) < 0) {
629: perror("binding API socket");
630: return 0;
631: }
632: length = sizeof server;
633: if (getsockname(serversock, &server, &length) < 0) {
634: perror("getting API socket name");
635: (void) close(serversock);
636: }
637: listen(serversock, 1);
638: /* Get name to advertise in address list */
639: strcpy(sockNAME, "API3270=");
640: gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME));
641: if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) {
642: fprintf(stderr, "Local hostname too large; using 'localhost'.\n");
643: strcpy(sockNAME, "localhost");
644: }
645: sprintf(sockNAME+strlen(sockNAME), ":%d", ntohs(server.sin_port));
646: sprintf(sockNAME+strlen(sockNAME), ":%s", keyname);
647:
648: if (whereAPI == 0) {
649: char **ptr, **nextenv;
650: extern char **environ;
651:
652: ptr = environ;
653: nextenv = ourENVlist;
654: while (*ptr) {
655: if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) {
656: fprintf(stderr, "Too many environmental variables\n");
657: break;
658: }
659: *nextenv++ = *ptr++;
660: }
661: whereAPI = nextenv++;
662: *nextenv++ = 0;
663: environ = ourENVlist; /* New environment */
664: }
665: *whereAPI = sockNAME;
666:
667: child_died(); /* Start up signal handler */
668: shell_active = 1; /* We are running down below */
669: if (shell_pid = vfork()) {
670: if (shell_pid == -1) {
671: perror("vfork");
672: (void) close(serversock);
673: } else {
674: state = UNCONNECTED;
675: }
676: } else { /* New process */
677: register int i;
678:
679: for (i = 3; i < 30; i++) {
680: (void) close(i);
681: }
682: if (argc == 1) { /* Just get a shell */
683: char *cmdname;
684: extern char *getenv();
685:
686: cmdname = getenv("SHELL");
687: execlp(cmdname, cmdname, 0);
688: perror("Exec'ing new shell...\n");
689: exit(1);
690: } else {
691: execvp(argv[1], &argv[1]);
692: perror("Exec'ing command.\n");
693: exit(1);
694: }
695: /*NOTREACHED*/
696: }
697: return shell_active; /* Go back to main loop */
698: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.