View Javadoc
1   package org.apache.maven.wagon.providers.ssh;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.mina.util.Base64;
23  import org.apache.sshd.server.PublickeyAuthenticator;
24  import org.apache.sshd.server.session.ServerSession;
25  import org.codehaus.plexus.util.IOUtil;
26  
27  import javax.crypto.Cipher;
28  import java.io.InputStream;
29  import java.math.BigInteger;
30  import java.security.KeyFactory;
31  import java.security.PrivateKey;
32  import java.security.PublicKey;
33  import java.security.interfaces.RSAPublicKey;
34  import java.security.spec.DSAPublicKeySpec;
35  import java.security.spec.RSAPublicKeySpec;
36  import java.util.ArrayList;
37  import java.util.List;
38  
39  /**
40   * @author Olivier Lamy
41   */
42  public class TestPublickeyAuthenticator
43      implements PublickeyAuthenticator
44  {
45      private List<PublickeyAuthenticatorRequest> publickeyAuthenticatorRequests =
46          new ArrayList<PublickeyAuthenticatorRequest>();
47  
48      private boolean keyAuthz;
49  
50      public TestPublickeyAuthenticator( boolean keyAuthz )
51      {
52          this.keyAuthz = keyAuthz;
53      }
54  
55      public boolean authenticate( String username, PublicKey key, ServerSession session )
56      {
57          if ( !keyAuthz )
58          {
59              return false;
60          }
61          InputStream in = null;
62          try
63          {
64              in = Thread.currentThread().getContextClassLoader().getResourceAsStream( "ssh-keys/id_rsa.pub" );
65              PublicKey publicKey = decodePublicKey( IOUtil.toString( in ) );
66              in.close();
67              in = null;
68  
69              publickeyAuthenticatorRequests.add( new PublickeyAuthenticatorRequest( username, key ) );
70  
71              return ( (RSAPublicKey) publicKey ).getModulus().equals( ( (RSAPublicKey) publicKey ).getModulus() );
72          }
73          catch ( Exception e )
74          {
75              throw new RuntimeException( e.getMessage(), e );
76          }
77          finally
78          {
79              IOUtil.close( in );
80          }
81      }
82  
83      public static byte[] decrypt( byte[] text, PrivateKey key )
84          throws Exception
85      {
86          byte[] dectyptedText = null;
87          Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding" );
88          cipher.init( Cipher.DECRYPT_MODE, key );
89          dectyptedText = cipher.doFinal( text );
90          return dectyptedText;
91      }
92  
93      /**
94       * 
95       */
96      public static class PublickeyAuthenticatorRequest
97      {
98          private String username;
99  
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 }