Пример #1
0
  @Override
  public Header authenticate(
      final Credentials credentials, final HttpRequest request, final HttpContext context)
      throws AuthenticationException {
    Args.notNull(request, "HTTP request");
    switch (state) {
      case UNINITIATED:
        throw new AuthenticationException(
            getSchemeName() + " authentication has not been initiated");
      case FAILED:
        throw new AuthenticationException(getSchemeName() + " authentication has failed");
      case CHALLENGE_RECEIVED:
        try {
          final HttpRoute route = (HttpRoute) context.getAttribute(HttpClientContext.HTTP_ROUTE);
          if (route == null) {
            throw new AuthenticationException("Connection route is not available");
          }
          HttpHost host;
          if (isProxy()) {
            host = route.getProxyHost();
            if (host == null) {
              host = route.getTargetHost();
            }
          } else {
            host = route.getTargetHost();
          }
          final String authServer;
          String hostname = host.getHostName();

          if (this.useCanonicalHostname) {
            try {
              // TODO: uncomment this statement and delete the resolveCanonicalHostname,
              // TODO: as soon canonical hostname resolving is implemented in the
              // SystemDefaultDnsResolver
              // final DnsResolver dnsResolver = SystemDefaultDnsResolver.INSTANCE;
              // hostname = dnsResolver.resolveCanonicalHostname(host.getHostName());
              hostname = resolveCanonicalHostname(hostname);
            } catch (UnknownHostException ignore) {
            }
          }
          if (this.stripPort) { // || host.getPort()==80 || host.getPort()==443) {
            authServer = hostname;
          } else {
            authServer = hostname + ":" + host.getPort();
          }

          if (log.isDebugEnabled()) {
            log.debug("init " + authServer);
          }
          token = generateToken(token, authServer, credentials);
          state = State.TOKEN_GENERATED;
        } catch (final GSSException gsse) {
          state = State.FAILED;
          if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL
              || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED) {
            throw new InvalidCredentialsException(gsse.getMessage(), gsse);
          }
          if (gsse.getMajor() == GSSException.NO_CRED) {
            throw new InvalidCredentialsException(gsse.getMessage(), gsse);
          }
          if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN
              || gsse.getMajor() == GSSException.DUPLICATE_TOKEN
              || gsse.getMajor() == GSSException.OLD_TOKEN) {
            throw new AuthenticationException(gsse.getMessage(), gsse);
          }
          // other error
          throw new AuthenticationException(gsse.getMessage());
        }
      case TOKEN_GENERATED:
        final String tokenstr = new String(base64codec.encode(token));
        if (log.isDebugEnabled()) {
          log.debug("Sending response '" + tokenstr + "' back to the auth server");
        }
        final CharArrayBuffer buffer = new CharArrayBuffer(32);
        if (isProxy()) {
          buffer.append(AUTH.PROXY_AUTH_RESP);
        } else {
          buffer.append(AUTH.WWW_AUTH_RESP);
        }
        buffer.append(": Negotiate ");
        buffer.append(tokenstr);
        return new BufferedHeader(buffer);
      default:
        throw new IllegalStateException("Illegal state: " + state);
    }
  }
