tmi2_fluffos_v2/
tmi2_fluffos_v2/bin/
tmi2_fluffos_v2/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/ChangeLog.old/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/Win32/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/compat/simuls/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/clone/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/command/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/data/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/etc/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/include/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/inherit/master/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/log/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/compiler/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/efuns/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/single/tests/operators/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/testsuite/u/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/tmp/
tmi2_fluffos_v2/fluffos-2.7-ds2.018/windows/
tmi2_fluffos_v2/lib/
tmi2_fluffos_v2/lib/adm/
tmi2_fluffos_v2/lib/adm/daemons/languages/
tmi2_fluffos_v2/lib/adm/daemons/network/I3/
tmi2_fluffos_v2/lib/adm/daemons/virtual/
tmi2_fluffos_v2/lib/adm/daemons/virtual/template/
tmi2_fluffos_v2/lib/adm/news/
tmi2_fluffos_v2/lib/adm/obj/
tmi2_fluffos_v2/lib/adm/obj/master/
tmi2_fluffos_v2/lib/adm/priv/
tmi2_fluffos_v2/lib/adm/shell/
tmi2_fluffos_v2/lib/adm/tmp/
tmi2_fluffos_v2/lib/cmds/
tmi2_fluffos_v2/lib/d/
tmi2_fluffos_v2/lib/d/Conf/
tmi2_fluffos_v2/lib/d/Conf/adm/
tmi2_fluffos_v2/lib/d/Conf/boards/
tmi2_fluffos_v2/lib/d/Conf/cmds/
tmi2_fluffos_v2/lib/d/Conf/data/
tmi2_fluffos_v2/lib/d/Conf/logs/
tmi2_fluffos_v2/lib/d/Conf/obj/
tmi2_fluffos_v2/lib/d/Conf/text/help/
tmi2_fluffos_v2/lib/d/Fooland/adm/
tmi2_fluffos_v2/lib/d/Fooland/data/
tmi2_fluffos_v2/lib/d/Fooland/data/attic/
tmi2_fluffos_v2/lib/d/Fooland/items/
tmi2_fluffos_v2/lib/d/TMI/
tmi2_fluffos_v2/lib/d/TMI/adm/
tmi2_fluffos_v2/lib/d/TMI/boards/
tmi2_fluffos_v2/lib/d/TMI/data/
tmi2_fluffos_v2/lib/d/TMI/rooms/
tmi2_fluffos_v2/lib/d/grid/
tmi2_fluffos_v2/lib/d/grid/adm/
tmi2_fluffos_v2/lib/d/grid/data/
tmi2_fluffos_v2/lib/d/std/
tmi2_fluffos_v2/lib/d/std/adm/
tmi2_fluffos_v2/lib/data/adm/
tmi2_fluffos_v2/lib/data/adm/daemons/
tmi2_fluffos_v2/lib/data/adm/daemons/doc_d/
tmi2_fluffos_v2/lib/data/adm/daemons/emoted/
tmi2_fluffos_v2/lib/data/adm/daemons/network/http/
tmi2_fluffos_v2/lib/data/adm/daemons/network/services/mail_q/
tmi2_fluffos_v2/lib/data/adm/daemons/network/smtp/
tmi2_fluffos_v2/lib/data/adm/daemons/news/archives/
tmi2_fluffos_v2/lib/data/attic/connection/
tmi2_fluffos_v2/lib/data/attic/user/
tmi2_fluffos_v2/lib/data/std/connection/b/
tmi2_fluffos_v2/lib/data/std/connection/l/
tmi2_fluffos_v2/lib/data/std/user/a/
tmi2_fluffos_v2/lib/data/std/user/b/
tmi2_fluffos_v2/lib/data/std/user/d/
tmi2_fluffos_v2/lib/data/std/user/f/
tmi2_fluffos_v2/lib/data/std/user/l/
tmi2_fluffos_v2/lib/data/std/user/x/
tmi2_fluffos_v2/lib/data/u/d/dm/working/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/doc_d/
tmi2_fluffos_v2/lib/data/u/l/leto/smtp/
tmi2_fluffos_v2/lib/doc/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/
tmi2_fluffos_v2/lib/doc/driverdoc/applies/interactive/
tmi2_fluffos_v2/lib/doc/driverdoc/concepts/
tmi2_fluffos_v2/lib/doc/driverdoc/driver/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/arrays/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/buffers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/compile/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/ed/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/filesystem/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/floats/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/functions/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/general/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/mappings/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/numbers/
tmi2_fluffos_v2/lib/doc/driverdoc/efuns/parsing/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/constructs/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/preprocessor/
tmi2_fluffos_v2/lib/doc/driverdoc/lpc/types/
tmi2_fluffos_v2/lib/doc/driverdoc/platforms/
tmi2_fluffos_v2/lib/doc/mudlib/
tmi2_fluffos_v2/lib/ftp/
tmi2_fluffos_v2/lib/include/driver/
tmi2_fluffos_v2/lib/log/
tmi2_fluffos_v2/lib/log/driver/
tmi2_fluffos_v2/lib/obj/net/
tmi2_fluffos_v2/lib/obj/shells/
tmi2_fluffos_v2/lib/obj/tools/
tmi2_fluffos_v2/lib/std/adt/
tmi2_fluffos_v2/lib/std/board/
tmi2_fluffos_v2/lib/std/body/
tmi2_fluffos_v2/lib/std/fun/
tmi2_fluffos_v2/lib/std/living/
tmi2_fluffos_v2/lib/std/object/
tmi2_fluffos_v2/lib/std/shop/
tmi2_fluffos_v2/lib/std/socket/
tmi2_fluffos_v2/lib/std/user/
tmi2_fluffos_v2/lib/std/virtual/
tmi2_fluffos_v2/lib/student/
tmi2_fluffos_v2/lib/student/kalypso/
tmi2_fluffos_v2/lib/student/kalypso/armor/
tmi2_fluffos_v2/lib/student/kalypso/rooms/
tmi2_fluffos_v2/lib/student/kalypso/weapons/
tmi2_fluffos_v2/lib/u/l/leto/
tmi2_fluffos_v2/lib/u/l/leto/cmds/
tmi2_fluffos_v2/lib/www/errors/
tmi2_fluffos_v2/lib/www/gateways/
tmi2_fluffos_v2/lib/www/images/
tmi2_fluffos_v2/old/
tmi2_fluffos_v2/win32/
/*
 * A simple client interface to Identification Protocol servers
 *   (was Authentication Service Protocol, RFC931 (obsolete))
 *
 * See RFC1413 (supercedes RFC931) for a full understanding of the protocol.
 * Some quotes from section 6 on "Security Considerations":
 *
 * ``The information returned by this protocol is at most as trustworthy
 *   as the host providing it OR the organization operating the host.''
 *
 * ``The Identification Protocol is not intended as an authorization or
 *   access control protocol.  At best, it provides some additional
 *   auditing information with respect to TCP connections.''
 *
 * ``The use of the information returned by this protocol for other than
 *   auditing is strongly discouraged.''
 *
 * Note: this client is not fully conformant (robust) with the
 *   specification, for example: it expects US-ASCII character set, and
 *   does not process octet strings
 *
 * ident.c by Robocoder 95.03.15 - another tool for evil admin logging >=)
 */

