1 /* 2 * Gophernicus - Copyright (c) 2009-2018 Kim Holviala <kimholviala@fastmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #ifndef _GOPHERNICUS_H 26 #define _GOPHERNICUS_H 27 28 29 /* 30 * Ignore useless snprintf() format truncation warnings on GCC 7+ 31 */ 32 #if __GNUC__ >= 7 33 #pragma GCC diagnostic ignored "-Wformat-truncation" 34 #endif 35 36 37 /* 38 * Features 39 */ 40 #undef ENABLE_STRICT_RFC1436 /* Follow RFC1436 to the letter */ 41 #undef ENABLE_AUTOHIDING /* Hide manually listed resources from generated menus */ 42 #define ENABLE_HAPROXY1 /* Autodetect HAproxy/Stunnel proxy protocol v1 */ 43 44 45 /* 46 * Platform configuration 47 */ 48 49 /* Defaults should fit standard POSIX systems */ 50 #define HAVE_IPv4 /* IPv4 should work anywhere */ 51 #define HAVE_IPv6 /* Requires modern POSIX */ 52 #define HAVE_PASSWD /* For systems with passwd-like userdb */ 53 #define PASSWD_MIN_UID 100 /* Minimum allowed UID for ~userdirs */ 54 #define HAVE_LOCALES /* setlocale() and friends */ 55 #define HAVE_SHMEM /* Shared memory support */ 56 #define HAVE_UNAME /* uname() */ 57 #define HAVE_POPEN /* popen() */ 58 #define HAVE_STRLCPY /* strlcpy() from OpenBSD */ 59 #undef HAVE_SENDFILE /* sendfile() in Linux & others */ 60 /* #undef HAVE_LIBWRAP autodetected, don't enable here */ 61 62 /* Linux */ 63 #ifdef __linux 64 #undef PASSWD_MIN_UID 65 #define PASSWD_MIN_UID 500 66 #define _FILE_OFFSET_BITS 64 67 #endif 68 69 /* Embedded Linux with uClibc */ 70 #ifdef __UCLIBC__ 71 #undef HAVE_SHMEM 72 #undef HAVE_PASSWD 73 #endif 74 75 /* Haiku */ 76 #ifdef __HAIKU__ 77 #undef HAVE_SHMEM 78 #undef HAVE_PASSWD 79 #endif 80 81 /* OpenBSD */ 82 #ifdef __OpenBSD__ 83 #define HAVE_STRLCPY 84 #endif 85 86 /* MacOS */ 87 #if defined(__APPLE__) 88 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 89 #define HAVE_STRLCPY 90 #endif 91 #endif 92 93 /* AIX */ 94 #if defined(_AIX) 95 #define _LARGE_FILES 1 96 #endif 97 98 /* Add other OS-specific defines here */ 99 100 /* 101 * Include headers 102 */ 103 #include <stdio.h> 104 #include <stdlib.h> 105 #include <unistd.h> 106 #include <sys/types.h> 107 #include <sys/stat.h> 108 #include <dirent.h> 109 #include <string.h> 110 #include <libgen.h> 111 #include <time.h> 112 #include <syslog.h> 113 #include <errno.h> 114 #include <pwd.h> 115 #include <limits.h> 116 117 #ifdef HAVE_SENDFILE 118 #include <sys/sendfile.h> 119 #include <fcntl.h> 120 #endif 121 122 #ifdef HAVE_LOCALES 123 #include <locale.h> 124 #endif 125 126 #ifdef HAVE_SHMEM 127 #include <sys/ipc.h> 128 #include <sys/shm.h> 129 #else 130 #define shm_state void 131 #endif 132 133 #if defined(HAVE_IPv4) || defined(HAVE_IPv6) 134 #include <sys/socket.h> 135 #include <netinet/in.h> 136 #include <arpa/inet.h> 137 #endif 138 139 #ifdef HAVE_UNAME 140 #include <sys/utsname.h> 141 #endif 142 143 #if !defined(HAVE_STRLCPY) 144 size_t strlcpy(char *dst, const char *src, size_t siz); 145 size_t strlcat(char *dst, const char *src, size_t siz); 146 #endif 147 148 #ifdef HAVE_LIBWRAP 149 #include <tcpd.h> 150 #endif 151 152 /* 153 * Compile-time configuration 154 */ 155 156 /* Common stuff */ 157 #define CRLF "\r\n" 158 #define EMPTY "" 159 #define PARENT ".." 160 #define ROOT "/" 161 162 #define FALSE 0 163 #define TRUE 1 164 165 #define QUIT 1 166 #define OK 0 167 #define ERROR -1 168 169 #define MATCH 0 170 #define WRAP_DENIED 0 171 172 173 /* Gopher filetypes */ 174 #define TYPE_TEXT '0' 175 #define TYPE_MENU '1' 176 #define TYPE_ERROR '3' 177 #define TYPE_GZIP '5' 178 #define TYPE_QUERY '7' 179 #define TYPE_BINARY '9' 180 #define TYPE_GIF 'g' 181 #define TYPE_HTML 'h' 182 #define TYPE_INFO 'i' 183 #define TYPE_IMAGE 'I' 184 #define TYPE_MIME 'M' 185 #define TYPE_DOC 'd' 186 #define TYPE_TITLE '!' 187 188 /* Protocols */ 189 #define PROTO_GOPHER 'g' 190 #define PROTO_HTTP 'h' 191 192 /* Charsets */ 193 #define AUTO 0 194 #define US_ASCII 1 195 #define ISO_8859_1 2 196 #define UTF_8 3 197 198 /* HTTP protocol stuff for logging */ 199 #define HTTP_OK 200 200 #define HTTP_404 404 201 #define HTTP_DATE "%d/%b/%Y:%T %z" 202 #define HTTP_USERAGENT "Unknown gopher client" 203 204 /* Defaults for settings */ 205 #define DEFAULT_HOST "localhost" 206 #define DEFAULT_PORT 70 207 #define DEFAULT_TLS_PORT 0 208 #define DEFAULT_TYPE TYPE_TEXT 209 #define DEFAULT_MAP "gophermap" 210 #define DEFAULT_TAG "gophertag" 211 #define DEFAULT_CGI "/cgi-bin/" 212 #define DEFAULT_USERDIR "public_gopher" 213 #define DEFAULT_WIDTH 76 214 #define DEFAULT_CHARSET US_ASCII 215 #define MIN_WIDTH 33 216 #define MAX_WIDTH 200 217 #define UNKNOWN_ADDR "unknown" 218 219 /* Session defaults */ 220 #define DEFAULT_SESSION_TIMEOUT 1800 221 #define DEFAULT_SESSION_MAX_KBYTES 4194304 222 #define DEFAULT_SESSION_MAX_HITS 4096 223 224 /* Dummy values for gopher protocol */ 225 #define DUMMY_SELECTOR "null" 226 #define DUMMY_HOST "null.host\t1" 227 228 /* Safe $PATH for exec() */ 229 #ifdef __HAIKU__ 230 #define SAFE_PATH "/boot/common/bin:/bin" 231 #else 232 #define SAFE_PATH "/usr/bin:/bin" 233 #endif 234 235 /* Special requests */ 236 #define SERVER_STATUS "/server-status" 237 #define CAPS_TXT "/caps.txt" 238 239 /* Error messages */ 240 #define ERR_ACCESS "Access denied!" 241 #define ERR_NOTFOUND "File or directory not found!" 242 243 #define ERROR_HOST "error.host\t1" 244 #define ERROR_PREFIX "Error: " 245 246 /* Strings */ 247 #define SERVER_SOFTWARE "Gophernicus" 248 #define SERVER_SOFTWARE_FULL SERVER_SOFTWARE "/" VERSION " (%s)" 249 250 #define HEADER_FORMAT "[%s]" 251 #define FOOTER_FORMAT "Gophered by Gophernicus/" VERSION " on %s" 252 253 #define UNITS "KB", "MB", "GB", "TB", "PB", NULL 254 #define DATE_FORMAT "%Y-%b-%d %H:%M" /* See man 3 strftime */ 255 #define DATE_WIDTH 17 256 #define DATE_LOCALE "POSIX" 257 258 #define USERDIR_FORMAT "~%s", pwd->pw_name /* See man 3 getpwent */ 259 #define VHOST_FORMAT "gopher://%s/" 260 261 /* ISO-8859-1 to US-ASCII look-alike conversion table */ 262 #define ASCII \ 263 "E?,f..++^%S<??Z?" \ 264 "?''\"\"*--~?s>??zY" \ 265 " !c_*Y|$\"C?<?-R-" \ 266 "??23'u?*,1?>????" \ 267 "AAAAAAACEEEEIIII" \ 268 "DNOOOOO*OUUUUYTB" \ 269 "aaaaaaaceeeeiiii" \ 270 "dnooooo/ouuuuyty" 271 272 #define UNKNOWN '?' 273 274 /* Sizes & maximums */ 275 #define BUFSIZE 1024 /* Default size for string buffers */ 276 #define MAX_HIDDEN 32 /* Maximum number of hidden files */ 277 #define MAX_FILETYPES 128 /* Maximum number of suffix to filetype mappings */ 278 #define MAX_FILTERS 16 /* Maximum number of file filters */ 279 #define MAX_SDIRENT 1024 /* Maximum number of files per directory to handle */ 280 #define MAX_REWRITE 32 /* Maximum number of selector rewrite options */ 281 282 /* Struct for file suffix -> gopher filetype mapping */ 283 typedef struct { 284 char suffix[15]; 285 char type; 286 } ftype; 287 288 /* Struct for selector rewriting */ 289 typedef struct { 290 char match[BUFSIZE]; 291 char replace[BUFSIZE]; 292 } srewrite; 293 294 /* Struct for keeping the current options & state */ 295 typedef struct { 296 297 /* Request */ 298 char req_selector[BUFSIZE]; 299 char req_realpath[BUFSIZE]; 300 char req_query_string[BUFSIZE]; 301 char req_search[BUFSIZE]; 302 char req_referrer[BUFSIZE]; 303 char req_local_addr[64]; 304 char req_remote_addr[64]; 305 char req_filetype; 306 char req_protocol; 307 off_t req_filesize; 308 309 /* Output */ 310 int out_width; 311 int out_charset; 312 313 /* Settings */ 314 char server_description[64]; 315 char server_location[64]; 316 char server_platform[64]; 317 char server_admin[64]; 318 char server_root[256]; 319 char server_host_default[64]; 320 char server_host[64]; 321 int server_port; 322 int server_tls_port; 323 324 char default_filetype; 325 char map_file[64]; 326 char tag_file[64]; 327 char cgi_file[64]; 328 char user_dir[64]; 329 char log_file[256]; 330 331 char hidden[MAX_HIDDEN][256]; 332 int hidden_count; 333 334 ftype filetype[MAX_FILETYPES]; 335 int filetype_count; 336 char filter_dir[64]; 337 338 srewrite rewrite[MAX_REWRITE]; 339 int rewrite_count; 340 341 /* Session */ 342 int session_timeout; 343 int session_max_kbytes; 344 int session_max_hits; 345 int session_id; 346 347 /* Feature options */ 348 char opt_parent; 349 char opt_header; 350 char opt_footer; 351 char opt_date; 352 char opt_syslog; 353 char opt_magic; 354 char opt_iconv; 355 char opt_vhost; 356 char opt_query; 357 char opt_caps; 358 char opt_status; 359 char opt_shm; 360 char opt_root; 361 char opt_proxy; 362 char opt_exec; 363 char opt_personal_spaces; 364 char debug; 365 } state; 366 367 /* Shared memory for session & accounting data */ 368 #ifdef HAVE_SHMEM 369 370 #define SHM_KEY 0xbeeb0008 /* Unique identifier + struct version */ 371 #define SHM_MODE 0600 /* Access mode for the shared memory */ 372 #define SHM_SESSIONS 256 /* Max amount of user sessions to track */ 373 374 typedef struct { 375 long hits; 376 long kbytes; 377 378 time_t req_atime; 379 char req_selector[128]; 380 char req_remote_addr[64]; 381 char req_filetype; 382 int session_id; 383 384 char server_host[64]; 385 int server_port; 386 } shm_session; 387 388 typedef struct { 389 time_t start_time; 390 long hits; 391 long kbytes; 392 char server_platform[64]; 393 char server_description[64]; 394 shm_session session[SHM_SESSIONS]; 395 } shm_state; 396 397 #endif 398 399 /* Struct for directory sorting */ 400 typedef struct { 401 char name[128]; /* Should be 256 but we're saving stack space */ 402 mode_t mode; 403 uid_t uid; 404 gid_t gid; 405 off_t size; 406 time_t mtime; 407 } sdirent; 408 409 410 /* File suffix to gopher filetype mappings */ 411 #define FILETYPES \ 412 "txt","0","pl","0","py","0","sh","0","tcl","0","c","0","cpp","0", "h","0","log","0", \ 413 "conf","0","php","0","php3","0", \ 414 "map","1","menu","1", \ 415 "hqx","4", \ 416 "Z","5","gz","5","tgz","5","tar","5","zip","5","bz2","5","rar","5","sea","5", \ 417 "q","7","qry","7", \ 418 "iso","9","so","9","o","9","rtf","9","ttf","9","bin","9", \ 419 "ics","c","ical","c", \ 420 "gif","g", \ 421 "html","h","htm","h","xhtml","h","css","h","swf","h","rdf","h","rss","h","xml","h", \ 422 "jpg","I","jpeg","I","png","I","bmp","I","svg","I","tif","I","tiff","I", \ 423 "ico","I","xbm","I","xpm","I","pcx","I", \ 424 "mbox","M", \ 425 "pdf","d","ps","d","doc","d","ppt","d","xls","d","xlsx","d","docx","d","pptx","d", \ 426 "mp3","s","wav","s","mid","s","wma","s","flac","s","ogg","s","aiff","s","aac","s", \ 427 "avi",";","mp4",";","mpg",";","mov",";","qt",";","asf",";","mpv",";","m4v",";","webm",";","ogv",";", \ 428 NULL, NULL 429 430 /* 431 * Useful macros 432 */ 433 #define strclear(str) str[0] = '\0'; 434 #define sstrlcpy(dest, src) strlcpy(dest, src, sizeof(dest)) 435 #define sstrlcat(dest, src) strlcat(dest, src, sizeof(dest)) 436 #define sstrncmp(s1, s2) strncmp(s1, s2, sizeof(s2) - 1) 437 #define sstrncasecmp(s1, s2) strncasecmp(s1, s2, sizeof(s2) - 1) 438 #define sstrniconv(charset, out, in) strniconv(charset, out, in, sizeof(out)) 439 #define max(a,b) (((a) > (b)) ? (a) : (b)) 440 #define min(a,b) (((a) < (b)) ? (a) : (b)) 441 442 /* 443 * Include generated headers 444 */ 445 #include "functions.h" 446 #include "files.h" 447 448 #endif 449 450 451