Пример #2
0
  public int initSecContext(InputStream inStream, OutputStream outStream) throws GSSException {

    if (mechCtxt != null && currentState != IN_PROGRESS) {
      throw new GSSExceptionImpl(GSSException.FAILURE, "Illegal call to initSecContext");
    }

    GSSHeader gssHeader = null;
    int inTokenLen = -1;
    GSSCredentialSpi credElement = null;
    boolean firstToken = false;

    try {
      if (mechCtxt == null) {
        if (myCred != null) {
          try {
            credElement = myCred.getElement(mechOid, true);
          } catch (GSSException ge) {
            if (GSSUtil.isSpNegoMech(mechOid) && ge.getMajor() == GSSException.NO_CRED) {
              credElement = myCred.getElement(myCred.getMechs()[0], true);
            } else {
              throw ge;
            }
          }
        }
        GSSNameSpi nameElement = targName.getElement(mechOid);
        mechCtxt = gssManager.getMechanismContext(nameElement, credElement, reqLifetime, mechOid);
        mechCtxt.requestConf(reqConfState);
        mechCtxt.requestInteg(reqIntegState);
        mechCtxt.requestCredDeleg(reqCredDelegState);
        mechCtxt.requestMutualAuth(reqMutualAuthState);
        mechCtxt.requestReplayDet(reqReplayDetState);
        mechCtxt.requestSequenceDet(reqSequenceDetState);
        mechCtxt.requestAnonymity(reqAnonState);
        mechCtxt.setChannelBinding(channelBindings);
        mechCtxt.requestDelegPolicy(reqDelegPolicyState);

        objId = new ObjectIdentifier(mechOid.toString());

        currentState = IN_PROGRESS;
        firstToken = true;
      } else {
        if (mechCtxt.getProvider().getName().equals("SunNativeGSS")
            || GSSUtil.isSpNegoMech(mechOid)) {
          // do not parse GSS header for native provider or SPNEGO
          // mech
        } else {
          // parse GSS header
          gssHeader = new GSSHeader(inStream);
          if (!gssHeader.getOid().equals((Object) objId))
            throw new GSSExceptionImpl(
                GSSException.DEFECTIVE_TOKEN,
                "Mechanism not equal to " + mechOid.toString() + " in initSecContext token");
          inTokenLen = gssHeader.getMechTokenLength();
        }
      }

      byte[] obuf = mechCtxt.initSecContext(inStream, inTokenLen);

      int retVal = 0;

      if (obuf != null) {
        retVal = obuf.length;
        if (mechCtxt.getProvider().getName().equals("SunNativeGSS")
            || (!firstToken && GSSUtil.isSpNegoMech(mechOid))) {
          // do not add GSS header for native provider or SPNEGO
          // except for the first SPNEGO token
        } else {
          // add GSS header
          gssHeader = new GSSHeader(objId, obuf.length);
          retVal += gssHeader.encode(outStream);
        }
        outStream.write(obuf);
      }

      if (mechCtxt.isEstablished()) currentState = READY;

      return retVal;

    } catch (IOException e) {
      throw new GSSExceptionImpl(GSSException.DEFECTIVE_TOKEN, e.getMessage());
    }
  }
  public String generateToken(String authServer) throws Throwable {

    try {
      if (this.stripPort) {
        authServer = authServer.substring(0, authServer.indexOf(":"));
      }

      if (log.isDebugEnabled()) {
        log.debug("init " + authServer);
      }
      /* Using the SPNEGO OID is the correct method.
       * Kerberos v5 works for IIS but not JBoss. Unwrapping
       * the initial token when using SPNEGO OID looks like what is
       * described here...
       *
       * http://msdn.microsoft.com/en-us/library/ms995330.aspx
       *
       * Another helpful URL...
       *
       * http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/tsec_SPNEGO_token.html
       *
       * Unfortunately SPNEGO is JRE >=1.6.
       */

      /** Try SPNEGO by default, fall back to Kerberos later if error */
      negotiationOid = new Oid(SPNEGO_OID);

      boolean tryKerberos = false;
      try {
        GSSManager manager = GSSManager.getInstance();
        GSSName serverName = manager.createName("HTTP/" + authServer, null);
        gssContext =
            manager.createContext(
                serverName.canonicalize(negotiationOid),
                negotiationOid,
                null,
                GSSContext.DEFAULT_LIFETIME);
        gssContext.requestMutualAuth(true);
        gssContext.requestCredDeleg(true);
      } catch (GSSException ex) {
        log.error("generateToken", ex);
        // BAD MECH means we are likely to be using 1.5, fall back to Kerberos MECH.
        // Rethrow any other exception.
        if (ex.getMajor() == GSSException.BAD_MECH) {
          log.debug("GSSException BAD_MECH, retry with Kerberos MECH");
          tryKerberos = true;
        } else {
          throw ex;
        }
      }
      if (tryKerberos) {
        /* Kerberos v5 GSS-API mechanism defined in RFC 1964.*/
        log.debug("Using Kerberos MECH " + KERBEROS_OID);
        negotiationOid = new Oid(KERBEROS_OID);
        GSSManager manager = GSSManager.getInstance();
        GSSName serverName = manager.createName("HTTP/" + authServer, null);
        gssContext =
            manager.createContext(
                serverName.canonicalize(negotiationOid),
                negotiationOid,
                null,
                GSSContext.DEFAULT_LIFETIME);
        gssContext.requestMutualAuth(true);
        gssContext.requestCredDeleg(true);
      }
      if (token == null) {
        token = new byte[0];
      }
      token = gssContext.initSecContext(token, 0, token.length);
      if (token == null) {
        throw new Exception("GSS security context initialization failed");
      }

      /*
       * IIS accepts Kerberos and SPNEGO tokens. Some other servers Jboss, Glassfish?
       * seem to only accept SPNEGO. Below wraps Kerberos into SPNEGO token.
       */
      if (spengoGenerator != null && negotiationOid.toString().equals(KERBEROS_OID)) {
        token = spengoGenerator.generateSpnegoDERObject(token);
      }

      String tokenstr = new String(Base64.encode(token));
      if (log.isDebugEnabled()) {
        log.debug("Sending response '" + tokenstr + "' back to the auth server");
      }
      return "Negotiate " + tokenstr;
    } catch (GSSException gsse) {
      log.error("generateToken", gsse);
      if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL
          || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED)
        throw new Exception(gsse.getMessage(), gsse);
      if (gsse.getMajor() == GSSException.NO_CRED) throw new Exception(gsse.getMessage(), gsse);
      if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN
          || gsse.getMajor() == GSSException.DUPLICATE_TOKEN
          || gsse.getMajor() == GSSException.OLD_TOKEN)
        throw new Exception(gsse.getMessage(), gsse);
      // other error
      throw new Exception(gsse.getMessage());
    } catch (IOException ex) {
      throw new Exception(ex.getMessage());
    }
  }