#include <config.h>

#define __tmi__
#ifdef __tmi__

/* assume TMI */

#  include <mudlib.h>
#  include <uid.h>
#  include <net/socket.h>
#  include <logs.h>
#  include <driver/socket_err.h>
#  include <driver/runtime_config.h>
#  include <driver/origin.h>

inherit DAEMON;

#endif

#ifdef __nightmare__

#  include <std.h>
#  include <dirs.h>
#  include <daemons.h>
#  include <network.h>
#  include <security.h>

inherit DAEMON;

#define LOG_DIR DIR_LOGS "/"

#endif


#ifndef NET_IDENT_H
#define NET_IDENT_H

#ifndef IDENT_LOG
#define IDENT_LOG "IDENT"
#define IDENT_ERR_LOG "IDENT.err"
#endif

#define MAX_USER_ID_LEN         128
#define TIMEOUT_AUTH_INTERVAL   (60)
#define TIMEOUT_AUTH_CHECK      (5 * 60)

#endif /* NET_IDENT_H */

#define AUTH_PORT       113

#define IDENT_GAVE_UP   1
#define IDENT_TIMED_OUT 2

mapping noident;
mapping sockinfo;

#define LOCAL_ID(f) sockinfo[(f)][0]
#define ID_OWNER(f) sockinfo[(f)][1]
#define CALLBACK(f) sockinfo[(f)][2]
#define TREQUEST(f) sockinfo[(f)][3]
#define SOCKADDR(f) sockinfo[(f)][4]

