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 try 062 { 063 InputStream is = 064 Thread.currentThread().getContextClassLoader().getResourceAsStream( "ssh-keys/id_rsa.pub" ); 065 PublicKey publicKey = decodePublicKey( IOUtil.toString( is ) ); 066 publickeyAuthenticatorRequests.add( new PublickeyAuthenticatorRequest( username, key ) ); 067 068 return ( (RSAPublicKey) publicKey ).getModulus().equals( ( (RSAPublicKey) publicKey ).getModulus() ); 069 } 070 catch ( Exception e ) 071 { 072 throw new RuntimeException( e.getMessage(), e ); 073 } 074 } 075 076 public static byte[] decrypt( byte[] text, PrivateKey key ) 077 throws Exception 078 { 079 byte[] dectyptedText = null; 080 Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding" ); 081 cipher.init( Cipher.DECRYPT_MODE, key ); 082 dectyptedText = cipher.doFinal( text ); 083 return dectyptedText; 084 } 085 086 /** 087 * 088 */ 089 public static class PublickeyAuthenticatorRequest 090 { 091 private String username; 092 093 private PublicKey publicKey; 094 095 public PublickeyAuthenticatorRequest( String username, PublicKey publicKey ) 096 { 097 this.username = username; 098 this.publicKey = publicKey; 099 } 100 101 @Override 102 public String toString() 103 { 104 final StringBuilder sb = new StringBuilder(); 105 sb.append( "PublickeyAuthenticatorRequest" ); 106 sb.append( "{username='" ).append( username ).append( '\'' ); 107 sb.append( ", publicKey=" ).append( publicKey ); 108 sb.append( '}' ); 109 return sb.toString(); 110 } 111 } 112 113 private byte[] bytes; 114 115 private int pos; 116 117 public PublicKey decodePublicKey( String keyLine ) 118 throws Exception 119 { 120 bytes = null; 121 pos = 0; 122 123 for ( String part : keyLine.split( " " ) ) 124 { 125 if ( part.startsWith( "AAAA" ) ) 126 { 127 bytes = Base64.decodeBase64( part.getBytes() ); 128 break; 129 } 130 } 131 if ( bytes == null ) 132 { 133 throw new IllegalArgumentException( "no Base64 part to decode" ); 134 } 135 136 String type = decodeType(); 137 if ( type.equals( "ssh-rsa" ) ) 138 { 139 BigInteger e = decodeBigInt(); 140 BigInteger m = decodeBigInt(); 141 RSAPublicKeySpec spec = new RSAPublicKeySpec( m, e ); 142 return KeyFactory.getInstance( "RSA" ).generatePublic( spec ); 143 } 144 else if ( type.equals( "ssh-dss" ) ) 145 { 146 BigInteger p = decodeBigInt(); 147 BigInteger q = decodeBigInt(); 148 BigInteger g = decodeBigInt(); 149 BigInteger y = decodeBigInt(); 150 DSAPublicKeySpec spec = new DSAPublicKeySpec( y, p, q, g ); 151 return KeyFactory.getInstance( "DSA" ).generatePublic( spec ); 152 } 153 else 154 { 155 throw new IllegalArgumentException( "unknown type " + type ); 156 } 157 } 158 159 private String decodeType() 160 { 161 int len = decodeInt(); 162 String type = new String( bytes, pos, len ); 163 pos += len; 164 return type; 165 } 166 167 private int decodeInt() 168 { 169 // CHECKSTYLE_OFF: MagicNumber 170 return ( ( bytes[pos++] & 0xFF ) << 24 ) | ( ( bytes[pos++] & 0xFF ) << 16 ) | ( ( bytes[pos++] & 0xFF ) << 8 ) 171 | ( bytes[pos++] & 0xFF ); 172 // CHECKSTYLE_ON: MagicNumber 173 } 174 175 private BigInteger decodeBigInt() 176 { 177 int len = decodeInt(); 178 byte[] bigIntBytes = new byte[len]; 179 System.arraycopy( bytes, pos, bigIntBytes, 0, len ); 180 pos += len; 181 return new BigInteger( bigIntBytes ); 182 } 183 184}