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          try
62          {
63              InputStream is =
64                  Thread.currentThread().getContextClassLoader().getResourceAsStream( "ssh-keys/id_rsa.pub" );
65              PublicKey publicKey = decodePublicKey( IOUtil.toString( is ) );
66              publickeyAuthenticatorRequests.add( new PublickeyAuthenticatorRequest( username, key ) );
67  
68              return ( (RSAPublicKey) publicKey ).getModulus().equals( ( (RSAPublicKey) publicKey ).getModulus() );
69          }
70          catch ( Exception e )
71          {
72              throw new RuntimeException( e.getMessage(), e );
73          }
74      }
75  
76      public static byte[] decrypt( byte[] text, PrivateKey key )
77          throws Exception
78      {
79          byte[] dectyptedText = null;
80          Cipher cipher = Cipher.getInstance( "RSA/ECB/PKCS1Padding" );
81          cipher.init( Cipher.DECRYPT_MODE, key );
82          dectyptedText = cipher.doFinal( text );
83          return dectyptedText;
84      }
85  
86      /**
87       * 
88       */
89      public static class PublickeyAuthenticatorRequest
90      {
91          private String username;
92  
93          private PublicKey publicKey;
94  
95          public PublickeyAuthenticatorRequest( String username, PublicKey publicKey )
96          {
97              this.username = username;
98              this.publicKey = publicKey;
99          }
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 }