Hello,
I've updated glewlwyd/2.5.2-2+deb11u2 with the
glewlwyd_2.5.2-2+deb11u2...2.5.2-2+deb11u3.debdiff file.
Now both CVEs (CVE-2022-27240 and CVE-2022-29967) are fixed in the update.
The fix for CVE-2022-27240 only addresses the buffer overflow,
o_base64url_decode isn't changed to o_base64_decode anymore.
The CVE-2022-29967 requires more changes though.
The bug fix uses 'realpath' to avoid traversal access.
Although if an accessed file is a soft link, realpath returns the
realpath of the file which isn't in /usr/share/glewlwyd/webapp, so an
error 404 is raised. The solution is to copy jquery, popper.js,
bootstrap and fonts-fork-awesome files from their respective
installation into /usr/share/glewlwyd/webapp.diff -Nru glewlwyd-2.5.2/debian/changelog glewlwyd-2.5.2/debian/changelog
--- glewlwyd-2.5.2/debian/changelog 2021-12-17 07:51:46.000000000 -0500
+++ glewlwyd-2.5.2/debian/changelog 2022-03-17 21:13:09.000000000 -0400
@@ -1,3 +1,15 @@
+glewlwyd (2.5.2-2+deb11u3) bullseye; urgency=medium
+
+ * d/patches: Fix CVE-2022-27240
+ possible buffer overflow during webauthn signature assertion
+ * d/patches: Fix CVE-2022-29967
+ static_compressed_inmemory_website_callback.c in Glewlwyd
+ through 2.6.2 allows directory traversal
+ * d/glewlwyd-common.install: copy bootstrap, jquery, fork-awesome
+ instead of linking it
+
+ -- Nicolas Mora <babelou...@debian.org> Thu, 17 Mar 2022 21:13:09 -0400
+
glewlwyd (2.5.2-2+deb11u2) bullseye; urgency=medium
* d/patches: Fix possible privilege escalation (Closes: #1001849)
diff -Nru glewlwyd-2.5.2/debian/control glewlwyd-2.5.2/debian/control
--- glewlwyd-2.5.2/debian/control 2021-12-17 07:51:46.000000000 -0500
+++ glewlwyd-2.5.2/debian/control 2022-03-17 21:13:09.000000000 -0400
@@ -35,6 +35,10 @@
, node-i18next-http-backend
, node-qrcode-generator
, webpack
+ , fonts-fork-awesome
+ , libjs-jquery
+ , libjs-bootstrap4
+ , libjs-popper.js
Standards-Version: 4.5.1
Homepage: https://github.com/babelouest/glewlwyd
Vcs-Browser: https://salsa.debian.org/debian-iot-team/oauth2/glewlwyd.git
diff -Nru glewlwyd-2.5.2/debian/glewlwyd-common.install
glewlwyd-2.5.2/debian/glewlwyd-common.install
--- glewlwyd-2.5.2/debian/glewlwyd-common.install 2021-12-17
07:51:46.000000000 -0500
+++ glewlwyd-2.5.2/debian/glewlwyd-common.install 2022-03-17
21:13:09.000000000 -0400
@@ -1,5 +1,6 @@
-webapp-src/css/glewlwyd*.css usr/share/glewlwyd/webapp/css/
-webapp-src/css/*-custom.css usr/share/glewlwyd/webapp/css/
+webapp-src/css/* usr/share/glewlwyd/webapp/css/
+webapp-src/js/* usr/share/glewlwyd/webapp/js/
+webapp-src/fonts/* usr/share/glewlwyd/webapp/fonts/
webapp-src/locales/ usr/share/glewlwyd/webapp/
webapp-src/img/ usr/share/glewlwyd/webapp/
webapp-src/output/*.js usr/share/glewlwyd/webapp/
@@ -7,3 +8,4 @@
webapp-src/favicon.ico usr/share/glewlwyd/webapp/
debian/config.json usr/share/glewlwyd/templates/
+debian/config.json usr/share/glewlwyd/webapp/
diff -Nru glewlwyd-2.5.2/debian/glewlwyd-common.links
glewlwyd-2.5.2/debian/glewlwyd-common.links
--- glewlwyd-2.5.2/debian/glewlwyd-common.links 2021-12-17 07:51:46.000000000
-0500
+++ glewlwyd-2.5.2/debian/glewlwyd-common.links 1969-12-31 19:00:00.000000000
-0500
@@ -1,19 +0,0 @@
-usr/share/javascript/jquery/jquery.min.js
usr/share/glewlwyd/webapp/js/jquery.min.js
-usr/share/javascript/jquery/jquery.min.js
usr/share/glewlwyd/webapp/js/jquery.min.js
-usr/share/javascript/popper.js/umd/popper.min.js
usr/share/glewlwyd/webapp/js/popper.min.js
-usr/share/javascript/popper.js/umd/popper-utils.min.js
usr/share/glewlwyd/webapp/js/popper-utils.min.js
-
-usr/share/nodejs/bootstrap/dist/js/bootstrap.min.js
usr/share/glewlwyd/webapp/js/bootstrap.min.js
-usr/share/nodejs/bootstrap/dist/js/bootstrap.min.js.map
usr/share/glewlwyd/webapp/js/bootstrap.min.js.map
-usr/share/nodejs/bootstrap/dist/css/bootstrap.min.css
usr/share/glewlwyd/webapp/css/bootstrap.min.css
-usr/share/nodejs/bootstrap/dist/css/bootstrap.min.css.map
usr/share/glewlwyd/webapp/css/bootstrap.min.css.map
-
-usr/share/fonts-fork-awesome/css/fork-awesome.css
usr/share/glewlwyd/webapp/css/fork-awesome.min.css
-usr/share/fonts-fork-awesome/css/v5-compat.css
usr/share/glewlwyd/webapp/css/v5-compat.min.css
-usr/share/fonts/eot/fork-awesome/forkawesome-webfont.eot
usr/share/glewlwyd/webapp/fonts/forkawesome-webfont.eot
-usr/share/fonts/svg/fork-awesome/forkawesome-webfont.svg
usr/share/glewlwyd/webapp/fonts/forkawesome-webfont.svg
-usr/share/fonts/truetype/fork-awesome/forkawesome-webfont.ttf
usr/share/glewlwyd/webapp/fonts/forkawesome-webfont.ttf
-usr/share/fonts/woff/fork-awesome/forkawesome-webfont.woff
usr/share/glewlwyd/webapp/fonts/forkawesome-webfont.woff
-usr/share/fonts/woff/fork-awesome/forkawesome-webfont.woff2
usr/share/glewlwyd/webapp/fonts/forkawesome-webfont.woff2
-
-etc/glewlwyd/config.json usr/share/glewlwyd/webapp/config.json
diff -Nru glewlwyd-2.5.2/debian/patches/CVE-2022-29967.patch
glewlwyd-2.5.2/debian/patches/CVE-2022-29967.patch
--- glewlwyd-2.5.2/debian/patches/CVE-2022-29967.patch 1969-12-31
19:00:00.000000000 -0500
+++ glewlwyd-2.5.2/debian/patches/CVE-2022-29967.patch 2022-03-17
21:13:09.000000000 -0400
@@ -0,0 +1,263 @@
+--- a/src/static_compressed_inmemory_website_callback.c
++++ b/src/static_compressed_inmemory_website_callback.c
+@@ -158,7 +158,7 @@
+ static int callback_static_file_uncompressed (const struct _u_request *
request, struct _u_response * response, void * user_data) {
+ size_t length;
+ FILE * f;
+- char * file_requested, * file_path, * url_dup_save;
++ char * file_requested, * file_path, * url_dup_save, * real_path = NULL;
+ const char * content_type;
+ int ret = U_CALLBACK_CONTINUE;
+
+@@ -188,24 +188,33 @@
+ }
+
+ file_path = msprintf("%s/%s", ((struct
_u_compressed_inmemory_website_config *)user_data)->files_path, file_requested);
++ real_path = realpath(file_path, NULL);
++ if (0 == o_strncmp(((struct _u_compressed_inmemory_website_config
*)user_data)->files_path, real_path, o_strlen(((struct
_u_compressed_inmemory_website_config *)user_data)->files_path))) {
++ if (access(file_path, F_OK) != -1) {
++ f = fopen (file_path, "rb");
++ if (f) {
++ fseek (f, 0, SEEK_END);
++ length = ftell (f);
++ fseek (f, 0, SEEK_SET);
++
++ content_type = u_map_get_case(&((struct
_u_compressed_inmemory_website_config *)user_data)->mime_types,
get_filename_ext(file_requested));
++ if (content_type == NULL) {
++ content_type = u_map_get(&((struct
_u_compressed_inmemory_website_config *)user_data)->mime_types, "*");
++ y_log_message(Y_LOG_LEVEL_WARNING, "Static File Server - Unknown
mime type for extension %s", get_filename_ext(file_requested));
++ }
++ u_map_put(response->map_header, "Content-Type", content_type);
++ u_map_copy_into(response->map_header, &((struct
_u_compressed_inmemory_website_config *)user_data)->map_header);
+
+- if (access(file_path, F_OK) != -1) {
+- f = fopen (file_path, "rb");
+- if (f) {
+- fseek (f, 0, SEEK_END);
+- length = ftell (f);
+- fseek (f, 0, SEEK_SET);
+-
+- content_type = u_map_get_case(&((struct
_u_compressed_inmemory_website_config *)user_data)->mime_types,
get_filename_ext(file_requested));
+- if (content_type == NULL) {
+- content_type = u_map_get(&((struct
_u_compressed_inmemory_website_config *)user_data)->mime_types, "*");
+- y_log_message(Y_LOG_LEVEL_WARNING, "Static File Server - Unknown
mime type for extension %s", get_filename_ext(file_requested));
++ if (ulfius_set_stream_response(response, 200,
callback_static_file_uncompressed_stream,
callback_static_file_uncompressed_stream_free, length, CHUNK, f) != U_OK) {
++ y_log_message(Y_LOG_LEVEL_ERROR, "Static File Server - Error
ulfius_set_stream_response");
++ }
+ }
+- u_map_put(response->map_header, "Content-Type", content_type);
+- u_map_copy_into(response->map_header, &((struct
_u_compressed_inmemory_website_config *)user_data)->map_header);
+-
+- if (ulfius_set_stream_response(response, 200,
callback_static_file_uncompressed_stream,
callback_static_file_uncompressed_stream_free, length, CHUNK, f) != U_OK) {
+- y_log_message(Y_LOG_LEVEL_ERROR, "Static File Server - Error
ulfius_set_stream_response");
++ } else {
++ if (((struct _u_compressed_inmemory_website_config
*)user_data)->redirect_on_404 == NULL) {
++ ret = U_CALLBACK_IGNORE;
++ } else {
++ ulfius_add_header_to_response(response, "Location", ((struct
_u_compressed_inmemory_website_config *)user_data)->redirect_on_404);
++ response->status = 302;
+ }
+ }
+ } else {
+@@ -217,6 +226,7 @@
+ }
+ }
+ o_free(file_path);
++ free(real_path); // realpath uses malloc
+ o_free(url_dup_save);
+ } else {
+ y_log_message(Y_LOG_LEVEL_ERROR, "Static File Server - Error, user_data
is NULL or inconsistent");
+@@ -295,7 +305,7 @@
+ unsigned char * file_content, * file_content_orig = NULL;
+ size_t length, read_length, offset, data_zip_len = 0;
+ FILE * f;
+- char * file_requested, * file_path, * url_dup_save, * data_zip = NULL;
++ char * file_requested, * file_path, * url_dup_save, * data_zip = NULL, *
real_path = NULL;
+ const char * content_type;
+
+ /*
+@@ -357,92 +367,101 @@
+ u_map_put(response->map_header, U_CONTENT_HEADER,
U_ACCEPT_DEFLATE);
+ } else {
+ file_path = msprintf("%s/%s", ((struct
_u_compressed_inmemory_website_config *)user_data)->files_path, file_requested);
+-
+- if (access(file_path, F_OK) != -1) {
+- if (!pthread_mutex_lock(&config->lock)) {
+- f = fopen (file_path, "rb");
+- if (f) {
+- fseek (f, 0, SEEK_END);
+- offset = length = ftell (f);
+- fseek (f, 0, SEEK_SET);
+-
+- if ((file_content_orig = file_content = o_malloc(length))
!= NULL && (data_zip = o_malloc((2*length)+20)) != NULL) {
+- defstream.zalloc = u_zalloc;
+- defstream.zfree = u_zfree;
+- defstream.opaque = Z_NULL;
+- defstream.avail_in = (uInt)length;
+- defstream.next_in = (Bytef *)file_content;
+- while ((read_length = fread(file_content, sizeof(char),
offset, f))) {
+- file_content += read_length;
+- offset -= read_length;
+- }
+-
+- if (compress_mode == U_COMPRESS_GZIP) {
+- if (deflateInit2(&defstream,
+- Z_DEFAULT_COMPRESSION,
+- Z_DEFLATED,
+- U_GZIP_WINDOW_BITS | U_GZIP_ENCODING,
+- 8,
+- Z_DEFAULT_STRATEGY) != Z_OK) {
+- y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error deflateInit (gzip)");
+- ret = U_CALLBACK_ERROR;
++ real_path = realpath(file_path, NULL);
++ if (0 == o_strncmp(((struct _u_compressed_inmemory_website_config
*)user_data)->files_path, real_path, o_strlen(((struct
_u_compressed_inmemory_website_config *)user_data)->files_path))) {
++ if (access(file_path, F_OK) != -1) {
++ if (!pthread_mutex_lock(&config->lock)) {
++ f = fopen (file_path, "rb");
++ if (f) {
++ fseek (f, 0, SEEK_END);
++ offset = length = ftell (f);
++ fseek (f, 0, SEEK_SET);
++
++ if ((file_content_orig = file_content = o_malloc(length))
!= NULL && (data_zip = o_malloc((2*length)+20)) != NULL) {
++ defstream.zalloc = u_zalloc;
++ defstream.zfree = u_zfree;
++ defstream.opaque = Z_NULL;
++ defstream.avail_in = (uInt)length;
++ defstream.next_in = (Bytef *)file_content;
++ while ((read_length = fread(file_content, sizeof(char),
offset, f))) {
++ file_content += read_length;
++ offset -= read_length;
+ }
+- } else {
+- if (deflateInit(&defstream, Z_BEST_COMPRESSION) !=
Z_OK) {
+- y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error deflateInit (deflate)");
+- ret = U_CALLBACK_ERROR;
+- }
+- }
+- if (ret == U_CALLBACK_CONTINUE) {
+- do {
+- if ((data_zip = o_realloc(data_zip,
data_zip_len+_U_W_BLOCK_SIZE)) != NULL) {
+- defstream.avail_out = _U_W_BLOCK_SIZE;
+- defstream.next_out = ((Bytef
*)data_zip)+data_zip_len;
+- switch ((res = deflate(&defstream, Z_FINISH))) {
+- case Z_OK:
+- case Z_STREAM_END:
+- case Z_BUF_ERROR:
+- break;
+- default:
+- y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error deflate %d", res);
+- ret = U_CALLBACK_ERROR;
+- break;
+- }
+- data_zip_len += _U_W_BLOCK_SIZE -
defstream.avail_out;
+- } else {
+- y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error allocating resources for
data_zip");
++
++ if (compress_mode == U_COMPRESS_GZIP) {
++ if (deflateInit2(&defstream,
++ Z_DEFAULT_COMPRESSION,
++ Z_DEFLATED,
++ U_GZIP_WINDOW_BITS | U_GZIP_ENCODING,
++ 8,
++ Z_DEFAULT_STRATEGY) != Z_OK) {
++ y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error deflateInit (gzip)");
+ ret = U_CALLBACK_ERROR;
+ }
+- } while (U_CALLBACK_CONTINUE == ret &&
defstream.avail_out == 0);
+-
++ } else {
++ if (deflateInit(&defstream, Z_BEST_COMPRESSION) !=
Z_OK) {
++ y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error deflateInit (deflate)");
++ ret = U_CALLBACK_ERROR;
++ }
++ }
+ if (ret == U_CALLBACK_CONTINUE) {
+- if (compress_mode == U_COMPRESS_GZIP) {
+- if (config->allow_cache_compressed) {
+- u_map_put_binary(&config->gzip_files,
file_requested, data_zip, 0, defstream.total_out);
++ do {
++ if ((data_zip = o_realloc(data_zip,
data_zip_len+_U_W_BLOCK_SIZE)) != NULL) {
++ defstream.avail_out = _U_W_BLOCK_SIZE;
++ defstream.next_out = ((Bytef
*)data_zip)+data_zip_len;
++ switch ((res = deflate(&defstream, Z_FINISH))) {
++ case Z_OK:
++ case Z_STREAM_END:
++ case Z_BUF_ERROR:
++ break;
++ default:
++ y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error deflate %d", res);
++ ret = U_CALLBACK_ERROR;
++ break;
++ }
++ data_zip_len += _U_W_BLOCK_SIZE -
defstream.avail_out;
++ } else {
++ y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error allocating resources for
data_zip");
++ ret = U_CALLBACK_ERROR;
+ }
+- ulfius_set_binary_body_response(response, 200,
u_map_get(&config->gzip_files, file_requested),
u_map_get_length(&config->gzip_files, file_requested));
+- } else {
+- if (config->allow_cache_compressed) {
+- u_map_put_binary(&config->deflate_files,
file_requested, data_zip, 0, defstream.total_out);
++ } while (U_CALLBACK_CONTINUE == ret &&
defstream.avail_out == 0);
++
++ if (ret == U_CALLBACK_CONTINUE) {
++ if (compress_mode == U_COMPRESS_GZIP) {
++ if (config->allow_cache_compressed) {
++ u_map_put_binary(&config->gzip_files,
file_requested, data_zip, 0, defstream.total_out);
++ }
++ ulfius_set_binary_body_response(response, 200,
u_map_get(&config->gzip_files, file_requested),
u_map_get_length(&config->gzip_files, file_requested));
++ } else {
++ if (config->allow_cache_compressed) {
++ u_map_put_binary(&config->deflate_files,
file_requested, data_zip, 0, defstream.total_out);
++ }
++ ulfius_set_binary_body_response(response, 200,
u_map_get(&config->deflate_files, file_requested),
u_map_get_length(&config->deflate_files, file_requested));
+ }
+- ulfius_set_binary_body_response(response, 200,
u_map_get(&config->deflate_files, file_requested),
u_map_get_length(&config->deflate_files, file_requested));
++ u_map_put(response->map_header, U_CONTENT_HEADER,
compress_mode==U_COMPRESS_GZIP?U_ACCEPT_GZIP:U_ACCEPT_DEFLATE);
+ }
+- u_map_put(response->map_header, U_CONTENT_HEADER,
compress_mode==U_COMPRESS_GZIP?U_ACCEPT_GZIP:U_ACCEPT_DEFLATE);
+ }
++ deflateEnd(&defstream);
++ o_free(data_zip);
++ } else {
++ y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error allocating resource for
file_content or data_zip");
++ ret = U_CALLBACK_ERROR;
+ }
+- deflateEnd(&defstream);
+- o_free(data_zip);
+- } else {
+- y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error allocating resource for
file_content or data_zip");
+- ret = U_CALLBACK_ERROR;
++ o_free(file_content_orig);
++ fclose(f);
+ }
+- o_free(file_content_orig);
+- fclose(f);
++ pthread_mutex_unlock(&config->lock);
++ } else {
++ y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error pthread_lock_mutex");
++ ret = U_CALLBACK_ERROR;
+ }
+- pthread_mutex_unlock(&config->lock);
+ } else {
+- y_log_message(Y_LOG_LEVEL_ERROR,
"callback_static_compressed_inmemory_website - Error pthread_lock_mutex");
+- ret = U_CALLBACK_ERROR;
++ if (((struct _u_compressed_inmemory_website_config
*)user_data)->redirect_on_404 == NULL) {
++ ret = U_CALLBACK_IGNORE;
++ } else {
++ ulfius_add_header_to_response(response, "Location",
((struct _u_compressed_inmemory_website_config *)user_data)->redirect_on_404);
++ response->status = 302;
++ }
+ }
+ } else {
+ if (((struct _u_compressed_inmemory_website_config
*)user_data)->redirect_on_404 == NULL) {
+@@ -453,6 +472,8 @@
+ }
+ }
+ o_free(file_path);
++ free(real_path); // realpath uses malloc
++
+ }
+ } else {
+ ret = callback_static_file_uncompressed(request, response,
user_data);
diff -Nru glewlwyd-2.5.2/debian/patches/series
glewlwyd-2.5.2/debian/patches/series
--- glewlwyd-2.5.2/debian/patches/series 2021-12-17 07:51:46.000000000
-0500
+++ glewlwyd-2.5.2/debian/patches/series 2022-03-17 21:13:09.000000000
-0400
@@ -1,3 +1,5 @@
#webpack.patch
+webauthn-2.patch
webauthn.patch
auth.patch
+CVE-2022-29967.patch
diff -Nru glewlwyd-2.5.2/debian/patches/webauthn-2.patch
glewlwyd-2.5.2/debian/patches/webauthn-2.patch
--- glewlwyd-2.5.2/debian/patches/webauthn-2.patch 1969-12-31
19:00:00.000000000 -0500
+++ glewlwyd-2.5.2/debian/patches/webauthn-2.patch 2022-03-17
21:13:09.000000000 -0400
@@ -0,0 +1,32 @@
+Description: Fix buffer overflow
+Author: Nicolas Mora <babelou...@debian.org>
+Forwarded: not-needed
+--- a/src/scheme/webauthn.c
++++ b/src/scheme/webauthn.c
+@@ -2336,12 +2336,24 @@
+ break;
+ }
+
+- if (!o_base64url_decode((const unsigned char
*)json_string_value(json_object_get(json_object_get(json_object_get(j_scheme_data,
"credential"), "response"), "signature")),
json_string_length(json_object_get(json_object_get(json_object_get(j_scheme_data,
"credential"), "response"), "signature")), sig, &sig_len)) {
+- y_log_message(Y_LOG_LEVEL_DEBUG, "check_assertion - Error
o_base64url_decode signature");
++ if (!o_base64url_decode((const unsigned char
*)json_string_value(json_object_get(json_object_get(json_object_get(j_scheme_data,
"credential"), "response"), "signature")),
json_string_length(json_object_get(json_object_get(json_object_get(j_scheme_data,
"credential"), "response"), "signature")), NULL, &sig_len)) {
++ y_log_message(Y_LOG_LEVEL_DEBUG, "check_assertion - Invalid signature
format");
+ ret = G_ERROR_PARAM;
+ break;
+ }
+
++ if (sig_len > 128) {
++ y_log_message(Y_LOG_LEVEL_DEBUG, "check_assertion - Invalid
signature");
++ ret = G_ERROR_PARAM;
++ break;
++ }
++
++ if (!o_base64url_decode((const unsigned char
*)json_string_value(json_object_get(json_object_get(json_object_get(j_scheme_data,
"credential"), "response"), "signature")),
json_string_length(json_object_get(json_object_get(json_object_get(j_scheme_data,
"credential"), "response"), "signature")), sig, &sig_len)) {
++ y_log_message(Y_LOG_LEVEL_DEBUG, "check_assertion - Error
o_base64url_decode signature");
++ ret = G_ERROR;
++ break;
++ }
++
+ memcpy(data_signed, auth_data, auth_data_len);
+ memcpy(data_signed+auth_data_len, cdata_hash, cdata_hash_len);
+
diff -Nru glewlwyd-2.5.2/debian/rules glewlwyd-2.5.2/debian/rules
--- glewlwyd-2.5.2/debian/rules 2021-12-17 07:51:46.000000000 -0500
+++ glewlwyd-2.5.2/debian/rules 2022-03-17 21:13:09.000000000 -0400
@@ -29,6 +29,20 @@
# Build webapp
cp -RL /usr/share/nodejs webapp-src/node_modules || true
cp -RL /usr/lib/nodejs/* webapp-src/node_modules/ || true
+ cp /usr/share/javascript/jquery/jquery.min.js webapp-src/js/
+ cp /usr/share/javascript/popper.js/umd/popper.min.js webapp-src/js/
+ cp /usr/share/javascript/popper.js/umd/popper-utils.min.js
webapp-src/js/
+ cp /usr/share/nodejs/bootstrap/dist/js/bootstrap.min.js webapp-src/js/
+ cp /usr/share/nodejs/bootstrap/dist/js/bootstrap.min.js.map
webapp-src/js/
+ cp /usr/share/nodejs/bootstrap/dist/css/bootstrap.min.css
webapp-src/css/
+ cp /usr/share/nodejs/bootstrap/dist/css/bootstrap.min.css.map
webapp-src/css/
+ cp /usr/share/fonts-fork-awesome/css/fork-awesome.css webapp-src/css/
+ cp /usr/share/fonts-fork-awesome/css/v5-compat.css webapp-src/css/
+ cp /usr/share/fonts/eot/fork-awesome/forkawesome-webfont.eot
webapp-src/fonts/
+ cp /usr/share/fonts/svg/fork-awesome/forkawesome-webfont.svg
webapp-src/fonts/
+ cp /usr/share/fonts/truetype/fork-awesome/forkawesome-webfont.ttf
webapp-src/fonts/
+ cp /usr/share/fonts/woff/fork-awesome/forkawesome-webfont.woff
webapp-src/fonts/
+ cp /usr/share/fonts/woff/fork-awesome/forkawesome-webfont.woff2
webapp-src/fonts/
(cd webapp-src && webpack --config webpack.config.js)
override_dh_auto_install: