Пример #1
0
/* ------------------------------------------------------------- **
** Extract a comma delimited address/port from buf. buf is unchecked
** user input so make sure we don't do anything stupid here...
** ------------------------------------------------------------- */
struct sockaddr_in extract_address(const sstr * buf)
{
	int i, a[6];
	struct sockaddr_in tmp;
	sstr *p = sstr_dup(buf);

	memset(&tmp, 0, sizeof(tmp));

	sstr_split(p, NULL, 0, sstr_pbrk2(p, "01234456789"));
	for(i = 0; i < 6; i++) {
		a[i] = sstr_atoi(p);
		if(a[i] < 0 || a[i] > 255) {
			sstr_free(p);
			write_log(ATTACK,
				  "PORT/PASV command number out of range");
			return tmp;
		}
		if(i != 5 && sstr_token(p, NULL, ",", 0) == -1) {
			sstr_free(p);
			return (tmp);
		}
	}

	tmp = com2n(a[0], a[1], a[2], a[3], a[4], a[5]);
	sstr_free(p);
	return (tmp);
}
Пример #2
0
void send_ccommand(const char *cmd, const char *arg)
{
	sstr *scmd, *sarg;
	scmd = sstr_dup2(cmd);
	sarg = sstr_dup2(arg);

	send_command(scmd, sarg);

	sstr_free(scmd);
	sstr_free(sarg);
}
Пример #3
0
int store_addressrange(sstr * str, struct in_addr *addr, struct in_addr *msk)
{
	sstr *tok;
	int sep, i;
	tok = sstr_init(0);

	sep = sstr_token(str, tok, " /->\r\n", 0);
	if(name2addr(tok, addr)==-1) return(-1);

	if (sep == '/') {
		sep = sstr_token(str, tok, " /->\r\n", 0);
		if (sstr_chr(tok, '.')==-1) {	/* x.x.x.x/yy */
			i = sstr_atoi(tok);
			msk->s_addr = htonl(0xFFFFFFFF << (32 - i));
		} else
			if(name2addr(tok, msk)==-1) return(-1);
	} else {		/*No mask given */
		if (addr->s_addr == INADDR_ANY)
			msk->s_addr = INADDR_ANY;
		else
			msk->s_addr = INADDR_BROADCAST;
	}
	sstr_free(tok);
	return (0);
}
Пример #4
0
int store_acl(sstr * str, struct acl_list *acls)
{
	sstr *tok;
	struct acl_item item;

	tok = sstr_init(0);

	sstr_token(str, tok, " \t\n", 0);

	if (!sstr_casecmp2(tok, "Allow"))
		item.action = ALLOW;
	else if (!sstr_casecmp2(tok, "Deny"))
		item.action = DENY;
	else
		return (-1);
	sstr_free(tok);

	parse_match(str, &item);

	acls->list = realloc(acls->list,
			     (acls->num + 1) * sizeof(struct acl_item));
	if(!acls->list) return(-1);
	memcpy(acls->list + acls->num, &item, sizeof(struct acl_item));
	acls->num++;
	return (0);
}
Пример #5
0
int read_config()
{
	struct option_array *opt;
	sstr *buf;

	if (!fp) {
		if (config.config_file == NULL) fp = fopen(CONFIG_FILE, "r");
		else fp = fopen(config.config_file, "r");
		if (fp == NULL) return (-1);
		line_no=0;
	}

	buf = sstr_init(0);
	while (sstr_fgets(buf, fp) != NULL) {
		line_no++;
		switch (parse_line(buf)) {
		case -1:
			sstr_free(buf);
			if (sublevel == 0) fclose(fp);
			return (-1);
		case 0:
			break;

		case 1:	/* end subsection */
			sstr_free(buf);
			return (0);
		}
	};
	sstr_free(buf);
	fclose(fp);
	fp = NULL;

	opt = opts;
	while (opt->name != NULL && !opt->essential)
		opt++;
	if (opt->name != NULL) {
		fprintf(stderr, "Essential option \"%s\" not specified.\n",
			opt->name);
		return (-1);
	}
	process_opts();
#ifdef DEBUG
	if(!config.inetd) print_config();
#endif
	return (0);
}
Пример #6
0
void send_cmessage(int code, const char *msg)
{
	sstr *smsg;
	smsg = sstr_dup2(msg);

	send_message(code, smsg);

	sstr_free(smsg);
}
Пример #7
0
int make_tmpdir(void)
{
	sstr *name;
	struct stat tmp;

	name = sstr_init(0);
	sstr_apprintf(name, "%s/tmp", config.chroot);

	if(stat(sstr_buf(name), &tmp) == -1) {
		if(mkdir(sstr_buf(name), S_IRWXU) == -1) {
			write_log(ERROR, "Unable to make tmp dir %s",
				  sstr_buf(name));
			sstr_free(name);
			return (-1);
		}
		chown(sstr_buf(name), config.uid, config.gid);
		sstr_free(name);
	}
	return 0;
}
Пример #8
0
/* ------------------------------------------------------------- **
** Functions to read / parse the config file.
** ------------------------------------------------------------- */
int process_cmdline(int argc, char *argv[])
{
	int i;
	struct option_array *opt;
	sstr *arg;
	char *optp, *argp;

	set_defaults();
	if (argc <= 1)
		return 0;

	arg = sstr_init(0);

	i = 1;
	optp = argv[i] + 1;

	while (i < argc) {
		if (argv[i][0] != '-')
			usage(-1);
		opt = opts;
		if (*optp == '-')
			usage(-1);	/*?TODO longopts */
		else {
			while (opt->name != NULL && opt->cmdline != *optp)
				opt++;
			if (opt->name == NULL)
				usage(*optp);
			if (strlen(cmdline_set) < 99)
				cmdline_set[strlen(cmdline_set)] = *optp;
			if (opt->type == BOOL) {
				sstr_cpy2(arg, "yes");
				set_opt(opt, arg);
				if (*(++optp) == 0) {
					i++;
					optp = argv[i] + 1;
				}
			} else {
				argp = optp + 1;
				if (*argp == 0) {
					if (i >= argc - 1 ||
					    *(argp = argv[++i]) == '-')
						usage(*optp);

				}
				sstr_cpy2(arg, argp);
				set_opt(opt, arg);
				i++;
				optp = argv[i] + 1;
			}
		}
	}
	sstr_free(arg);
	return (0);
}
Пример #9
0
/* Escape non printable characters, and any characters from extras in the url
 * with the %xx equivalent. If % must be escaped then include it in extras.
 */
