001package org.apache.maven.wagon.providers.ssh; 002/* 003 * Licensed to the Apache Software Foundation (ASF) under one 004 * or more contributor license agreements. See the NOTICE file 005 * distributed with this work for additional information 006 * regarding copyright ownership. The ASF licenses this file 007 * to you under the Apache License, Version 2.0 (the 008 * "License"); you may not use this file except in compliance 009 * with the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, 014 * software distributed under the License is distributed on an 015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 016 * KIND, either express or implied. See the License for the 017 * specific language governing permissions and limitations 018 * under the License. 019 */ 020 021import org.apache.mina.util.Base64; 022import org.apache.sshd.server.PublickeyAuthenticator; 023import org.apache.sshd.server.session.ServerSession; 024import org.codehaus.plexus.util.IOUtil; 025 026import javax.crypto.Cipher; 027import java.io.InputStream; 028import java.math.BigInteger; 029import java.security.KeyFactory; 030import java.security.PrivateKey; 031import java.security.PublicKey; 032import java.security.interfaces.RSAPublicKey; 033import java.security.spec.DSAPublicKeySpec; 034import java.security.spec.RSAPublicKeySpec; 035import java.util.ArrayList; 036import java.util.List; 037 038/** 039 * @author Olivier Lamy 040 */ 041public class TestPublickeyAuthenticator 042 implements PublickeyAuthenticator 043{ 044 public List<PublickeyAuthenticatorRequest> publickeyAuthenticatorRequests = 045 new ArrayList<PublickeyAuthenticatorRequest>(); 046 047 public boolean keyAuthz; 048 049 public TestPublickeyAuthenticator( boolean keyAuthz ) 050 { 051 this.keyAuthz = keyAuthz; 052 } 053 054 public boolean authenticate( String username, PublicKey key, ServerSession session ) 055 { 056 if ( !keyAuthz ) 057 { 058 return false; 059 } 060 try 061 { 062 InputStream is = 063 Thread.currentThread().getContextClassLoader().getResourceAsStream( "ssh-keys/id_rsa.pub" ); 064 PublicKey publicKey = decodePublicKey( IOUtil.toString( is ) ); 065 publickeyAuthenticatorRequests.add( new PublickeyAuthenticatorRequest( username, key ) ); 066 067 return ( (RSAPublicKey) publicKey ).getModulus().equals( ( (RSAPublicKey) publicKey ).getModulus() ); 068 } 069 catch ( Exception e ) 070 { 071 throw new RuntimeException( e.getMessage(), e ); 072 } 073 } 074 075 public static byte[] decrypt( byte[] text, PrivateKey key ) 076 throws Exception 077 { 078 byte[] dectyptedText = null; 079 Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding" ); 080 cipher.init( Cipher.DECRYPT_MODE, key ); 081 dectyptedText = cipher.doFinal( text ); 082 return dectyptedText; 083 } 084 085 public static class PublickeyAuthenticatorRequest 086 { 087 public String username; 088 089 public PublicKey publicKey; 090 091 public PublickeyAuthenticatorRequest( String username, PublicKey publicKey ) 092 { 093 this.username = username; 094 this.publicKey = publicKey; 095 } 096 097 @Override 098 public String toString() 099 { 100 final StringBuilder sb = new StringBuilder(); 101 sb.append( "PublickeyAuthenticatorRequest" ); 102 sb.append( "{username='" ).append( username ).append( '\'' ); 103 sb.append( ", publicKey=" ).append( publicKey ); 104 sb.append( '}' ); 105 return sb.toString(); 106 } 107 } 108 109 private byte[] bytes; 110 111 private int pos; 112 113 public PublicKey decodePublicKey( String keyLine ) 114 throws Exception 115 { 116 bytes = null; 117 pos = 0; 118 119 for ( String part : keyLine.split( " " ) ) 120 { 121 if ( part.startsWith( "AAAA" ) ) 122 { 123 bytes = Base64.decodeBase64( part.getBytes() ); 124 break; 125 } 126 } 127 if ( bytes == null ) 128 { 129 throw new IllegalArgumentException( "no Base64 part to decode" ); 130 } 131 132 String type = decodeType(); 133 if ( type.equals( "ssh-rsa" ) ) 134 { 135 BigInteger e = decodeBigInt(); 136 BigInteger m = decodeBigInt(); 137 RSAPublicKeySpec spec = new RSAPublicKeySpec( m, e ); 138 return KeyFactory.getInstance( "RSA" ).generatePublic( spec ); 139 } 140 else if ( type.equals( "ssh-dss" ) ) 141 { 142 BigInteger p = decodeBigInt(); 143 BigInteger q = decodeBigInt(); 144 BigInteger g = decodeBigInt(); 145 BigInteger y = decodeBigInt(); 146 DSAPublicKeySpec spec = new DSAPublicKeySpec( y, p, q, g ); 147 return KeyFactory.getInstance( "DSA" ).generatePublic( spec ); 148 } 149 else 150 { 151 throw new IllegalArgumentException( "unknown type " + type ); 152 } 153 } 154 155 private String decodeType() 156 { 157 int len = decodeInt(); 158 String type = new String( bytes, pos, len ); 159 pos += len; 160 return type; 161 } 162 163 private int decodeInt() 164 { 165 return ( ( bytes[pos++] & 0xFF ) << 24 ) | ( ( bytes[pos++] & 0xFF ) << 16 ) | ( ( bytes[pos++] & 0xFF ) << 8 ) 166 | ( bytes[pos++] & 0xFF ); 167 } 168 169 private BigInteger decodeBigInt() 170 { 171 int len = decodeInt(); 172 byte[] bigIntBytes = new byte[len]; 173 System.arraycopy( bytes, pos, bigIntBytes, 0, len ); 174 pos += len; 175 return new BigInteger( bigIntBytes ); 176 } 177 178}