/* ------------------------------------------------------------- ** ** Removes one line of control stream from buf (up to '\r\n'). <= 5 ** chars are returned in cmd (up to 4 + \0), and <= MAX_LINE_LEN in ** arg. Must accept any NULL terminated buf and give sane output. ** ** returns 0 on success, 1 if there is not a complete line in ** buf, and -X on non-sane buf. contents of buf unchanged on ** return(1), undefined on return(-X) ** ------------------------------------------------------------- */ int extract_clientcmd(sstr * buf, sstr ** pcmd, sstr ** parg) { static sstr *cmd = NULL, *arg = NULL; if(!cmd) cmd = sstr_init(4); if(!arg) arg = sstr_init(MAX_LINE_LEN); if(pcmd) *pcmd = cmd; if(parg) *parg = arg; if(!sstr_hasline(buf)) return (1); switch (sstr_token(buf, cmd, " \t\n\r", 0)) { case -1: /*Token doesn't fit in cmd */ return (-1); case ' ': case '\t': sstr_token(buf, arg, "\r\n", 0); break; default: /*end of line */ sstr_empty(arg); } if(!config.nonasciiok) sstr_makeprintable(arg, '?'); return (0); }
int parse_line(sstr * buf) { struct option_array *opt; sstr *tok; tok = sstr_init(0); if (sstr_getchar(buf, 0) == '#') return (0); if (sstr_token(buf, tok, " =\t\r\n", 0) == -1) return (0); if (!sstr_casecmp2(tok, "EndSection")) return (sublevel > 0 ? 1 : -1); opt = opts; while (opt->name != NULL && sstr_casecmp2(tok, opt->name)) opt++; if (opt->name == NULL) { fprintf(stderr,"Unrecognised option \"%s\" at line %d of %s\n", sstr_buf(tok), line_no, config.config_file); return (-1); } if (opt->cmdline && strchr(cmdline_set, opt->cmdline)) { fprintf(stderr, "\"%s\" specified on the command line: ignored\n", opt->name); return (0); } if (set_opt(opt, buf) == -1) { fprintf(stderr, "Invalid argument to %s at line %d of %s\n", opt->name, line_no, config.config_file); return (-1); } return (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); }
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); }
/* ------------------------------------------------------------- ** ** As extract_clientcmd, but returns the code as an int. ** If code==0 then we are in a multiline. code<0 means we are ** starting a multiline. ** ------------------------------------------------------------- */ int extract_servercmd(sstr * buf, int *code, sstr ** pmsg) { static int multiline = 0; static sstr *scode = NULL, *msg = NULL; if(!scode) scode = sstr_init(4); if(!msg) msg = sstr_init(MAX_LINE_LEN); if(pmsg) *pmsg = msg; if(!sstr_hasline(buf)) return (1); if(sstr_token(buf, msg, "\r\n", 0) == -1) return (-1); if(!multiline || (sstr_atoi(msg) == multiline && sstr_getchar(msg, 3) == ' ')) { multiline = 0; if(sstr_split(msg, scode, 0, 4) == -1) return (-1); *code = sstr_atoi(scode); switch (sstr_getchar(scode, 3)) { case '-': multiline = *code; *code = -*code; case ' ': break; default: return (-1); } } else { *code = 0; } if(!config.nonasciiok) sstr_makeprintable(msg, '?'); return (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); }
/* ------------------------------------------------------------- ** ** Allocate and initialise session_info structure. Also determine ** destination address if possible. ** ------------------------------------------------------------- */ static session_info *init_info(int fd, struct sockaddr_in source) { session_info *i; i = (session_info *) malloc(sizeof(session_info)); if(i == NULL) die(ERROR, "Malloc failed", 0, NULL, -1); memset(i, 0, sizeof(session_info)); i->server_listen = i->client_listen = -1; i->client_data.fd = i->server_data.fd = -1; i->server_control.fd = -1; i->server_control.buf = sstr_init(BUF_LEN); i->client_control.buf = sstr_init(BUF_LEN); i->server_data.buf = sstr_init(DATA_BUF_LEN); i->client_data.buf = sstr_init(DATA_BUF_LEN); i->last_command = sstr_init(0); i->server_name = sstr_init(0); i->username = sstr_init(0); i->passwd = sstr_init(0); i->strictpath = sstr_init(0); i->cmd_arrays[CACHE_CMDS] = NULL; i->cmd_arrays[FTP_CMDS] = ftp_cmds; i->filename = sstr_init(0); if(config.apconv) i->mode = APCONV; else i->mode = ACTIVE; i->state = NEITHER; i->greeting = AWAITED; i->client_control.address = source; i->client_control.fd = fd; get_orig_dest(fd, &i->server_control.address); i->apparent_server_address = i->server_control.address; return i; }
/* ------------------------------------------------------------- ** ** Return hostname of address, or failing that the IP as a string ** ------------------------------------------------------------- */ sstr *addr2name(struct in_addr address) { struct hostent *hostinfo; static sstr *buf = NULL; if(!buf) buf = sstr_init(MAX_LINE_LEN); sstr_cpy2(buf, inet_ntoa(address)); if((hostinfo = gethostbyaddr((char *) &address, sizeof(address), AF_INET)) != NULL) sstr_apprintf(buf, "(%s)", hostinfo->h_name); return (buf); }
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); }
/** * SACT.Init (1.0~) * SACT全体の初期化 */ void Init() { int p1 = getCaliValue(); /* ISys3x */ // ゲームタイトルによるバージョン設定 if (0 == strcmp(nact->game_title_name, GT_ESUKA)) { sact.version = 100; } else if (0 == strcmp(nact->game_title_name, GT_RANCE5D)){ sact.version = 110; } else { sact.version = 120; } NOTICE("SACT version = %d\n", sact.version); // 初期座標原点 sact.origin.x = 0; sact.origin.y = 0; // 各サブシステム初期化 sp_init(); sstr_init(); ssel_init(); stimer_init(); ssnd_init(); if (nact->files.sact01) { smask_init(nact->files.sact01); } // create depth map sact.dmap = sf_create_pixel(sf0->width, sf0->height, 16); // その他 System35 のデフォルト動作の変更 nact->ags.font->antialiase_on = TRUE; sys_setHankakuMode(2); // 全角半角変換無し ags_autorepeat(FALSE); // key auto repeat off if (sact.version >= 120) { sact.logging = TRUE; } else { sact.logging = FALSE; } DEBUG_COMMAND("SACT.Init %d:\n", p1); }
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); }
/* 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; }
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); }
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; }
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); }
/* ------------------------------------------------------------- ** ** 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); }
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); }
/* ------------------------------------------------------------- ** ** 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); }
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); }