View Javadoc
1   package org.apache.maven.shared.release.util;
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 javax.inject.Inject;
23  import javax.inject.Named;
24  import javax.inject.Singleton;
25  
26  import java.util.Properties;
27  
28  import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
29  import org.sonatype.plexus.components.cipher.PlexusCipher;
30  import org.sonatype.plexus.components.cipher.PlexusCipherException;
31  import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
32  import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
33  import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
34  import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
35  
36  
37  /**
38   * A shared utility to access {@link DefaultSecDispatcher} service.
39   *
40   * @since TBD
41   */
42  @Singleton
43  @Named
44  public class MavenCrypto
45  {
46      /**
47       * Exception thrown when "something" of crypto operation did not succeed. All the code all over the place
48       * was catching sec dispatcher and plexus cipher exceptions just to neglect it (maybe log in DEBUG), so
49       * this is one single exception here.
50       */
51      public static class MavenCryptoException extends Exception
52      {
53          private MavenCryptoException( String message )
54          {
55              super( message );
56          }
57  
58          private MavenCryptoException( String message, Throwable cause )
59          {
60              super( message, cause );
61          }
62      }
63  
64      private final DefaultSecDispatcher secDispatcher;
65  
66      private final PlexusCipher plexusCipher;
67  
68      @Inject
69      public MavenCrypto( DefaultSecDispatcher secDispatcher, PlexusCipher plexusCipher )
70      {
71          this.secDispatcher = secDispatcher;
72          this.plexusCipher = plexusCipher;
73      }
74  
75      public String decrypt( String value ) throws MavenCryptoException
76      {
77          try
78          {
79              return secDispatcher.decrypt( value );
80          }
81          catch ( SecDispatcherException e )
82          {
83              throw new MavenCryptoException( "decrypt failed", e );
84          }
85      }
86  
87      public void decryptProperties( Properties properties ) throws MavenCryptoException
88      {
89          String[] keys = new String[] {"scm.password", "scm.passphrase"};
90  
91          for ( String key : keys )
92          {
93              String value = properties.getProperty( key );
94              if ( value != null )
95              {
96                  properties.put( key, decryptDecorated( value ) );
97              }
98          }
99      }
100 
101     public String encryptAndDecorate( String passwd ) throws MavenCryptoException
102     {
103         try
104         {
105             final String master = getMaster();
106 
107             DefaultPlexusCipher cipher = new DefaultPlexusCipher();
108             String masterPasswd = cipher.decryptDecorated( master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION );
109             return cipher.encryptAndDecorate( passwd, masterPasswd );
110         }
111         catch ( PlexusCipherException e )
112         {
113             throw new MavenCryptoException( "encrypt failed", e );
114         }
115     }
116 
117     public boolean isEncryptedString( String str )
118     {
119         return plexusCipher.isEncryptedString( str );
120     }
121 
122     private String decryptDecorated( String value ) throws MavenCryptoException
123     {
124         try
125         {
126             final String master = getMaster();
127 
128             DefaultPlexusCipher cipher = new DefaultPlexusCipher();
129             String masterPasswd = cipher.decryptDecorated( master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION );
130             return cipher.decryptDecorated( value, masterPasswd );
131         }
132         catch ( PlexusCipherException e )
133         {
134             throw new MavenCryptoException( "decrypt failed", e );
135         }
136     }
137 
138     private String getMaster() throws MavenCryptoException
139     {
140         String configurationFile = secDispatcher.getConfigurationFile();
141 
142         if ( configurationFile.startsWith( "~" ) )
143         {
144             configurationFile = System.getProperty( "user.home" ) + configurationFile.substring( 1 );
145         }
146 
147         String file = System.getProperty( DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile );
148 
149         String master = null;
150 
151         try
152         {
153             SettingsSecurity sec = SecUtil.read( file, true );
154             if ( sec != null )
155             {
156                 master = sec.getMaster();
157             }
158         }
159         catch ( SecDispatcherException e )
160         {
161             throw new MavenCryptoException( "config file read failed", e );
162         }
163 
164         if ( master == null )
165         {
166             throw new MavenCryptoException( "Master password is not set in the setting security file: " + file );
167         }
168 
169         return master;
170     }
171 }