source: Main/trunk/Server/config.c@ 377

Last change on this file since 377 was 359, checked in by Nishi, on Oct 16, 2024 at 11:34:51 PM

add dos supportr

  • Property svn:keywords set to Id
File size: 16.1 KB
RevLine 
[4]1/* $Id: config.c 359 2024-10-16 14:34:51Z nishi $ */
2
[16]3#define SOURCE
4
[312]5#include "../config.h"
[4]6
7#include <stdio.h>
[7]8#include <stdint.h>
[4]9#include <stdlib.h>
10#include <string.h>
[257]11#include <sys/stat.h>
[212]12
[215]13#if !defined(_MSC_VER) && !defined(__BORLANDC__)
[12]14#include <unistd.h>
[212]15#endif
[4]16
[359]17#if defined(__MINGW32__) || defined(_MSC_VER) || defined(__BORLANDC__) || (defined(__WATCOMC__) && !defined(__OS2__) && !defined(__NETWARE__) && !defined(__DOS__))
[240]18#ifdef USE_WINSOCK1
19#include <winsock.h>
20#else
[20]21#include <winsock2.h>
22#endif
[240]23#endif
[20]24
[4]25#include <cm_string.h>
26#include <cm_log.h>
27
[312]28#ifdef __OS2__
29#include <types.h>
30#include <netinet/in.h>
31#include <tcpustd.h>
32#endif
33
[347]34#ifdef __NETWARE__
[349]35#include <sys/socket.h>
[347]36#endif
[312]37#include "tw_config.h"
38#include "tw_module.h"
39
[6]40struct tw_config config;
41
[12]42struct tw_config_entry* tw_vhost_match(const char* name, int port) {
43 int i;
44 for(i = 0; i < config.vhost_count; i++) {
[13]45 if(strcmp(config.vhosts[i].name, name) == 0 && (config.vhosts[i].port == -1 ? 1 : config.vhosts[i].port == port)) {
[12]46 return &config.vhosts[i];
47 }
48 }
49 return &config.root;
50}
51
[22]52bool tw_permission_allowed(const char* path, SOCKADDR addr, struct tw_http_request req, struct tw_config_entry* vhost) {
[21]53 int i;
54 bool found = false;
55 bool pathstart = false;
56 bool perm = false;
57again:
[22]58 for(i = 0; i < vhost->dir_count; i++) {
[212]59 char* noslash;
[21]60 struct tw_dir_entry* e = &vhost->dirs[i];
61 pathstart = false;
[22]62 if(strlen(path) >= strlen(e->dir)) {
[212]63 int j;
[21]64 pathstart = true;
[22]65 for(j = 0; path[j] != 0 && e->dir[j] != 0; j++) {
66 if(path[j] != e->dir[j]) {
[21]67 pathstart = false;
68 break;
69 }
70 }
71 }
[212]72 noslash = cm_strdup(e->dir);
[21]73 noslash[strlen(noslash) - 1] = 0;
[22]74 if(strcmp(e->dir, path) == 0 || strcmp(noslash, path) == 0 || pathstart) {
[21]75 found = true;
[22]76 if(strcmp(e->name, "all") == 0) {
[21]77 perm = e->type == TW_DIR_ALLOW;
78 }
79 }
80 free(noslash);
81 }
[22]82 if(!found && vhost != &config.root) {
[21]83 vhost = &config.root;
84 goto again;
85 }
86 return perm;
87}
88
[7]89void tw_config_init(void) {
90 int i;
91 for(i = 0; i < MAX_PORTS + 1; i++) {
92 config.ports[i] = -1;
93 }
[12]94 for(i = 0; i < MAX_VHOSTS; i++) {
[156]95#ifndef NO_SSL
[12]96 config.vhosts[i].sslkey = NULL;
97 config.vhosts[i].sslcert = NULL;
[156]98#endif
[19]99 config.vhosts[i].root = NULL;
[156]100#ifdef HAS_CHROOT
101 config.vhosts[i].chroot_path = NULL;
102#endif
[12]103 }
[156]104#ifndef NO_SSL
[12]105 config.root.sslkey = NULL;
106 config.root.sslcert = NULL;
[156]107#endif
[19]108 config.root.root = NULL;
[21]109 config.root.mime_count = 0;
110 config.root.dir_count = 0;
[22]111 config.root.icon_count = 0;
[24]112 config.root.index_count = 0;
[33]113 config.root.readme_count = 0;
[123]114 config.root.hideport = 0;
[156]115#ifdef HAS_CHROOT
116 config.root.chroot_path = NULL;
117#endif
[12]118 config.vhost_count = 0;
[18]119 config.module_count = 0;
120 config.extension = NULL;
[17]121 config.server_root = cm_strdup(PREFIX);
[128]122 config.server_admin = cm_strdup(SERVER_ADMIN);
[156]123 config.defined[0] = NULL;
[187]124#if defined(_PSP)
[182]125 strcpy(config.hostname, "psp");
[187]126#elif defined(__PPU__)
127 strcpy(config.hostname, "ps3");
[189]128#elif defined(__ps2sdk__)
129 strcpy(config.hostname, "ps2");
[315]130#elif defined(__NETWARE__)
131 strcpy(config.hostname, "netware");
[182]132#else
[12]133 gethostname(config.hostname, 1024);
[182]134#endif
[161]135#ifdef HAS_CHROOT
136 tw_add_define("HAS_CHROOT");
137#endif
[174]138#ifndef NO_SSL
139 tw_add_define("HAS_SSL");
140#endif
[7]141}
[6]142
143int tw_config_read(const char* path) {
[4]144 char cbuf[2];
[6]145 int ln = 0;
[156]146 int ifbr = 0;
147 int ignore = -1;
[253]148 int portcount;
[212]149 FILE* f;
150 cm_log("Config", "Reading %s", path);
151 f = fopen(path, "r");
152 cbuf[1] = 0;
[6]153 if(f != NULL) {
[4]154 char* line = malloc(1);
[6]155 int stop = 0;
[12]156 struct tw_config_entry* current = &config.root;
[6]157 char* vhost = NULL;
[21]158 char* dir = NULL;
[212]159 line[0] = 0;
[6]160 while(stop == 0) {
[4]161 int c = fread(cbuf, 1, 1, f);
[6]162 if(cbuf[0] == '\n' || c <= 0) {
[212]163 char* l = cm_trim(line);
[6]164 ln++;
165 if(strlen(l) > 0 && l[0] != '#') {
[5]166 char** r = cm_split(l, " \t");
167 int i;
[156]168 if(ignore != -1 && ifbr >= ignore) {
169 if(cm_strcaseequ(r[0], "EndIf")) ifbr--;
170 if(ifbr == 0) {
171 ignore = -1;
172 }
173 } else if(cm_strcaseequ(r[0], "Include") || cm_strcaseequ(r[0], "IncludeOptional")) {
[6]174 for(i = 1; r[i] != NULL; i++) {
175 if(tw_config_read(r[i]) != 0 && cm_strcaseequ(r[0], "Include")) {
176 stop = 1;
177 break;
[5]178 }
179 }
[156]180 } else if(cm_strcaseequ(r[0], "Define")) {
181 if(r[1] == NULL) {
182 cm_log("Config", "Missing name at line %d", ln);
183 stop = 1;
184 } else {
185 tw_add_define(r[1]);
186 }
187 } else if(cm_strcaseequ(r[0], "Undefine")) {
188 if(r[1] == NULL) {
189 cm_log("Config", "Missing name at line %d", ln);
190 stop = 1;
191 } else {
192 tw_delete_define(r[1]);
193 }
[21]194 } else if(cm_strcaseequ(r[0], "BeginDirectory")) {
195 if(dir != NULL) {
196 cm_log("Config", "Already in directory section at line %d", ln);
197 stop = 1;
198 } else {
199 if(r[1] == NULL) {
200 cm_log("Config", "Missing directory at line %d", ln);
201 stop = 1;
202 } else {
203 dir = cm_strcat(r[1], r[1][strlen(r[1]) - 1] == '/' ? "" : "/");
204 }
205 }
206 } else if(cm_strcaseequ(r[0], "EndDirectory")) {
207 if(dir == NULL) {
208 cm_log("Config", "Not in directory section at line %d", ln);
209 stop = 1;
210 } else {
211 free(dir);
212 dir = NULL;
213 }
214 } else if(cm_strcaseequ(r[0], "Allow")) {
215 if(dir == NULL) {
216 cm_log("Config", "Not in directory section at line %d", ln);
217 stop = 1;
218 } else {
219 if(r[1] == NULL) {
220 cm_log("Config", "Missing argument at line %d", ln);
221 stop = 1;
222 } else {
223 struct tw_dir_entry* e = &current->dirs[current->dir_count++];
224 e->name = cm_strdup(r[1]);
225 e->dir = cm_strdup(dir);
226 e->type = TW_DIR_ALLOW;
227 }
228 }
229 } else if(cm_strcaseequ(r[0], "Deny")) {
230 if(dir == NULL) {
231 cm_log("Config", "Not in directory section at line %d", ln);
232 stop = 1;
233 } else {
234 if(r[1] == NULL) {
235 cm_log("Config", "Missing argument at line %d", ln);
236 stop = 1;
237 } else {
238 struct tw_dir_entry* e = &current->dirs[current->dir_count++];
239 e->name = cm_strdup(r[1]);
240 e->dir = cm_strdup(dir);
241 e->type = TW_DIR_DENY;
242 }
243 }
[6]244 } else if(cm_strcaseequ(r[0], "BeginVirtualHost")) {
245 if(vhost != NULL) {
[12]246 cm_log("Config", "Already in virtual host section at line %d", ln);
[6]247 stop = 1;
248 } else {
249 if(r[1] == NULL) {
[12]250 cm_log("Config", "Missing virtual host at line %d", ln);
[6]251 stop = 1;
252 } else {
[212]253 int i;
[6]254 vhost = cm_strdup(r[1]);
[12]255 current = &config.vhosts[config.vhost_count++];
[21]256 current->dir_count = 0;
257 current->mime_count = 0;
[22]258 current->icon_count = 0;
[24]259 current->index_count = 0;
[33]260 current->readme_count = 0;
[123]261 current->hideport = -1;
[12]262 current->name = cm_strdup(vhost);
[13]263 current->port = -1;
[12]264 for(i = 0; vhost[i] != 0; i++) {
265 if(vhost[i] == ':') {
266 current->name[i] = 0;
267 current->port = atoi(current->name + i + 1);
268 break;
269 }
270 }
[6]271 }
272 }
273 } else if(cm_strcaseequ(r[0], "EndVirtualHost")) {
274 if(vhost == NULL) {
[12]275 cm_log("Config", "Not in virtual host section at line %d", ln);
[6]276 stop = 1;
277 } else {
278 free(vhost);
279 vhost = NULL;
[12]280 current = &config.root;
[6]281 }
[174]282 } else if(cm_strcaseequ(r[0], "Listen")
283#ifndef NO_SSL
284 || cm_strcaseequ(r[0], "ListenSSL")
285#endif
286 ) {
[7]287 for(i = 1; r[i] != NULL; i++) {
[215]288#if defined(_MSC_VER) || defined(__BORLANDC__)
[212]289 uint32_t port = atoi(r[i]);
290#else
[7]291 uint64_t port = atoi(r[i]);
[212]292#endif
293 int j;
[7]294 cm_log("Config", "Going to listen at port %d%s", (int)port, cm_strcaseequ(r[0], "ListenSSL") ? " with SSL" : "");
[215]295#if defined(_MSC_VER) || defined(__BORLANDC__)
[212]296 if(cm_strcaseequ(r[0], "ListenSSL")) port |= (1UL << 31);
297#else
298 if(cm_strcaseequ(r[0], "ListenSSL")) port |= (1ULL << 31);
299#endif
[7]300 for(j = 0; config.ports[j] != -1; j++)
301 ;
302 config.ports[j] = port;
303 }
[123]304 } else if(cm_strcaseequ(r[0], "HidePort")) {
305 current->hideport = 1;
306 } else if(cm_strcaseequ(r[0], "ShowPort")) {
307 current->hideport = 0;
[156]308#ifndef NO_SSL
[12]309 } else if(cm_strcaseequ(r[0], "SSLKey")) {
310 if(r[1] == NULL) {
311 cm_log("Config", "Missing path at line %d", ln);
312 stop = 1;
313 } else {
314 if(current->sslkey != NULL) free(current->sslkey);
315 current->sslkey = cm_strdup(r[1]);
316 }
317 } else if(cm_strcaseequ(r[0], "SSLCertificate")) {
318 if(r[1] == NULL) {
319 cm_log("Config", "Missing path at line %d", ln);
320 stop = 1;
321 } else {
322 if(current->sslcert != NULL) free(current->sslcert);
323 current->sslcert = cm_strdup(r[1]);
324 }
[156]325#endif
[161]326#ifdef HAS_CHROOT
327 } else if(cm_strcaseequ(r[0], "ChrootDirectory")) {
328 if(r[1] == NULL) {
329 cm_log("Config", "Missing path at line %d", ln);
330 stop = 1;
331 } else {
332 if(current->chroot_path != NULL) free(current->chroot_path);
333 current->chroot_path = cm_strdup(r[1]);
334 }
335#endif
[156]336 } else if(cm_strcaseequ(r[0], "ForceLog")) {
337 if(r[1] == NULL) {
338 cm_log("Config", "Missing log at line %d", ln);
339 stop = 1;
340 } else {
341 cm_force_log(r[1]);
342 }
343 } else if(cm_strcaseequ(r[0], "EndIf")) {
344 if(ifbr == 0) {
345 cm_log("Config", "Missing BeginIf at line %d", ln);
346 stop = 1;
347 }
348 ifbr--;
349 } else if(cm_strcaseequ(r[0], "BeginIf") || cm_strcaseequ(r[0], "BeginIfNot")) {
350 if(r[1] == NULL) {
351 cm_log("Config", "Missing condition type at line %d", ln);
352 } else {
[212]353 bool ign = false;
[156]354 ifbr++;
355 if(cm_strcaseequ(r[1], "False")) {
356 ign = true;
357 } else if(cm_strcaseequ(r[1], "True")) {
358 } else if(cm_strcaseequ(r[1], "Defined")) {
359 if(r[2] == NULL) {
360 cm_log("Config", "Missing name at line %d", ln);
361 stop = 1;
362 } else {
363 int i;
364 bool fndit = false;
365 for(i = 0; config.defined[i] != NULL; i++) {
366 if(strcmp(config.defined[i], r[2]) == 0) {
367 fndit = true;
368 break;
369 }
370 }
371 if(!fndit) {
372 ign = true;
373 }
374 }
375 } else {
376 cm_log("Config", "Unknown condition type at line %d", ln);
377 stop = 1;
378 }
379 if(cm_strcaseequ(r[0], "BeginIfNot")) ign = !ign;
380 if(ign) {
381 ignore = ifbr - 1;
382 }
383 }
[61]384 } else if(cm_strcaseequ(r[0], "ServerRoot")) {
385 if(r[1] == NULL) {
386 cm_log("Config", "Missing path at line %d", ln);
387 stop = 1;
388 } else {
389 chdir(r[1]);
[127]390 free(config.server_root);
391 config.server_root = cm_strdup(r[1]);
[61]392 }
[128]393 } else if(cm_strcaseequ(r[0], "ServerAdmin")) {
394 if(r[1] == NULL) {
395 cm_log("Config", "Missing email at line %d", ln);
396 stop = 1;
397 } else {
398 free(config.server_admin);
399 config.server_admin = cm_strdup(r[1]);
400 }
[19]401 } else if(cm_strcaseequ(r[0], "DocumentRoot")) {
402 if(r[1] == NULL) {
403 cm_log("Config", "Missing path at line %d", ln);
404 stop = 1;
405 } else {
406 if(current->root != NULL) free(current->root);
[21]407 current->root = cm_strdup(strcmp(r[1], "/") == 0 ? "" : r[1]);
[19]408 }
[21]409 } else if(cm_strcaseequ(r[0], "MIMEType")) {
410 if(r[1] == NULL) {
411 cm_log("Config", "Missing extension at line %d", ln);
412 stop = 1;
[22]413 } else if(r[2] == NULL) {
[21]414 cm_log("Config", "Missing MIME at line %d", ln);
415 stop = 1;
416 } else {
417 struct tw_mime_entry* e = &current->mimes[current->mime_count++];
418 e->ext = cm_strdup(r[1]);
419 e->mime = cm_strdup(r[2]);
420 }
[257]421 } else if(cm_strcaseequ(r[0], "MIMEFile")) {
422 if(r[1] == NULL) {
423 cm_log("Config", "Missing path at line %d", ln);
424 stop = 1;
425 } else {
426 FILE* mimefile = fopen(r[1], "r");
427 if(mimefile == NULL) {
428 cm_log("Config", "Could not load the file at line %d", ln);
429 stop = 1;
430 } else {
431 char* line = malloc(1);
432 int i;
433 struct stat st;
434 char* buf;
435 int incr = 0;
436 stat(r[1], &st);
437
438 buf = malloc(st.st_size + 1);
439 fread(buf, st.st_size, 1, mimefile);
440
441 for(i = 0;; i++) {
442 if(buf[i] == '\n' || buf[i] == 0) {
443 char oldc = buf[i];
444 char* line;
445 buf[i] = 0;
446
447 line = buf + incr;
448
449 if(strlen(line) > 0 && line[0] != '#') {
450 int j;
451 for(j = 0; line[j] != 0; j++) {
452 if(line[j] == ' ' || line[j] == '\t') {
453 line[j] = 0;
454 j++;
455 for(; line[j] != 0; j++) {
456 if(line[j] != ' ' && line[j] != '\t') {
457 char* name = line;
458 char* mimes = line + j;
459 int k = 0;
460 int incr2 = 0;
461 for(k = 0;; k++) {
462 if(mimes[k] == ' ' || mimes[k] == 0) {
463 char oldc2 = mimes[k];
464 struct tw_mime_entry* e;
465 mimes[k] = 0;
466
467 e = &current->mimes[current->mime_count++];
468 e->ext = cm_strcat(".", mimes + incr2);
469 e->mime = cm_strdup(name);
470 if(current->mime_count == MAX_MIME) {
471 cm_log("Config", "Too many MIME types, cannot handle");
472 stop = 1;
473 break;
474 }
475
476 incr2 = k + 1;
477 if(oldc2 == 0) break;
478 }
479 }
480 break;
481 }
482 }
483 break;
484 }
485 if(stop) break;
486 }
487 }
488
489 incr = i + 1;
490 if(oldc == 0) break;
491 }
492 }
493
494 free(buf);
495
496 fclose(mimefile);
497 }
498 }
[22]499 } else if(cm_strcaseequ(r[0], "Icon")) {
500 if(r[1] == NULL) {
501 cm_log("Config", "Missing MIME at line %d", ln);
502 stop = 1;
503 } else if(r[2] == NULL) {
504 cm_log("Config", "Missing path at line %d", ln);
505 stop = 1;
506 } else {
507 struct tw_icon_entry* e = &current->icons[current->icon_count++];
508 e->mime = cm_strdup(r[1]);
509 e->icon = cm_strdup(r[2]);
510 }
[17]511 } else if(cm_strcaseequ(r[0], "LoadModule")) {
512 for(i = 1; r[i] != NULL; i++) {
513 void* mod = tw_module_load(r[i]);
514 if(mod != NULL) {
[18]515 config.modules[config.module_count++] = mod;
[17]516 if(tw_module_init(mod) != 0) {
517 stop = 1;
518 break;
519 }
520 } else {
[127]521 cm_log("Config", "Could not load the module at line %d", ln);
[17]522 stop = 1;
523 break;
524 }
525 }
[24]526 } else if(cm_strcaseequ(r[0], "DirectoryIndex")) {
527 for(i = 1; r[i] != NULL; i++) {
528 current->indexes[current->index_count++] = cm_strdup(r[i]);
529 }
[178]530 } else if(cm_strcaseequ(r[0], "ReadmeFile") || cm_strcaseequ(r[0], "Readme")) {
[182]531 if(cm_strcaseequ(r[0], "Readme")) {
[178]532 cm_force_log("NOTE: Readme directive is deprecated.");
533 }
[33]534 for(i = 1; r[i] != NULL; i++) {
535 current->readmes[current->readme_count++] = cm_strdup(r[i]);
536 }
[6]537 } else {
[39]538 stop = 1;
[6]539 if(r[0] != NULL) {
[39]540 int argc;
[212]541 int i;
542 bool called = false;
543 struct tw_tool tools;
[39]544 for(argc = 0; r[argc] != NULL; argc++)
545 ;
546 stop = 0;
547 tw_init_tools(&tools);
548 for(i = 0; i < config.module_count; i++) {
549 tw_mod_config_t mod_config = (tw_mod_config_t)tw_module_symbol(config.modules[i], "mod_config");
550 int resp;
551 if(mod_config != NULL && (resp = mod_config(&tools, r, argc)) == TW_CONFIG_PARSED) {
552 called = true;
553 break;
554 }
555 if(resp == TW_CONFIG_ERROR) {
556 stop = 1;
557 called = true;
558 break;
559 }
560 }
561 if(!called) {
562 cm_log("Config", "Unknown directive `%s' at line %d", r[0], ln);
563 stop = 1;
564 }
[6]565 }
[5]566 }
567 for(i = 0; r[i] != NULL; i++) free(r[i]);
568 free(r);
[4]569 }
570 free(l);
571 free(line);
572 line = malloc(1);
573 line[0] = 0;
574 if(c <= 0) break;
[6]575 } else if(cbuf[0] != '\r') {
[4]576 char* tmp = line;
577 line = cm_strcat(tmp, cbuf);
578 free(tmp);
579 }
580 }
581 free(line);
582 fclose(f);
[255]583 for(portcount = 0; config.ports[portcount] != -1; portcount++)
584 ;
585 if(portcount == 0) {
[253]586 return 1;
[255]587 } else {
[253]588 return stop;
589 }
[6]590 } else {
[5]591 cm_log("Config", "Could not open the file");
[4]592 return 1;
593 }
594}
Note: See TracBrowser for help on using the repository browser.