/*
 * some prototypes for local functions
 */
void write_cb(int fd, string str);
void close_cb(int fd);

/*
 * initialization
 */
void create() {

#ifdef __tmi__
    seteuid(ROOT_UID);
#endif

#ifdef __nightmare__
    daemon::create();
    set_no_clean(1);
#endif

    sockinfo = ([ ]);
    noident = ([ ]);
    call_out("check_connections", TIMEOUT_AUTH_CHECK);
}

/*
 * initiate an Ident lookup with the remote server
 *
 * Inputs:
 *   id - name of user, if ob_or_fd is the player object
 *      - name of daemon requesting the service, if ob_or_fd is a socket
 *   ob_or_fd - an object or a socket descriptor (see above)
 *   myport - the local endpoint of the socket connection;
 *            usually the mud login port
 *   callback - an optional callback function of the form:
 *
 *      void mycallback(mixed ob_or_fd, string user_id);
 *
 *            - where ob_or_fd is a copy of what ident was given
 *              and user_id is the response from a successful query
 *            - note: the callback is _only_ called when an ident query
 *              was successful
 */
void ident_user(string id, mixed ob_or_fd, int myport, mixed callback) {
    string addr;
    int myfd, ret, i;

    if (!id)
        return;

    if (!myport)
        myport = __PORT__;

    if (stringp(callback))

// Leto
        callback = (: previous_object(), $(callback) :);

    if (callback && !functionp(callback))
        return;

    if ((addr = socket_address(ob_or_fd)) == "0.0.0.0 0")
        return;

    if ((myfd = socket_create(STREAM, "read_cb", "close_cb")) < 0)
        return;

    /*
     * socket_connect() usually always succeeds since inetd super server
     * handles initial connection before launching the ident server
     */
    if (socket_connect(myfd,
          sprintf("%s%d", addr[0..i = strsrch(addr, ' ')], AUTH_PORT),
          "read_cb", "write_cb") != EESUCCESS) {
        socket_close(myfd);

        /* log error */
        write_file(LOG_DIR IDENT_LOG,
              sprintf("[%s] %s@%s CONNECT REFUSED\n", ctime(time())[4..15],
                    LOCAL_ID(myfd), SOCKADDR(myfd)));
        return;
    }

    sockinfo[myfd] = ({ id, ob_or_fd, callback, time(), addr[0..i-1] });

    write_cb(myfd, sprintf("%s, %d\r\n", addr[i+1..<1], myport));
}

/*
 * receive ident response
 *
 * format of response (string):
 *     their_port, our_port : USERID : operating_system : user_id
 *     their_port, our_port : USERID : OTHER : user_id_octet_string
 *     their_port, our_port : ERROR : INVALID-PORT
 *     their_port, our_port : ERROR : NO-USER
 *     their_port, our_port : ERROR : HIDDEN-USER
 *     their_port, our_port : ERROR : UNKNOWN-ERROR
 *
 * NB: we don't log errors...
 */
