private String getWebSocketAccept(String key) {
   synchronized (sha1Helper) {
     sha1Helper.reset();
     sha1Helper.update(key.getBytes(B2CConverter.ISO_8859_1));
     return Base64.encode(sha1Helper.digest(WS_ACCEPT));
   }
 }
  private void doTestBasic(
      String user,
      String pwd,
      String uri,
      boolean verifyAuthSchemeCase,
      boolean expectedReject1,
      int expectedRC1,
      boolean expectedReject2,
      int expectedRC2)
      throws Exception {

    // the first access attempt should be challenged
    Map<String, List<String>> reqHeaders1 = new HashMap<>();
    Map<String, List<String>> respHeaders1 = new HashMap<>();

    ByteChunk bc = new ByteChunk();
    int rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders1, respHeaders1);

    if (expectedReject1) {
      assertEquals(expectedRC1, rc);
      assertTrue(bc.getLength() > 0);
    } else {
      assertEquals(200, rc);
      assertEquals("OK", bc.toString());
      return;
    }

    // the second access attempt should be sucessful
    String credentials = user + ":" + pwd;
    byte[] credentialsBytes = ByteChunk.convertToBytes(credentials);
    String base64auth = Base64.encode(credentialsBytes);
    String authScheme = verifyAuthSchemeCase ? "bAsIc " : "Basic ";
    String authLine = authScheme + base64auth;

    List<String> auth = new ArrayList<>();
    auth.add(authLine);
    Map<String, List<String>> reqHeaders2 = new HashMap<>();
    reqHeaders2.put(CLIENT_AUTH_HEADER, auth);

    Map<String, List<String>> respHeaders2 = new HashMap<>();

    bc.recycle();
    rc = getUrl(HTTP_PREFIX + getPort() + uri, bc, reqHeaders2, respHeaders2);

    if (expectedReject2) {
      assertEquals(expectedRC2, rc);
      assertTrue(bc.getLength() > 0);
    } else {
      assertEquals(200, rc);
      assertEquals("OK", bc.toString());
    }
  }
  /**
   * Execute the specified command, based on the configured properties. The input stream will be
   * closed upon completion of this task, whether it was executed successfully or not.
   *
   * @param command Command to be executed
   * @param istream InputStream to include in an HTTP PUT, if any
   * @param contentType Content type to specify for the input, if any
   * @param contentLength Content length to specify for the input, if any
   * @exception BuildException if an error occurs
   */
  public void execute(String command, InputStream istream, String contentType, int contentLength)
      throws BuildException {

    URLConnection conn = null;
    InputStreamReader reader = null;
    try {

      // Create a connection for this command
      conn = (new URL(url + command)).openConnection();
      HttpURLConnection hconn = (HttpURLConnection) conn;

      // Set up standard connection characteristics
      hconn.setAllowUserInteraction(false);
      hconn.setDoInput(true);
      hconn.setUseCaches(false);
      if (istream != null) {
        hconn.setDoOutput(true);
        hconn.setRequestMethod("PUT");
        if (contentType != null) {
          hconn.setRequestProperty("Content-Type", contentType);
        }
        if (contentLength >= 0) {
          hconn.setRequestProperty("Content-Length", "" + contentLength);
        }
      } else {
        hconn.setDoOutput(false);
        hconn.setRequestMethod("GET");
      }
      hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0");

      // Set up an authorization header with our credentials
      String input = username + ":" + password;
      String output = new String(Base64.encode(input.getBytes()));
      hconn.setRequestProperty("Authorization", "Basic " + output);

      // Establish the connection with the server
      hconn.connect();

      // Send the request data (if any)
      if (istream != null) {
        BufferedOutputStream ostream = new BufferedOutputStream(hconn.getOutputStream(), 1024);
        byte buffer[] = new byte[1024];
        while (true) {
          int n = istream.read(buffer);
          if (n < 0) {
            break;
          }
          ostream.write(buffer, 0, n);
        }
        ostream.flush();
        ostream.close();
        istream.close();
      }

      // Process the response message
      reader = new InputStreamReader(hconn.getInputStream(), CHARSET);
      StringBuffer buff = new StringBuffer();
      String error = null;
      int msgPriority = Project.MSG_INFO;
      boolean first = true;
      while (true) {
        int ch = reader.read();
        if (ch < 0) {
          break;
        } else if ((ch == '\r') || (ch == '\n')) {
          // in Win \r\n would cause handleOutput() to be called
          // twice, the second time with an empty string,
          // producing blank lines
          if (buff.length() > 0) {
            String line = buff.toString();
            buff.setLength(0);
            if (first) {
              if (!line.startsWith("OK -")) {
                error = line;
                msgPriority = Project.MSG_ERR;
              }
              first = false;
            }
            handleOutput(line, msgPriority);
          }
        } else {
          buff.append((char) ch);
        }
      }
      if (buff.length() > 0) {
        handleOutput(buff.toString(), msgPriority);
      }
      if (error != null && isFailOnError()) {
        // exception should be thrown only if failOnError == true
        // or error line will be logged twice
        throw new BuildException(error);
      }
    } catch (Throwable t) {
      if (isFailOnError()) {
        throw new BuildException(t);
      } else {
        handleErrorOutput(t.getMessage());
      }
    } finally {
      closeRedirector();
      if (reader != null) {
        try {
          reader.close();
        } catch (Throwable u) {;
        }
        reader = null;
      }
      if (istream != null) {
        try {
          istream.close();
        } catch (Throwable u) {;
        }
        istream = null;
      }
    }
  }
  /**
   * Authenticate the user making this request, based on the specified login configuration. Return
   * <code>true</code> if any specified constraint has been satisfied, or <code>false</code> if we
   * have created a response challenge already.
   *
   * @param request Request we are processing
   * @param response Response we are creating
   * @param config Login configuration describing how authentication should be performed
   * @exception IOException if an input/output error occurs
   */
  @Override
  public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config)
      throws IOException {

    // Have we already authenticated someone?
    Principal principal = request.getUserPrincipal();
    String ssoId = (String) request.getNote(Constants.REQ_SSOID_NOTE);
    if (principal != null) {
      if (log.isDebugEnabled()) log.debug("Already authenticated '" + principal.getName() + "'");
      // Associate the session with any existing SSO session
      if (ssoId != null) associate(ssoId, request.getSessionInternal(true));
      return (true);
    }

    // Is there an SSO session against which we can try to reauthenticate?
    if (ssoId != null) {
      if (log.isDebugEnabled())
        log.debug("SSO Id " + ssoId + " set; attempting " + "reauthentication");
      /* Try to reauthenticate using data cached by SSO.  If this fails,
      either the original SSO logon was of DIGEST or SSL (which
      we can't reauthenticate ourselves because there is no
      cached username and password), or the realm denied
      the user's reauthentication for some reason.
      In either case we have to prompt the user for a logon */
      if (reauthenticateFromSSO(ssoId, request)) return true;
    }

    // Validate any credentials already included with this request
    String username = null;
    String password = null;

    MessageBytes authorization =
        request.getCoyoteRequest().getMimeHeaders().getValue("authorization");

    if (authorization != null) {
      authorization.toBytes();
      ByteChunk authorizationBC = authorization.getByteChunk();
      if (authorizationBC.startsWithIgnoreCase("basic ", 0)) {
        authorizationBC.setOffset(authorizationBC.getOffset() + 6);
        // FIXME: Add trimming
        // authorizationBC.trim();

        CharChunk authorizationCC = authorization.getCharChunk();
        Base64.decode(authorizationBC, authorizationCC);

        // Get username and password
        int colon = authorizationCC.indexOf(':');
        if (colon < 0) {
          username = authorizationCC.toString();
        } else {
          char[] buf = authorizationCC.getBuffer();
          username = new String(buf, 0, colon);
          password = new String(buf, colon + 1, authorizationCC.getEnd() - colon - 1);
        }

        authorizationBC.setOffset(authorizationBC.getOffset() - 6);
      }

      principal = context.getRealm().authenticate(username, password);
      if (principal != null) {
        register(request, response, principal, Constants.BASIC_METHOD, username, password);
        return (true);
      }
    }

    StringBuilder value = new StringBuilder(16);
    value.append("Basic realm=\"");
    if (config.getRealmName() == null) {
      value.append(REALM_NAME);
    } else {
      value.append(config.getRealmName());
    }
    value.append('\"');
    response.setHeader(AUTH_HEADER_NAME, value.toString());
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    return (false);
  }