/**
  * Data is only validated on the client side. No Server Side Validation is Performed
  *
  * @param userdata data submitted by user
  */
 public void doPost(HttpServletRequest request, HttpServletResponse response)
     throws ServletException, IOException {
   // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
   ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
   // Attempting to recover username of session that made request
   HttpSession ses = request.getSession(true);
   if (Validate.validateSession(ses)) {
     ShepherdLogManager.setRequestIp(
         request.getRemoteAddr(),
         request.getHeader("X-Forwarded-For"),
         ses.getAttribute("userName").toString());
     log.debug(levelName + " servlet accessed by: " + ses.getAttribute("userName").toString());
     PrintWriter out = response.getWriter();
     out.print(getServletInfo());
     try {
       String userData = request.getParameter("userdata");
       log.debug("User Submitted - " + userData);
       String htmlOutput = new String();
       int userNumber = Integer.parseInt(userData);
       if (userNumber < 0) {
         // Get key and add it to the output
         String userKey =
             Hash.generateUserSolution(levelResult, (String) ses.getAttribute("userName"));
         log.debug("Negative Number Submitted");
         htmlOutput =
             "<h2 class='title'>Validation Bypassed</h2><p>You defeated the lesson validation. Result Key: <a>"
                 + userKey
                 + "</a></p>";
       } else {
         log.debug("Valid Number Submitted");
         htmlOutput =
             "<h2 class='title'>Valid Number Submitted</h2><p>The Number "
                 + userNumber
                 + " is a valid number.";
       }
       log.debug("Outputting HTML");
       out.write(htmlOutput);
     } catch (Exception e) {
       out.write("An Error Occurred! You must be getting funky!");
       log.fatal(levelName + " - " + e.toString());
     }
   } else {
     log.error(levelName + " servlet accessed with no session");
   }
 }
  /**
   * A user with the submitted email address is set a new random password, the password is also
   * returned from the database procedure and is forwards through to the HTTP response. This
   * response is not consumed by the client interface by default, and the user will have to discover
   * it.
   *
   * @param subEmail Sub schema user email address
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
    HttpSession ses = request.getSession(true);

    // Translation Stuff
    Locale locale = new Locale(Validate.validateLanguage(request.getSession()));
    ResourceBundle errors = ResourceBundle.getBundle("i18n.servlets.errors", locale);
    ResourceBundle bundle =
        ResourceBundle.getBundle(
            "i18n.servlets.challenges.sessionManagement.sessionManagement2", locale);

    if (Validate.validateSession(ses)) {
      ShepherdLogManager.setRequestIp(
          request.getRemoteAddr(),
          request.getHeader("X-Forwarded-For"),
          ses.getAttribute("userName").toString());
      log.debug(levelName + " servlet accessed by: " + ses.getAttribute("userName").toString());
      PrintWriter out = response.getWriter();
      out.print(getServletInfo());
      Encoder encoder = ESAPI.encoder();
      String htmlOutput = new String();
      log.debug(levelName + " Servlet accessed");
      try {
        log.debug("Getting Challenge Parameter");
        Object emailObj = request.getParameter("subEmail");
        String subEmail = new String();
        if (emailObj != null) subEmail = (String) emailObj;
        log.debug("subEmail = " + subEmail);

        log.debug("Getting ApplicationRoot");
        String ApplicationRoot = getServletContext().getRealPath("");

        String newPassword = Hash.randomString();
        try {
          Connection conn =
              Database.getChallengeConnection(ApplicationRoot, "BrokenAuthAndSessMangChalTwo");
          log.debug("Checking credentials");
          PreparedStatement callstmt =
              conn.prepareStatement("UPDATE users SET userPassword = SHA(?) WHERE userAddress = ?");
          callstmt.setString(1, newPassword);
          callstmt.setString(2, subEmail);
          log.debug("Executing resetPassword");
          callstmt.execute();
          log.debug("Statement executed");

          log.debug("Committing changes made to database");
          callstmt = conn.prepareStatement("COMMIT");
          callstmt.execute();
          log.debug("Changes committed.");

          htmlOutput = encoder.encodeForHTML(newPassword);
          Database.closeConnection(conn);
        } catch (SQLException e) {
          log.error(levelName + " SQL Error: " + e.toString());
        }
        log.debug("Outputting HTML");
        out.write(bundle.getString("response.changedTo") + " " + htmlOutput);
      } catch (Exception e) {
        out.write(errors.getString("error.funky"));
        log.fatal(levelName + " - " + e.toString());
      }
    } else {
      log.error(levelName + " servlet accessed with no session");
    }
  }
  /**
   * System users are insecurely directed by their user name in a post request parameter. Users can
   * abuse this to retrieve an administrator's information.
   *
   * @param username User name of profile to retrieve
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));

    // Translation Stuff
    Locale locale = new Locale(Validate.validateLanguage(request.getSession()));
    ResourceBundle errors = ResourceBundle.getBundle("i18n.servlets.errors", locale);
    ResourceBundle bundle = ResourceBundle.getBundle("i18n.servlets.lessons.directObject", locale);

    // Attempting to recover username of session that made request
    HttpSession ses = request.getSession(true);
    PrintWriter out = response.getWriter();
    out.print(getServletInfo());
    if (Validate.validateSession(ses)) {
      ShepherdLogManager.setRequestIp(
          request.getRemoteAddr(),
          request.getHeader("X-Forwarded-For"),
          ses.getAttribute("userName").toString());
      log.debug(levelName + " servlet accessed by: " + ses.getAttribute("userName").toString());
      try {
        String userName = request.getParameter("username");
        log.debug("User Submitted - " + userName);
        String ApplicationRoot = getServletContext().getRealPath("");
        log.debug("Servlet root = " + ApplicationRoot);
        String htmlOutput = new String();
        if (userName.equalsIgnoreCase("guest")) {
          log.debug("Guest Profile Found");
          htmlOutput = htmlGuest(bundle);
        } else if (userName.equalsIgnoreCase("admin")) {
          // Get key and add it to the output
          String userKey =
              Hash.generateUserSolution(levelResult, (String) ses.getAttribute("userName"));
          log.debug("Admin Profile Found");
          htmlOutput = htmlAdmin(bundle, userKey);
        } else {
          log.debug("No Profile Found");
          Encoder encoder = ESAPI.encoder();
          htmlOutput =
              "<h2 class='title'>"
                  + bundle.getString("response.user")
                  + ": "
                  + bundle.getString("response.notFound")
                  + "</h2><p>"
                  + bundle.getString("response.user")
                  + " '"
                  + encoder.encodeForHTML(userName)
                  + "' "
                  + bundle.getString("response.couldNotFind")
                  + ".</p>";
        }
        log.debug("Outputting HTML");
        out.write(htmlOutput);
      } catch (Exception e) {
        out.write(errors.getString("error.funky"));
        log.fatal("Insecure Direct Object Lesson Lesson - " + e.toString());
      }
    } else {
      out.write(errors.getString("error.noSession"));
      log.error(levelName + " servlet accessed with no session");
    }
  }
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
    // Attempting to recover username of session that made request
    HttpSession ses = request.getSession(true);
    PrintWriter out = response.getWriter();
    out.print(getServletInfo());

    // Translation Stuff
    Locale locale = new Locale(Validate.validateLanguage(request.getSession()));
    ResourceBundle errors = ResourceBundle.getBundle("i18n.servlets.errors", locale);
    ResourceBundle bundle =
        ResourceBundle.getBundle("i18n.servlets.lessons.securityMisconfig", locale);

    if (Validate.validateSession(ses)) {
      ShepherdLogManager.setRequestIp(
          request.getRemoteAddr(),
          request.getHeader("X-Forwarded-For"),
          ses.getAttribute("userName").toString());
      log.debug(levelName + " servlet accessed by: " + ses.getAttribute("userName").toString());
      try {
        String userName = request.getParameter("userName");
        log.debug("User Name - " + userName);
        String userPass = request.getParameter("userPass");
        log.debug("User Pass - " + userName);
        boolean loggedIn = userName.contentEquals("admin") && userPass.contentEquals("password");
        String htmlOutput = new String();
        if (!loggedIn) {
          if (userName.contentEquals("admin"))
            htmlOutput = bundle.getString("response.incorrectPassword");
          else {
            Encoder encoder = ESAPI.encoder();
            htmlOutput =
                bundle.getString("response.noUserFound")
                    + " \""
                    + encoder.encodeForHTML(userName)
                    + "\"";
          }
          htmlOutput =
              "<h2 class='title'>"
                  + bundle.getString("response.authError")
                  + "</h2><p>"
                  + htmlOutput
                  + "</p>";
        } else {
          // Default username and password were used
          log.debug("User has signed in as admin");
          htmlOutput =
              "<h2 class='title'>"
                  + bundle.getString("response.authSuccess")
                  + "</h2><p>"
                  + bundle.getString("result.youDidIt")
                  + "<br><br>"
                  + bundle.getString("result.key")
                  + ": <a>"
                  + Hash.generateUserSolution(levelResult, ses.getAttribute("userName").toString())
                  + "</a>";
        }
        log.debug("Outputting HTML");
        out.write(htmlOutput);
      } catch (Exception e) {
        out.write(errors.getString("error.funky"));
        log.fatal(levelName + " - " + e.toString());
      }
    } else {
      log.error(levelName + " servlet accessed with no session");
      out.write(bundle.getString("error.noSession"));
    }
  }
  /**
   * Cross Site Request Forgery safe Reflected XSS vulnerability. cannot be remotely exploited, and
   * there fore only is executable against the person initiating the function.
   *
   * @param searchTerm To be spat back out at the user after been encoded for wrong HTML Context
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
    log.debug("Cross-Site Scripting Challenge Four Servlet");
    PrintWriter out = response.getWriter();
    out.print(getServletInfo());

    // Translation Stuff
    Locale locale = new Locale(Validate.validateLanguage(request.getSession()));
    ResourceBundle errors = ResourceBundle.getBundle("i18n.servlets.errors", locale);
    ResourceBundle bundle = ResourceBundle.getBundle("i18n.servlets.challenges.xss.xss4", locale);

    try {
      HttpSession ses = request.getSession(true);
      if (Validate.validateSession(ses)) {
        ShepherdLogManager.setRequestIp(
            request.getRemoteAddr(),
            request.getHeader("X-Forwarded-For"),
            ses.getAttribute("userName").toString());
        log.debug(levelName + " servlet accessed by: " + ses.getAttribute("userName").toString());
        Cookie tokenCookie = Validate.getToken(request.getCookies());
        Object tokenParmeter = request.getParameter("csrfToken");
        if (Validate.validateTokens(tokenCookie, tokenParmeter)) {
          String htmlOutput = new String();
          String userPost = new String();
          String searchTerm = request.getParameter("searchTerm");
          log.debug("User Submitted - " + searchTerm);
          if (!searchTerm.startsWith("http")) {
            searchTerm = "https://www.owasp.org/index.php/OWASP_Security_Shepherd";
            userPost =
                "<a href=\""
                    + searchTerm
                    + "\" alt=\"OWASP Security Shepherd\">"
                    + searchTerm
                    + "</a>";
          } else {

            searchTerm = XssFilter.encodeForHtml(searchTerm);
            userPost =
                "<a href=\"" + searchTerm + "\" alt=\"" + searchTerm + "\">" + searchTerm + "</a>";
            log.debug("After Encoding - " + searchTerm);
            if (FindXSS.search(userPost)) {
              htmlOutput =
                  "<h2 class='title'>"
                      + bundle.getString("result.wellDone")
                      + "</h2>"
                      + "<p>"
                      + bundle.getString("result.youDidIt")
                      + "<br />"
                      + bundle.getString("result.resultKey")
                      + " <a>"
                      + Hash.generateUserSolution(
                          Getter.getModuleResultFromHash(
                              getServletContext().getRealPath(""), levelHash),
                          (String) ses.getAttribute("userName"))
                      + "</a>";
            }
          }
          log.debug("Adding searchTerm to Html: " + searchTerm);
          htmlOutput +=
              "<h2 class='title'>"
                  + bundle.getString("response.yourPost")
                  + "</h2>"
                  + "<p>"
                  + bundle.getString("response.linkPosted")
                  + "</p> "
                  + userPost
                  + "</p>";
          out.write(htmlOutput);
        }
      } else {
        log.error(levelName + " servlet was accessed without a valid session");
        out.write(errors.getString("error.noSession"));
      }
    } catch (Exception e) {
      out.write(errors.getString("error.funky"));
      log.fatal("Cross Site Scripting Challenge 4 - " + e.toString());
    }
  }
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
    log.debug("&&& servlets.module.SolutionSubmit &&&");
    PrintWriter out = response.getWriter();
    out.print(getServletInfo());
    HttpSession ses = request.getSession(true);
    if (Validate.validateSession(ses)) {
      ShepherdLogManager.setRequestIp(
          request.getRemoteAddr(),
          request.getHeader("X-Forwarded-For"),
          ses.getAttribute("userName").toString());
      log.debug("Current User: "******"userName").toString());
      Cookie tokenCookie = Validate.getToken(request.getCookies());
      Object tokenParmeter = request.getParameter("csrfToken");
      if (Validate.validateTokens(tokenCookie, tokenParmeter)) {
        boolean notNull = false;
        String storedResult = null;
        try {
          log.debug("Getting ApplicationRoot");
          String ApplicationRoot = getServletContext().getRealPath("");
          log.debug("Servlet root = " + ApplicationRoot);

          log.debug("Getting Parameters");
          String moduleId = (String) request.getParameter("moduleId");
          ;
          log.debug("moduleId = " + moduleId.toString());
          String solutionKey = (String) request.getParameter("solutionKey");
          ;
          log.debug("solutionKey = " + solutionKey.toString());

          log.debug("Getting session parameters");
          String userId = (String) ses.getAttribute("userStamp");
          String userName = (String) ses.getAttribute("userName");
          log.debug("userId = " + userId);

          // Validation
          notNull = (moduleId != null && solutionKey != null);
          if (notNull) {
            storedResult = Getter.getModuleResult(ApplicationRoot, moduleId);
          }
          if (notNull && storedResult != null) {
            boolean validKey = false;
            // Identify if solution is a user Specific key (Does it need to be decrypted?)
            if (Getter.getModuleKeyType(ApplicationRoot, moduleId))
              validKey = storedResult.compareTo(solutionKey) == 0;
            else {
              String decryptedKey = new String();
              try {
                // Encrypted Solution key,  must be decrypted before compare
                decryptedKey =
                    Hash.decryptUserSpecificSolution(
                        Validate.validateEncryptionKey(userName), solutionKey);
              } catch (Exception e) {
                log.error("Could not decrypt result key: " + e.toString());
                // Key likely could not be decrypted because somebody submitted a string that could
                // not be decrypted.
                // This is a bad submission so they should be warned. String will continue from this
                // point as an empty value and will cause the function to run the Bad Submission
                // procedure
              }
              storedResult +=
                  Hash.getCurrentSalt(); // Add server solution salt to base key before compare with
              // decrypted key
              validKey = storedResult.compareTo(decryptedKey) == 0;
              log.debug("Decrypted Submitted Key: " + decryptedKey);
              log.debug("Stored Expected Key    : " + storedResult);
            }
            if (validKey) {
              log.debug("Correct key submitted, checking that module not already completed");
              String result = Getter.checkPlayerResult(ApplicationRoot, moduleId, userId);
              if (result != null) {
                // If Feedback is enabled, the user must complete another step. This step is
                // continued in FeedbackSubmit.java
                if (FeedbackStatus.isEnabled()) {
                  log.debug("Returning Feedback Form for module: " + result);
                  out.write(
                      "<h2 class=\"title\">Solution Submission Success</h2><br>"
                          + "<p> You are one step away from completing <a>"
                          + encoder.encodeForHTML(result)
                          + "</a>! To complete the level please submit your feedback!"
                          + "</p><br/>"
                          + generateFeedbackForm(moduleId, (String) tokenParmeter, solutionKey));
                } else // Feedback is disabled
                {
                  log.debug("Feedback is disabled, Marking as completed");
                  String htmlOutput = new String();
                  result =
                      Setter.updatePlayerResult(
                          ApplicationRoot, moduleId, userId, "Feedback is Disabled", 1, 1, 1);
                  if (result != null) {
                    ResourceBundle bundle =
                        ResourceBundle.getBundle(
                            "i18n.moduleGenerics.moduleNames",
                            new Locale(Validate.validateLanguage(request.getSession())));
                    String compltedModuleLocalName = bundle.getString(result);
                    log.debug(
                        "Solution Submission for module " + compltedModuleLocalName + " succeeded");
                    htmlOutput =
                        new String(
                            "<h2 class=\"title\">Solution Submission Success</h2><br>"
                                + "<p>"
                                + compltedModuleLocalName
                                + " completed! Congratulations.");
                    htmlOutput += "</p>";
                    // Refresh Side Menu
                    htmlOutput +=
                        FeedbackSubmit.refreshMenuScript(
                            encoder.encodeForHTML((String) tokenParmeter), "Refresh Error");
                    log.debug("Resetting user's Bad Submisison count to 0");
                    Setter.resetBadSubmission(ApplicationRoot, userId);
                    out.write(htmlOutput);
                  } else {
                    htmlOutput = new String("Could not update user result");
                    out.print(
                        "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                            + "<p><font color=\"red\">"
                            + "Sorry but an error Occurred!"
                            + "</font></p>");
                  }
                }
              } else {
                log.error("User has completed this module before. Returning Error");
                out.write(
                    "<h2 class=\"title\">Haven't You Done This Already?</h2><br>"
                        + "<p>"
                        + "Our records say you have already completed this module! Go try another one!"
                        + "</p>");
              }
            } else {
              log.error("Incorrect key submitted, returning error");
              out.print(
                  "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                      + "<p><font color=\"red\">"
                      + "Incorrect Solution Key Submitted.<br><br>You have limited amounts of incorrect key submissions before you will loose 10% of your points. Contact the OWASP Security Shepherd if you think you have found the correct key but it is failing you."
                      + "</font></p>");

              log.error("Invoking Bad Submission procedure...");
              Setter.incrementBadSubmission(ApplicationRoot, userId);
              log.error(userName + " has been warned and potentially has lost points");
            }
          } else {
            // Validation Error Responses
            String errorMessage = "An Error Occurred: ";
            if (!notNull) {
              log.error("Null values detected");
              errorMessage += "Invalid Request. Please try again";
            } else if (storedResult == null) {
              log.error("Module not found");
              errorMessage += "Module Not Found. Please try again";
            }
            out.print(
                "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                    + "<p><font color=\"red\">"
                    + encoder.encodeForHTML(errorMessage)
                    + "</font><p>");
          }
        } catch (Exception e) {
          log.error("Solution Submission Error: " + e.toString());
          out.print(
              "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                  + "<p>"
                  + "<font color=\"red\">An error Occurred! Please try again.</font>"
                  + "<p>");
        }
      } else {
        log.debug("CSRF Tokens did not match");
        out.print(
            "<h2 class=\"title\">Solution Submission Failure</h2><br>"
                + "<p>"
                + "<font color=\"red\">An error Occurred! Please try again.</font>"
                + "<p>");
      }
    } else {
      out.print(
          "<h2 class=\"title\">Solution Submission Failure</h2><br>"
              + "<p>"
              + "<font color=\"red\">An error Occurred! Please Log in!</font>"
              + "<p>");
    }
    log.debug("&&& END SolutionSubmit &&&");
  }
  /**
   * Shopping cart addition algorithm is vulnerable to integer overflow. If the cost is high enough,
   * the final value will go negative.
   */
  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    // Setting IpAddress To Log and taking header for original IP if forwarded from proxy
    ShepherdLogManager.setRequestIp(request.getRemoteAddr(), request.getHeader("X-Forwarded-For"));
    HttpSession ses = request.getSession(true);
    if (Validate.validateSession(ses)) {
      // Translation Stuff
      Locale locale = new Locale(Validate.validateLanguage(request.getSession()));
      ResourceBundle bundle =
          ResourceBundle.getBundle(
              "i18n.servlets.challenges.poorValidation.poorValidationStrings", locale);

      String currentUser = ses.getAttribute("userName").toString();
      ShepherdLogManager.setRequestIp(
          request.getRemoteAddr(), request.getHeader("X-Forwarded-For"), currentUser);
      log.debug(levelName + " servlet accessed by: " + ses.getAttribute("userName").toString());
      PrintWriter out = response.getWriter();
      out.print(getServletInfo());
      String htmlOutput = new String();
      try {
        int megustaAmount = validateAmount(Integer.parseInt(request.getParameter("megustaAmount")));
        log.debug("megustaAmount - " + megustaAmount);
        int trollAmount = validateAmount(Integer.parseInt(request.getParameter("trollAmount")));
        log.debug("trollAmount - " + trollAmount);
        int rageAmount = validateAmount(Integer.parseInt(request.getParameter("rageAmount")));
        log.debug("rageAmount - " + rageAmount);
        int notBadAmount = validateAmount(Integer.parseInt(request.getParameter("notBadAmount")));
        log.debug("notBadAmount - " + notBadAmount);

        // Working out costs
        int megustaCost = megustaAmount * 30;
        int trollCost = trollAmount * 3000;
        int rageCost = rageAmount * 45;
        int notBadCost = notBadAmount * 15;

        htmlOutput = new String();

        // Work Out Final Cost
        int finalCost = megustaCost + rageCost + notBadCost + trollCost;

        // Output Order
        htmlOutput =
            "<h3 class='title'>"
                + bundle.getString("poorValidation.orderComplete")
                + "</h3>"
                + "<p>"
                + bundle.getString("poorValidation.orderComplete.message")
                + "</p><br/>"
                + "<p>"
                + bundle.getString("poorValidation.orderTotal")
                + " <a><strong>$"
                + finalCost
                + "</strong></a></p>";
        if (finalCost <= 0 && trollAmount > 0) {
          htmlOutput +=
              "<br><p>"
                  + bundle.getString("poorValidation.freeTrolls")
                  + " - "
                  + Hash.generateUserSolution(levelSolution, currentUser)
                  + "</p>";
        }
      } catch (Exception e) {
        log.debug("Didn't complete order: " + e.toString());
        htmlOutput += "<p>" + bundle.getString("poorValidation.badOrder") + "</p>";
      }
      try {
        Thread.sleep(1000);
      } catch (Exception e) {
        log.error("Failed to Pause: " + e.toString());
      }
      out.write(htmlOutput);
    } else {
      log.error(levelName + " servlet accessed with no session");
    }
  }