1/* 2 * lws-minimal-http-server-deaddrop 3 * 4 * Written in 2010-2020 by Andy Green <andy@warmcat.com> 5 * 6 * This file is made available under the Creative Commons CC0 1.0 7 * Universal Public Domain Dedication. 8 * 9 * This demonstrates how you can leverage the lws deaddrop plugin to make a 10 * secure, modern html5 file upload and sharing application. 11 * 12 * Because the guts are in a plugin, you can avoid all this setup by using the 13 * plugin from lwsws and do the config in JSON. 14 */ 15 16#include <libwebsockets.h> 17#include <string.h> 18#include <signal.h> 19#include <time.h> 20 21#define LWS_PLUGIN_STATIC 22#include "../plugins/deaddrop/protocol_lws_deaddrop.c" 23 24static struct lws_protocols protocols[] = { 25 LWS_PLUGIN_PROTOCOL_DEADDROP, 26 LWS_PROTOCOL_LIST_TERM 27}; 28 29 30static int interrupted; 31 32/* 33 * teach the /get mount how to present various filetypes to the client... 34 * lws won't serve files it doesn't know the mimetype for as a security 35 * measure. 36 */ 37 38static struct lws_protocol_vhost_options em3 = { 39 NULL, NULL, ".zip", "application/zip" 40}, em2 = { 41 &em3, NULL, ".pdf", "application/pdf" 42}, extra_mimetypes = { 43 &em2, NULL, ".tar.gz", "application/x-gzip" 44}; 45 46/* wire up /upload URLs to the plugin (protected by basic auth) */ 47 48static const struct lws_http_mount mount_upload = { 49 /* .mount_next */ NULL, 50 /* .mountpoint */ "/upload", /* mountpoint URL */ 51 /* .origin */ "lws-deaddrop", 52 /* .def */ "", 53 /* .protocol */ NULL, 54 /* .cgienv */ NULL, 55 /* .extra_mimetypes */ NULL, 56 /* .interpret */ NULL, 57 /* .cgi_timeout */ 0, 58 /* .cache_max_age */ 0, 59 /* .auth_mask */ 0, 60 /* .cache_reusable */ 0, 61 /* .cache_revalidate */ 0, 62 /* .cache_intermediaries */ 0, 63 /* .origin_protocol */ LWSMPRO_CALLBACK, 64 /* .mountpoint_len */ 7, /* char count */ 65 /* .basic_auth_login_file */ "./ba-passwords", 66}; 67 68/* wire up /get URLs to the upload directory (protected by basic auth) */ 69 70static const struct lws_http_mount mount_get = { 71 /* .mount_next */ &mount_upload, /* linked-list "next" */ 72 /* .mountpoint */ "/get", /* mountpoint URL */ 73 /* .origin */ "./uploads", 74 /* .def */ "", 75 /* .protocol */ NULL, 76 /* .cgienv */ NULL, 77 /* .extra_mimetypes */ &extra_mimetypes, 78 /* .interpret */ NULL, 79 /* .cgi_timeout */ 0, 80 /* .cache_max_age */ 0, 81 /* .auth_mask */ 0, 82 /* .cache_reusable */ 0, 83 /* .cache_revalidate */ 0, 84 /* .cache_intermediaries */ 0, 85 /* .origin_protocol */ LWSMPRO_FILE, /* dynamic */ 86 /* .mountpoint_len */ 4, /* char count */ 87 /* .basic_auth_login_file */ "./ba-passwords", 88}; 89 90/* wire up / to serve from ./mount-origin (protected by basic auth) */ 91 92static const struct lws_http_mount mount = { 93 /* .mount_next */ &mount_get, /* linked-list "next" */ 94 /* .mountpoint */ "/", /* mountpoint URL */ 95 /* .origin */ "./mount-origin", /* serve from dir */ 96 /* .def */ "index.html", /* default filename */ 97 /* .protocol */ NULL, 98 /* .cgienv */ NULL, 99 /* .extra_mimetypes */ NULL, 100 /* .interpret */ NULL, 101 /* .cgi_timeout */ 0, 102 /* .cache_max_age */ 0, 103 /* .auth_mask */ 0, 104 /* .cache_reusable */ 0, 105 /* .cache_revalidate */ 0, 106 /* .cache_intermediaries */ 0, 107 /* .origin_protocol */ LWSMPRO_FILE, /* files in a dir */ 108 /* .mountpoint_len */ 1, /* char count */ 109 /* .basic_auth_login_file */ "./ba-passwords", 110}; 111 112/* pass config options to the deaddrop plugin using pvos */ 113 114static struct lws_protocol_vhost_options pvo3 = { 115 /* make the wss also require to pass basic auth */ 116 NULL, NULL, "basic-auth", "./ba-passwords" 117}, pvo2 = { 118 &pvo3, NULL, "max-size", "10000000" 119}, pvo1 = { 120 &pvo2, NULL, "upload-dir", "./uploads" /* would be an absolute path */ 121}, pvo = { 122 NULL, /* "next" pvo linked-list */ 123 &pvo1, /* "child" pvo linked-list */ 124 "lws-deaddrop", /* protocol name we belong to on this vhost */ 125 "" /* ignored */ 126}; 127 128void sigint_handler(int sig) 129{ 130 interrupted = 1; 131} 132 133int main(int argc, const char **argv) 134{ 135 struct lws_context_creation_info info; 136 struct lws_context *context; 137 const char *p; 138 int n = 0, logs = LLL_USER | LLL_ERR | LLL_WARN | LLL_NOTICE; 139 140 signal(SIGINT, sigint_handler); 141 142 if ((p = lws_cmdline_option(argc, argv, "-d"))) 143 logs = atoi(p); 144 145 lws_set_log_level(logs, NULL); 146 lwsl_user("LWS minimal http server deaddrop | visit https://localhost:7681\n"); 147 148 memset(&info, 0, sizeof info); /* otherwise uninitialized garbage */ 149 info.port = 7681; 150 info.mounts = &mount; 151 info.pvo = &pvo; 152 info.protocols = protocols; 153 info.error_document_404 = "/404.html"; 154 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT | 155 LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE; 156#if defined(LWS_WITH_TLS) 157 info.ssl_cert_filepath = "localhost-100y.cert"; 158 info.ssl_private_key_filepath = "localhost-100y.key"; 159#endif 160 161 context = lws_create_context(&info); 162 if (!context) { 163 lwsl_err("lws init failed\n"); 164 return 1; 165 } 166 167 while (n >= 0 && !interrupted) 168 n = lws_service(context, 0); 169 170 lws_context_destroy(context); 171 172 return 0; 173} 174