4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / WorkspaceUtils.java JAVA
package com.f5.tmui.locallb.handler.workspace;

import com.f5.form.ShellCommandValidator;
import com.f5.log.F5Logger;
import com.f5.model.db.DBConnection;
import com.f5.tmui.util.FolderUtils;
import com.f5.tmui.util.Syscall;
import com.f5.tmui.util.Syscall.CallException;
import com.f5.tmui.util.Syscall.Result;
import com.f5.util.F5Exception;
import com.f5.util.NLSEngine;
import com.f5.util.SHA1;
import com.f5.util.User;
import com.f5.util.WebUtils;
import com.f5.view.web.pagerenderer.Html;
import com.f5.view.web.pagerenderer.Link;
import com.f5.view.web.pagerenderer.TableRow;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.json.simple.JSONObject;

public class WorkspaceUtils {
   public static final String CHMOD_COMMAND = "/bin/chmod";
   public static final String CHOWN_COMMAND = "/bin/chown";
   public static final String FILE_GROUP = "sdm";
   public static final String FILE_MODE = "664";
   public static final String JSON_CHILDREN = "children";
   public static final String JSON_DIRECTORY = "dir";
   public static final String JSON_FILE = "file";
   private static final String ilxWorkspacesDir = "/var/ilx/workspaces/";
   private static final String pluginsDir = "/var/sdm/plugin_store/plugins/";
   private static final Set whitelistDirSet = new HashSet(Arrays.asList("/var/ilx/workspaces/", "/var/sdm/plugin_store/plugins/"));
   private static final List WHITELISTED_QUERIES = Arrays.asList("locallb.irule.ilx.select_plugin_path");
   private static final List WHITELISTED_TMSH_MODULES = Arrays.asList("ilx");
   private static final int OPERATION_IDX = 0;
   private static final int MODULE_IDX = 2;
   private static final String TMUI_DUBBUF_NAME = "Tmui-Dubbuf";

   public static boolean csrfValidated(String bufForm, String timenow, String bufHeader) {
      return bufHeader != null && bufForm != null && timenow != null && bufForm.equals(SHA1.hash(bufHeader + timenow));
   }

   public static JSONObject runTmshCommand(String command, HttpServletRequest request) {
      F5Logger logger = (F5Logger)F5Logger.getLogger(WorkspaceUtils.class);
      JSONObject resultObject = new JSONObject();
      String output = "";
      String error = "";
      if (!csrfValidated(request.getHeader("_bufvalue"), request.getHeader("_timenow"), request.getHeader("Tmui-Dubbuf"))) {
         logger.warn("Invalid user token - token provided by user is not authorized");
         resultObject.put("output", output);
         resultObject.put("error", NLSEngine.getString("ilx.workspace.error.InvalidUserToken"));
         return resultObject;
      } else {
         if ("POST".equalsIgnoreCase(request.getMethod())) {
            String[] cmdArray = command.split(" ");
            String operation = cmdArray[0];
            String module = cmdArray[2];
            if (!ShellCommandValidator.checkForBadShellCharacters(command) && (operation.equals("create") || operation.equals("delete") || operation.equals("list") || operation.equals("modify")) && WHITELISTED_TMSH_MODULES.contains(module)) {
               try {
                  String[] args = new String[]{command};
                  Result result = Syscall.callElevated(Syscall.TMSH, args);
                  output = result.getOutput();
                  error = result.getError();
               } catch (CallException var11) {
                  logger.error(NLSEngine.getString("ilx.workspace.error.TmshCommandFailed") + ": " + var11.getMessage());
                  error = var11.getMessage();
               }
            } else {
               error = NLSEngine.getString("ilx.workspace.error.RejectedTmshCommand");
            }
         } else {
            error = NLSEngine.getString("ilx.workspace.error.InvalidMethod");
         }

         resultObject.put("output", output);
         resultObject.put("error", error);
         return resultObject;
      }
   }

   private static void listDirectoryRecursive(File dir, JsonArray parent) {
      File[] list = dir.listFiles();
      Arrays.sort(list);
      File[] arr$ = list;
      int len$ = list.length;

      for(int i$ = 0; i$ < len$; ++i$) {
         File file = arr$[i$];
         JsonObject dirObj;
         if (file.isDirectory()) {
            dirObj = new JsonObject();
            dirObj.addProperty("dir", file.getName());
            parent.add(dirObj);
            JsonArray children = new JsonArray();
            dirObj.add("children", children);
            listDirectoryRecursive(file, children);
         } else {
            dirObj = new JsonObject();
            dirObj.addProperty("file", file.getName());
            parent.add(dirObj);
         }
      }

   }

   public static JSONObject listDirectory(String directoryPath) throws Exception {
      JSONObject resultObject = new JSONObject();
      File directory = new File(directoryPath);
      if (directory.exists()) {
         JsonObject listObj = new JsonObject();
         listObj.addProperty("dir", directory.getName());
         JsonArray children = new JsonArray();
         listObj.add("children", children);
         listDirectoryRecursive(directory, children);
         resultObject.put("output", listObj);
      }

      return resultObject;
   }

   public static JSONObject readFile(String fileName) throws FileNotFoundException {
      JSONObject resultObject = new JSONObject();
      File file = new File(fileName);
      StringBuilder fileContents = new StringBuilder((int)file.length());
      Scanner scanner = new Scanner(new BufferedReader(new FileReader(file)));
      String lineSeparator = System.getProperty("line.separator");

      JSONObject var6;
      try {
         while(scanner.hasNextLine()) {
            fileContents.append(scanner.nextLine() + lineSeparator);
         }

         resultObject.put("output", fileContents.toString());
         var6 = resultObject;
      } finally {
         scanner.close();
      }

      return var6;
   }

   public static JSONObject saveFile(HttpServletRequest request) throws IOException {
      F5Logger logger = (F5Logger)F5Logger.getLogger(WorkspaceUtils.class);
      PrintWriter writer = null;
      JSONObject resultObject = new JSONObject();

      label75: {
         JSONObject var4;
         try {
            String content;
            try {
               if (csrfValidated(request.getHeader("_bufvalue"), request.getHeader("_timenow"), request.getHeader("Tmui-Dubbuf"))) {
                  String fileName = WebUtils.getProperty(request, "fileName");
                  content = WebUtils.getProperty(request, "content");
                  writer = new PrintWriter(new FileWriter(fileName));
                  writer.println(content);
                  String[] chmodCmd = new String[]{"/bin/chmod", "664", fileName};
                  Runtime.getRuntime().exec(chmodCmd);
                  String[] chownCmd = new String[]{"/bin/chown", ":sdm", fileName};
                  Runtime.getRuntime().exec(chownCmd);
                  break label75;
               }

               logger.warn("Invalid user token - token provided by user is not authorized");
               resultObject.put("error", NLSEngine.getString("ilx.workspace.error.InvalidUserToken"));
               var4 = resultObject;
            } catch (IOException var12) {
               content = NLSEngine.getString("ilx.workspace.error.ErrorWritingFile") + ": " + var12.getMessage();
               logger.error(content);
               throw var12;
            } catch (SecurityException var13) {
               content = NLSEngine.getString("ilx.workspace.error.ErrorWritingFile") + ": " + var13.getMessage();
               logger.error(content);
               throw var13;
            }
         } finally {
            if (writer != null) {
               writer.close();
            }

         }

         return var4;
      }

      resultObject.put("output", "Success");
      return resultObject;
   }

   public static void addArrayItemsToRow(ArrayList list, TableRow row, String linkBase) {
      Iterator iterator = list.iterator();
      String pluginName = (String)iterator.next();
      Link link = new Link(linkBase + pluginName, FolderUtils.getLeafName(pluginName));

      Link newLink;
      for(Link parentEle = link; iterator.hasNext(); parentEle = newLink) {
         pluginName = (String)iterator.next();
         Html comma = new Html("<span>,</span>");
         parentEle.setChildRowElement(comma);
         newLink = new Link(linkBase + pluginName, FolderUtils.getLeafName(pluginName));
         comma.setChildRowElement(newLink);
      }

      row.addChainedRowElement(link);
   }

   public static String archiveArgPath(String partition, String file) {
      return "/" + partition + "/" + file;
   }

   public static String archiveRealPath(String partition, String file) {
      return "/var/ilx/workspaces/" + partition + "/archive/" + file;
   }

   public static JSONObject dbQuery(String queryName, String objName, String columnName) throws SQLException, F5Exception {
      if (!WHITELISTED_QUERIES.contains(queryName)) {
         throw new F5Exception("Illegal query: " + queryName);
      } else {
         JSONObject resultObject = new JSONObject();

         JSONObject var6;
         try {
            if (!DBConnection.isAllocated()) {
               DBConnection.allocate();
            }

            ResultSet rs = DBConnection.execute(queryName, new Object[]{objName});
            String result = "";
            if (rs != null && rs.next()) {
               result = rs.getString(columnName);
            }

            resultObject.put("output", result);
            var6 = resultObject;
         } catch (SQLException var15) {
            throw var15;
         } finally {
            try {
               if (DBConnection.isAllocated()) {
                  DBConnection.deallocate();
               }
            } catch (SQLException var14) {
               throw var14;
            }

         }

         return var6;
      }
   }

   public static boolean isFileWhitelisted(String fileName) throws IOException {
      F5Logger log = (F5Logger)F5Logger.getLogger(WorkspaceUtils.class);
      boolean isWhitelisted = false;
      File file = new File(fileName);
      String canonFilename = file.getCanonicalPath();
      Path canonPath = Paths.get(canonFilename);
      log.debug("Input filename " + fileName + " has canon name " + canonFilename);
      if (!Files.isDirectory(canonPath.getParent(), new LinkOption[0])) {
         log.debug("Directory for file " + canonFilename + " does not exist; failing");
         throw new FileNotFoundException("Dir path to file " + fileName + " does not exist.");
      } else {
         Path realDirPath = canonPath.getParent().toRealPath();
         Iterator i$ = whitelistDirSet.iterator();

         while(i$.hasNext()) {
            String whitelistDir = (String)i$.next();
            Path whitelistDirPath = Paths.get(whitelistDir);
            log.debug("Checking if " + canonFilename + " lies under directory " + whitelistDir);
            if (realDirPath.startsWith(whitelistDirPath)) {
               log.debug("  > " + canonFilename + " is whitelisted under " + whitelistDir);
               isWhitelisted = true;
               break;
            }
         }

         log.debug(canonFilename + " is " + (isWhitelisted ? "" : "not ") + "a whitelisted file");
         return isWhitelisted;
      }
   }

   public static boolean isUserAuthorized(User user) {
      switch(user.getRawRoleId()) {
      case 0:
      case 20:
      case 100:
      case 510:
         return true;
      default:
         return false;
      }
   }

   public static boolean userCanAccessPartition(User user, String fileName, boolean checkUserPartitionPermission) throws IOException {
      F5Logger log = (F5Logger)F5Logger.getLogger(WorkspaceUtils.class);
      File file = new File(fileName);
      String canonFilename = file.getCanonicalPath();
      Path canonPath = Paths.get(canonFilename);
      log.debug("Input filename " + fileName + " has canon name " + canonFilename);
      String partition = null;
      int delimiterIndex;
      if (canonFilename.startsWith("/var/ilx/workspaces/")) {
         delimiterIndex = canonFilename.indexOf(47, "/var/ilx/workspaces/".length());
         if (delimiterIndex < 0) {
            log.error(canonFilename + " is a file with no partition. Failing.");
            return false;
         }

         partition = canonFilename.substring("/var/ilx/workspaces/".length(), delimiterIndex);
      } else {
         if (!canonFilename.startsWith("/var/sdm/plugin_store/plugins/")) {
            log.error("Filename " + canonFilename + " is not in a whitelisted directory");
            return false;
         }

         delimiterIndex = canonFilename.indexOf(58, "/var/sdm/plugin_store/plugins/".length() + 1);
         if (delimiterIndex < 0) {
            log.error(canonFilename + " is a file with no partition. Failing.");
            return false;
         }

         partition = canonFilename.substring("/var/sdm/plugin_store/plugins/".length() + 1, delimiterIndex);
      }

      List allowedPartitions = user.getAllowedPartitions();
      log.debug(canonFilename + " lies in partition " + partition + "; this is" + (allowedPartitions.contains(partition) ? "" : " not") + " a permitted partition from user's partitions of " + allowedPartitions.toString());
      if (!allowedPartitions.contains(partition)) {
         return false;
      } else if (checkUserPartitionPermission) {
         HashMap allRoles = user.getAllRoles();
         log.debug(user.getUsername() + " has roles " + allRoles.toString());
         int partitionRole = true;
         int partitionRole;
         if (allRoles.containsKey("[All]")) {
            partitionRole = (Integer)allRoles.get("[All]");
         } else {
            if (!allRoles.containsKey(partition)) {
               log.debug(user.getUsername() + " has no role for partition " + partition);
               return false;
            }

            partitionRole = (Integer)allRoles.get(partition);
         }

         log.debug(user.getUsername() + " has role " + User.getRoleName(partitionRole) + " on partition " + partition);
         boolean isSuperAdmin = partitionRole == 0;
         boolean isAdminReadOnly = partitionRole == 20;
         boolean isManager = partitionRole == 100;
         boolean isIRuleManager = partitionRole == 510;
         return isSuperAdmin || isAdminReadOnly || isManager || isIRuleManager;
      } else {
         return true;
      }
   }
}