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