Annotation of 43BSDReno/contrib/isode-beta/ftp-ftam/ftpd.c, revision 1.1.1.1

1.1       root        1: /* ftpd.c - FTAM/FTP gateway */
                      2: 
                      3: #ifndef        lint
                      4: static char *rcsid = "$Header: /f/osi/ftp-ftam/RCS/ftpd.c,v 7.0 89/11/23 21:55:21 mrose Rel $";
                      5: #endif
                      6: 
                      7: /* 
                      8:  * $Header: /f/osi/ftp-ftam/RCS/ftpd.c,v 7.0 89/11/23 21:55:21 mrose Rel $
                      9:  *
                     10:  * Author:     John A. Scott           <[email protected]>
                     11:  *             The MITRE Corporation
                     12:  *             Washington C3I Division
                     13:  *             7525 Colshire Drive
                     14:  *             Mclean, Virginia 22102
                     15:  *             +1-703-883-5915
                     16:  *
                     17:  * $Log:       ftpd.c,v $
                     18:  * Revision 7.0  89/11/23  21:55:21  mrose
                     19:  * Release 6.0
                     20:  * 
                     21:  */
                     22: 
                     23: /*
                     24:  *                               NOTICE
                     25:  *
                     26:  *     The MITRE Corporation (hereafter MITRE) makes this software available 
                     27:  *     on an "as is" basis.  No guarantees, either explicit or implied, are 
                     28:  *     given as to performance or suitability.  
                     29:  *
                     30:  */
                     31: 
                     32: /*
                     33:  *     Shamelessly taken from UCB
                     34:  */
                     35: 
                     36: /*
                     37:  * FTP server.
                     38:  */
                     39: #include "config.h"
                     40: #include <sys/param.h>
                     41: #include <sys/stat.h>
                     42: #include <sys/ioctl.h>
                     43: #include <sys/socket.h>
                     44: #include <sys/file.h>
                     45: 
                     46: #include <netinet/in.h>
                     47: 
                     48: #include <arpa/ftp.h>
                     49: #include <arpa/inet.h>
                     50: 
                     51: #include <stdio.h>
                     52: #include <signal.h>
                     53: #include <pwd.h>
                     54: #include <setjmp.h>
                     55: #include <netdb.h>
                     56: #include <errno.h>
                     57: #include "general.h"
                     58: #include "manifest.h"
                     59: #include "logger.h"
                     60: extern LLog _ftam_log, *ftam_log;
                     61: #include <varargs.h>
                     62: 
                     63: char *ctime();
                     64: time_t time();
                     65: void adios (), advise ();
                     66: 
                     67: /*
                     68:  * File containing login names
                     69:  * NOT to be used on this machine.
                     70:  * Commonly used to disallow uucp.
                     71:  */
                     72: /*
                     73:  * This may be rework to provide bridge access control. JAS
                     74:  */
                     75: #define        FTPUSERS        "/usr/etc/ftpusers"
                     76: 
                     77: extern int errno;
                     78: extern char *sys_errlist[];
                     79: extern  char ftam_error[];
                     80: extern char version[];
                     81: 
                     82: struct sockaddr_in ctrl_addr;
                     83: struct sockaddr_in data_source;
                     84: struct sockaddr_in data_dest;
                     85: struct sockaddr_in his_addr;
                     86: 
                     87: int    data;
                     88: jmp_buf        errcatch;
                     89: int    logged_in;
                     90: int    debug = 0;
                     91: int    watch = 1;
                     92: int    timeout;
                     93: int    logging = 0;
                     94: int    type;
                     95: int    form;
                     96: int    stru;                   /* avoid C keyword */
                     97: int    mode;
                     98: int    usedefault = 1;         /* for data transfers */
                     99: char   hostname[32];
                    100: char   remotehost[32];
                    101: char   *osi_host;
                    102: char   *ftp_user;
                    103: char   *ftp_account;
                    104: char   *ftp_passwd;
                    105: int    verbose = 0;
                    106: #define NVEC 100
                    107: char *vec[NVEC];
                    108: 
                    109: /*
                    110:  * Timeout intervals for retrying connections
                    111:  * to hosts that don't accept PORT cmds.  This
                    112:  * is a kludge, but given the problems with TCP...
                    113:  */
                    114: #define        SWAITMAX        90      /* wait at most 90 seconds */
                    115: #define        SWAITINT        5       /* interval between retries */
                    116: 
                    117: int    swaitmax = SWAITMAX;
                    118: int    swaitint = SWAITINT;
                    119: 
                    120: SFD    lostconn();
                    121: 
                    122: main(argc, argv)
                    123:        int argc;
                    124:        char *argv[];
                    125: {
                    126:        int     addrlen;
                    127:        char *ptr, *index();
                    128:        struct servent *sp;
                    129: 
                    130:        isodetailor (ptr = argv[0], 0);
                    131:        argc--, argv++;
                    132:        if (verbose = isatty (fileno (stderr)))
                    133:            ll_dbinit (ftam_log, ptr);
                    134:        else {
                    135:            ftam_log -> ll_stat &= ~LLOGCLS;
                    136:            ll_hdinit (ftam_log, ptr);
                    137:        }
                    138: 
                    139:        advise (NULLCP, "starting");
                    140: 
                    141:        addrlen = sizeof his_addr;
                    142:        if (getpeername (0, (struct sockaddr *) &his_addr, &addrlen) == NOTOK)
                    143:            adios ("failed", "getpeername");
                    144:        sp = getservbyname("ftp", "tcp");
                    145:        if (sp == 0) {
                    146:                advise(NULLCP, "ftp/tcp: unknown service");
                    147: abort();
                    148:                exit(1);
                    149:        }
                    150:        ctrl_addr.sin_port = sp->s_port;
                    151:        data_source.sin_port = htons(ntohs((u_short) sp->s_port) - 1);
                    152:        (void)signal(SIGPIPE, lostconn);
                    153:        (void)signal(SIGCHLD, SIG_IGN);
                    154:        (void)dup2(0, 1);
                    155:        /* do telnet option negotiation here */
                    156:        /*
                    157:         * Set up default state
                    158:         */
                    159:        rcinit(); /* FTAM state initialize */
                    160:        logged_in = 0;
                    161:        data = -1;
                    162:        type = TYPE_A;
                    163:        form = FORM_N;
                    164:        stru = STRU_F;
                    165:        mode = MODE_S;
                    166:        addrlen = sizeof ctrl_addr;
                    167:        if (getsockname(0, (struct sockaddr *) &ctrl_addr, &addrlen) == NOTOK)
                    168:            adios ("failed", "getsockname");
                    169:        (void)gethostname(hostname, sizeof (hostname));
                    170:        ptr = index(hostname,'.'); /* strip off domain name */
                    171:        if (ptr) *ptr = '\0';
                    172:        reply(220, "%s FTP/FTAM gateway (%s) ready.",
                    173:                hostname, version);
                    174:        for (;;) {
                    175:                (void)setjmp(errcatch);
                    176:                (void)yyparse();
                    177:        }
                    178: }
                    179: 
                    180: SFD
                    181: lostconn()
                    182: {
                    183: 
                    184:        advise (NULLCP,"lost connection");
                    185:        dologout(-1);
                    186: }
                    187: 
                    188: char *
                    189: savestr(s)
                    190:        char *s;
                    191: {
                    192:        char *malloc();
                    193:        char *new = malloc((unsigned) (strlen(s) + 1));
                    194:        
                    195:        if (new != NULL)
                    196:                (void)strcpy(new, s);
                    197:        return (new);
                    198: }
                    199: 
                    200: retrieve(name)
                    201:        char *name;
                    202: {
                    203:        int result;
                    204: 
                    205:  /* FTAM file retrieval block function.  Return values:
                    206:   * OK    -- file transfered without error
                    207:   * NOTOK -- file transfer error
                    208:   * DONE  -- Problem opening TCP connection for transfer
                    209:   *          Error response made by dataconn routine.
                    210:   */
                    211:        vec[0] = "f_get";
                    212:        vec[1] = name;
                    213:        vec[2] = NULL;
                    214: 
                    215:        if ((result = f_get(vec)) == NOTOK){
                    216:                reply(550, "%s: %s.", name, ftam_error);
                    217:        } else if (result == OK)
                    218:                reply(226, "Transfer complete.");
                    219: 
                    220:        data = -1;
                    221:        return;
                    222: }
                    223: 
                    224: ftp_store(name, modeX)
                    225:        char *name, *modeX;
                    226: {
                    227:        int result;
                    228: /*
                    229:  * f_put is FTAM file storage block function.  First arguement
                    230:  * controls file overwrite or append selection.
                    231:  * OK    -- file transfered without error
                    232:  * NOTOK -- file transfer error
                    233:  * DONE  -- Problem opening TCP connection for transfer
                    234:  *          Error response made by dataconn routine.
                    235:  */
                    236: 
                    237:        vec[0] = strcmp(modeX,"a") ? "put" : "append";
                    238:        vec[1] = name;
                    239:        vec[2] = NULL;
                    240:        if ((result = f_put(vec)) == NOTOK)
                    241:                reply(550, "%s: %s.", name, ftam_error);
                    242:        else if (result == OK)
                    243:                reply(226, "Transfer complete.");
                    244:        data = -1;
                    245: }
                    246: 
                    247: int
                    248: getdatasock()
                    249: {
                    250: /* UCB data socket creation routine */
                    251:        int s;
                    252: #ifdef BSD43
                    253:        int on = 1;
                    254: #endif
                    255: 
                    256:        if (data >= 0)
                    257:                return (data);
                    258:        s = socket(AF_INET, SOCK_STREAM, 0);
                    259:        if (s < 0)
                    260:                return (NOTOK);
                    261: #ifndef        BSD43
                    262:        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) 0, 0) < 0)
                    263: #else
                    264:        if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof on) < 0)
                    265: #endif
                    266:                goto bad;
                    267:        /* anchor socket to avoid multi-homing problems */
                    268:        data_source.sin_family = AF_INET;
                    269:        data_source.sin_addr = ctrl_addr.sin_addr;
                    270:        if (bind(s, (struct sockaddr *) &data_source, sizeof (data_source)) < 0)
                    271:                goto bad;
                    272:        return (s);
                    273: bad:
                    274:        (void)close(s);
                    275:        return (NOTOK);
                    276: }
                    277: 
                    278: int
                    279: dataconn(name)
                    280:        char *name;
                    281: {
                    282: /* UCB data connection routine */
                    283:        int retry = 0;
                    284: 
                    285:        if (data >= 0) {
                    286:                reply(125, "Using existing data connection for %s.",
                    287:                    name);
                    288:                usedefault = 1;
                    289:                return (data);
                    290:        }
                    291:        if (usedefault)
                    292:                data_dest = his_addr;
                    293:        usedefault = 1;
                    294:        data = getdatasock();
                    295:        if (data == NOTOK){
                    296:                reply(425, "Can't create data socket (%s,%d): %s.",
                    297:                    inet_ntoa(data_source.sin_addr),
                    298:                    ntohs(data_source.sin_port),
                    299:                    sys_errlist[errno]);
                    300:                return (NOTOK);
                    301:        }
                    302:        reply(150, "Opening data connection for %s (%s,%d).",
                    303:            name, inet_ntoa(data_dest.sin_addr),
                    304:            ntohs(data_dest.sin_port));
                    305:        while (connect(data, (struct sockaddr *)&data_dest, sizeof (data_dest)) < 0) {
                    306:                if (errno == EADDRINUSE && retry < swaitmax) {
                    307:                        sleep((unsigned) swaitint);
                    308:                        retry += swaitint;
                    309:                        continue;
                    310:                }
                    311:                reply(425, "Can't build data connection: %s.",
                    312:                    sys_errlist[errno]);
                    313:                (void) close(data);
                    314:                data = -1;
                    315:                return (NOTOK);
                    316:        }
                    317:        return (data);
                    318: }
                    319: 
                    320: fatal(s)
                    321:        char *s;
                    322: {
                    323:        reply(451, "Error in server: %s\n", s);
                    324:        /* reply(221, "Closing connection due to server error.");*/
                    325:        dologout(0);
                    326: }
                    327: 
                    328: #ifndef        lint
                    329: reply(va_alist)
                    330: va_dcl
                    331: {
                    332:     int        n;
                    333:     va_list ap;
                    334: 
                    335:     va_start (ap);
                    336: 
                    337:     n = va_arg (ap, int);
                    338: 
                    339:     _reply (n, ' ', ap);
                    340: 
                    341:     va_end (ap);
                    342: }
                    343: 
                    344: lreply(va_alist)
                    345: va_dcl
                    346: {
                    347:     int        n;
                    348:     va_list ap;
                    349: 
                    350:     va_start (ap);
                    351: 
                    352:     n = va_arg (ap, int);
                    353: 
                    354:     _reply (n, '-', ap);
                    355: 
                    356:     va_end (ap);
                    357: }
                    358: 
                    359: static _reply (n, c, ap)
                    360: int    n;
                    361: char    c;
                    362: va_list ap;
                    363: {
                    364:     char    buffer[BUFSIZ];
                    365: 
                    366:     _asprintf (buffer, NULLCP, ap);
                    367: 
                    368:     printf ("%d%c%s\r\n", n, c, buffer);
                    369:     (void)fflush (stdout);
                    370: 
                    371:     if (verbose)
                    372:        advise (NULLCP,"<--- %d%c%s", n, c, buffer);
                    373: }
                    374: #else
                    375: /* VARARGS2 */
                    376: 
                    377: reply(n,fmt)
                    378: int    n;
                    379: char   *fmt;
                    380: {
                    381:     reply(n,fmt);
                    382: }
                    383: /* VARARGS2 */
                    384: 
                    385: lreply(n,fmt)
                    386: int    n;
                    387: char   *fmt;
                    388: {
                    389:     lreply(n,fmt);
                    390: }
                    391: #endif
                    392: 
                    393: replystr(s)
                    394:        char *s;
                    395: {
                    396:        printf("%s\r\n", s);
                    397:        (void)fflush(stdout);
                    398:        if (verbose)
                    399:            advise(NULLCP,"<--- %s", s);
                    400: }
                    401: 
                    402: ack(s)
                    403:        char *s;
                    404: {
                    405:        reply(200, "%s command okay.", s);
                    406: }
                    407: 
                    408: nack(s)
                    409:        char *s;
                    410: {
                    411:        reply(502, "%s command not implemented.", s);
                    412: }
                    413: 
                    414: /*ARGSUSED*/
                    415: yyerror(s)
                    416: char *s;
                    417: {
                    418:        reply(500, "Command not understood.");
                    419: }
                    420: 
                    421: ftp_delete(name)
                    422:        char *name;
                    423: {
                    424: /* f_rm is the general purpose FTAM file/directory deletion routine.
                    425:  * Change information is formatted in ftam_error.
                    426:  */
                    427:        vec[0] = "f_rm";
                    428:        vec[1] = name;
                    429:        vec[2] = NULL;
                    430: 
                    431:        if (f_rm(vec) == NOTOK){
                    432:                reply(550, "%s: %s.", name, ftam_error);
                    433:                return;
                    434:        }
                    435:        ack("DELE");
                    436: }
                    437: 
                    438: makedir(name)
                    439:        char *name;
                    440: {
                    441:        
                    442: /* f_mkdir is the FTAM directory creation routine */
                    443: 
                    444:        vec[0] = "f_mkdir";
                    445:        vec[1] = name;
                    446:        vec[2] = NULL;
                    447:        
                    448:        if (f_mkdir(vec) == NOTOK){
                    449:                reply(550, "%s: %s.", name, ftam_error);
                    450:                return;
                    451:        }
                    452:        ack("MKDIR");
                    453: }
                    454: 
                    455: removedir(name)
                    456:        char *name;
                    457: {
                    458: 
                    459: /* f_rm is the general purpose FTAM file/directory deletion routine.
                    460:  */
                    461:        vec[0] = "f_rm";
                    462:        vec[1] = name;
                    463:        vec[2] = NULL;
                    464: 
                    465:        if (f_rm(vec) == NOTOK){
                    466:                reply(550, "%s: %s.", name, ftam_error);
                    467:                return;
                    468:        }
                    469:        ack("RMDIR");
                    470: }
                    471: 
                    472: char *
                    473: renamefrom(name)
                    474:        char *name;
                    475: {
                    476:        reply(350, "Ready for destination name");
                    477:        return (name);
                    478: }
                    479: 
                    480: renamecmd(from, to)
                    481:        char *from, *to;
                    482: {
                    483: 
                    484: /* f_mv is FTAM block function to select and change attributes 
                    485:  * (i.e. file name)
                    486:  */
                    487:        vec[0] ="f_mv";
                    488:        vec[1] = from;
                    489:        vec[2] = to;
                    490:        vec[3] = NULL;
                    491: 
                    492:        if (f_mv(vec) == NOTOK){
                    493:                reply(550, "rename: %s.", ftam_error);
                    494:                return;
                    495:        }
                    496:        ack("RNTO");
                    497: }
                    498: 
                    499: dolog(sin)
                    500:        struct sockaddr_in *sin;
                    501: {
                    502: #ifdef notanymore
                    503:        struct hostent *hp = gethostbyaddr((char*)&sin->sin_addr,
                    504:                sizeof (struct in_addr), AF_INET);
                    505: #endif
                    506:        time_t t;
                    507: 
                    508: #ifdef notanymore
                    509:        if (hp) {
                    510:                (void)strncpy(remotehost, hp->h_name, sizeof (remotehost));
                    511:                endhostent();
                    512:        } else
                    513: #endif
                    514:                (void)strncpy(remotehost, inet_ntoa(sin->sin_addr),
                    515:                    sizeof (remotehost));
                    516:        t = time((time_t*)0);
                    517:        if (!logging)
                    518:                return;
                    519:        advise(NULLCP,"connection from %s at %s", remotehost, ctime(&t));
                    520: }
                    521: directory(how,name)
                    522: char *how, *name;
                    523: {
                    524: 
                    525:        int result;
                    526: /* f_ls does a directory contents transfer.  The first arguement
                    527:  * determines whether a name list (NLST) or long list (LIST) is returned.
                    528:  * Results:
                    529:  * OK    -- list transfered without error
                    530:  * NOTOK -- list transfer error
                    531:  * DONE  -- Problem opening TCP connection for transfer
                    532:  *          Error response made by dataconn routine.
                    533:  */
                    534: 
                    535:        vec[0] = strcmp(how,"NLST") ? "dir" : "ls";
                    536:        vec[1] = name;
                    537:        vec[2] = NULL;
                    538: 
                    539:        if ((result = f_ls(vec)) == OK)
                    540:                reply(226, "Transfer complete.");
                    541:        else if (result == NOTOK)
                    542:                reply(500, ftam_error);
                    543:        data = -1;
                    544: 
                    545: }
                    546: /*
                    547:  * Execute FTAM login if all necessary arguements present
                    548:  */
                    549: dologin()
                    550: {
                    551: 
                    552:        if (!ftp_user) {
                    553:                reply(500,"Send USER command first");
                    554:                return(0);
                    555:        }
                    556:        if (!ftp_passwd) {
                    557:                reply(330,"Send PASS command");
                    558:                return(0);
                    559:        }
                    560:        if (!osi_host){
                    561:        /* Success is returned since most user FTP response scanners
                    562:          * are not prepared for a continue at this point.  The osi
                    563:          * host may be specified by encoding it with the user name
                    564:          * (i.e. user@osihost) or using the SITE command (SITE osihost).
                    565:         * Gateway users are expected to know if the remote site
                    566:         * requires account charging information.  The bridge makes
                    567:          * ACCT optional.
                    568:          */
                    569:                reply(200,"Specify OSI destination with SITE command");
                    570:                return(0);
                    571:        }
                    572:        vec[0] = "f_open";
                    573:        vec[1] = osi_host;
                    574:        vec[2] = ftp_user;
                    575:        vec[3] = (ftp_account) ? "" : ftp_account;
                    576:        vec[4] = ftp_passwd;
                    577: 
                    578:        advise (NULLCP,
                    579:                "attempting connection with OSI host \"%s\" for user \"%s\"",
                    580:               osi_host, ftp_user);
                    581: 
                    582:        /* f_open performs the FTAM initialization (including login) */
                    583:        if (f_open(vec) == NOTOK){
                    584:                reply(500,"Login failed");
                    585:                return(0);
                    586:        }
                    587: 
                    588:        reply(200,"Logged into %s", osi_host);
                    589:        return(1);
                    590: 
                    591: }
                    592: 
                    593: /*
                    594:  * exit with supplied status.
                    595:  */
                    596: dologout(status)
                    597:        int status;
                    598: {
                    599: 
                    600:        vec[0] = "f_close";
                    601:        vec[1] = NULL;
                    602:        /* f_close performs the logout sequence and receives charging
                    603:          * information 
                    604:          */
                    605:        (void) f_close(vec);
                    606:        if (status>=0)
                    607:                reply(221,"Logged off. %s",ftam_error);
                    608:        /* beware of flushing buffers after a SIGPIPE */
                    609:        _exit(status);
                    610: }
                    611: 
                    612: 
                    613: /*
                    614:  * Check user requesting login priviledges.
                    615:  * Disallow anyone mentioned in the file FTPUSERS
                    616:  * to allow people such as uucp to be avoided.
                    617:  */
                    618: checkuser(name)
                    619:        register char *name;
                    620: {
                    621:        char line[BUFSIZ], *index();
                    622:        FILE *fd, *fopen();
                    623:        int found = 0;
                    624: 
                    625:        fd = fopen(FTPUSERS, "r");
                    626:        if (fd == NULL)
                    627:                return (1);
                    628:        while (fgets(line, sizeof (line), fd) != NULL) {
                    629:                register char *cp = index(line, '\n');
                    630: 
                    631:                if (cp)
                    632:                        *cp = '\0';
                    633:                if (strcmp(line, name) == 0) {
                    634:                        found++;
                    635:                        break;
                    636:                }
                    637:        }
                    638:        (void)fclose(fd);
                    639:        return (!found);
                    640: }
                    641: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.