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.hbase.security.token;
020
021import java.io.DataInput;
022import java.io.DataOutput;
023import java.io.IOException;
024
025import org.apache.yetus.audience.InterfaceAudience;
026import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
027import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos;
028import org.apache.hadoop.io.Text;
029import org.apache.hadoop.security.UserGroupInformation;
030import org.apache.hadoop.security.token.TokenIdentifier;
031
032import com.google.protobuf.ByteString;
033
034/**
035 * Represents the identity information stored in an HBase authentication token.
036 */
037@InterfaceAudience.Private
038public class AuthenticationTokenIdentifier extends TokenIdentifier {
039  public static final Text AUTH_TOKEN_TYPE = new Text("HBASE_AUTH_TOKEN");
040
041  protected String username;
042  protected int keyId;
043  protected long issueDate;
044  protected long expirationDate;
045  protected long sequenceNumber;
046
047  public AuthenticationTokenIdentifier() {
048  }
049
050  public AuthenticationTokenIdentifier(String username) {
051    this.username = username;
052  }
053
054  public AuthenticationTokenIdentifier(String username, int keyId,
055      long issueDate, long expirationDate) {
056    this.username = username;
057    this.keyId = keyId;
058    this.issueDate = issueDate;
059    this.expirationDate = expirationDate;
060  }
061
062  @Override
063  public Text getKind() {
064    return AUTH_TOKEN_TYPE;
065  }
066
067  @Override
068  public UserGroupInformation getUser() {
069    if (username == null || "".equals(username)) {
070      return null;
071    }
072    return UserGroupInformation.createRemoteUser(username);
073  }
074
075  public String getUsername() {
076    return username;
077  }
078
079  void setUsername(String name) {
080    this.username = name;
081  }
082
083  public int getKeyId() {
084    return keyId;
085  }
086
087  void setKeyId(int id) {
088    this.keyId = id;
089  }
090
091  public long getIssueDate() {
092    return issueDate;
093  }
094
095  void setIssueDate(long timestamp) {
096    this.issueDate = timestamp;
097  }
098
099  public long getExpirationDate() {
100    return expirationDate;
101  }
102
103  void setExpirationDate(long timestamp) {
104    this.expirationDate = timestamp;
105  }
106
107  public long getSequenceNumber() {
108    return sequenceNumber;
109  }
110
111  void setSequenceNumber(long seq) {
112    this.sequenceNumber = seq;
113  }
114
115  public byte[] toBytes() {
116    AuthenticationProtos.TokenIdentifier.Builder builder =
117        AuthenticationProtos.TokenIdentifier.newBuilder();
118    builder.setKind(AuthenticationProtos.TokenIdentifier.Kind.HBASE_AUTH_TOKEN);
119    if (username != null) {
120      builder.setUsername(ByteString.copyFromUtf8(username));
121    }
122    builder.setIssueDate(issueDate)
123        .setExpirationDate(expirationDate)
124        .setKeyId(keyId)
125        .setSequenceNumber(sequenceNumber);
126    return builder.build().toByteArray();
127  }
128
129  @Override
130  public void write(DataOutput out) throws IOException {
131    byte[] pbBytes = toBytes();
132    out.writeInt(pbBytes.length);
133    out.write(pbBytes);
134  }
135
136  @Override
137  public void readFields(DataInput in) throws IOException {
138    int len = in.readInt();
139    byte[] inBytes = new byte[len];
140    in.readFully(inBytes);
141    AuthenticationProtos.TokenIdentifier.Builder builder =
142      AuthenticationProtos.TokenIdentifier.newBuilder();
143    ProtobufUtil.mergeFrom(builder, inBytes);
144    AuthenticationProtos.TokenIdentifier identifier = builder.build();
145    // sanity check on type
146    if (!identifier.hasKind() ||
147        identifier.getKind() != AuthenticationProtos.TokenIdentifier.Kind.HBASE_AUTH_TOKEN) {
148      throw new IOException("Invalid TokenIdentifier kind from input "+identifier.getKind());
149    }
150
151    // copy the field values
152    if (identifier.hasUsername()) {
153      username = identifier.getUsername().toStringUtf8();
154    }
155    if (identifier.hasKeyId()) {
156      keyId = identifier.getKeyId();
157    }
158    if (identifier.hasIssueDate()) {
159      issueDate = identifier.getIssueDate();
160    }
161    if (identifier.hasExpirationDate()) {
162      expirationDate = identifier.getExpirationDate();
163    }
164    if (identifier.hasSequenceNumber()) {
165      sequenceNumber = identifier.getSequenceNumber();
166    }
167  }
168
169  @Override
170  public boolean equals(Object other) {
171    if (other == null) {
172      return false;
173    }
174    if (other instanceof AuthenticationTokenIdentifier) {
175      AuthenticationTokenIdentifier ident = (AuthenticationTokenIdentifier)other;
176      return sequenceNumber == ident.getSequenceNumber()
177          && keyId == ident.getKeyId()
178          && issueDate == ident.getIssueDate()
179          && expirationDate == ident.getExpirationDate()
180          && (username == null ? ident.getUsername() == null :
181              username.equals(ident.getUsername()));
182    }
183    return false;
184  }
185
186  @Override
187  public int hashCode() {
188    return (int)sequenceNumber;
189  }
190}