1 package fr.in2p3.jsaga.adaptor.security;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.security.PrivateKey;
6 import java.security.cert.X509Certificate;
7 import java.text.ParseException;
8 import java.util.Map;
9
10 import org.bouncycastle.openssl.PasswordFinder;
11 import org.globus.common.Version;
12 import org.globus.gsi.CredentialException;
13 import org.globus.gsi.GSIConstants;
14 import org.globus.gsi.GSIConstants.CertificateType;
15 import org.globus.gsi.X509Credential;
16 import org.globus.gsi.bc.BouncyCastleCertProcessingFactory;
17 import org.globus.gsi.gssapi.GlobusGSSCredentialImpl;
18 import org.globus.gsi.util.CertificateLoadUtil;
19 import org.globus.util.Util;
20 import org.ietf.jgss.GSSCredential;
21 import org.ietf.jgss.GSSException;
22 import org.ogf.saga.context.Context;
23 import org.ogf.saga.error.BadParameterException;
24 import org.ogf.saga.error.IncorrectStateException;
25 import org.ogf.saga.error.NoSuccessException;
26
27 import fr.in2p3.jsaga.adaptor.base.usage.UDuration;
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class GlobusProxyFactory {
42 public static final int OID_OLD = 2;
43 public static final int OID_GLOBUS = 3;
44 public static final int OID_RFC3820 = 4;
45
46 private static final int PROXY_BITS = 1024;
47 private static final int DEFAULT_PROXY_LIFETIME = 3600 * 12;
48
49 protected static final int CERTIFICATE_PEM = 0;
50 protected static final int CERTIFICATE_PKCS12 = 1;
51
52 private X509Credential m_userCredential = null;
53 private String m_proxyFile = "";
54 private int m_proxyLifetime = 0;
55 private CertificateType m_proxyType = null;
56 private String m_cadir = null;
57
58 public GlobusProxyFactory(Map attributes, int certificateFormat) throws BadParameterException, ParseException {
59
60 String passphrase = (String) attributes.get(Context.USERPASS);
61 m_cadir = (String) attributes.get(Context.CERTREPOSITORY);
62 m_proxyFile = (String) attributes.get(Context.USERPROXY);
63
64 if ("".equals(passphrase)) {
65 passphrase = null;
66 }
67
68 final char[] pwd;
69 if(passphrase != null){
70 pwd = passphrase.toCharArray();
71 }else{
72 pwd = null;
73 }
74 switch(certificateFormat) {
75 case CERTIFICATE_PEM:
76 String userCert = (String) attributes.get(Context.USERCERT);
77 String userKey = (String) attributes.get(Context.USERKEY);
78 try {
79 X509Certificate[] x509Certificates = CertificateLoadUtil.loadCertificates(userCert);
80 PrivateKey privateKey = CertificateLoadUtil.loadPrivateKey(userKey, new PasswordFinder() {
81 public char[] getPassword() {
82 return pwd;
83 }
84 });
85 m_userCredential = new X509Credential(privateKey, x509Certificates);
86 } catch (Exception e) {
87 throw new BadParameterException("Unable to load the provided pems files (cert: '" + userCert + "', key: '" + userKey, e);
88 }
89 break;
90 case CERTIFICATE_PKCS12:
91 String pkcs12 = (String) attributes.get(GlobusContext.USERCERTKEY);
92 try {
93 m_userCredential = CertificateLoadUtil.loadKeystore(pkcs12, passphrase != null ? passphrase.toCharArray() : null, null, null, "PKCS12");
94 } catch (Exception e) {
95 throw new BadParameterException("Unable to load the provided pkcs12 file (" + pkcs12 + ")");
96 }
97 break;
98 default:
99 throw new BadParameterException("Invalid case, either PEM or PKCS12 certificates is supported");
100 }
101
102
103 if (attributes.containsKey(Context.LIFETIME)) {
104 m_proxyLifetime = UDuration.toInt(attributes.get(Context.LIFETIME));
105 }else{
106 m_proxyLifetime = DEFAULT_PROXY_LIFETIME;
107 }
108 boolean limited = false;
109 if (attributes.containsKey(GlobusContext.DELEGATION)) {
110 limited = ((String)attributes.get(GlobusContext.DELEGATION)).equalsIgnoreCase("limited");
111 }
112 int oid = ProxyTypeMap.toProxyType((String)attributes.get(GlobusContext.PROXYTYPE));
113 switch(oid) {
114 case OID_OLD:
115 m_proxyType = (limited) ?
116 GSIConstants.CertificateType.GSI_2_LIMITED_PROXY :
117 GSIConstants.CertificateType.GSI_2_PROXY;
118 break;
119 case OID_GLOBUS:
120 m_proxyType = (limited) ?
121 GSIConstants.CertificateType.GSI_3_LIMITED_PROXY :
122 GSIConstants.CertificateType.GSI_3_IMPERSONATION_PROXY;
123 break;
124 case OID_RFC3820:
125 m_proxyType = (limited) ?
126 GSIConstants.CertificateType.GSI_4_LIMITED_PROXY :
127 GSIConstants.CertificateType.GSI_4_IMPERSONATION_PROXY;
128 break;
129 }
130 }
131
132 public GSSCredential createProxy() throws IncorrectStateException, NoSuccessException {
133 BouncyCastleCertProcessingFactory bouncyCastleCertProcessingFactory = BouncyCastleCertProcessingFactory.getDefault();
134 X509Credential proxy;
135 try {
136 proxy = bouncyCastleCertProcessingFactory.createCredential(m_userCredential.getCertificateChain(), m_userCredential.getPrivateKey(), PROXY_BITS, m_proxyLifetime, m_proxyType);
137 } catch (Exception e) {
138 throw new NoSuccessException("Unable to generate the user proxy", e);
139 }
140 try {
141 proxy.verify(m_cadir);
142 } catch (CredentialException e) {
143 if(proxy.getTimeLeft() < 0){
144 throw new IncorrectStateException("Your certificate is expired", e);
145 }else{
146 throw new NoSuccessException("Proxy verification failed", e);
147 }
148 }
149 try {
150 GlobusGSSCredentialImpl globusGSSCredentialImpl = new GlobusGSSCredentialImpl(proxy, GSSCredential.INITIATE_ONLY);
151 proxy.writeToFile(new File(m_proxyFile));
152 Util.setFilePermissions(m_proxyFile, 600);
153 return globusGSSCredentialImpl;
154 } catch (GSSException e) {
155 throw new NoSuccessException("Proxy convertion failed", e);
156 } catch (CredentialException e) {
157 throw new NoSuccessException("Unable to save the generated proxy in '" +m_proxyFile + "'", e);
158 } catch (IOException e) {
159 throw new NoSuccessException("Unable to save the generated proxy in '" +m_proxyFile + "'", e);
160 }
161 }
162
163 public String getVersion() {
164 return Version.getVersion();
165 }
166 }