001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.apache.hadoop.security.rpcauth;
020
021import java.io.DataOutput;
022import java.io.IOException;
023import java.util.Map;
024
025import javax.security.auth.callback.CallbackHandler;
026import javax.security.sasl.Sasl;
027import javax.security.sasl.SaslClient;
028import javax.security.sasl.SaslClientFactory;
029import javax.security.sasl.SaslException;
030
031import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
032
033public class FakeKerberosAuthMethod extends RpcAuthMethod {
034  private static final String FAKE_SASL_MECH_NAME = "FAKE-SASL-MECHANISM";
035  private static final byte KERBEROS_AUTH_CODE = 81;
036
037  static {
038    java.security.Security.addProvider(new FakeSaslProvider());
039  }
040
041  static final RpcAuthMethod INSTANCE = new FakeKerberosAuthMethod();
042  private FakeKerberosAuthMethod() {
043    super((byte) 0xff, "fake", FAKE_SASL_MECH_NAME, AuthenticationMethod.SIMPLE);
044  }
045
046
047  private static final String[] LOGIN_MODULES = {
048    "org.apache.hadoop.security.login.PermissiveLoginModule"
049  };
050  @Override
051  public String[] loginModules() {
052    return LOGIN_MODULES;
053  }
054
055  /** Write to out. */
056  @Override
057  public void write(DataOutput out) throws IOException {
058    out.write(KERBEROS_AUTH_CODE);
059  }
060
061  @Override
062  public boolean isSasl() {
063    return true;
064  }
065
066  @Override
067  public SaslClient createSaslClient(final Map<String, Object> saslProperties)
068      throws IOException {
069    return Sasl.createSaslClient(new String[] {mechanismName},
070      null, null, null, saslProperties, null);
071 }
072
073  @SuppressWarnings("serial")
074  public static class FakeSaslProvider extends java.security.Provider {
075    public FakeSaslProvider() {
076      super("FakeSasl", 1.0, "Fake SASL provider");
077      put("SaslClientFactory." + FAKE_SASL_MECH_NAME, FakeSaslClientFactory.class.getName());
078    }
079  }
080
081  public static class FakeSaslClientFactory implements SaslClientFactory {
082
083    @Override
084    public String[] getMechanismNames(Map<String, ?> props) {
085      return new String[] { FAKE_SASL_MECH_NAME };
086    }
087
088    @Override
089    public SaslClient createSaslClient(String[] mechanisms,
090        String authorizationId, String protocol, String serverName,
091        Map<String, ?> props, CallbackHandler cbh) throws SaslException {
092      if ( mechanisms != null ) {
093        for ( String mechanism : mechanisms ) {
094          if (FAKE_SASL_MECH_NAME.equals(mechanism)) {
095            return new FakeSaslClient();
096          }
097        }
098      }
099      return null;
100    }
101  }
102
103  public static class FakeSaslClient implements SaslClient {
104    private boolean firstPass = true;
105
106    @Override
107    public String getMechanismName() {
108      return FAKE_SASL_MECH_NAME;
109    }
110
111    @Override
112    public boolean hasInitialResponse() {
113      return true;
114    }
115
116    private static final byte[] FAKE_TOKEN = {'F', 'A', 'K', 'E', 'T', 'O', 'K', 'E', 'N'};
117    @Override
118    public byte[] evaluateChallenge(byte[] challenge) throws SaslException {
119      return FAKE_TOKEN;
120    }
121
122    @Override
123    public boolean isComplete() {
124      if (firstPass) {
125        firstPass = false;
126        return false;
127      }
128      return true;
129    }
130
131    @Override
132    public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException {
133      return null;
134    }
135
136    @Override
137    public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException {
138      return null;
139    }
140
141    @Override
142    public Object getNegotiatedProperty(String propName) {
143      return null;
144    }
145
146    @Override
147    public void dispose() throws SaslException {
148    }
149  }
150}