Пример #4
0
  /**
   * Processes the authentication request.
   *
   * @param callbacks
   * @param state
   * @return -1 as succeeded; 0 as failed.
   * @exception AuthLoginException upon any failure.
   */
  public int process(Callback[] callbacks, int state) throws AuthLoginException {
    int result = ISAuthConstants.LOGIN_IGNORE;

    if (!getConfigParams()) {
      initWindowsDesktopSSOAuth(options);
    }

    // retrieve the spnego token
    byte[] spnegoToken = getSPNEGOTokenFromHTTPRequest(getHttpServletRequest());
    if (spnegoToken == null) {
      spnegoToken = getSPNEGOTokenFromCallback(callbacks);
    }

    if (spnegoToken == null) {
      debug.message("spnego token is not valid.");
      throw new AuthLoginException(amAuthWindowsDesktopSSO, "token", null);
    }

    if (debug.messageEnabled()) {
      debug.message(
          "SPNEGO token: \n" + DerValue.printByteArray(spnegoToken, 0, spnegoToken.length));
    }
    // parse the spnego token and extract the kerberos mech token from it
    final byte[] kerberosToken = parseToken(spnegoToken);
    if (kerberosToken == null) {
      debug.message("kerberos token is not valid.");
      throw new AuthLoginException(amAuthWindowsDesktopSSO, "token", null);
    }
    if (debug.messageEnabled()) {
      debug.message(
          "Kerberos token retrieved from SPNEGO token: \n"
              + DerValue.printByteArray(kerberosToken, 0, kerberosToken.length));
    }

    // authenticate the user with the kerberos token
    try {
      authenticateToken(kerberosToken);
      debug.message("WindowsDesktopSSO authentication succeeded.");
      result = ISAuthConstants.LOGIN_SUCCEED;
    } catch (PrivilegedActionException pe) {
      Exception e = extractException(pe);
      if (e instanceof GSSException) {
        int major = ((GSSException) e).getMajor();
        if (major == GSSException.CREDENTIALS_EXPIRED) {
          debug.message("Credential expired. Re-establish credential...");
          serviceLogin();
          try {
            authenticateToken(kerberosToken);
            debug.message("Authentication succeeded with new cred.");
            result = ISAuthConstants.LOGIN_SUCCEED;
          } catch (Exception ee) {
            debug.message("Authentication failed with new cred.");
            throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, ee);
          }
        } else {
          debug.message("Authentication failed with GSSException.");
          throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, e);
        }
      }
    } catch (GSSException e) {
      int major = e.getMajor();
      if (major == GSSException.CREDENTIALS_EXPIRED) {
        debug.message("Credential expired. Re-establish credential...");
        serviceLogin();
        try {
          authenticateToken(kerberosToken);
          debug.message("Authentication succeeded with new cred.");
          result = ISAuthConstants.LOGIN_SUCCEED;
        } catch (Exception ee) {
          debug.message("Authentication failed with new cred.");
          throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, ee);
        }
      } else {
        debug.message("Authentication failed with GSSException.");
        throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, e);
      }
    } catch (AuthLoginException e) {
      throw e;
    } catch (Exception e) {
      debug.message("Authentication failed with generic exception.");
      throw new AuthLoginException(amAuthWindowsDesktopSSO, "auth", null, e);
    }
    return result;
  }
