#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#ifdef HAVE_SSL
#include <openssl/crypto.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#endif
#include "sbuf.h"
#include "struct.h"
#include "send.h"
unsigned int req = 0;
extern void *pmalloc(size_t size);
#define CONFCMD(x) int x(confetti * jr, int pargc, char **pargv)
CONFCMD(conf_listen);
CONFCMD(conf_listenex);
#ifdef HAVE_SSL
CONFCMD(conf_publickey);
CONFCMD(conf_privatekey);
#endif
CONFCMD(gen_c);
CONFCMD(gen_d);
CONFCMD(gen_p);
CONFCMD(gen_s);
CONFCMD(gen_v);
CONFCMD(gen_x);
CONFCMD(gen_l);
CONFCMD(gen_m);
CONFCMD(gen_w);
CONFCMD(gen_a);
CONFCMD(gen_b);
CONFCMD(gen_i);
CONFCMD(conf_password);
CONFCMD(conf_allow);
struct confcmd
{
char *name;
CONFCMD((*func));
};
struct confcmd confcmdlist[] =
{
{"C",gen_c},
{"D",gen_d},
{"P",gen_p},
{"S",gen_s},
{"V",gen_v},
{"X",gen_x},
{"L",gen_l},
{"M",gen_m},
{"W",gen_w},
{"A",gen_a},
{"B",gen_b},
{"I",gen_i},
{"LISTEN", conf_listen},
{"LISTENEX", conf_listenex},
#ifdef HAVE_SSL
{ "PUBLICKEY", conf_publickey},
{ "PRIVATEKEY", conf_privatekey},
#endif
{"PASSWORD",conf_password},
{"ADMINPASS",gen_s},
{"ALLOW",conf_allow},
{"VHOST",gen_v},
{"DEFAULTVHOST",gen_x},
{"PIDFILE",gen_p},
{"MOTDFILE",gen_m},
{"USEIDENTWD",gen_w},
{"LOGFILE",gen_l},
{NULL,NULL}
};
int mytoi(char *buf)
{
int acum;
int p;
acum=0;
for(p=0;buf[p];p++)
{
if( isdigit( buf[p] ))
{
acum*=10;
acum+= ( buf[p] - '0' );
}
}
return acum;
}
void add_access (confetti * jr, accesslist * a)
{
if (!jr->has_alist)
{
jr->alist = jr->alist_end = a;
jr->has_alist++;
}
else
{
jr->alist_end->next = a;
jr->alist_end = a;
}
}
CONFCMD(conf_password)
{
if(pargc < 2)
{
return -1;
}
strncpy (jr->dpass, pargv[1], PASSLEN);
jr->dpass[PASSLEN]='\0';
jr->dpassf = 1;
return 0;
}
CONFCMD(conf_listenex)
{
int idx;
char *opt;
unsigned int flags;
int f_argc;
char *f_argv[1];
char *localhost;
char *maxusers;
char *port;
char *strend;
unsigned long ulport;
localhost = NULL;
maxusers = NULL;
flags = 0;
f_argc = 0;
idx = 1;
while(idx < pargc)
{
opt = pargv[idx++];
if(*opt == '-')
{
++opt;
if(*opt == '-')
{
++opt;
// long options
if( strcasecmp(opt, "localhost") == 0)
{
if(idx >= pargc)
{
fprintf(stderr, "--localhost requires argument\n");
return -1;
}
localhost = pargv[idx++];
}
else if( strcasecmp(opt, "limit") == 0)
{
if(idx >= pargc)
{
fprintf(stderr, "--limit requires argument\n");
return -1;
}
maxusers = pargv[idx++];
}
else if( strcasecmp(opt, "ipv6") == 0)
{
flags |= USE_IPV6;
}
#ifdef HAVE_SSL
else if(strcasecmp(opt, "ssl") == 0)
{
flags |= USE_SSL;
}
#endif
else
{
fprintf(stderr, "Unknown long options --%s\n", opt);
return -1;
}
}
else
{
// short options
}
}
else
{
if(f_argc >= 1)
break;
f_argv[f_argc++] = opt;
}
}
if(f_argc < 1)
return -1;
port = f_argv[0];
if(localhost)
{
strncpy(jr->dhost, localhost, HOSTLEN);
jr->dhost[HOSTLEN] = 0;
}
if(maxusers)
{
unsigned long t;
t = strtoul(maxusers, &strend, 0);
if(t > UINT_MAX || strend == maxusers)
{
fprintf(stderr, "Invalid maxusers argument\n");
return -1;
}
jr->maxusers = t;
}
ulport = strtoul(port, &strend, 0);
if(ulport > USHRT_MAX || strend == port)
{
fprintf(stderr, "Invalid port %lu\n", ulport);
return -1;
}
jr->dport = ulport;
jr->optflags |= flags;
req |= 1;
return 0;
}
CONFCMD(conf_listen)
{
char *src;
char *dest;
char *eod;
char *port;
#if 0
int p;
for(p = 0; p < pargc; p++)
{
printf("(%i) %s\n", p, pargv[p]);
}
#endif
if(pargc < 2)
{
return -1;
}
port = pargv[1];
for(src = pargv[1]; *src; src++)
{
if(*src == '[')
{
for(src++; *src; src++)
{
if(*src == ']')
{
src++;
break;
}
}
}
if(*src == ':')
{
int flag;
port = src + 1;
dest = jr->dhost;
eod = dest + HOSTLEN;
flag = 0;
for(src = pargv[1]; *src; src++)
{
if( *src == '[' && (flag & 1) == 0)
{
flag |= 1;
continue;
}
if( *src == ']' && (flag & 1) == 1)
{
flag &= ~1;
continue;
}
if( *src == ':' && (flag & 1) == 0)
break;
if(dest >= eod)
break;
*dest++ = *src;
}
*eod = '\0';
break;
}
}
jr->dport = (mytoi(port) % 65535);
jr->maxusers=0;
req|=1;
if(pargc < 3)
{
return 0;
}
jr->maxusers=mytoi(pargv[2]);
return 0;
}
#ifdef HAVE_SSL
CONFCMD(conf_publickey)
{
if (pargc < 2)
{
return 0;
}
strncpy (jr->public_cert_file, pargv[1], FILELEN);
jr->public_cert_file[FILELEN]='\0';
return 0;
}
CONFCMD(conf_privatekey)
{
if (pargc < 2)
{
return 0;
}
strncpy (jr->private_cert_file, pargv[1], FILELEN);
jr->private_cert_file[FILELEN]='\0';
return 0;
}
#endif
CONFCMD(conf_allow)
{
accesslist *na;
int p;
if (pargc < 2)
{
return 0;
}
for(p=1;p<pargc;p++)
{
na = pmalloc (sizeof (accesslist));
na->type = 1;
strncpy (na->addr, pargv[p], HOSTLEN);
na->addr[HOSTLEN]='\0';
na->next = NULL;
add_access (jr, na);
}
return 0;
}
CONFCMD(gen_c)
{
if(pargc < 2)
{
return 0;
}
jr->cport = mytoi(pargv[1]);
if(jr->cport < 0)
{
jr->cport=0;
}
if(jr->cport > 65535)
{
jr->cport = 65535;
}
return 0;
}
CONFCMD(gen_d)
{
if (pargc < 3)
{
return 0;
}
req |= 1;
jr->dport = mytoi (pargv[1]);
jr->maxusers = mytoi (pargv[2]);
if (pargc > 3)
{
strncpy (jr->dpass, pargv[3], PASSLEN);
jr->dpass[PASSLEN]='\0';
jr->dpassf = 1;
}
return 0;
}
CONFCMD(gen_p)
{
if (pargc < 2)
{
return 0;
}
strncpy (jr->pidfile, pargv[1], FILELEN);
jr->pidfile[FILELEN]='\0';
return 0;
}
CONFCMD(gen_s)
{
if (pargc < 2)
{
return 0;
}
strncpy (jr->spass, pargv[1], PASSLEN);
jr->spass[PASSLEN]='\0';
req |= 2;
return 0;
}
CONFCMD(gen_v)
{
struct vhostentry *vhost_ptr;
if (pargc < 2)
{
return 0;
}
vhost_ptr = (struct vhostentry *) pmalloc (sizeof (struct vhostentry));
if (vhost_ptr == NULL)
{
return 0;
}
vhost_ptr->next=jr->vhostlist;
jr->vhostlist=vhost_ptr;
strncpy (vhost_ptr->vhost, pargv[1], HOSTLEN);
vhost_ptr->vhost[HOSTLEN]='\0';
return 0;
}
CONFCMD(gen_x)
{
if (pargc < 2)
{
return 0;
}
strncpy (jr->vhostdefault, pargv[1], HOSTLEN);
jr->vhostdefault[HOSTLEN]='\0';
return 0;
}
CONFCMD(gen_l)
{
if (pargc < 2)
{
return 0;
}
if ((jr->logfile = fopen (pargv[1], "ab")) != NULL)
{
jr->logf = 1;
}
return 0;
}
CONFCMD(gen_m)
{
if (pargc < 2)
{
return 0;
}
strncpy (jr->motdf, pargv[1], 256);
jr->motdf[256]='\0';
jr->usemotd = 1;
return 0;
}
CONFCMD(gen_w)
{
if (pargc < 2)
{
jr->identwd = 1;
return 0;
}
jr->identwd = mytoi (pargv[1]);
return 0;
}
CONFCMD(gen_a)
{
accesslist *na;
if (pargc < 3)
{
return 0;
}
if (mytoi (pargv[1]) > 2)
{
return 0;
}
na = pmalloc (sizeof (accesslist));
na->type = mytoi (pargv[1]);
strncpy (na->addr, pargv[2], HOSTLEN);
na->addr[HOSTLEN]='\0';
na->next = NULL;
add_access (jr, na);
return 0;
}
CONFCMD(gen_b)
{
if(pargc < 2)
{
return 0;
}
jr->mtype=mytoi(pargv[1]);
if(jr->mtype > 1)
{
jr->mtype=1;
}
printf("mtype is %i\n",jr->mtype);
return 0;
}
CONFCMD(gen_i)
{
if (pargc < 2)
{
jr->logfile = fopen (".ident", "ab");
}
else
{
jr->logfile = fopen (pargv[1], "ab");
}
return 0;
}
/******************************
printf ("--Option line in error:(%i)\n", pargc);
for (p = 0; p < pargc; p++)
{
printf (" %i:%s\n", p, pargv[p]);
}
*******************************/
int confoption(confetti * jr, int pargc, char **pargv)
{
int p;
for(p=0;confcmdlist[p].name;p++)
{
if(!strcasecmp(confcmdlist[p].name,pargv[0]))
{
return confcmdlist[p].func(jr,pargc,pargv);
}
}
printf ("Skipping unknown Field in conf file: (%s)\n", pargv[0]);
return -1;
}
int loadconf (char *fname, confetti * jr)
{
FILE *src;
unsigned char linbuff[1024];
char *pargv[100];
char *tmp;
int p;
int err;
int line;
// set some defaults
jr->maxusers = 0;
jr->optflags = 0;
req = 0;
if ((src = fopen (fname, "rb")) == NULL)
{
return CONFNOTFOUND;
}
line=0;
while (!feof (src))
{
if ((fgets (linbuff, 1024, src)) == NULL)
{
break;
}
line++;
p = 0;
if(strlen(linbuff) < 2)
continue;
if(linbuff[1] == ':')
{
/* old style */
printf("old style\n");
tmp = strtok (linbuff, ":\n\r");
if (tmp != NULL)
{
if(tmp[0] == '#')
{
continue;
}
pargv[p++] = tmp;
while ((tmp = strtok (NULL, ": \n\r")) != NULL)
{
pargv[p++] = tmp;
if (p > 100)
{
break;
}
}
err = confoption (jr, p, pargv);
if(err == -1)
{
printf ("--Option line in error:(%i)\n", line);
}
}
}
else
{
tmp = strtok (linbuff, " \n\r,");
if (tmp != NULL)
{
if(tmp[0] == '#')
{
continue;
}
pargv[p++] = tmp;
while ((tmp = strtok (NULL, " \n\r,")) != NULL)
{
pargv[p++] = tmp;
if (p > 100)
{
break;
}
}
err = confoption (jr, p, pargv);
if(err == -1)
{
printf ("--Option line in error:(%i)\n", line);
}
}
}
}
fclose (src);
if (req != 3)
{
return CONFREQNOTHAPPY;
}
return 0;
}
unsigned char tolowertab[] =
{
0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0x1e, 0x1f,
' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
'*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
':', ';', '<', '=', '>', '?',
'@', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
'_',
'`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
unsigned char touppertab[] =
{
0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa,
0xb, 0xc, 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14,
0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
0x1e, 0x1f,
' ', '!', '"', '#', '$', '%', '&', 0x27, '(', ')',
'*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
':', ';', '<', '=', '>', '?',
'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
0x5f,
'`', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^',
0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9,
0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
syntax highlighted by Code2HTML, v. 0.9.1