void read_cb(int fd, string str) {
    int i;
    string user_id;

    if (undefinedp(sockinfo[fd]) || origin() != ORIGIN_DRIVER)
        return;

    if ((i = strsrch(str, "USERID")) != -1) {
        /* get the user_id portion of the response */
        i = strsrch(str, ':', i);
        user_id = str[i..<3]; /* skip trailing "\r\n" */
        if (strlen(user_id) > MAX_USER_ID_LEN)
            user_id = user_id[0..MAX_USER_ID_LEN-1];

        /* log ident */
        write_file(LOG_DIR IDENT_LOG,
              sprintf("[%s] %s@s%s\n", ctime(time())[4..15],
                    LOCAL_ID(fd), SOCKADDR(fd), user_id));

        /* perform callback (if possible) */
        if (CALLBACK(fd) && ID_OWNER(fd))
              (*CALLBACK(fd))(ID_OWNER(fd), user_id);
    } else if ((i = strsrch(str, "ERROR")) != -1) {
        i = strsrch(str, ':', i);

        /* log error */
        write_file(LOG_DIR IDENT_LOG,
              sprintf("[%s] %s@%s error%s\n", ctime(time())[4..15],
                    LOCAL_ID(fd), SOCKADDR(fd), str[i..<3]));
    }
    close_cb(fd);
}

/*
 * send ident request to remote server
 */
void write_cb(int fd, string str) {
    int ret;

    if (undefinedp(sockinfo[fd]) ||
//          !(origin() & (ORIGIN_DRIVER | ORIGIN_LOCAL)))
	 ( (origin() != ORIGIN_DRIVER) && (origin()!=ORIGIN_LOCAL) ) )
        return;

    if ((ret = socket_write(fd, str)) == EESUCCESS ||
          ret == EECALLBACK)
        /* wait for the reply */
        ;
 else if (ret == EEWOULDBLOCK || ret == EEALREADY)
        /* can't service request at this time...try again later */
        call_out("write_cb", 15, str);
    else {
        /*
         * can't service request at all...just give up;
         * log it only if we haven't logged it before
         */
        if (undefinedp(noident[SOCKADDR(fd)])) {
            write_file(LOG_DIR IDENT_ERR_LOG,
                  sprintf("[%s] %s@%s: GAVE UP", ctime(time())[4..15],
                        LOCAL_ID(fd), SOCKADDR(fd)));
            noident[SOCKADDR(fd)] = IDENT_GAVE_UP;
        }
        close_cb(fd);
    }
}

/*
 * close socket, and take care of internal accounting
 */
void close_cb(int fd) {
    if (undefinedp(sockinfo[fd]) ||
(  (origin()==ORIGIN_DRIVER)||(origin()==ORIGIN_LOCAL) ) )
        return;

    map_delete(sockinfo, fd);
    socket_close(fd);
}

/*
 * periodically scan sockinfo for timed-out ident requests
 * (ie response not received)
 */
void check_connections() {
    int *fds, s;

    if (fds = keys(sockinfo)) {
        s = sizeof(fds);
        while (s--)
            /* timed-out...remove */
            if ((TREQUEST(fds[s]) + TIMEOUT_AUTH_INTERVAL) > time()) {
                close_cb(fds[s]);

                /* log it only if we haven't logged it before */
                if (undefinedp(noident[SOCKADDR(fds[s])])) {
                    write_file(LOG_DIR IDENT_ERR_LOG,
                          sprintf("[%s] %s@%s: TIMED OUT",
                                ctime(time())[4..15], LOCAL_ID(fds[s]),
                                SOCKADDR(fds[s])));
                    noident[SOCKADDR(fds[s])] = IDENT_TIMED_OUT;
                }
            }
    }
    call_out("check_connections", TIMEOUT_AUTH_CHECK);
}

/* eof */