Skip to content

Commit 7530946

Browse files
committed
Cherry-pick security fixes and community improvements
PR sismics#763: Replace log4j 1.2.17 with reload4j via slf4j-reload4j, bump Guava 31→33, H2 1.4→2.2, OkHttp 4.10→4.12, Jersey 3.0→3.1, commons-compress 1.22→1.25, add parsson + xercesImpl, exclude transitive log4j from subethasmtp. Patch libgnutls30 in Dockerfile. PR sismics#773 (selective): Fix garbled non-ASCII filenames in downloads by URL-encoding Content-Disposition header. Attribute email-imported documents to the Teedy user matching the sender address instead of always defaulting to admin. Made-with: Cursor
1 parent 8dd8c05 commit 7530946

8 files changed

Lines changed: 178 additions & 56 deletions

File tree

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ENV JETTY_HOME=/opt/jetty
1111

1212
# Install packages
1313
RUN apt-get update && \
14+
apt-get upgrade -y -q libgnutls30 && \
1415
apt-get -y -q --no-install-recommends install \
1516
vim less procps unzip wget tzdata openjdk-11-jdk \
1617
ffmpeg \

docs-core/pom.xml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,13 @@
6363
</dependency>
6464

6565
<dependency>
66-
<groupId>log4j</groupId>
67-
<artifactId>log4j</artifactId>
66+
<groupId>org.apache.logging.log4j</groupId>
67+
<artifactId>log4j-core</artifactId>
6868
</dependency>
6969

7070
<dependency>
7171
<groupId>org.slf4j</groupId>
72-
<artifactId>slf4j-log4j12</artifactId>
72+
<artifactId>slf4j-reload4j</artifactId>
7373
</dependency>
7474

7575
<dependency>
@@ -158,6 +158,11 @@
158158
<artifactId>fr.opensagres.poi.xwpf.converter.pdf</artifactId>
159159
</dependency>
160160

161+
<dependency>
162+
<groupId>xerces</groupId>
163+
<artifactId>xercesImpl</artifactId>
164+
</dependency>
165+
161166
<!-- ImageIO plugins -->
162167
<dependency>
163168
<groupId>com.twelvemonkeys.imageio</groupId>

docs-core/src/main/java/com/sismics/docs/core/dao/UserDao.java

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package com.sismics.docs.core.dao;
22

3-
import com.google.common.base.Joiner;
4-
import com.google.common.base.Strings;
5-
import at.favre.lib.crypto.bcrypt.BCrypt;
3+
import java.sql.Timestamp;
4+
import java.util.ArrayList;
5+
import java.util.Date;
6+
import java.util.HashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.UUID;
10+
611
import org.joda.time.DateTime;
712
import org.slf4j.Logger;
813
import org.slf4j.LoggerFactory;
914

15+
import com.google.common.base.Joiner;
16+
import com.google.common.base.Strings;
1017
import com.sismics.docs.core.constant.AuditLogType;
1118
import com.sismics.docs.core.constant.Constants;
1219
import com.sismics.docs.core.dao.criteria.UserCriteria;
@@ -19,11 +26,10 @@
1926
import com.sismics.docs.core.util.jpa.SortCriteria;
2027
import com.sismics.util.context.ThreadLocalContext;
2128

29+
import at.favre.lib.crypto.bcrypt.BCrypt;
2230
import jakarta.persistence.EntityManager;
2331
import jakarta.persistence.NoResultException;
2432
import jakarta.persistence.Query;
25-
import java.sql.Timestamp;
26-
import java.util.*;
2733

2834
/**
2935
* User DAO.
@@ -233,6 +239,23 @@ public User getActiveByUsername(String username) {
233239
return null;
234240
}
235241
}
242+
243+
/**
244+
* Gets an active user by its email.
245+
*
246+
* @param email User's email
247+
* @return User
248+
*/
249+
public User getByEmail(String email) {
250+
EntityManager em = ThreadLocalContext.get().getEntityManager();
251+
try {
252+
Query q = em.createQuery("select u from User u where u.email = :email and u.deleteDate is null");
253+
q.setParameter("email", email);
254+
return (User) q.getSingleResult();
255+
} catch (NoResultException e) {
256+
return null;
257+
}
258+
}
236259

