This is daemon.c in view mode; [Download] [Up]
/*
Webster Access, a program to use NeXT online Webster dictionary.
Copyright (C) 1994 Benoit Grange, ben@fizz.fdn.org
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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#import <stdio.h>
#import <stdlib.h>
#import <libc.h>
#import <sys/types.h>
#import <errno.h>
#import <strings.h>
#import <memory.h>
#import <sys/socket.h>
#import <sys/socketvar.h>
#import <netinet/in.h>
#import <arpa/inet.h>
#import <netdb.h>
#include <syslog.h>
#import "daemon.h"
#import "commands.h"
#import "config.h"
const char* pgmname;
// Used to run the connection
struct sockaddr_in remoteAddress;
int remoteAddressLength = sizeof(remoteAddress);
int cx;
FILE *clientR = NULL;
FILE *clientW = NULL;
void report()
{
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
syslog(LOG_INFO, "CPU time = %lg ms\n",
((double)usage.ru_utime.tv_sec + (double)usage.ru_stime.tv_sec) * 1000.0 +
((double)usage.ru_utime.tv_usec + (double)usage.ru_stime.tv_usec) / 1000.0);
}
void runCx(void)
{
struct hostent *h1 = NULL, *h2 = NULL;
if (!(clientR = fdopen(cx, "r")))
perror("fdopen"), exit(1);
if (!(clientW = fdopen(cx, "a")))
perror("fdopen"), exit(1);
if (remoteAddressLength != sizeof(remoteAddress)) {
syslog(LOG_ERR, "socket address is too short (%d < %lu)\n",
remoteAddressLength, sizeof(remoteAddress));
exit(1);
}
/* Double check, find name from address, and check that address is one of the
listed one for this address. This will prevent NS spoofing
*/
h1 = gethostbyaddr((void *)&remoteAddress.sin_addr, sizeof(remoteAddress.sin_addr),
AF_INET);
if (h1) h2 = gethostbyname(h1->h_name);
if (h2) {
// h1 is name from address, ununsed later
// h2 is name & addresse(s) from name
// check that h2 lists the remoteAddress
long **hlist = (long **)h2->h_addr_list;
while (**hlist != 0) {
if (**hlist == (long)remoteAddress.sin_addr.S_un.S_addr) break;
hlist++;
}
if (**hlist == 0) {
syslog(LOG_NOTICE,
"Address %s maps to host '%s', this maps to '%s', "
"but %s is not listed in its adresses (DNS spoofing suspected)",
inet_ntoa(remoteAddress.sin_addr),
h1?h1->h_name:"unknown host",
h2?h2->h_name:"unknown host",
inet_ntoa(remoteAddress.sin_addr)
);
h2 = NULL;
}
}
if (requirements & hostname && !h2) goto fail;
/* Check that cx is allowed, no requirements -> allow all */
if (allowedList) {
allow *a = allowedList;
while (a) {
if (a->domain && h2) {
if ((strlen(h2->h_name) >= strlen(a->domain)) &&
!strcmp(a->domain, h2->h_name + strlen(h2->h_name) - strlen(a->domain))) break;
} else {
if ((remoteAddress.sin_addr.s_addr & a->mask) == a->addr) break;
}
a = a->next;
}
if (!a) goto fail;
}
syslog(LOG_INFO, "accepted connection from %s (%s)\n",
h2?h2->h_name:"unknown host",
inet_ntoa(remoteAddress.sin_addr));
// fprintf(clientW, "200 %s\n",
// greetingText?greetingText:"Connected");
fflush(clientW);
commandLoop();
report();
return;
fail:
syslog(LOG_NOTICE, "refused connection from %s (%s)\n",
h2?h2->h_name:"unknown host",
inet_ntoa(remoteAddress.sin_addr));
fprintf(clientW, "529 You are not allowed to use this service\n");
fflush(clientW);
fclose(clientR);
fclose(clientW);
exit(1);
}
void waitCx(int port)
/* Create a socket, listen, and process ONE connection */
{
int listener, on = 1;
struct sockaddr_in localAddress;
int localAddressLength = sizeof(localAddress);
if ((listener = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
perror("socket"), exit(1);
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))<0)
perror("setsockopt SO_REUSEADDR"), exit(1);
localAddress.sin_family = AF_INET;
localAddress.sin_port = htons(port);
localAddress.sin_addr.s_addr = 0; /* Unbound */
if (bind(listener, (struct sockaddr *)&localAddress, localAddressLength)<0)
syslog(LOG_ERR, "bind(): %m"), exit(1);
if (listen(listener, 1)<0)
syslog(LOG_ERR, "listen(): %m"), exit(1);
remoteAddressLength = sizeof(remoteAddress);
if ((cx = accept(listener, (struct sockaddr *)&remoteAddress, &remoteAddressLength))<0)
syslog(LOG_ERR, "accept(): %m"), exit(1);
if (close(listener)<0)
syslog(LOG_ERR, "close(): %m"), exit(1);
runCx();
report();
}
int main(int argc, char **argv)
{
pgmname = *argv;
argv++; argc--;
readConfig(NULL);
openlog("websterd", LOG_PID, logFacility);
if (*argv && !strcmp(*argv, "-")) {
syslog(LOG_DEBUG, "Started (stdin)");
cx = 0;
if (!(clientR = fdopen(0, "rb"))) perror("fdopen"), exit(1);
if (!(clientW = fdopen(1, "ab"))) perror("fdopen"), exit(1);
fprintf(clientW, "211%cConnected to standard input\n", (greetingText)?'-':' ');
if (greetingText) fprintf(clientW, "211 %s\n", greetingText);
commandLoop();
fclose(clientW);
fclose(clientR);
exit(0);
}
/* Testing if launched by inetd, if this is the case, file 0 is a socket */
if (getpeername(0, (struct sockaddr *)&remoteAddress, &remoteAddressLength)<0) {
if (errno != ENOTSOCK) syslog(LOG_ERR, "getpeername(0,...): %m"), exit(1);
waitCx(tcpPort);
} else {
cx = 0;
runCx();
}
fclose(clientW);
fclose(clientR);
return(0);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.