Пример #5
0
  @Override
  public Header authenticate(
      final Credentials credentials, final HttpRequest request, final HttpContext context)
      throws AuthenticationException {
    Args.notNull(request, "HTTP request");
    switch (state) {
      case UNINITIATED:
        throw new AuthenticationException(
            getSchemeName() + " authentication has not been initiated");
      case FAILED:
        throw new AuthenticationException(getSchemeName() + " authentication has failed");
      case CHALLENGE_RECEIVED:
        try {
          final HttpRoute route = (HttpRoute) context.getAttribute(HttpClientContext.HTTP_ROUTE);
          if (route == null) {
            throw new AuthenticationException("Connection route is not available");
          }
          HttpHost host;
          if (isProxy()) {
            host = route.getProxyHost();
            if (host == null) {
              host = route.getTargetHost();
            }
          } else {
            host = route.getTargetHost();
          }
          final String authServer;
          if (!this.stripPort && host.getPort() > 0) {
            authServer = host.toHostString();
          } else {
            authServer = host.getHostName();
          }

          if (log.isDebugEnabled()) {
            log.debug("init " + authServer);
          }
          token = generateToken(token, authServer);
          state = State.TOKEN_GENERATED;
        } catch (final GSSException gsse) {
          state = State.FAILED;
          if (gsse.getMajor() == GSSException.DEFECTIVE_CREDENTIAL
              || gsse.getMajor() == GSSException.CREDENTIALS_EXPIRED) {
            throw new InvalidCredentialsException(gsse.getMessage(), gsse);
          }
          if (gsse.getMajor() == GSSException.NO_CRED) {
            throw new InvalidCredentialsException(gsse.getMessage(), gsse);
          }
          if (gsse.getMajor() == GSSException.DEFECTIVE_TOKEN
              || gsse.getMajor() == GSSException.DUPLICATE_TOKEN
              || gsse.getMajor() == GSSException.OLD_TOKEN) {
            throw new AuthenticationException(gsse.getMessage(), gsse);
          }
          // other error
          throw new AuthenticationException(gsse.getMessage());
        }
      case TOKEN_GENERATED:
        final String tokenstr = new String(base64codec.encode(token));
        if (log.isDebugEnabled()) {
          log.debug("Sending response '" + tokenstr + "' back to the auth server");
        }
        final CharArrayBuffer buffer = new CharArrayBuffer(32);
        if (isProxy()) {
          buffer.append(AUTH.PROXY_AUTH_RESP);
        } else {
          buffer.append(AUTH.WWW_AUTH_RESP);
        }
        buffer.append(": Negotiate ");
        buffer.append(tokenstr);
        return new BufferedHeader(buffer);
      default:
        throw new IllegalStateException("Illegal state: " + state);
    }
  }