Skip to content

Commit 3586802

Browse files
committed
windows fs security
1 parent 72958ff commit 3586802

File tree

1 file changed

+154
-133
lines changed

1 file changed

+154
-133
lines changed

src/main/java/fr/cnes/sonar/plugin/ws/ExportTask.java

+154-133
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.IOException;
2222
import java.io.OutputStreamWriter;
2323
import java.nio.charset.StandardCharsets;
24+
import java.nio.file.AccessDeniedException;
2425
import java.nio.file.Files;
2526
import java.nio.file.Path;
2627
import java.nio.file.attribute.FileAttribute;
@@ -31,6 +32,8 @@
3132
import java.util.Arrays;
3233
import java.util.List;
3334
import java.util.Set;
35+
import java.util.logging.Level;
36+
import java.util.logging.Logger;
3437

3538
import org.apache.commons.io.FileUtils;
3639
import org.apache.commons.lang.SystemUtils;
@@ -75,163 +78,181 @@ public class ExportTask implements RequestHandler {
7578

7679
/**
7780
* public constructor
81+
*
7882
* @param config sonarqube configuration
7983
*/
80-
ExportTask(Configuration config){
84+
ExportTask(Configuration config) {
8185
this.config = config;
8286
}
8387

8488
/**
8589
* Handles a request and writes the output in the response stream.
86-
* @param request The request object containing the details of the client's request.
90+
*
91+
* @param request The request object containing the details of the client's
92+
* request.
8793
* @param response The response object used to send the data back to the client.
8894
*/
8995
@Override
9096
public void handle(Request request, Response response) throws BadExportationDataTypeException, IOException,
91-
UnknownQualityGateException, OpenXML4JException, XmlException, SonarQubeException, ParseException {
97+
UnknownQualityGateException, OpenXML4JException, XmlException, SonarQubeException, ParseException,
98+
AccessDeniedException {
9299

93100
// Get project key
94101
String projectKey = request.getParam(PluginStringManager.getProperty("api.report.args.key")).getValue();
95102

96103
// Getting stream and change headers
97104
Response.Stream stream = response.stream();
98105

99-
// Get a temp folder
106+
// Get a safe temporary folder for UNIX or windows.
100107

101108
Path tempDirectory;
102-
103-
if (SystemUtils.IS_OS_UNIX) {
104-
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions
105-
.asFileAttribute(PosixFilePermissions.fromString("rwx------"));
106-
Files.createTempFile("cnesreport", ".tmp", attr);
107-
tempDirectory = Files.createTempDirectory("cnesreport", attr);
108-
} else {
109-
File f = Files.createTempFile("cnesreport", ".tmp").toFile();
110-
f.setReadable(false);
111-
f.setWritable(false);
112-
f.setExecutable(false);
113-
f.setReadable(true, true);
114-
f.setWritable(true, true);
115-
f.setExecutable(true, true);
116-
tempDirectory = f.toPath();
117-
}
118-
final File outputDirectory = File.createTempFile("cnesreport", Long.toString(System.nanoTime()), tempDirectory.toFile());
119-
120-
121-
// Last line create file instead of folder, we delete file to put folder at the same place later
122-
Files.delete(outputDirectory.toPath());
123-
124-
// Start generation, re-using standalone script
109+
File outputDirectory = null;
125110
try {
126-
final Request.StringParam pBranch =
127-
request.getParam(PluginStringManager.getProperty("api.report.args.branch"));
128-
129-
final Request.StringParam pLanguage =
130-
request.getParam(PluginStringManager.getProperty("api.report.args.language"));
131-
132-
final Request.StringParam pEnableDocx =
133-
request.getParam(PluginStringManager.getProperty("api.report.args.enableDocx"));
134-
135-
final Request.StringParam pEnableMd =
136-
request.getParam(PluginStringManager.getProperty("api.report.args.enableMd"));
137-
138-
final Request.StringParam pEnableXlsx =
139-
request.getParam(PluginStringManager.getProperty("api.report.args.enableXlsx"));
140-
141-
final Request.StringParam pEnableCsv =
142-
request.getParam(PluginStringManager.getProperty("api.report.args.enableCsv"));
143-
144-
final Request.StringParam pEnableConf =
145-
request.getParam(PluginStringManager.getProperty("api.report.args.enableConf"));
146-
147-
// Build SonarQube local URL
148-
String port = config.get("sonar.web.port").orElse(PluginStringManager.getProperty("plugin.defaultPort"));
149-
String context = config.get("sonar.web.context").orElse(PluginStringManager.getProperty("plugin.defaultContext"));
150-
String sonarUrl = String.format(PluginStringManager.getProperty("plugin.defaultHost"), port, context);
151-
152-
// Get files templates paths if defined in the decicated SonarQube configuration panel
153-
String docxPath = config.get("sonar.cnesreport.docx.path").orElse(null);
154-
String mdPath = config.get("sonar.cnesreport.md.path").orElse(null);
155-
String xlsxPath = config.get("sonar.cnesreport.xlsx.path").orElse(null);
156-
157-
// create a new client to talk with sonarqube's services
158-
WsClient wsClient = WsClientFactories.getLocal().newClient(request.localConnector());
159-
160-
// prepare params for the report generation
161-
List<String> reportParams = new ArrayList<>(Arrays.asList(
162-
"report",
163-
"-o", outputDirectory.getAbsolutePath(),
164-
"-s", sonarUrl,
165-
"-p", projectKey,
166-
"-b", pBranch.isPresent()?pBranch.getValue(): DefaultBranch.getDefaultBranchFromProject(wsClient, projectKey),
167-
"-a", request.getParam(PluginStringManager.getProperty("api.report.args.author")).getValue(),
168-
"-t", request.getParam(PluginStringManager.getProperty("api.report.args.token")).getValue(),
169-
"-l", pLanguage.isPresent()?pLanguage.getValue(): StringManager.getProperty(StringManager.DEFAULT_LANGUAGE)
170-
));
171-
172-
// add files templates paths to params if defined
173-
if (docxPath != null) {
174-
reportParams.add("-r");
175-
reportParams.add(docxPath);
111+
if (SystemUtils.IS_OS_UNIX) {
112+
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions
113+
.asFileAttribute(PosixFilePermissions.fromString("rwx------"));
114+
Files.createTempFile("cnesreport", ".tmp", attr);
115+
tempDirectory = Files.createTempDirectory("cnesreport", attr);
116+
} else {
117+
File f = Files.createTempFile("cnesreport", ".tmp").toFile();
118+
boolean isOk = true;
119+
isOk = isOk && f.setReadable(false);
120+
isOk = isOk && f.setWritable(false);
121+
isOk = isOk && f.setExecutable(false);
122+
isOk = isOk && f.setReadable(true, true);
123+
isOk = isOk && f.setWritable(true, true);
124+
isOk = isOk && f.setExecutable(true, true);
125+
tempDirectory = f.toPath();
126+
if (!isOk)
127+
throw new AccessDeniedException(f.toString(), "", "Could not set permissions of temporary file: ");
176128
}
177-
if (mdPath != null) {
178-
reportParams.add("-n");
179-
reportParams.add(mdPath);
180-
}
181-
if (xlsxPath != null) {
182-
reportParams.add("-x");
183-
reportParams.add(xlsxPath);
184-
}
185-
186-
String pEnableDocxValue = pEnableDocx.getValue();
187-
String pEnableMdValue = pEnableMd.getValue();
188-
String pEnableXlsxValue = pEnableXlsx.getValue();
189-
String pEnableCsvValue = pEnableCsv.getValue();
190-
String pEnableConfValue = pEnableConf.getValue();
191-
192-
// add disable files generation params if requested
193-
if(pEnableDocxValue != null && (pEnableDocxValue.equals(FALSE) || pEnableDocxValue.equals(NO))) {
194-
reportParams.add("-w");
195-
}
196-
if(pEnableMdValue != null && (pEnableMdValue.equals(FALSE) || pEnableMdValue.equals(NO))) {
197-
reportParams.add("-m");
198-
}
199-
if(pEnableXlsxValue != null && (pEnableXlsxValue.equals(FALSE) || pEnableXlsxValue.equals(NO))) {
200-
reportParams.add("-e");
201-
}
202-
if(pEnableCsvValue != null && (pEnableCsvValue.equals(FALSE) || pEnableCsvValue.equals(NO))) {
203-
reportParams.add("-f");
204-
}
205-
if(pEnableConfValue != null && (pEnableConfValue.equals(FALSE) || pEnableConfValue.equals(NO))) {
206-
reportParams.add("-c");
129+
outputDirectory = File.createTempFile("cnesreport", Long.toString(System.nanoTime()),
130+
tempDirectory.toFile());
131+
} catch (AccessDeniedException e) {
132+
Logger logger = Logger.getLogger(ExportTask.class.getName());
133+
logger.log(Level.SEVERE, "{0}{1}", new Object[] { e.getReason(), e.getFile() });
134+
}
135+
// Last line create file instead of folder, we delete file to put folder at the
136+
// same place later
137+
if (outputDirectory != null) {
138+
Files.delete(outputDirectory.toPath());
139+
140+
// Start generation, re-using standalone script
141+
try {
142+
final Request.StringParam pBranch = request
143+
.getParam(PluginStringManager.getProperty("api.report.args.branch"));
144+
145+
final Request.StringParam pLanguage = request
146+
.getParam(PluginStringManager.getProperty("api.report.args.language"));
147+
148+
final Request.StringParam pEnableDocx = request
149+
.getParam(PluginStringManager.getProperty("api.report.args.enableDocx"));
150+
151+
final Request.StringParam pEnableMd = request
152+
.getParam(PluginStringManager.getProperty("api.report.args.enableMd"));
153+
154+
final Request.StringParam pEnableXlsx = request
155+
.getParam(PluginStringManager.getProperty("api.report.args.enableXlsx"));
156+
157+
final Request.StringParam pEnableCsv = request
158+
.getParam(PluginStringManager.getProperty("api.report.args.enableCsv"));
159+
160+
final Request.StringParam pEnableConf = request
161+
.getParam(PluginStringManager.getProperty("api.report.args.enableConf"));
162+
163+
// Build SonarQube local URL
164+
String port = config.get("sonar.web.port")
165+
.orElse(PluginStringManager.getProperty("plugin.defaultPort"));
166+
String context = config.get("sonar.web.context")
167+
.orElse(PluginStringManager.getProperty("plugin.defaultContext"));
168+
String sonarUrl = String.format(PluginStringManager.getProperty("plugin.defaultHost"), port, context);
169+
170+
// Get files templates paths if defined in the decicated SonarQube configuration
171+
// panel
172+
String docxPath = config.get("sonar.cnesreport.docx.path").orElse(null);
173+
String mdPath = config.get("sonar.cnesreport.md.path").orElse(null);
174+
String xlsxPath = config.get("sonar.cnesreport.xlsx.path").orElse(null);
175+
176+
// create a new client to talk with sonarqube's services
177+
WsClient wsClient = WsClientFactories.getLocal().newClient(request.localConnector());
178+
179+
// prepare params for the report generation
180+
List<String> reportParams = new ArrayList<>(Arrays.asList(
181+
"report",
182+
"-o", outputDirectory.getAbsolutePath(),
183+
"-s", sonarUrl,
184+
"-p", projectKey,
185+
"-b",
186+
pBranch.isPresent() ? pBranch.getValue()
187+
: DefaultBranch.getDefaultBranchFromProject(wsClient, projectKey),
188+
"-a", request.getParam(PluginStringManager.getProperty("api.report.args.author")).getValue(),
189+
"-t", request.getParam(PluginStringManager.getProperty("api.report.args.token")).getValue(),
190+
"-l", pLanguage.isPresent() ? pLanguage.getValue()
191+
: StringManager.getProperty(StringManager.DEFAULT_LANGUAGE)));
192+
193+
// add files templates paths to params if defined
194+
if (docxPath != null) {
195+
reportParams.add("-r");
196+
reportParams.add(docxPath);
197+
}
198+
if (mdPath != null) {
199+
reportParams.add("-n");
200+
reportParams.add(mdPath);
201+
}
202+
if (xlsxPath != null) {
203+
reportParams.add("-x");
204+
reportParams.add(xlsxPath);
205+
}
206+
207+
String pEnableDocxValue = pEnableDocx.getValue();
208+
String pEnableMdValue = pEnableMd.getValue();
209+
String pEnableXlsxValue = pEnableXlsx.getValue();
210+
String pEnableCsvValue = pEnableCsv.getValue();
211+
String pEnableConfValue = pEnableConf.getValue();
212+
213+
// add disable files generation params if requested
214+
if (pEnableDocxValue != null && (pEnableDocxValue.equals(FALSE) || pEnableDocxValue.equals(NO))) {
215+
reportParams.add("-w");
216+
}
217+
if (pEnableMdValue != null && (pEnableMdValue.equals(FALSE) || pEnableMdValue.equals(NO))) {
218+
reportParams.add("-m");
219+
}
220+
if (pEnableXlsxValue != null && (pEnableXlsxValue.equals(FALSE) || pEnableXlsxValue.equals(NO))) {
221+
reportParams.add("-e");
222+
}
223+
if (pEnableCsvValue != null && (pEnableCsvValue.equals(FALSE) || pEnableCsvValue.equals(NO))) {
224+
reportParams.add("-f");
225+
}
226+
if (pEnableConfValue != null && (pEnableConfValue.equals(FALSE) || pEnableConfValue.equals(NO))) {
227+
reportParams.add("-c");
228+
}
229+
230+
// Execute report generation
231+
ReportCommandLine.execute(reportParams.toArray(new String[reportParams.size()]));
232+
233+
stream.setMediaType("application/zip");
234+
String filename = ReportFactory.formatFilename("zip.report.output", "", "", projectKey);
235+
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + '"');
236+
237+
// generate zip output and send it
238+
ZipFolder.pack(outputDirectory.getAbsolutePath(), outputDirectory.getAbsolutePath() + ".zip");
239+
File zip = new File(outputDirectory.getAbsolutePath() + ".zip");
240+
FileUtils.copyFile(zip, stream.output());
241+
Files.deleteIfExists(zip.toPath());
242+
} catch (BadSonarQubeRequestException e) {
243+
response.stream().setMediaType(MediaTypes.JSON);
244+
try (
245+
OutputStreamWriter writer = new OutputStreamWriter(response.stream().output(),
246+
StandardCharsets.UTF_8);
247+
JsonWriter jsonWriter = new JsonWriter(writer);) {
248+
jsonWriter.beginObject();
249+
jsonWriter.name("error").value(PluginStringManager.getProperty("api.tokenerror"));
250+
jsonWriter.endObject();
251+
jsonWriter.flush();
252+
}
207253
}
208254

209-
// Execute report generation
210-
ReportCommandLine.execute(reportParams.toArray(new String[reportParams.size()]));
211-
212-
stream.setMediaType("application/zip");
213-
String filename = ReportFactory.formatFilename("zip.report.output", "", "", projectKey);
214-
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + '"');
215-
216-
217-
// generate zip output and send it
218-
ZipFolder.pack(outputDirectory.getAbsolutePath(), outputDirectory.getAbsolutePath() + ".zip");
219-
File zip = new File(outputDirectory.getAbsolutePath() + ".zip");
220-
FileUtils.copyFile(zip, stream.output());
221-
Files.deleteIfExists(zip.toPath());
222-
} catch (BadSonarQubeRequestException e) {
223-
response.stream().setMediaType(MediaTypes.JSON);
224-
try (
225-
OutputStreamWriter writer = new OutputStreamWriter(response.stream().output(), StandardCharsets.UTF_8);
226-
JsonWriter jsonWriter = new JsonWriter(writer);
227-
) {
228-
jsonWriter.beginObject();
229-
jsonWriter.name("error").value(PluginStringManager.getProperty("api.tokenerror"));
230-
jsonWriter.endObject();
231-
jsonWriter.flush();
232-
}
255+
FileTools.deleteFolder(outputDirectory);
233256
}
234-
235-
FileTools.deleteFolder(outputDirectory);
236257
}
237258
}

0 commit comments

Comments
 (0)