int urlescape(sstr * url, char *extras)
{
	int i;
	sstr *tmp = sstr_init(0);

	for(i = 0; i < sstr_len(url); i++) {
		char c = sstr_getchar(url, i);
		if(strchr(extras, c) || !isprint(c)) {
			sstr_ncat(tmp, url, i);
			sstr_apprintf(tmp, "%%%x", c);
			sstr_split(url, NULL, 0, i + 1);
			i = -1;
		}
	}
	sstr_cat(tmp, url);
	sstr_cpy(url, tmp);
	sstr_free(tmp);
	return 0;
}
Пример #10
0
void write_log(int priority, const char *msg, ...)
{
	char *buf = NULL;
	int sz = MAX_LINE_LEN, n;
	va_list argptr;
	time_t tstamp;

	if(priority > config.loglevel)
		return;
	do {			/* Modified from printf(3) man page */
		if((buf = realloc(buf, sz)) == NULL)
			die(ERROR, "Out of memory.", 0, 0, -1);

		va_start(argptr, msg);
		n = vsnprintf(buf, sz, msg, argptr);
		va_end(argptr);

		if(n == -1)	/* glibc 2.0 */
			sz *= 2;	/* Try a bigger buffer */
		else if(n >= sz)	/* C99 compliant / glibc 2.1 */
			sz = n + 1;	/* precisely what is needed */
		else
			break;	/*It worked */
	} while(1);

	if(config.logfile) {
		sstr *s;
		s = sstr_init(0);
		time(&tstamp);
		sstr_cpy2(s, ctime(&tstamp));
		sstr_setchar(s, sstr_chr(s, '\n'), ' ');
		sstr_apprintf(s, "frox[%d] %s\n", getpid(), buf);
		sstr_write(2, s, 0);
		sstr_free(s);
	} else {
		if(priority == ERROR || priority == ATTACK) {
			syslog(LOG_ERR | LOG_DAEMON, "%s\n", buf);
		} else {
			syslog(LOG_NOTICE | LOG_DAEMON, "%s\n", buf);
		}
	}
	free(buf);
}
Пример #11
0
/* ------------------------------------------------------------- **
** init ssl context
** ------------------------------------------------------------- */
void ssl_init(void)
{
	sstr *msg;
	int i;

	if(!config.usessl)
		return;
	if(info->greeting == FAKED || info->greeting == AWAITED) {
		get_message(&i, &msg);
		if(i != 220) {
			die(INFO, "Unable to contact server in ntp", 421,
			    "Server Unable to accept connection", 0);
		}
		info->greetingmsg = sstr_dup(msg);
		info->greeting = info->greeting == FAKED ? DONE : SUPPRESSED;
	}

	send_ccommand("AUTH", config.datassl ? "TLS-P" : "TLS");
	get_message(&i, &msg);
	if(i != 234) {
		write_log(IMPORT, "SSL connection refused. "
			  "Using unencrypted connection");
		return;
	}

	SSL_load_error_strings();
	SSL_library_init();
	ctx = SSL_CTX_new(SSLv23_client_method());
	if(!ctx)
		die(ERROR, "Unable to initialise SSL", 0, 0, -1);

	info->ssl_sc = ssl_initfd(info->server_control.fd, SSL_CTRL);
	if(info->ssl_sc)
		write_log(IMPORT, "SSL initialised on control connection");
	else
		die(ERROR, "Unable to initialise SSL", 0, 0, -1);

	if(info->greeting == SUPPRESSED) {
		send_message(220, info->greetingmsg);
		info->greeting = DONE;
		sstr_free(info->greetingmsg);
	}
}
Пример #12
0
void parse_match(sstr *str, struct acl_item *item)
{
	sstr *tok;
	tok = sstr_init(0);

	item->user = NULL;
	sstr_token(str, tok, " \t\n", 0);
	item->src = strdup(sstr_buf(tok));
	sstr_token(str, NULL, " \t\n", 0); /*Removes the " - " from the ACL*/
	if(sstr_chr(str, '@')!=-1) {
		sstr_token(str, tok, "@", 0);
		item->user = strdup(sstr_buf(tok));
		config.fakentp = TRUE;
	}
	sstr_token(str, tok, " \t\n", 0);
	item->dst = strdup(sstr_buf(tok));
	item->ntp_ports = get_portlist(str);

	sstr_free(tok);
}
Пример #13
0
void set_defaults(void)
{
	sstr *tmp;
	tmp = sstr_init(0);

	config.resolvhack = NULL;
	config.device = NULL;
	sstr_cpy2(tmp, "ControlPorts 40000-50000");
	parse_line(tmp);
	sstr_cpy2(tmp, "PassivePorts 40000-50000");
	parse_line(tmp);
	sstr_cpy2(tmp, "ActivePorts 40000-50000");
	parse_line(tmp);
	config.timeout = 300;
	config.user = NULL;
	config.group = NULL;
	config.nonasciiok = FALSE;
	config.bdefend = TRUE;
	config.loglevel = 15;
	config.xferlogging = TRUE;
#ifdef TRANS_DATA
#endif
#ifdef USE_CACHE
	config.cachemod = NULL;
#endif
#ifdef USE_CCP
	config.ccpcmd = NULL;
	config.oldccp = TRUE;
#endif
#ifdef DO_VSCAN
	config.vscanner = NULL;
	config.vscanok = 0;
	config.vscanpm = 0;
#endif
#ifdef DO_SSL
	config.datassl = TRUE;
	config.anonssl = TRUE;
#endif

	sstr_free(tmp);
}
Пример #14
0
/* ------------------------------------------------------------- **
** Send message to client
** ------------------------------------------------------------- */
void send_message(int code, sstr * msg)
{
	sstr *buf;
	if(!ccp_allowmsg(&code, msg))
		return;

	buf = sstr_init(MAX_LINE_LEN + 10);

	if(code != 0)
		sstr_apprintf(buf, "%d%c", abs(code), code > 0 ? ' ' : '-');
	sstr_cat(buf, msg);
	sstr_ncat2(buf, "\r\n", 2);

#ifdef DEBUG
	fprintf(stderr, "  S: \033[34m%s\033[37m", sstr_buf(buf));
#else
	write_log(VERBOSE, "  S: %s", sstr_buf(buf));
#endif
	sstr_write(info->client_control.fd, buf, 0);
	sstr_free(buf);
}
Пример #15
0
u_int16_t *get_portlist(sstr * str)
{
	sstr *tok;
	int i = 0, sep;
	u_int16_t *ports = NULL;
	tok = sstr_init(0);

	do {
		ports = realloc(ports, (i + 2) * sizeof(u_int16_t));
		if(!ports) die(ERROR, "Out of memory reading config file",
			       0, 0, -1);
		sep = sstr_token(str, tok, " \t,-\r\n", 0);
		if (sep == -1)
			break;

		if (!sstr_cmp2(tok, "*")) {
			ports[i] = 1;
			ports[i + 1] = 0xFFFF;
			i += 2;
			break;
		}
		ports[i] = ports[i + 1] = sstr_atoi(tok);

		if (sep == '-') {
			sep = sstr_token(str, tok, " \t,\n", 0);
			if (sep == -1)
				ports[i + 1] = 0xFFFF;
			else
				ports[i + 1] = sstr_atoi(tok);
		}
		i += 2;
	} while (sep != -1);

	ports[i] = ports[i + 1] = 0;
	sstr_free(tok);
	return (ports);
}
Пример #16
0
/* ------------------------------------------------------------- **
** Send command to server 
** ------------------------------------------------------------- */
void send_command(sstr * cmd, sstr * arg)
{
	sstr *buf;
	buf = sstr_init(MAX_LINE_LEN + 10);

	sstr_cat(buf, cmd);
	if(sstr_len(arg) != 0) {
		sstr_ncat2(buf, " ", 1);
		sstr_cat(buf, arg);
	}
	sstr_ncat2(buf, "\r\n", 2);

#ifdef DEBUG
	fprintf(stderr, "  C: \033[31m%s\033[37m", sstr_buf(buf));
#else
	write_log(VERBOSE, "  C: %s", sstr_buf(buf));
#endif
	if(info->ssl_sc)
		ssl_write(info->ssl_sc, buf);
	else
		sstr_write(info->server_control.fd, buf, 0);

	sstr_free(buf);
}
Пример #17
0
static int _cmd_to_proto(char **target, const char *format, va_list ap) {
    const char *c = format;
    char *cmd = NULL; /* final command */
    int pos; /* position in final command */
    sstr curarg, newarg;
    int touched = 0; /* was the current argument touched? */
    char **curargv = NULL, **newargv = NULL;
    int argc = 0;
    int totlen = 0;
    int j;

    /* Abort if there is not target to set */
    if (target == NULL)
        return -1;

    /* Build the command string accordingly to protocol */
    curarg = sstr_empty();
    if (curarg == NULL)
        return -1;

    while(*c != '\0') {
        if (*c != '%' || c[1] == '\0') {
            if (*c == ' ') {
                if (touched) {
                    newargv = realloc(curargv,sizeof(char*)*(argc+1));
                    if (newargv == NULL) goto err;
                    curargv = newargv;
                    curargv[argc++] = curarg;
                    totlen += bulklen(sstr_len(curarg));

                    /* curarg is put in argv so it can be overwritten. */
                    curarg = sstr_empty();
                    if (curarg == NULL) goto err;
                    touched = 0;
                }
            } else {
                    newarg = sstr_catlen(curarg,c,1);
                if (newarg == NULL) goto err;
                curarg = newarg;
                touched = 1;
            }
        } else {
            char *arg;
            size_t size;

            /* Set newarg so it can be checked even if it is not touched. */
            newarg = curarg;

            switch(c[1]) {
            case 's':
                arg = va_arg(ap,char*);
                size = strlen(arg);
                if (size > 0)
                        newarg = sstr_catlen(curarg,arg,size);
                break;
            case 'b':
                arg = va_arg(ap,char*);
                size = va_arg(ap,size_t);
                if (size > 0)
                        newarg = sstr_catlen(curarg,arg,size);
                break;
            case '%':
                    newarg = sstr_cat(curarg,"%"); 
                break;
            default:
                /* Try to detect printf format */
                {
                    static const char intfmts[] = "diouxX";
                    char _format[16];
                    const char *_p = c+1;
                    size_t _l = 0;
                    va_list _cpy;

                    /* Flags */
                    if (*_p != '\0' && *_p == '#') _p++;
                    if (*_p != '\0' && *_p == '0') _p++;
                    if (*_p != '\0' && *_p == '-') _p++;
                    if (*_p != '\0' && *_p == ' ') _p++;
                    if (*_p != '\0' && *_p == '+') _p++;

                    /* Field width */
                    while (*_p != '\0' && isdigit(*_p)) _p++;

                    /* Precision */
                    if (*_p == '.') {
                        _p++;
                        while (*_p != '\0' && isdigit(*_p)) _p++;
                    }

                    /* Copy va_list before consuming with va_arg */
                    va_copy(_cpy,ap);

                    /* Integer conversion (without modifiers) */
                    if (strchr(intfmts,*_p) != NULL) {
                        va_arg(ap,int);
                        goto fmt_valid;
                    }

                    /* Double conversion (without modifiers) */
                    if (strchr("eEfFgGaA",*_p) != NULL) {
                        va_arg(ap,double);
                        goto fmt_valid;
                    }

                    /* Size: char */
                    if (_p[0] == 'h' && _p[1] == 'h') {
                        _p += 2;
                        if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                            va_arg(ap,int); /* char gets promoted to int */
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                    /* Size: short */
                    if (_p[0] == 'h') {
                        _p += 1;
                        if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                            va_arg(ap,int); /* short gets promoted to int */
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                    /* Size: long long */
                    if (_p[0] == 'l' && _p[1] == 'l') {
                        _p += 2;
                        if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                            va_arg(ap,long long);
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                    /* Size: long */
                    if (_p[0] == 'l') {
                        _p += 1;
                        if (*_p != '\0' && strchr(intfmts,*_p) != NULL) {
                            va_arg(ap,long);
                            goto fmt_valid;
                        }
                        goto fmt_invalid;
                    }

                fmt_invalid:
                    va_end(_cpy);
                    goto err;

                fmt_valid:
                    _l = (_p+1)-c;
                    if (_l < sizeof(_format)-2) {
                        memcpy(_format,c,_l);
                        _format[_l] = '\0';
                        newarg = sstr_catvprintf(curarg,_format,_cpy);

                        /* Update current position (note: outer blocks
                         * increment c twice so compensate here) */
                        c = _p-1;
                    }

                    va_end(_cpy);
                    break;
                }
            }

            if (newarg == NULL) goto err;
            curarg = newarg;

            touched = 1;
            c++;
        }
        c++;
    }

    /* Add the last argument if needed */
    if (touched) {
        newargv = realloc(curargv,sizeof(char*)*(argc+1));
        if (newargv == NULL) goto err;
        curargv = newargv;
        curargv[argc++] = curarg;
        totlen += bulklen(sstr_len(curarg));
    } else {
            sstr_free(curarg);
    }

    /* Clear curarg because it was put in curargv or was free'd. */
    curarg = NULL;

    /* Add bytes needed to hold multi bulk count */
    totlen += 1+intlen(argc)+2;

    /* Build the command at protocol level */
    cmd = malloc(totlen+1);
    if (cmd == NULL) goto err;

    pos = sprintf(cmd,"*%d\r\n",argc);
    for (j = 0; j < argc; j++) {
            pos += sprintf(cmd+pos,"$%zu\r\n",sstr_len(curargv[j]));
            memcpy(cmd+pos,curargv[j],sstr_len(curargv[j]));
            pos += sstr_len(curargv[j]);
            sstr_free(curargv[j]);
        cmd[pos++] = '\r';
        cmd[pos++] = '\n';
    }
    assert(pos == totlen);
    cmd[pos] = '\0';

    free(curargv);
    *target = cmd;
    return totlen;

err:
    while(argc--)
            sstr_free(curargv[argc]);
    free(curargv);

    if (curarg != NULL)
            sstr_free(curarg);

    /* No need to check cmd since it is the last statement that can fail,
     * but do it anyway to be as defensive as possible. */
    if (cmd != NULL)
        free(cmd);

    return -1;
}
Пример #18
0
int set_opt(struct option_array *opt, sstr * str)
{
	sstr *tok;
	int sep;

	if (rereading && !opt->reloadable)
		return (0);

	tok = sstr_init(0);

	sstr_ncat2(str, "\n", 1);	/*For sstr_token */
	opt->essential = FALSE;

	switch (opt->type) {
	case BOOL:
		sstr_token(str, tok, " \t\r\n", 0);
		if (!sstr_casecmp2(tok, "yes"))
			*(int *) opt->var = TRUE;
		else if (!sstr_casecmp2(tok, "no"))
			*(int *) opt->var = FALSE;
		else
			return (-1);
		break;
	case FILENAME:
	case STRING:
		sstr_token(str, tok, " \t\r\n", SSTR_QTOK);
		*(char **) opt->var = strdup(sstr_buf(tok));
		break;
	case DIRECTRY:
		sstr_token(str, tok, " \t\r\n", SSTR_QTOK);
		if (sstr_getchar(tok, sstr_len(tok) - 1) != '/')
			sstr_ncat2(tok, "/", 1);
		*(char **) opt->var = strdup(sstr_buf(tok));
		break;
	case ADDRESS:
		sstr_token(str, tok, " \t\r\n", 0);
		return name2addr(tok, (struct in_addr *) opt->var);
		break;
	case ADDRPRT:
		sep = sstr_token(str, tok, " :\t\r\n", 0);
		if( name2addr(tok, &((struct sockaddr_in *) opt->var)->sin_addr)==-1)
			return(-1);
		if (sep == ':')
			((struct sockaddr_in *) opt->var)->sin_port
			    = ntohs(sstr_atoi(str));
		((struct sockaddr_in *) opt->var)->sin_family = AF_INET;
		break;
	case INT:
		sstr_token(str, tok, " \t\r\n", 0);
		*(int *) opt->var = sstr_atoi(tok);
		break;
	case PRTRNGE:
		sstr_token(str, tok, " \t-,\r\n", 0);
		((int *) opt->var)[0] = sstr_atoi(tok);
		((int *) opt->var)[1] = sstr_atoi(str);
		if(!valid_uint16(((int *) opt->var)[0]) ||
		   !valid_uint16(((int *) opt->var)[1])) {
			fprintf(stderr, "Port out of range\n");
			return -1;
		}
		if(((int *) opt->var)[0] >= ((int *) opt->var)[1]) {
			fprintf(stderr, "Port range is inverted\n");
			return -1;
		}
		break;
	case ACL:
		return store_acl(str, (struct acl_list *) opt->var);
		break;
	case SUBSECT:
		return store_subsect(str, (struct subsect_list *) opt->var);
	}
	sstr_free(tok);
	return (0);
}