1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
|
/* fingerd.c -- Simple daemon body. */
/* Copyright (C) 1996-1997 Janos Farkas
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, 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. */
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/syslog.h>
#include <string.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <netinet/in.h>
#ifdef HAVE_TCPD_H
#include <tcpd.h>
#endif
#include "util.h"
#include "finger.h"
#include "broken.h"
/* Tweaking room, feel free to change these flags */
struct fng_info deffi =
{
/* Show [login name/real name/home dir/shell] respectively. */
1, 1, 1, 1,
/* Show [room number/work phone/home phone/other field] respectively. */
1, 1, 1, 1,
/* Show [new mail date/mail last read date] */
1, 1,
/* Show [last login/if online/origin] */
1, 1, 1,
/* Show [plan/project/pgpkey/nofinger] files */
1, 1, 1, 1
};
struct fng_config deffg =
{
/* True if this is a `local' finger. Not used yet. */
0,
/* True if you want to `match' fingered names against the GECOS
field. */
1,
/* The names of the plan, project, pgpkey and nofinger files,
respectively. If NULL, the appropriate field is not used. */
".plan",
".project",
".pgpkey",
".nofinger",
/* The program you want to run when someone does not specify a
user in finger. In an open environment, I would
prefer to run `w', but that's too much in general... :) */
"/usr/bin/finger",
/* The uniform message to be returned when no user found. */
"sorry, no such user.",
/* The message which will be returned when libwrap tells us
they are refused. This is my preferred text.. :) */
"Sorry, you either don't run identd, or don't have a host name\n"
"for your IP address. Both problem can be fixed quite easily,\n"
"so complain to your system/network administrator.\n"
"Please try again only if you have fixed this problem.\n"
};
#ifdef HAVE_LIBWRAP
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
#endif
char *basename (const char *);
static void
logentry (const char *name, const char *client, int refused)
{
char *buf = xmalloc ((name ? strlen (name) : 0) + 16);
if (name != 0 && *name != '\0') {
sprintf (buf, "%singer `%s'", refused ? "f" : "F", name);
} else {
sprintf (buf, "%sserlist", refused ? "u" : "U");
}
syslog (LOG_WARNING, "%s%s from %s", refused ? "Refused " : "", buf, client);
free (buf);
}
int
main (int argc, char *argv[])
{
char *client, *info, *ip;
char *progname, *buf;
struct fng_info *fi = &deffi;
struct fng_config *fg = &deffg;
struct sockaddr_in snam;
int count, refused;
#ifdef HAVE_LIBWRAP
struct request_info req;
#endif
/* I happen to like to reuse variables sometimes... sorry.. :) */
refused = sizeof(snam);
progname = basename (argv[0]);
if (getpeername (0, (struct sockaddr *)&snam, &refused)) {
fprintf (stderr, "%s: stdin is not socket\n", progname);
exit (1);
}
openlog (progname, LOG_PID, LOG_AUTHPRIV);
/* Are we run from tcpserver? Then it's easier to look these up,
* and faster too */
refused = 0;
client = getenv("TCPREMOTEHOST");
ip = getenv("TCPREMOTEIP");
info = getenv("TCPREMOTEINFO");
buf = xmalloc(1024);
if (client || info || ip) {
if (ip && !info)
info = ip, ip = 0;
snprintf(buf, 1024, "%s%s%s%s%s%s",
info?info:"",
info?"@":"",
client?client:"",
ip?" [":"",
ip?ip:"",
ip?"]":"");
client = buf;
} else {
#ifdef HAVE_LIBWRAP
request_init (&req, RQ_DAEMON, argv[0], RQ_FILE, 0, NULL);
fromhost(&req);
refused = !hosts_access (&req);
client = xstrdup (eval_client (&req));
#else
/* no overflow, IP addresses must fit there */
client = strcpy(buf,(char *)inet_ntoa(snam.sin_addr)), buf;
#endif
}
buf = xmalloc (1024);
if (!fgets(buf, 1024-1, stdin)) {
syslog (LOG_WARNING, "Empty finger from %s", client);
/* XXX: print something? */
exit (0);
}
buf[1024-1] = 0;
count = strlen (buf);
if (count > 0 && buf[count-1] == '\n')
buf[--count] = 0;
if (count > 0 && buf[count-1] == '\r')
buf[--count] = 0;
/* This is just an arbitrary limit... Who has longer usernames? */
if (count > 80) {
syslog (LOG_WARNING, "Long finger from %s", client);
printf ("finger: %s\n", fg->nouser);
exit (0);
}
/* Compatibility with finger -l, why punt them? */
if (strncmp (buf, "/W ", 3) == 0) {
buf += 3;
} else if (strncmp (buf, "-l ", 3) == 0) {
buf += 3;
}
/* Log the access, then prepare the reply. */
logentry (buf, client, refused);
if (refused) {
if (fg->refused)
printf(fg->refused);
} else {
finger_name (fi, fg, buf);
}
exit (0);
}
|