| New file |
| | |
| | | package com.gitblit.transport.ssh; |
| | | |
| | | import java.io.Serializable; |
| | | import java.security.PublicKey; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | import org.apache.commons.codec.binary.Base64; |
| | | import org.apache.sshd.common.SshException; |
| | | import org.apache.sshd.common.util.Buffer; |
| | | import org.eclipse.jgit.lib.Constants; |
| | | |
| | | import com.gitblit.Constants.AccessPermission; |
| | | import com.gitblit.utils.StringUtils; |
| | | |
| | | /** |
| | | * Class that encapsulates a public SSH key and it's metadata. |
| | | * |
| | | * @author James Moger |
| | | * |
| | | */ |
| | | public class SshKey implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | private String rawData; |
| | | |
| | | private PublicKey publicKey; |
| | | |
| | | private String comment; |
| | | |
| | | private String fingerprint; |
| | | |
| | | private String toString; |
| | | |
| | | private AccessPermission permission; |
| | | |
| | | public SshKey(String data) { |
| | | this.rawData = data; |
| | | this.permission = AccessPermission.PUSH; |
| | | } |
| | | |
| | | public SshKey(PublicKey key) { |
| | | this.publicKey = key; |
| | | this.comment = ""; |
| | | this.permission = AccessPermission.PUSH; |
| | | } |
| | | |
| | | public PublicKey getPublicKey() { |
| | | if (publicKey == null && rawData != null) { |
| | | // instantiate the public key from the raw key data |
| | | final String[] parts = rawData.split(" ", 3); |
| | | if (comment == null && parts.length == 3) { |
| | | comment = parts[2]; |
| | | } |
| | | final byte[] bin = Base64.decodeBase64(Constants.encodeASCII(parts[1])); |
| | | try { |
| | | publicKey = new Buffer(bin).getRawPublicKey(); |
| | | } catch (SshException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | return publicKey; |
| | | } |
| | | |
| | | public String getAlgorithm() { |
| | | return getPublicKey().getAlgorithm(); |
| | | } |
| | | |
| | | public String getComment() { |
| | | if (comment == null && rawData != null) { |
| | | // extract comment from the raw data |
| | | final String[] parts = rawData.split(" ", 3); |
| | | if (parts.length == 3) { |
| | | comment = parts[2]; |
| | | } |
| | | } |
| | | return comment; |
| | | } |
| | | |
| | | public void setComment(String comment) { |
| | | this.comment = comment; |
| | | if (rawData != null) { |
| | | rawData = null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns true if this key may be used to clone or fetch. |
| | | * |
| | | * @return true if this key can be used to clone or fetch |
| | | */ |
| | | public boolean canClone() { |
| | | return permission.atLeast(AccessPermission.CLONE); |
| | | } |
| | | |
| | | /** |
| | | * Returns true if this key may be used to push changes. |
| | | * |
| | | * @return true if this key can be used to push changes |
| | | */ |
| | | public boolean canPush() { |
| | | return permission.atLeast(AccessPermission.PUSH); |
| | | } |
| | | |
| | | /** |
| | | * Returns the access permission for the key. |
| | | * |
| | | * @return the access permission for the key |
| | | */ |
| | | public AccessPermission getPermission() { |
| | | return permission; |
| | | } |
| | | |
| | | /** |
| | | * Control the access permission assigned to this key. |
| | | * |
| | | * @param value |
| | | */ |
| | | public void setPermission(AccessPermission value) throws IllegalArgumentException { |
| | | List<AccessPermission> permitted = Arrays.asList(AccessPermission.SSHPERMISSIONS); |
| | | if (!permitted.contains(value)) { |
| | | throw new IllegalArgumentException("Illegal SSH public key permission specified: " + value); |
| | | } |
| | | this.permission = value; |
| | | } |
| | | |
| | | public String getRawData() { |
| | | if (rawData == null && publicKey != null) { |
| | | // build the raw data manually from the public key |
| | | Buffer buf = new Buffer(); |
| | | |
| | | // 1: identify the algorithm |
| | | buf.putRawPublicKey(publicKey); |
| | | String alg = buf.getString(); |
| | | |
| | | // 2: encode the key |
| | | buf.clear(); |
| | | buf.putPublicKey(publicKey); |
| | | String b64 = Base64.encodeBase64String(buf.getBytes()); |
| | | |
| | | String c = getComment(); |
| | | rawData = alg + " " + b64 + (StringUtils.isEmpty(c) ? "" : (" " + c)); |
| | | } |
| | | return rawData; |
| | | } |
| | | |
| | | public String getFingerprint() { |
| | | if (fingerprint == null) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | // append the key hash as colon-separated pairs |
| | | String hash; |
| | | if (rawData != null) { |
| | | final String[] parts = rawData.split(" ", 3); |
| | | final byte [] bin = Base64.decodeBase64(Constants.encodeASCII(parts[1])); |
| | | hash = StringUtils.getMD5(bin); |
| | | } else { |
| | | // TODO calculate the correct hash from a PublicKey instance |
| | | hash = StringUtils.getMD5(getPublicKey().getEncoded()); |
| | | } |
| | | for (int i = 0; i < hash.length(); i += 2) { |
| | | sb.append(hash.charAt(i)).append(hash.charAt(i + 1)).append(':'); |
| | | } |
| | | sb.setLength(sb.length() - 1); |
| | | fingerprint = sb.toString(); |
| | | } |
| | | return fingerprint; |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(Object o) { |
| | | if (o instanceof PublicKey) { |
| | | return getPublicKey().equals(o); |
| | | } else if (o instanceof SshKey) { |
| | | return getPublicKey().equals(((SshKey) o).getPublicKey()); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return getPublicKey().hashCode(); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | if (toString == null) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | // TODO append the keysize |
| | | int keySize = 0; |
| | | if (keySize > 0) { |
| | | sb.append(keySize).append(' '); |
| | | } |
| | | // append fingerprint |
| | | sb.append(' '); |
| | | sb.append(getFingerprint()); |
| | | // append the comment |
| | | String c = getComment(); |
| | | if (!StringUtils.isEmpty(c)) { |
| | | sb.append(' '); |
| | | sb.append(c); |
| | | } |
| | | // append algorithm |
| | | String alg = getAlgorithm(); |
| | | if (!StringUtils.isEmpty(alg)) { |
| | | sb.append(" (").append(alg).append(")"); |
| | | } |
| | | toString = sb.toString(); |
| | | } |
| | | return toString; |
| | | } |
| | | } |