View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.release.util;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.util.Properties;
26  
27  import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
28  import org.sonatype.plexus.components.cipher.PlexusCipher;
29  import org.sonatype.plexus.components.cipher.PlexusCipherException;
30  import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
31  import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
32  import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
33  import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
34  
35  /**
36   * A shared utility to access {@link DefaultSecDispatcher} service.
37   *
38   * @since TBD
39   */
40  @Singleton
41  @Named
42  public class MavenCrypto {
43      /**
44       * Exception thrown when "something" of crypto operation did not succeed. All the code all over the place
45       * was catching sec dispatcher and plexus cipher exceptions just to neglect it (maybe log in DEBUG), so
46       * this is one single exception here.
47       */
48      public static class MavenCryptoException extends Exception {
49          private MavenCryptoException(String message) {
50              super(message);
51          }
52  
53          private MavenCryptoException(String message, Throwable cause) {
54              super(message, cause);
55          }
56      }
57  
58      private final DefaultSecDispatcher secDispatcher;
59  
60      private final PlexusCipher plexusCipher;
61  
62      @Inject
63      public MavenCrypto(DefaultSecDispatcher secDispatcher, PlexusCipher plexusCipher) {
64          this.secDispatcher = secDispatcher;
65          this.plexusCipher = plexusCipher;
66  
67          // Adjust the default path (def path != maven path)
68          this.secDispatcher.setConfigurationFile("~/.m2/settings-security.xml");
69      }
70  
71      public String decrypt(String value) throws MavenCryptoException {
72          try {
73              return secDispatcher.decrypt(value);
74          } catch (SecDispatcherException e) {
75              throw new MavenCryptoException("decrypt failed", e);
76          }
77      }
78  
79      public void decryptProperties(Properties properties) throws MavenCryptoException {
80          String[] keys = new String[] {"scm.password", "scm.passphrase"};
81  
82          for (String key : keys) {
83              String value = properties.getProperty(key);
84              if (value != null) {
85                  properties.put(key, decryptDecorated(value));
86              }
87          }
88      }
89  
90      public String encryptAndDecorate(String passwd) throws MavenCryptoException {
91          try {
92              final String master = getMaster();
93  
94              DefaultPlexusCipher cipher = new DefaultPlexusCipher();
95              String masterPasswd = cipher.decryptDecorated(master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION);
96              return cipher.encryptAndDecorate(passwd, masterPasswd);
97          } catch (PlexusCipherException e) {
98              throw new MavenCryptoException("encrypt failed", e);
99          }
100     }
101 
102     public boolean isEncryptedString(String str) {
103         return plexusCipher.isEncryptedString(str);
104     }
105 
106     private String decryptDecorated(String value) throws MavenCryptoException {
107         try {
108             final String master = getMaster();
109 
110             DefaultPlexusCipher cipher = new DefaultPlexusCipher();
111             String masterPasswd = cipher.decryptDecorated(master, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION);
112             return cipher.decryptDecorated(value, masterPasswd);
113         } catch (PlexusCipherException e) {
114             throw new MavenCryptoException("decrypt failed", e);
115         }
116     }
117 
118     private String getMaster() throws MavenCryptoException {
119         String configurationFile = secDispatcher.getConfigurationFile();
120 
121         if (configurationFile.startsWith("~")) {
122             configurationFile = System.getProperty("user.home") + configurationFile.substring(1);
123         }
124 
125         String file = System.getProperty(DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION, configurationFile);
126 
127         String master = null;
128 
129         try {
130             SettingsSecurity sec = SecUtil.read(file, true);
131             if (sec != null) {
132                 master = sec.getMaster();
133             }
134         } catch (SecDispatcherException e) {
135             throw new MavenCryptoException("config file read failed", e);
136         }
137 
138         if (master == null) {
139             throw new MavenCryptoException("Master password is not set in the setting security file: " + file);
140         }
141 
142         return master;
143     }
144 }