home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3478 < prev    next >
Encoding:
Internet Message Format  |  1991-06-12  |  26.3 KB

  1. From: chip@chinacat.unicom.com (Chip Rosenthal)
  2. Newsgroups: alt.sources
  3. Subject: uucp over TCP/IP
  4. Message-ID: <1991Jun11.175522.22154@chinacat.unicom.com>
  5. Date: 11 Jun 91 17:55:22 GMT
  6.  
  7. I've now received about two dozen requests for this, so I figure it
  8. would be best to post.
  9.  
  10. The following package implements `uucp' over TCP/IP.  It is useful
  11. for systems which do not provide this capability.  There are two
  12. general methods for this:  TLI uucp and Berkeley uucpd.  This supports
  13. the second method.  This package has been tested with SCO XENIX (TCP
  14. 1.0) and SCO UNIX (TCP 1.1).
  15.  
  16. I'll gladly accept bug reports/fixes/hacks.
  17.  
  18. #! /bin/sh
  19. # this is a "shar" archive - run through "/bin/sh" to extract 4 files:
  20. #   README uucpm.c uucpd.c Makefile
  21. # Wrapped by chip@chinacat on Tue Jun 11 12:45:53 CDT 1991
  22. # Unpacking this archive requires:  sed test wc (possibly mkdir)
  23. # Existing files will not be clobbered unless "-c" is specified on the cmd line.
  24. if test -f README -a "$1" != "-c" ; then
  25.     echo "README: file exists - will not be overwritten"
  26. else
  27.     echo "x - README (file 1 of 4, 5277 chars)"
  28.     sed -e 's/^X//' << 'END_OF_FILE_README' > README
  29. X
  30. X               *** uucp over SCO UNIX/XENIX TCP/IP ***
  31. X
  32. XSUMMARY
  33. X
  34. X    This package provides two daemon to allow Berkeley-style uucp
  35. X    transfers over TCP/IP for SCO UNIX and SCO XENIX systems.  The
  36. X    `uucpd' daemon is a BSD UNIX program (version 5.9 6/1/90), ported
  37. X    to SCO.  It implements the slave (i.e. responding) end of the
  38. X    transfer.  The `uucpm' daemon was written specifically for this
  39. X    package.  It implements the master (i.e. initiating) end of the
  40. X    transfer.
  41. X
  42. XINSTALLATION
  43. X
  44. X    - Edit the site-specific customizations at the top of the `Makefile'.
  45. X
  46. X    - Run `make'.
  47. X
  48. X    - Install the `uucpd' and `uucpm' binaries.  I place them in a
  49. X      directory called `/etc/local'.  They may reside anywhere, but
  50. X      the rest of these directions assume that's where they are.
  51. X
  52. X    - Add a line to `/etc/inetd.conf' which says:
  53. X
  54. X    uucp    stream    tcp    nowait    root    /etc/local/uucpd uucpd
  55. X
  56. X      Yes, `uucpd' does need to run as root.
  57. X
  58. X    - Decide how many outgoing TCP/IP connections you want to support,
  59. X      and which pty(s) you wish to allocate to them.  Myself, I only
  60. X      support a single connection, and allocate the /dev/[pt]typ7
  61. X      pair.  The rest of these notes assume that configuration.
  62. X
  63. X    - Add the commands to start the `uucpm' daemon.  You could put them
  64. X      into `/etc/tcp' but I prefer not to since the `mkdev tcp' will
  65. X      trounce that script if you rerun it.  I add the command:
  66. X
  67. X        /etc/local/uucpm /dev/ptyp7
  68. X
  69. X      to an appropriate /etc/rc.d (XENIX) or /etc/rc2.d (UNIX) file.
  70. X      If you want to support multiple sessions, you will need to start
  71. X      a `uucpm' daemon upon each of the pty's selected.
  72. X
  73. X    - Declare the pty device(s) available for uucp.  This may be done with
  74. X      an entry in your /usr/lib/uucp/Devices file such as:
  75. X
  76. X        TCPIP  ttyp7  -  19200  direct
  77. X
  78. X      Note that `uucpm' was started on the master end of the pty
  79. X      (ptyp7), but here we give the slave end (ttyp7).  If you are
  80. X      supporting multiple sessions, provide similar entries for all
  81. X      of the pty's.
  82. X
  83. X    - Finally, enter the /usr/lib/uucp/Systems information for machines
  84. X      on the network:
  85. X
  86. X        coldsnap Any TCPIP Any - "" coldsnap gin: NAME word: PASSWORD
  87. X                     ^^^^^^^^^^^
  88. X
  89. X      The highlighted portion of the chat script is where the connection
  90. X      to the remote machine is established.  All you need to do is
  91. X      send out the machine name, and the `uucpm' daemon will establish
  92. X      a socket to the specified machine.  If there is no password on
  93. X      the account, `uucpd' will not prompt for one, and thus it may
  94. X      be left off.  Also note that for security reasons, `uucpd'
  95. X      insists that the login shell is `/usr/lib/uucp/uucico'.
  96. X
  97. X    - You are now ready to roll.  Remember - to test this stuff out
  98. X      you will need to either:  (1) `kill -1' the init process and
  99. X      manually start the `uucpm' daemon, or (2) reboot the system.
  100. X      `uucpm' has an undocumented `-D' switch to run in a debugging
  101. X      (non-daemon) mode.
  102. X
  103. X
  104. XTHEORY OF OPERATION - SLAVE SIDE
  105. X
  106. X    When a connection is established upon port 540, the `well known
  107. X    port' for uucp, the `inetd' superserver starts up the `uucpd'
  108. X    program.  This program prompts for and receives (through the
  109. X    network) the username and password for a uucp login.  It does the
  110. X    loginish things, like setup an environment and make /etc/wtmp
  111. X    entries.  Then, it forks off a child to run `uucico' for the remote
  112. X    system.  When `uucico' terminates `uucpd' cleans up (i.e.  makes
  113. X    the logout entry into /etc/wtmp, shuts down the socket, etc.) and
  114. X    terminates.
  115. X
  116. X
  117. XTHEORY OF OPERATION - MASTER SIDE
  118. X
  119. X    The `uucpm' daemon sits upon the master end of a pty, waiting for
  120. X    an incoming request.  When `uucico' attempts a connection to a
  121. X    networked system, it selects one of the TCPIP devices - the slave
  122. X    end of the pty.  `uucpm' reads one CR delimited line - the name
  123. X    of the remote system.  The chat script shown above starts with an
  124. X    `expect nothing/send system name' sequence, which provides `uucpm'
  125. X    the information it requires.  `uucpm' then attempts to establish
  126. X    a socket to port 540 on the named system, and if successful just
  127. X    passes data between the pty and the socket.  When either the socket
  128. X    shuts down (i.e. the remote slave uucico finishes) or the pty
  129. X    shuts down (i.e. the local master uucico finishes), `uucpm' closes
  130. X    up everything and reopens the pty awaiting another request.
  131. X
  132. X
  133. XWISHLIST
  134. X
  135. X    I am particularly unhappy with the way `uucpd' handles the /etc/wtmp
  136. X    file.  I think it could record more useful information.  It's also
  137. X    crummy that you always get a logout entry made - even if the login
  138. X    wasn't successful.  Unfortunately - this is extremely difficult
  139. X    to fix and still maintain compatibility with the non-inetd form
  140. X    of `uucpd'.  I'm tempted to rip that out and fix the wtmp stuff.
  141. X
  142. X    If somebody wanted to get fancy, it is theoretically possible to
  143. X    do a version of `uucpm' run as an SCO binary dialer.  That would
  144. X    avoid having to have a daemon laying around.  I'm not sure it's
  145. X    is worth it - it's certainly of no use on non-SCO systems.
  146. X
  147. X
  148. XChip Rosenthal
  149. X<chip@chinacat.unicom.com>
  150. XUnicom Systems Development, Inc.
  151. X
  152. X@(#) README 1.1 91/06/07 01:27:43
  153. X
  154. END_OF_FILE_README
  155.     size="`wc -c < README`"
  156.     if test 5277 -ne "$size" ; then
  157.     echo "README: extraction error - got $size chars"
  158.     fi
  159. fi
  160. if test -f uucpm.c -a "$1" != "-c" ; then
  161.     echo "uucpm.c: file exists - will not be overwritten"
  162. else
  163.     echo "x - uucpm.c (file 2 of 4, 7915 chars)"
  164.     sed -e 's/^X//' << 'END_OF_FILE_uucpm.c' > uucpm.c
  165. X/*
  166. X * uucpm - daemon to run master uucico process over TCP/IP network
  167. X *
  168. X * Chip Rosenthal <chip@chinacat.unicom.com>
  169. X * Unicom Systems Development, Inc.
  170. X *
  171. X * This program detatches itself to become a daemon, and then runs through
  172. X * an infinite loop - one iteration per uucico invocation.  At the top of
  173. X * the loop, it opens the master end of a pty.  When a uucico process opens
  174. X * the slave end, this program reads in the name of the target machine,
  175. X * establishes a socket to "uucpd" on that machine, and then passes data
  176. X * between the socket and pty.  When EOF is reached upon either the socket
  177. X * or the pty, both are shutdown, and the pty is reopened to await another
  178. X * uucico invocation.
  179. X */
  180. X
  181. X#ifndef lint
  182. Xstatic char SCCSID[] = "@(#) uucpm.c 1.2 91/06/11 12:45:16";
  183. X#endif
  184. X
  185. X#include <sys/types.h>
  186. X#include <sys/socket.h>
  187. X#include <netinet/in.h>
  188. X#include <netdb.h>
  189. X#include <syslog.h>
  190. X#include <signal.h>
  191. X#include <stdio.h>
  192. X#include <fcntl.h>
  193. X
  194. X#define USAGE    "usage: %s master_pty\n"
  195. X
  196. Xextern int errno;
  197. Xextern char *sys_errlist[];
  198. X#define errmssg    sys_errlist[errno]
  199. X
  200. X#define Dprintf if ( !Debug ) ; else fprintf
  201. Xint Debug = 0;
  202. X
  203. Xsigcatcher(sig)
  204. Xint sig;
  205. X{
  206. X    syslog(LOG_INFO, "caught signal %d - terminating", sig);
  207. X    exit(0);
  208. X}
  209. X
  210. Xmain(argc, argv)
  211. Xint argc;
  212. Xchar *argv[];
  213. X{
  214. X    int sfd, pfd, numfd, n;
  215. X    char host[64], buf[512], *ptypath;
  216. X    struct sockaddr_in sin;
  217. X    struct servent *sp;
  218. X    struct hostent *hp;
  219. X    fd_set fdset;
  220. X
  221. X    /*
  222. X     * Crack command line.
  223. X     */
  224. X    if ( argc == 2 ) {
  225. X        ptypath = argv[1];
  226. X    } else if ( argc == 3 && strcmp(argv[1], "-D") == 0 ) {
  227. X        ++Debug;
  228. X        ptypath = argv[2];
  229. X    } else {
  230. X        fprintf(stderr, USAGE, argv[0]);
  231. X        exit(1);
  232. X    }
  233. X
  234. X    /*
  235. X     * Verify the pty exists.
  236. X     */
  237. X    if ( access(ptypath, 06) != 0 ) {
  238. X        fprintf(stderr, "%s: can't access '%s' [%s]\n",
  239. X            argv[0], ptypath, errmssg);
  240. X        exit(1);
  241. X    }
  242. X
  243. X    openlog("uucpm", LOG_PID|LOG_CONS, LOG_DAEMON);
  244. X
  245. X    /*
  246. X     * Setup as daemon.
  247. X     */
  248. X    if ( !Debug ) {
  249. X
  250. X        /*
  251. X         * Fork off child process.
  252. X         */
  253. X        switch ( fork() ) {
  254. X            case -1:    syslog(LOG_ERR, "fork failed [%s]", errmssg); exit(1);
  255. X            case 0:        break;
  256. X            default:    exit(0);
  257. X        }
  258. X
  259. X        /*
  260. X         * Detatch from controlling terminal.
  261. X         */
  262. X        if ( setpgrp() < 0 ) {
  263. X            syslog(LOG_ERR, "process group detatch failed [%s]", errmssg);
  264. X            exit(1);
  265. X        }
  266. X        for ( n = 1 ; n <= NSIG ; ++n ) {
  267. X            switch ( n ) {
  268. X                case SIGHUP:    (void) signal(n, SIG_IGN); break;
  269. X                case SIGCLD:    (void) signal(n, SIG_DFL); break;
  270. X                default:        (void) signal(n, sigcatcher); break;
  271. X            }
  272. X        }
  273. X        (void) close(0);
  274. X        (void) close(1);
  275. X        (void) close(2);
  276. X        (void) chdir("/");
  277. X        (void) umask(0);
  278. X
  279. X        /*
  280. X         * Fork again so we become owned by init.
  281. X         */
  282. X        switch ( fork() ) {
  283. X            case -1:    syslog(LOG_ERR, "fork failed [%s]", errmssg); exit(1);
  284. X            case 0:        break;
  285. X            default:    exit(0);
  286. X        }
  287. X
  288. X    }
  289. X
  290. X    /*
  291. X     * Once through loop per uucp connection request.
  292. X     */
  293. X    syslog(LOG_INFO, "daemon running on '%s'", ptypath);
  294. X    sfd = pfd = -1;
  295. X    for (;;) {
  296. X
  297. X        /*
  298. X         * Shutdown any fd's open from last time.  Pause when shutting down
  299. X         * pty to allow uucico to close down and release the slave end.  The
  300. X         * sleep is ugly, but the alternatives (I can think of) are even
  301. X         * uglier (e.g. find the PID which has it locked and busy wait until
  302. X         * that PID terminates).
  303. X         */
  304. X        if ( sfd >= 0 ) {
  305. X            (void) close(sfd);
  306. X            sfd = -1;
  307. X        }
  308. X        if ( pfd >= 0 ) {
  309. X            (void) close(pfd);
  310. X            pfd = -1;
  311. X            sleep(5);
  312. X        }
  313. X
  314. X        /*
  315. X         * Open up the master side of the pty.
  316. X         */
  317. X        if ( (pfd=open(ptypath, O_RDWR)) < 0 ) {
  318. X            syslog(LOG_ERR, "open '%s' failed [%s]", ptypath, errmssg);
  319. X            exit(1);
  320. X        }
  321. X
  322. X        /*
  323. X         * Block until the slave side is opened, i.e. the pty is writeable.
  324. X         */
  325. X        Dprintf(stderr, "opened pty '%s' - blocking for slave\n", ptypath);
  326. X        FD_ZERO(&fdset);
  327. X        FD_SET(pfd, &fdset);
  328. X        if ( select(pfd+1, (fd_set *)0, &fdset, (fd_set *)0,
  329. X                (struct timeval *)0) < 0 || !FD_ISSET(pfd, &fdset) ) {
  330. X            syslog(LOG_ERR, "select failed [%s]", errmssg);
  331. X            continue;
  332. X        }
  333. X
  334. X        /*
  335. X         * Read in the host name.
  336. X         */
  337. X        Dprintf(stderr, "slave active - waiting for uucp request\n");
  338. X        if ( rdline(pfd, host, sizeof(host)) < 0 ) {
  339. X            syslog(LOG_ERR, "host name read on '%s' failed [%s]",
  340. X                ptypath, errmssg);
  341. X            continue;
  342. X        }
  343. X
  344. X        /*
  345. X         * Get the host and service information.
  346. X         */
  347. X        if ( (hp=gethostbyname(host)) == NULL ) {
  348. X            syslog(LOG_ERR, "host '%s' lookup failed", host);
  349. X            sprintf(buf, "error - unknown host '%s'\n", host);
  350. X            (void) wrbuf(pfd, "pty", buf, strlen(buf));
  351. X            continue;
  352. X        }
  353. X        if ( (sp=getservbyname("uucp", "tcp")) == NULL ) {
  354. X            syslog(LOG_ERR, "service 'uucp/tcp' lookup failed");
  355. X            exit(1);
  356. X        }
  357. X        Dprintf(stderr, "attempting connection - host %s, addr %s, port %d\n",
  358. X            host,
  359. X            inet_ntoa(*((struct in_addr *)hp->h_addr)),
  360. X            ntohs(sp->s_port)
  361. X        );
  362. X
  363. X        /*
  364. X         * Setup the socket to "uucpd" on the slave system.
  365. X         */
  366. X        bzero((char *)&sin, sizeof(sin));
  367. X        bcopy(hp->h_addr, (char*)&sin.sin_addr , hp->h_length);
  368. X        sin.sin_family = hp->h_addrtype;
  369. X        sin.sin_port = sp->s_port;
  370. X        if ( (sfd=socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
  371. X            syslog(LOG_ERR, "socket create failed [%s]", errmssg);
  372. X            continue;
  373. X        }
  374. X        if ( connect(sfd, (char *)&sin, sizeof(sin)) < 0 ) {
  375. X            syslog(LOG_ERR, "socket connect failed [%s]", errmssg);
  376. X            continue;
  377. X        }
  378. X
  379. X        /*
  380. X         * Multiplex the data between the local and remote uucico's.
  381. X         */
  382. X        numfd = ( pfd > sfd ? pfd : sfd ) + 1;
  383. X        Dprintf(stderr, "connect successful\n");
  384. X        for (;;) {
  385. X
  386. X            /*
  387. X             * Wait for some data to read.
  388. X             */
  389. X            FD_ZERO(&fdset);
  390. X            FD_SET(pfd, &fdset);
  391. X            FD_SET(sfd, &fdset);
  392. X            if ( select(numfd, &fdset, (fd_set *)0, (fd_set *)0,
  393. X                    (struct timeval *)0) < 0 ) {
  394. X                syslog(LOG_ERR, "select failed [%s]", errmssg);
  395. X                break;
  396. X            }
  397. X
  398. X            /*
  399. X             * Pass data from the pty to the socket.
  400. X             */
  401. X            if ( FD_ISSET(pfd, &fdset) ) {
  402. X                if ( (n=rdbuf(pfd, "pty", buf, sizeof(buf))) <= 0 )
  403. X                    break;
  404. X                if ( wrbuf(sfd, "socket", buf, n) < 0 )
  405. X                    break;
  406. X                continue;
  407. X            }
  408. X
  409. X            /*
  410. X             * Pass data from the socket to the pty.
  411. X             */
  412. X            if ( FD_ISSET(sfd, &fdset) ) {
  413. X                if ( (n=rdbuf(sfd, "socket", buf, sizeof(buf))) <= 0 )
  414. X                    break;
  415. X                if ( wrbuf(pfd, "pty", buf, n) < 0 )
  416. X                    break;
  417. X                continue;
  418. X            }
  419. X
  420. X            /* why did we wakeup?? */
  421. X
  422. X        }
  423. X
  424. X        /*
  425. X         * The uucico session is complete.  Loop back to wait for another
  426. X         * session.  The pty and socket fd's will be shutdown at the top
  427. X         * of the loop.
  428. X         */
  429. X
  430. X    }
  431. X
  432. X    /*NOTREACHED*/
  433. X
  434. X}
  435. X
  436. X
  437. X/*
  438. X * Read in a CR-terminated line of text.
  439. X * Return 0 upon success, -1 upon failure.
  440. X */
  441. Xint rdline(fd, buf, n)
  442. Xint fd;                    /* file descriptor to read from        */
  443. Xchar *buf;                /* place to stick the text            */
  444. Xint n;                    /* maximum number of chars to read    */
  445. X{
  446. X    while ( --n > 0 ) {
  447. X        if ( read(fd, buf, 1) != 1 )
  448. X            return -1;
  449. X        if ( *buf == '\r' )
  450. X            break;
  451. X        ++buf;
  452. X    }
  453. X    *buf = '\0';
  454. X    return 0;
  455. X}
  456. X
  457. X
  458. X/*
  459. X * Read in a bufferful of data.
  460. X * Returns number of bytes read, 0 upon EOF, -1 upon error.
  461. X */
  462. Xint rdbuf(fd, name, buf, buflen)
  463. Xint fd;                    /* file descriptor to read from        */
  464. Xchar *name;                /* name to use in diagnostics        */
  465. Xchar *buf;                /* place to stick the data            */
  466. Xint buflen;                /* maximum number of bytes to read    */
  467. X{
  468. X    register int n;
  469. X
  470. X    if ( (n=read(fd, buf, (unsigned)buflen)) < 0 ) {
  471. X        syslog(LOG_ERR, "%s read error [%s]", name, errmssg);
  472. X        return -1;
  473. X    }
  474. X    if ( n == 0 ) {
  475. X        Dprintf(stderr, "hangup on %s\n", name);
  476. X        return 0;
  477. X    }
  478. X    Dprintf(stderr, "read from %s %d bytes\n", name, n);
  479. X    return n;
  480. X}
  481. X
  482. X
  483. X/*
  484. X * Write out a bufferful of data.
  485. X * Returns 0 upon success, -1 upon error.
  486. X */
  487. Xint wrbuf(fd, name, buf, buflen)
  488. Xint fd;                    /* file descriptor to write to        */
  489. Xchar *name;                /* name to use in diagnostics        */
  490. Xregister char *buf;        /* the data to write out            */
  491. Xregister int buflen;    /* number of bytes to write            */
  492. X{
  493. X    register int n;
  494. X
  495. X    while ( buflen > 0 ) {
  496. X        if ( (n=write(fd, buf, (unsigned)buflen)) < 0 ) {
  497. X            syslog(LOG_ERR, "%s write error [%s]", name, errmssg);
  498. X            return -1;
  499. X        }
  500. X        Dprintf(stderr, "write to %s %d bytes\n", name, n);
  501. X        buflen -= n;
  502. X        buf += n;
  503. X    }
  504. X    return 0;
  505. X}
  506. X
  507. END_OF_FILE_uucpm.c
  508.     size="`wc -c < uucpm.c`"
  509.     if test 7915 -ne "$size" ; then
  510.     echo "uucpm.c: extraction error - got $size chars"
  511.     fi
  512. fi
  513. if test -f uucpd.c -a "$1" != "-c" ; then
  514.     echo "uucpd.c: file exists - will not be overwritten"
  515. else
  516.     echo "x - uucpd.c (file 3 of 4, 8481 chars)"
  517.     sed -e 's/^X//' << 'END_OF_FILE_uucpd.c' > uucpd.c
  518. X/*
  519. X * @(#) uucpd.c 1.1 91/06/07 01:33:44
  520. X *
  521. X * Chip Rosenthal <chip@chinacat.unicom.com>
  522. X * Unicom Systems Development, Inc.
  523. X *
  524. X * Ported to System Vr3.2 and XENIX V.  Compile with -DSYSV defined.
  525. X * Tested on SCO XENIX (TCP 1.0.1h) and SCO UNIX (TCP 1.1.3x).
  526. X *    Compile with -DLAI_TCP defined.
  527. X * Only tested under "inetd".  Compile with -DBSDINET defined.
  528. X * Made "lastlog" logging optional.  Omit by -DNO_LASTLOG.
  529. X * Made "(struct utmp *)->ut_host" optional.  Omit with -DNO_UTHOST.
  530. X * Added support to obtain password from "/etc/shadow".  Define -DSHADOWPWD.
  531. X * Support for the SCO/Secureware wretched monstrosity.  Use -DSECURECRAP.
  532. X */
  533. X
  534. X/*
  535. X * Copyright (c) 1985 The Regents of the University of California.
  536. X * All rights reserved.
  537. X *
  538. X * This code is derived from software contributed to Berkeley by
  539. X * Rick Adams.
  540. X *
  541. X * Redistribution and use in source and binary forms are permitted
  542. X * provided that: (1) source distributions retain this entire copyright
  543. X * notice and comment, and (2) distributions including binaries display
  544. X * the following acknowledgement:  ``This product includes software
  545. X * developed by the University of California, Berkeley and its contributors''
  546. X * in the documentation or other materials provided with the distribution
  547. X * and in all advertising materials mentioning features or use of this
  548. X * software. Neither the name of the University nor the names of its
  549. X * contributors may be used to endorse or promote products derived
  550. X * from this software without specific prior written permission.
  551. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  552. X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  553. X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  554. X */
  555. X
  556. X#ifndef lint
  557. Xchar copyright[] =
  558. X"@(#) Copyright (c) 1985 The Regents of the University of California.\n\
  559. X All rights reserved.\n";
  560. X#endif /* not lint */
  561. X
  562. X#ifndef lint
  563. Xstatic char sccsid[] = "@(#)uucpd.c    5.9 (Berkeley) 6/1/90";
  564. X#endif /* not lint */
  565. X
  566. X/*
  567. X * 4.2BSD TCP/IP server for uucico
  568. X * uucico's TCP channel causes this server to be run at the remote end.
  569. X */
  570. X
  571. X#include <sys/types.h>
  572. X#include <sys/socket.h>
  573. X#ifdef SYSV
  574. X#include <fcntl.h>
  575. X#else
  576. X#include <sys/wait.h>
  577. X#include <sys/ioctl.h>
  578. X#include <sys/file.h>
  579. X#endif
  580. X#include <netinet/in.h>
  581. X#include <netdb.h>
  582. X#include <signal.h>
  583. X#include <errno.h>
  584. X#include <pwd.h>
  585. X#include <stdio.h>
  586. X#ifdef SHADOWPWD
  587. X#include <shadow.h>
  588. X#endif
  589. X#ifdef SECURECRAP
  590. X#define SecureWare
  591. X#include <sys/security.h>
  592. X#include <prot.h>
  593. X#endif
  594. X#ifdef SYSV
  595. X#define    _PATH_UUCICO    "/usr/lib/uucp/uucico"
  596. X#define _PATH_WTMP    "/etc/wtmp"
  597. X#else
  598. X#include "pathnames.h"
  599. X#endif
  600. X
  601. Xstruct    sockaddr_in hisctladdr;
  602. Xint hisaddrlen = sizeof hisctladdr;
  603. Xstruct    sockaddr_in myctladdr;
  604. Xint mypid;
  605. X
  606. Xchar Username[64];
  607. Xchar *nenv[] = {
  608. X    Username,
  609. X    NULL,
  610. X};
  611. Xextern char **environ;
  612. X
  613. Xmain(argc, argv)
  614. Xint argc;
  615. Xchar **argv;
  616. X{
  617. X#ifndef BSDINETD
  618. X    register int s, tcp_socket;
  619. X    struct servent *sp;
  620. X#endif /*!BSDINETD*/
  621. X    extern int errno;
  622. X    int dologout();
  623. X
  624. X#ifdef SECURECRAP
  625. X    setluid(getuid());
  626. X#endif
  627. X
  628. X    environ = nenv;
  629. X#ifdef BSDINETD
  630. X    close(1); close(2);
  631. X    dup(0); dup(0);
  632. X    hisaddrlen = sizeof (hisctladdr);
  633. X    if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) {
  634. X        fprintf(stderr, "%s: ", argv[0]);
  635. X        perror("getpeername");
  636. X        _exit(1);
  637. X    }
  638. X    if (fork() == 0) {
  639. X        doit(&hisctladdr);
  640. X        exit(1);
  641. X    }
  642. X    dologout();
  643. X    exit(1);
  644. X#else /*!BSDINETD*/
  645. X    sp = getservbyname("uucp", "tcp");
  646. X    if (sp == NULL){
  647. X        perror("uucpd: getservbyname");
  648. X        exit(1);
  649. X    }
  650. X    if (fork())
  651. X        exit(0);
  652. X    if ((s=open(_PATH_TTY, 2)) >= 0){
  653. X        ioctl(s, TIOCNOTTY, (char *)0);
  654. X        close(s);
  655. X    }
  656. X
  657. X    bzero((char *)&myctladdr, sizeof (myctladdr));
  658. X    myctladdr.sin_family = AF_INET;
  659. X    myctladdr.sin_port = sp->s_port;
  660. X#ifdef BSD4_2
  661. X    tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
  662. X    if (tcp_socket < 0) {
  663. X        perror("uucpd: socket");
  664. X        exit(1);
  665. X    }
  666. X    if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) {
  667. X        perror("uucpd: bind");
  668. X        exit(1);
  669. X    }
  670. X    listen(tcp_socket, 3);    /* at most 3 simultaneuos uucp connections */
  671. X    signal(SIGCHLD, dologout);
  672. X
  673. X    for(;;) {
  674. X        s = accept(tcp_socket, &hisctladdr, &hisaddrlen);
  675. X        if (s < 0){
  676. X            if (errno == EINTR) 
  677. X                continue;
  678. X            perror("uucpd: accept");
  679. X            exit(1);
  680. X        }
  681. X        if (fork() == 0) {
  682. X            close(0); close(1); close(2);
  683. X            dup(s); dup(s); dup(s);
  684. X            close(tcp_socket); close(s);
  685. X            doit(&hisctladdr);
  686. X            exit(1);
  687. X        }
  688. X        close(s);
  689. X    }
  690. X#endif /*BSD4_2*/
  691. X
  692. X#endif    /*!BSDINETD*/
  693. X}
  694. X
  695. Xdoit(sinp)
  696. Xstruct sockaddr_in *sinp;
  697. X{
  698. X    char user[64], passwd[64];
  699. X    char *xpasswd, *crypt();
  700. X    struct passwd *pw, *getpwnam();
  701. X
  702. X    alarm(60);
  703. X    printf("login: "); fflush(stdout);
  704. X    if (readline(user, sizeof user) < 0) {
  705. X        fprintf(stderr, "user read\n");
  706. X        return;
  707. X    }
  708. X    /* truncate username to 8 characters */
  709. X    user[8] = '\0';
  710. X    pw = getpwnam(user);
  711. X    if (pw == NULL) {
  712. X        fprintf(stderr, "user unknown\n");
  713. X        return;
  714. X    }
  715. X#ifdef SHADOWPWD /*{*/
  716. X    {
  717. X        struct spwd *spw;
  718. X        if ( (spw=getspnam(user)) == NULL ) {
  719. X            fprintf(stderr, "user unknown\n");
  720. X            return;
  721. X        }
  722. X        pw->pw_passwd = spw->sp_pwdp;
  723. X    }
  724. X#endif /*}SHADOWPWD*/
  725. X#ifdef SECURECRAP /*{*/
  726. X    {
  727. X        struct pr_passwd *prpw;
  728. X        static char *av[] = { "uucpd", NULL };
  729. X        set_auth_parameters(1,av);
  730. X        if ( (prpw=getprpwnam(user)) == NULL ) {
  731. X            fprintf(stderr, "user unknown\n");
  732. X            return;
  733. X        }
  734. X        pw->pw_passwd = prpw->ufld.fd_encrypt;
  735. X    }
  736. X#endif /*}SECURECRAP*/
  737. X    if (strcmp(pw->pw_shell, _PATH_UUCICO)) {
  738. X        fprintf(stderr, "Login incorrect.\n");
  739. X        return;
  740. X    }
  741. X    if (pw->pw_passwd && *pw->pw_passwd != '\0') {
  742. X        printf("Password: "); fflush(stdout);
  743. X        if (readline(passwd, sizeof passwd) < 0) {
  744. X            fprintf(stderr, "passwd read\n");
  745. X            return;
  746. X        }
  747. X        xpasswd = crypt(passwd, pw->pw_passwd);
  748. X        if (strcmp(xpasswd, pw->pw_passwd)) {
  749. X            fprintf(stderr, "Login incorrect.\n");
  750. X            return;
  751. X        }
  752. X    }
  753. X    alarm(0);
  754. X    sprintf(Username, "USER=%s", user);
  755. X    dologin(pw, sinp);
  756. X    setgid(pw->pw_gid);
  757. X#ifdef BSD4_2
  758. X    initgroups(pw->pw_name, pw->pw_gid);
  759. X#endif /*BSD4_2*/
  760. X    chdir(pw->pw_dir);
  761. X    setuid(pw->pw_uid);
  762. X#ifdef BSD4_2
  763. X    execl(UUCICO, "uucico", (char *)0);
  764. X#endif /*BSD4_2*/
  765. X#ifdef SYSV
  766. X    execl(_PATH_UUCICO, "uucico", (char *)0);
  767. X#endif
  768. X    perror("uucico server: execl");
  769. X}
  770. X
  771. Xreadline(p, n)
  772. Xregister char *p;
  773. Xregister int n;
  774. X{
  775. X    char c;
  776. X
  777. X    while (n-- > 0) {
  778. X        if (read(0, &c, 1) <= 0)
  779. X            return(-1);
  780. X        c &= 0177;
  781. X        if (c == '\n' || c == '\r') {
  782. X            *p = '\0';
  783. X            return(0);
  784. X        }
  785. X        *p++ = c;
  786. X    }
  787. X    return(-1);
  788. X}
  789. X
  790. X#include <utmp.h>
  791. X#ifdef BSD4_2
  792. X#include <fcntl.h>
  793. X#endif /*BSD4_2*/
  794. X
  795. X#define    SCPYN(a, b)    strncpy(a, b, sizeof (a))
  796. X
  797. Xstruct    utmp utmp;
  798. X
  799. Xdologout()
  800. X{
  801. X#ifdef SYSV
  802. X    int status;
  803. X#else
  804. X    union wait status;
  805. X#endif
  806. X    char line[32];
  807. X    int pid, wtmp;
  808. X
  809. X#ifdef BSDINETD
  810. X    while ((pid=wait(&status)) > 0) {
  811. X#else  /*!BSDINETD*/
  812. X    while ((pid=wait3(&status,WNOHANG,0)) > 0) {
  813. X#endif /*!BSDINETD*/
  814. X        wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
  815. X        if (wtmp >= 0) {
  816. X            sprintf(line, "uucp%.04d", pid%10000);
  817. X            SCPYN(utmp.ut_line, line);
  818. X            SCPYN(utmp.ut_name, "");
  819. X#ifndef NO_UTHOST
  820. X            SCPYN(utmp.ut_host, "");
  821. X#endif
  822. X            (void) time(&utmp.ut_time);
  823. X#ifdef SYSV
  824. X            utmp.ut_type = DEAD_PROCESS;
  825. X            utmp.ut_pid = getpid();
  826. X            utmp.ut_exit.e_termination = status & 0xFF;
  827. X            utmp.ut_exit.e_exit = (status>>8) & 0xFF;
  828. X#endif
  829. X            (void) write(wtmp, (char *)&utmp, sizeof (utmp));
  830. X            (void) close(wtmp);
  831. X        }
  832. X    }
  833. X}
  834. X
  835. X/*
  836. X * Record login in wtmp file.
  837. X */
  838. Xdologin(pw, sin)
  839. Xstruct passwd *pw;
  840. Xstruct sockaddr_in *sin;
  841. X{
  842. X    char line[32];
  843. X    char remotehost[32];
  844. X    int wtmp;
  845. X#ifndef NO_LASTLOG
  846. X    int f;
  847. X#endif
  848. X    struct hostent *hp = gethostbyaddr(&sin->sin_addr,
  849. X        sizeof (struct in_addr), AF_INET);
  850. X
  851. X    if (hp) {
  852. X        strncpy(remotehost, hp->h_name, sizeof (remotehost));
  853. X        endhostent();
  854. X    } else
  855. X        strncpy(remotehost, inet_ntoa(sin->sin_addr),
  856. X            sizeof (remotehost));
  857. X    wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND);
  858. X    if (wtmp >= 0) {
  859. X        /* hack, but must be unique and no tty line */
  860. X        sprintf(line, "uucp%.04d", getpid()%10000);
  861. X        SCPYN(utmp.ut_line, line);
  862. X        SCPYN(utmp.ut_name, pw->pw_name);
  863. X#ifndef NO_UTHOST
  864. X        SCPYN(utmp.ut_host, remotehost);
  865. X#endif
  866. X        time(&utmp.ut_time);
  867. X#ifdef SYSV
  868. X        utmp.ut_type = USER_PROCESS;
  869. X        utmp.ut_pid = getpid();
  870. X        utmp.ut_exit.e_termination = 0;
  871. X        utmp.ut_exit.e_exit = 0;
  872. X#endif
  873. X        (void) write(wtmp, (char *)&utmp, sizeof (utmp));
  874. X        (void) close(wtmp);
  875. X    }
  876. X#ifndef NO_LASTLOG
  877. X    if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) {
  878. X        struct lastlog ll;
  879. X
  880. X        time(&ll.ll_time);
  881. X        lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0);
  882. X        strcpy(line, remotehost);
  883. X        SCPYN(ll.ll_line, line);
  884. X        SCPYN(ll.ll_host, remotehost);
  885. X        (void) write(f, (char *) &ll, sizeof ll);
  886. X        (void) close(f);
  887. X    }
  888. X#endif
  889. X}
  890. END_OF_FILE_uucpd.c
  891.     size="`wc -c < uucpd.c`"
  892.     if test 8481 -ne "$size" ; then
  893.     echo "uucpd.c: extraction error - got $size chars"
  894.     fi
  895. fi
  896. if test -f Makefile -a "$1" != "-c" ; then
  897.     echo "Makefile: file exists - will not be overwritten"
  898. else
  899.     echo "x - Makefile (file 4 of 4, 1784 chars)"
  900.     sed -e 's/^X//' << 'END_OF_FILE_Makefile' > Makefile
  901. X# @(#) Makefile 1.2 91/06/11 12:45:15
  902. X
  903. XSHELL = /bin/sh
  904. XCC = cc
  905. XALL = uucpm uucpd
  906. XLINT = uucpm.lint uucpd.lint
  907. XSRCS = README uucpm.c uucpd.c Makefile
  908. X
  909. Xall: $(ALL)
  910. Xlint: $(LINT)
  911. X
  912. X##############################################################################
  913. X#
  914. X# Site-specific customizations.
  915. X#
  916. X
  917. X#
  918. X# Site-specific definitions for networking.  SCO needs "-DLAI_TCP".
  919. X#
  920. XSITEDEFS = -DLAI_TCP
  921. X
  922. X#
  923. X# Enable the following for SCO UNIX.
  924. X#
  925. X#SECURECRAP = -DSECURECRAP
  926. X#LDPROT = -lprot
  927. X
  928. X#
  929. X# Enable the following for /etc/shadow support.
  930. X#
  931. XSHADOWPWD = -DSHADOWPWD
  932. XLDSHADOW = -lshadow
  933. X
  934. X#
  935. X# Define to point to your socket library - maybe "-lsocket", maybe "-linet".
  936. X#
  937. XLDSOCKET = -lsocket
  938. X
  939. X#
  940. X# Define to point to your crypt library - usually "-lcrypt".
  941. X#
  942. XLDCRYPT = -lcrypt
  943. X
  944. X#
  945. X# You probably want to define the following as "cp".
  946. X#
  947. XINST = inst -D
  948. X
  949. X#
  950. X# Enable the following if files are checked into SCCS.
  951. X#
  952. X$(SRCS) : SCCS/s.$$@ ; sccs get $@
  953. Xclobber : clean ; sccs clean ; sccs get Makefile
  954. X
  955. X#
  956. X##############################################################################
  957. X
  958. X
  959. XDEFS_M = $(SITEDEFS)
  960. XDEFS_D = -DSYSV -DBSDINETD -DNO_LASTLOG -DNO_UTHOST \
  961. X        $(SITEDEFS) $(SHADOWPWD) $(SECURECRAP)
  962. XLIBS_M = $(LDSOCKET)
  963. XLIBS_D = $(LDSOCKET) $(LDCRYPT) $(LDSHADOW) $(LDPROT)
  964. X
  965. Xclean:
  966. X    rm -f $(ALL) $(LINT) *.o a.out core
  967. X
  968. Xinstall: all
  969. X    $(INST) uucpm /etc/local/uucpm
  970. X    $(INST) uucpd /etc/local/uucpd
  971. X
  972. Xuucpm: uucpm.o
  973. X    $(CC) -o uucpm uucpm.o $(LIBS_M)
  974. X
  975. Xuucpd: uucpd.o
  976. X    $(CC) -o uucpd uucpd.o $(LIBS_D)
  977. X
  978. Xuucpm.o: uucpm.c
  979. X    $(CC) -O -c $(DEFS_M) uucpm.c
  980. X
  981. Xuucpd.o: uucpd.c
  982. X    $(CC) -O -c $(DEFS_D) uucpd.c
  983. X
  984. Xuucpm.lint:    uucpm
  985. X    lint -DNO_PROTOTYPE $(DEFS_M) uucpm.c $(LIBS_M) >$@
  986. X
  987. Xuucpd.lint:    uucpd
  988. X    lint -DNO_PROTOTYPE $(DEFS_D) uucpd.c $(LIBS_D) >$@
  989. X
  990. XSHAR = uucpm.shar
  991. Xshar : $(SHAR)
  992. X$(SHAR) : $(SRCS) ; shar $(SRCS) >$@
  993. X
  994. END_OF_FILE_Makefile
  995.     size="`wc -c < Makefile`"
  996.     if test 1784 -ne "$size" ; then
  997.     echo "Makefile: extraction error - got $size chars"
  998.     fi
  999. fi
  1000. echo "done - 4 files extracted"
  1001. exit 0
  1002. -- 
  1003. Chip Rosenthal     <chip@chinacat.Unicom.COM>  |  Don't play that
  1004. Unicom Systems Development      512-482-8260   |    loud, Mr. Collins.
  1005.