237260
/**
238261
* Deletes a user.

docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,32 @@
11
package com.sismics.docs.core.service;
22

3+
import java.util.Date;
4+
import java.util.HashMap;
5+
import java.util.HashSet;
6+
import java.util.List;
7+
import java.util.Map;
8+
import java.util.Properties;
9+
import java.util.concurrent.TimeUnit;
10+
import java.util.regex.Matcher;
11+
import java.util.regex.Pattern;
12+
13+
import javax.mail.Flags;
14+
import javax.mail.Folder;
15+
import javax.mail.FolderClosedException;
16+
import javax.mail.Message;
17+
import javax.mail.Session;
18+
import javax.mail.Store;
19+
import javax.mail.internet.InternetAddress;
20+
import javax.mail.search.FlagTerm;
21+
22+
import org.apache.commons.lang3.StringUtils;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
326
import com.google.common.util.concurrent.AbstractScheduledService;
427
import com.sismics.docs.core.constant.ConfigType;
528
import com.sismics.docs.core.dao.TagDao;
29+
import com.sismics.docs.core.dao.UserDao;
630
import com.sismics.docs.core.dao.criteria.TagCriteria;
731
import com.sismics.docs.core.dao.dto.TagDto;
832
import com.sismics.docs.core.event.DocumentCreatedAsyncEvent;
@@ -15,16 +39,6 @@
1539
import com.sismics.docs.core.util.jpa.SortCriteria;
1640
import com.sismics.util.EmailUtil;
1741
import com.sismics.util.context.ThreadLocalContext;
18-
import org.apache.commons.lang3.StringUtils;
19-
import org.slf4j.Logger;
20-
import org.slf4j.LoggerFactory;
21-
22-
import javax.mail.*;
23-
import javax.mail.search.FlagTerm;
24-
import java.util.*;
25-
import java.util.concurrent.TimeUnit;
26-
import java.util.regex.Matcher;
27-
import java.util.regex.Pattern;
2842

2943
/**
3044
* Inbox scanning service.
@@ -88,7 +102,8 @@ public void syncInbox() {
88102
Message[] messages = inbox.search(new FlagTerm(new Flags(Flags.Flag.SEEN), false));
89103
log.info(messages.length + " messages found");
90104
for (Message message : messages) {
91-
importMessage(message, tagsNameToId);
105+
InternetAddress sender = (InternetAddress) message.getFrom()[0];
106+
importMessage(message, tagsNameToId,sender);
92107
lastSyncMessageCount++;
93108
}
94109
} catch (FolderClosedException e) {
@@ -190,8 +205,8 @@ private Folder openInbox() throws Exception {
190205
* @param message Message
191206
* @throws Exception e
192207
*/
193-
private void importMessage(Message message, Map<String, String> tags) throws Exception {
194-
log.info("Importing message: " + message.getSubject());
208+
private void importMessage(Message message, Map<String, String> tags,InternetAddress sender) throws Exception {
209+
log.info("Importing message: " + message.getSubject()+",sender="+sender.getAddress());
195210

196211
// Parse the mail
197212
EmailUtil.MailContent mailContent = new EmailUtil.MailContent();
@@ -219,8 +234,12 @@ private void importMessage(Message message, Map<String, String> tags) throws Exc
219234
log.debug("Tags found: " + String.join(", ", tagsFound));
220235
subject = subject.trim().replaceAll(" +", " ");
221236
}
222-
223-
document.setUserId("admin");
237+
UserDao userDao = new UserDao();
238+
com.sismics.docs.core.model.jpa.User user = userDao.getByEmail(sender.getAddress());
239+
if(user!=null)
240+
document.setUserId(user.getId());
241+
else
242+
document.setUserId("admin");
224243
document.setTitle(StringUtils.abbreviate(subject, 100));
225244
document.setDescription(StringUtils.abbreviate(mailContent.getMessage(), 4000));
226245
document.setSubject(StringUtils.abbreviate(mailContent.getSubject(), 500));
@@ -232,9 +251,13 @@ private void importMessage(Message message, Map<String, String> tags) throws Exc
232251
} else {
233252
document.setCreateDate(mailContent.getDate());
234253
}
254+
if(user!=null)
255+
DocumentUtil.createDocument(document, user.getId());
256+
else{
257+
// Save the document, create the base ACLs
258+
DocumentUtil.createDocument(document, "admin");
259+
}
235260

236-
// Save the document, create the base ACLs
237-
DocumentUtil.createDocument(document, "admin");
238261

239262
// Add the tag
240263
String tagId = ConfigUtil.getConfigStringValue(ConfigType.INBOX_TAG);
@@ -253,12 +276,19 @@ private void importMessage(Message message, Map<String, String> tags) throws Exc
253276

254277
// Raise a document created event
255278
DocumentCreatedAsyncEvent documentCreatedAsyncEvent = new DocumentCreatedAsyncEvent();
256-
documentCreatedAsyncEvent.setUserId("admin");
279+
if(user!=null)
280+
documentCreatedAsyncEvent.setUserId(user.getId());
281+
else
282+
documentCreatedAsyncEvent.setUserId("admin");
257283
documentCreatedAsyncEvent.setDocumentId(document.getId());
258284
ThreadLocalContext.get().addAsyncEvent(documentCreatedAsyncEvent);
259285

260286
// Add files to the document
261287
for (EmailUtil.FileContent fileContent : mailContent.getFileContentList()) {
288+
if(user!=null)
289+
FileUtil.createFile(fileContent.getName(), null, fileContent.getFile(), fileContent.getSize(),
290+
document.getLanguage(), user.getId(), document.getId());
291+
else
262292
FileUtil.createFile(fileContent.getName(), null, fileContent.getFile(), fileContent.getSize(),
263293
document.getLanguage(), "admin", document.getId());
264294
}

