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
26
27
28
29
30
31
32
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,
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 }