/*
* ProFTPD - FTP server daemon
* Copyright (c) 1997, 1998 Public Flood Software
* Copyright (c) 2001, 2002, 2003 The ProFTPD Project team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu
* and other respective copyright holders give permission to link this program
* with OpenSSL, and distribute the resulting executable, without including
* the source code for OpenSSL in the source distribution.
*/
/*
* Ident (RFC1413) protocol support
* $Id: ident.c,v 1.21 2004/10/30 20:45:52 castaglia Exp $
*/
#include "conf.h"
static int ident_timeout;
static pr_netio_stream_t *nstrm = NULL;
static int ident_timeout_cb(CALLBACK_FRAME) {
ident_timeout++;
if (nstrm)
/* Abort the NetIO stream, which will cause netio_poll (and thus
* netio_read) to also abort. This is similar to the way data connects
* are aborted.
*/
pr_netio_abort(nstrm);
return 0;
}
char *pr_ident_lookup(pool *p, conn_t *c) {
char *ret = "UNKNOWN";
pool *tmp_pool = NULL;
conn_t *ident_conn = NULL, *ident_io = NULL;
char buf[256] = {'\0'}, *tok = NULL, *tmp = NULL;
int timerno, i = 0;
int ident_port = pr_inet_getservport(p, "ident", "tcp");
tmp_pool = make_sub_pool(p);
ident_timeout = 0;
nstrm = NULL;
if (ident_port == -1) {
destroy_pool(tmp_pool);
return pstrdup(p, ret);
}
/* Set up our timer before going any further. */
timerno = pr_timer_add(PR_TUNABLE_TIMEOUTIDENT, -1, NULL,
(callback_t) ident_timeout_cb);
if (timerno <= 0) {
destroy_pool(tmp_pool);
return pstrdup(p, ret);
}
ident_conn = pr_inet_create_connection(tmp_pool, NULL, -1, c->local_addr,
INPORT_ANY, FALSE);
pr_inet_set_nonblock(tmp_pool, ident_conn);
if ((i = pr_inet_connect_nowait(tmp_pool, ident_conn, c->remote_addr,
ident_port)) < 0) {
pr_timer_remove(timerno, ANY_MODULE);
pr_inet_close(tmp_pool, ident_conn);
pr_log_debug(DEBUG6, "ident connection failed: %s", strerror(errno));
destroy_pool(tmp_pool);
return pstrdup(p, ret);
}
if (!i) {
/* Not yet connected. */
nstrm = pr_netio_open(p, PR_NETIO_STRM_OTHR, ident_conn->listen_fd,
PR_NETIO_IO_RD);
pr_netio_set_poll_interval(nstrm, 1);
switch (pr_netio_poll(nstrm)) {
/* Aborted, timed out */
case 1:
if (ident_timeout) {
pr_timer_remove(timerno, ANY_MODULE);
pr_netio_close(nstrm);
pr_inet_close(tmp_pool, ident_conn);
pr_log_debug(DEBUG6, "ident lookup timed out, returning '%s'", ret);
destroy_pool(tmp_pool);
return pstrdup(p, ret);
}
break;
/* Error. */
case -1:
pr_timer_remove(timerno, ANY_MODULE);
pr_netio_close(nstrm);
pr_inet_close(tmp_pool, ident_conn);
pr_log_debug(DEBUG6, "ident lookup failed (%s), returning '%s'",
strerror(errno), ret);
destroy_pool(tmp_pool);
return pstrdup(p, ret);
/* Connected. */
default:
ident_conn->mode = CM_OPEN;
if (pr_inet_get_conn_info(ident_conn, ident_conn->listen_fd) < 0) {
pr_timer_remove(timerno, ANY_MODULE);
pr_netio_close(nstrm);
pr_inet_close(tmp_pool, ident_conn);
pr_log_debug(DEBUG2, "ident lookup timed out, returning '%s'", ret);
destroy_pool(tmp_pool);
return pstrdup(p, ret);
}
break;
}
}
if ((ident_io = pr_inet_openrw(tmp_pool, ident_conn, NULL, PR_NETIO_STRM_OTHR,
-1, -1, -1, FALSE)) == NULL) {
pr_timer_remove(timerno, ANY_MODULE);
pr_inet_close(tmp_pool, ident_conn);
destroy_pool(tmp_pool);
return pstrdup(p, ret);
}
nstrm = ident_io->instrm;
pr_inet_set_nonblock(tmp_pool, ident_io);
pr_netio_set_poll_interval(ident_io->instrm, 1);
pr_netio_set_poll_interval(ident_io->outstrm, 1);
pr_netio_printf(ident_io->outstrm, "%d, %d\r\n", c->remote_port,
c->local_port);
/* If the timer fires while in netio_gets(), netio_gets() will simply return
* either a partial string, or NULL. This works because ident_timeout_cb
* aborts the stream from which we are reading. netio_set_poll_interval() is
* used to make sure significant delays don't occur on systems that
* automatically restart syscalls after the SIGALRM signal.
*/
if (pr_netio_gets(buf, sizeof(buf), ident_io->instrm)) {
strip_end(buf, "\r\n");
tmp = buf;
tok = get_token(&tmp, ":");
if (tok && (tok = get_token(&tmp, ":"))) {
while (*tok && isspace((int) *tok))
tok++;
strip_end(tok, " \t");
if (strcasecmp(tok, "ERROR") == 0) {
if (tmp) {
while (*tmp && isspace((int) *tmp))
tmp++;
strip_end(tmp, " \t");
if (strcasecmp(tmp, "HIDDEN-USER") == 0)
ret = "HIDDEN-USER";
}
} else if (strcasecmp(tok, "USERID") == 0) {
if (tmp && (tok = get_token(&tmp, ":"))) {
if (tmp) {
while (*tmp && isspace((int) *tmp))
tmp++;
strip_end(tmp, " \t");
ret = tmp;
}
}
}
}
}
pr_timer_remove(timerno, ANY_MODULE);
pr_inet_close(tmp_pool, ident_io);
pr_inet_close(tmp_pool, ident_conn);
destroy_pool(tmp_pool);
return pstrdup(p, ret);
}
Last Updated: Thu Feb 23 11:07:16 2006
HTML generated by tj's src2html script