docs-web-common/pom.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@
3131
<groupId>org.glassfish.jersey.media</groupId>
3232
<artifactId>jersey-media-json-processing</artifactId>
3333
</dependency>
34+
35+
<dependency>
36+
<groupId>org.eclipse.parsson</groupId>
37+
<artifactId>parsson</artifactId>
38+
</dependency>
3439

3540
<!-- Other external dependencies -->
3641
<dependency>
@@ -49,8 +54,8 @@
4954
</dependency>
5055

5156
<dependency>
52-
<groupId>log4j</groupId>
53-
<artifactId>log4j</artifactId>
57+
<groupId>org.apache.logging.log4j</groupId>
58+
<artifactId>log4j-core</artifactId>
5459
</dependency>
5560

5661
<dependency>

docs-web/pom.xml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646
<groupId>org.glassfish.jersey.inject</groupId>
4747
<artifactId>jersey-hk2</artifactId>
4848
</dependency>
49+
50+
<dependency>
51+
<groupId>org.eclipse.parsson</groupId>
52+
<artifactId>parsson</artifactId>
53+
</dependency>
4954

5055
<!-- Other external dependencies -->
5156
<dependency>
@@ -64,8 +69,8 @@
6469
</dependency>
6570

6671
<dependency>
67-
<groupId>log4j</groupId>
68-
<artifactId>log4j</artifactId>
72+
<groupId>org.apache.logging.log4j</groupId>
73+
<artifactId>log4j-core</artifactId>
6974
</dependency>
7075

7176
<dependency>

docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
package com.sismics.docs.rest.resource;
22

3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.net.URISyntaxException;
6+
import java.net.URLDecoder;
7+
import java.nio.charset.StandardCharsets;
8+
import java.nio.file.Files;
9+
import java.nio.file.Paths;
10+
import java.nio.file.StandardCopyOption;
11+
import java.text.MessageFormat;
12+
import java.util.List;
13+
import java.util.zip.ZipEntry;
14+
import java.util.zip.ZipOutputStream;
15+
16+
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
17+
import org.glassfish.jersey.media.multipart.FormDataParam;
18+
319
import com.google.common.base.Strings;
420
import com.google.common.collect.Lists;
521
import com.google.common.io.ByteStreams;
@@ -27,30 +43,27 @@
2743
import com.sismics.util.JsonUtil;
2844
import com.sismics.util.context.ThreadLocalContext;
2945
import com.sismics.util.mime.MimeType;
30-
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
31-
import org.glassfish.jersey.media.multipart.FormDataParam;
3246

3347
import jakarta.json.Json;
3448
import jakarta.json.JsonArrayBuilder;
3549
import jakarta.json.JsonObjectBuilder;
36-
import jakarta.ws.rs.*;
50+
import jakarta.ws.rs.Consumes;
51+
import jakarta.ws.rs.DELETE;
52+
import jakarta.ws.rs.FormParam;
53+
import jakarta.ws.rs.GET;
54+
import jakarta.ws.rs.NotFoundException;
55+
import jakarta.ws.rs.POST;
56+
import jakarta.ws.rs.PUT;
57+
import jakarta.ws.rs.Path;
58+
import jakarta.ws.rs.PathParam;
59+
import jakarta.ws.rs.Produces;
60+
import jakarta.ws.rs.QueryParam;
61+
import jakarta.ws.rs.WebApplicationException;
3762
import jakarta.ws.rs.core.HttpHeaders;
3863
import jakarta.ws.rs.core.MediaType;
3964
import jakarta.ws.rs.core.Response;
4065
import jakarta.ws.rs.core.Response.Status;
4166
import jakarta.ws.rs.core.StreamingOutput;
42-
import java.io.IOException;
43-
import java.io.InputStream;
44-
import java.net.URISyntaxException;
45-
import java.net.URLDecoder;
46-
import java.nio.charset.StandardCharsets;
47-
import java.nio.file.Files;
48-
import java.nio.file.Paths;
49-
import java.nio.file.StandardCopyOption;
50-
import java.text.MessageFormat;
51-
import java.util.List;
52-
import java.util.zip.ZipEntry;
53-
import java.util.zip.ZipOutputStream;
5467

5568
/**
5669
* File REST resources.
@@ -637,7 +650,7 @@ public Response data(
637650
}
638651

639652
Response.ResponseBuilder builder = Response.ok(stream)
640-
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + file.getFullName("data") + "\"")
653+
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename*=utf-8''" + filenameEncode( file.getFullName("data") ))
641654
.header(HttpHeaders.CONTENT_TYPE, mimeType);
642655
if (decrypt) {
643656
// Cache real files
@@ -651,6 +664,15 @@ public Response data(
651664
return builder.build();
652665
}
653666

667+
private String filenameEncode(String name) {
668+
try {
669+
return java.net.URLEncoder.encode(name, "UTF-8").replace("+", "%20");
670+
} catch (java.io.UnsupportedEncodingException e) {
671+
e.printStackTrace();
672+
return name;
673+
}
674+
}
675+
654676
/**
655677
* Returns all files from a document, zipped.
656678
*

0 commit comments

Comments
 (0)