View Javadoc

1   package fr.in2p3.jsaga.adaptor.security;
2   
3   import fr.in2p3.jsaga.adaptor.base.defaults.Default;
4   import fr.in2p3.jsaga.adaptor.base.defaults.EnvironmentVariables;
5   import fr.in2p3.jsaga.adaptor.base.usage.*;
6   import fr.in2p3.jsaga.adaptor.security.impl.InMemoryProxySecurityCredential;
7   import org.bouncycastle.jce.provider.X509CertificateObject;
8   import org.globus.common.CoGProperties;
9   import org.globus.gsi.gssapi.GlobusGSSCredentialImpl;
10  import org.globus.util.Util;
11  import org.gridforum.jgss.ExtendedGSSCredential;
12  import org.gridforum.jgss.ExtendedGSSManager;
13  import org.ietf.jgss.GSSCredential;
14  import org.ietf.jgss.GSSException;
15  import org.ogf.saga.context.Context;
16  import org.ogf.saga.error.*;
17  
18  import java.io.*;
19  import java.lang.Exception;
20  import java.security.cert.X509Certificate;
21  import java.util.Map;
22  import org.globus.gsi.X509Credential;
23  
24  /* ***************************************************
25  * *** Centre de Calcul de l'IN2P3 - Lyon (France) ***
26  * ***             http://cc.in2p3.fr/             ***
27  * ***************************************************
28  * File:   GlobusSecurityAdaptor
29  * Author: Sylvain Reynaud (sreynaud@in2p3.fr)
30  * Date:   20 juil. 2007
31  * ***************************************************
32  * Description:                                      */
33  /**
34   *
35   */
36  public class GlobusSecurityAdaptor implements ExpirableSecurityAdaptor {
37      public static final int USAGE_INIT_PKCS12 = 1;
38      public static final int USAGE_INIT_PEM = 2;
39      public static final int USAGE_MEMORY = 3;
40      public static final int USAGE_LOAD = 4;
41  
42      public String getType() {
43          return "Globus";
44      }
45      public Class getSecurityCredentialClass() {
46          return GlobusSecurityCredential.class;
47      }
48  
49      protected Usage getPKCS12orPEM() {
50          Usage PKCS12 = new UFile(USAGE_INIT_PKCS12, GlobusContext.USERCERTKEY);
51          Usage PEM = new UAnd.Builder()
52                              .id(USAGE_INIT_PEM)
53                              .and(new UFile(Context.USERCERT))
54                              .and(new UFile(Context.USERKEY))
55                              .build();
56          return new UAnd.Builder()
57                                  .and(new UOr.Builder().or(PKCS12).or(PEM).build())
58                                  .and(new UFilePath(Context.USERPROXY))
59                                  .and(new UHidden(Context.USERPASS))
60                                  .and(new UDuration(Context.LIFETIME))
61                                  .and(getProxyType())
62                                  .and(getDelegation())
63                                  .build();
64      }
65      
66      protected Usage getProxyType() {
67          return new UOptional(GlobusContext.PROXYTYPE) {
68              protected Object throwExceptionIfInvalid(Object value) throws Exception {
69                  if (super.throwExceptionIfInvalid(value) != null) {
70                      String v = (String) value;
71                      if (!ProxyTypeMap.isValid(v)) {
72                          throw new BadParameterException(ProxyTypeMap.getExpected());
73                      }
74                  }
75                  return value;
76              }
77          };
78      }
79  
80      protected Usage getDelegation() {
81          return new UOptional(GlobusContext.DELEGATION) {
82              protected Object throwExceptionIfInvalid(Object value) throws Exception {
83                  if (super.throwExceptionIfInvalid(value) != null) {
84                      String v = (String) value;
85                      if (!DelegationTypeMap.isValid(v)) {
86                          throw new BadParameterException(DelegationTypeMap.getExpected());
87                      }
88                  }
89                  return value;
90              }
91          };
92      }
93      
94      public Usage getUsage() {
95  
96          return new UAnd.Builder()
97                  .and(new UOr.Builder()
98                          .or(new UNoPrompt(USAGE_MEMORY, GlobusContext.USERPROXYOBJECT))
99                          .or(new UFile(USAGE_LOAD, Context.USERPROXY))
100                         .or(getPKCS12orPEM())
101                         .build()
102                 )
103                 .and(new UFile(Context.CERTREPOSITORY))
104                 .build();
105     }
106 
107     public Default[] getDefaults(Map map) throws IncorrectStateException {
108         EnvironmentVariables env = EnvironmentVariables.getInstance();
109         return new Default[]{
110                 new Default(Context.USERPROXY, new String[]{
111                         env.getProperty("X509_USER_PROXY"),
112                         System.getProperty("java.io.tmpdir")+System.getProperty("file.separator")+"x509up_u"+
113                                 (System.getProperty("os.name").toLowerCase().startsWith("windows")
114                                         ? "_"+System.getProperty("user.name").toLowerCase()
115                                         : (env.getProperty("UID")!=null
116                                                 ? env.getProperty("UID")
117                                                 : getUnixUID()
118                                           )
119                                 )}),
120                 new Default(Context.USERCERT, new File[]{
121                         new File(env.getProperty("X509_USER_CERT")+""),
122                         new File(System.getProperty("user.home")+"/.globus/usercert.pem")}),
123                 new Default(Context.USERKEY, new File[]{
124                         new File(env.getProperty("X509_USER_KEY")+""),
125                         new File(System.getProperty("user.home")+"/.globus/userkey.pem")}),
126                 new Default(Context.CERTREPOSITORY, new File[]{
127                         new File(env.getProperty("X509_CERT_DIR")+""),
128                         new File(System.getProperty("user.home")+"/.globus/certificates/"),
129                         new File("/etc/grid-security/certificates/")}),
130                 new Default(Context.LIFETIME, "PT12H"),
131                 new Default(GlobusContext.PROXYTYPE, ProxyTypeMap.TYPE_RFC3820),
132                 new Default(GlobusContext.DELEGATION, DelegationTypeMap.FULL)
133         };
134     }
135     protected static String getUnixUID() throws IncorrectStateException {
136         try {
137             Process p = Runtime.getRuntime().exec("id -u");
138             BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
139             String uid = reader.readLine();
140             reader.close();
141             return uid;
142         } catch (IOException e) {
143             throw new IncorrectStateException(e);
144         }
145     }
146 
147     public SecurityCredential createSecurityCredential(int usage, Map attributes, String contextId) throws IncorrectStateException, NoSuccessException {
148         try {
149             switch(usage) {
150                 case USAGE_INIT_PKCS12:
151                 {
152                     GlobusProxyFactory factory = new GlobusProxyFactory(attributes, GlobusProxyFactory.CERTIFICATE_PKCS12);
153                     GSSCredential cred = factory.createProxy();
154                     return this.createSecurityAdaptor(cred, attributes);
155                 }
156                 case USAGE_INIT_PEM:
157                 {
158                     GlobusProxyFactory factory = new GlobusProxyFactory(attributes, GlobusProxyFactory.CERTIFICATE_PEM);
159                     GSSCredential cred = factory.createProxy();
160                     return this.createSecurityAdaptor(cred, attributes);
161                 }
162                 case USAGE_MEMORY:
163                 {
164                     String base64 = (String) attributes.get(GlobusContext.USERPROXYOBJECT);
165                     GSSCredential cred = InMemoryProxySecurityCredential.toGSSCredential(base64);
166                     return this.createSecurityAdaptor(cred, attributes);
167                 }
168                 case USAGE_LOAD:
169                 {
170                     CoGProperties.getDefault().setCaCertLocations((String) attributes.get(Context.CERTREPOSITORY));
171                     File proxyFile = new File((String) attributes.get(Context.USERPROXY));
172                     GSSCredential cred = load(proxyFile);
173                     return this.createSecurityAdaptor(cred, attributes);
174                 }
175                 default:
176                     throw new NoSuccessException("INTERNAL ERROR: unexpected exception");
177             }
178         } catch(IncorrectStateException e) {
179             throw e;
180         } catch(NoSuccessException e) {
181             throw e;
182         } catch(Exception e) {
183             throw new NoSuccessException(e);
184         }
185     }
186     private SecurityCredential createSecurityAdaptor(GSSCredential cred, Map attributes) throws IncorrectStateException {
187         if (!hasNonCriticalExtensions(cred)) {
188             File certRepository = new File((String) attributes.get(Context.CERTREPOSITORY));
189             return new GlobusSecurityCredential(cred, certRepository);
190         } else {
191             throw new IncorrectStateException("Security context is not of type: "+this.getType());
192         }
193     }
194 
195     public void destroySecurityAdaptor(Map attributes, String contextId) throws Exception {
196         String proxyFile = (String) attributes.get(Context.USERPROXY);
197         Util.destroy(proxyFile);
198     }
199 
200     protected static GSSCredential load(File proxyFile) throws IOException, GSSException {
201         byte [] proxyBytes = new byte[(int) proxyFile.length()];
202         FileInputStream in = new FileInputStream(proxyFile);
203         in.read(proxyBytes);
204         in.close();
205         ExtendedGSSManager manager = (ExtendedGSSManager) ExtendedGSSManager.getInstance();
206         return manager.createCredential(
207                 proxyBytes,
208                 ExtendedGSSCredential.IMPEXP_OPAQUE,
209                 GSSCredential.DEFAULT_LIFETIME,
210                 null, // use default mechanism: GSI
211                 GSSCredential.INITIATE_AND_ACCEPT);
212     }
213 
214     private static boolean hasNonCriticalExtensions(GSSCredential proxy) {
215         if (proxy instanceof GlobusGSSCredentialImpl) {
216             X509Credential globusProxy = ((GlobusGSSCredentialImpl)proxy).getX509Credential();
217             X509Certificate cert = globusProxy.getCertificateChain()[0];
218             if (cert instanceof X509CertificateObject) {
219                 X509CertificateObject bouncyCert = (X509CertificateObject) cert;
220                 return bouncyCert.getNonCriticalExtensionOIDs()!=null && !bouncyCert.getNonCriticalExtensionOIDs().isEmpty();
221             }
222         }
223         return false;
224     }
225 }