Skip to content

Commit 96955ce

Browse files
lampadkares
authored andcommitted
add OCSP support (#124)
* Basic structure of everything. Lots more to do. * Move toward more BC-centric processing TODO: - Replace manual construction of Request in #sign with OCSPReqBuilder - Fix verification * Verification of BasicResponses working * There seems to be an issue with decoding objects using ASN1.decode and then trying to reconstitute decoded objects by calling to_der on them. Some data seems to be left off. Not covering it here because of scope creep.
1 parent 2e70c2b commit 96955ce

File tree

11 files changed

+2554
-6
lines changed

11 files changed

+2554
-6
lines changed

src/main/java/org/jruby/ext/openssl/ASN1.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ private static void defaultObjects(final Ruby runtime) {
326326
addObject(runtime, 184, "AES-256-CBC", "aes-256-cbc","2.16.840.1.101.3.4.1.42");
327327
addObject(runtime, 185, "AES-256-OFB", "aes-256-ofb","2.16.840.1.101.3.4.1.43");
328328
addObject(runtime, 186, "AES-256-CFB", "aes-256-cfb","2.16.840.1.101.3.4.1.44");
329+
addObject(runtime, 672, "SHA256", "sha256", "2.16.840.1.101.3.4.2.1");
329330

330331
addObject(runtime, 660, "street", "streetAddress", "2.5.4.9");
331332
addObject(runtime, 391, "DC", "domainComponent", "0.9.2342.19200300.100.1.25");
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
/*
2+
* The contents of this file are subject to the Common Public License Version 1.0
3+
* (the "License"); you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at http://www.eclipse.org/legal/cpl-v10.html
5+
*
6+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
7+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
8+
* FOR APARTICULAR PURPOSE AND NONINFRINGEMENT.
9+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
10+
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
11+
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
12+
* DEALINGS IN THE SOFTWARE.
13+
*
14+
* Copyright (C) 2017 Donovan Lampa <[email protected]>
15+
* Copyright (C) 2009-2017 The JRuby Team
16+
*
17+
* Alternatively, the contents of this file may be used under the terms of
18+
* either of the GNU General Public License Version 2 or later (the "GPL"),
19+
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20+
* in which case the provisions of the GPL or the LGPL are applicable instead
21+
* of those above. If you wish to allow use of your version of this file only
22+
* under the terms of either the GPL or the LGPL, and not to allow others to
23+
* use your version of this file under the terms of the EPL, indicate your
24+
* decision by deleting the provisions above and replace them with the notice
25+
* and other provisions required by the GPL or the LGPL. If you do not delete
26+
* the provisions above, a recipient may use your version of this file under
27+
* the terms of any one of the EPL, the GPL or the LGPL.
28+
*
29+
*
30+
* JRuby-OpenSSL includes software by The Legion of the Bouncy Castle Inc.
31+
* Please, visit (http://bouncycastle.org/license.html) for licensing details.
32+
*/
33+
package org.jruby.ext.openssl;
34+
35+
import java.security.Security;
36+
import java.util.HashMap;
37+
import java.util.Map;
38+
39+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
40+
import org.jruby.Ruby;
41+
import org.jruby.RubyClass;
42+
import org.jruby.RubyFixnum;
43+
import org.jruby.RubyModule;
44+
import org.jruby.exceptions.RaiseException;
45+
import org.jruby.runtime.builtin.IRubyObject;
46+
47+
/**
48+
* OCSP
49+
*
50+
* @author lampad
51+
*/
52+
public class OCSP {
53+
54+
//Response has valid confirmations
55+
private static final String _RESPONSE_STATUS_SUCCESSFUL_STR = "RESPONSE_STATUS_SUCCESSFUL";
56+
private static final int _RESPONSE_STATUS_SUCCESSFUL = 0;
57+
//Illegal confirmation request
58+
private static final String _RESPONSE_STATUS_MALFORMEDREQUEST_STR = "RESPONSE_STATUS_MALFORMEDREQUEST";
59+
private static final int _RESPONSE_STATUS_MALFORMEDREQUEST = 1;
60+
//Internal error in issuer
61+
private static final String _RESPONSE_STATUS_INTERNALERROR_STR = "RESPONSE_STATUS_INTERNALERROR";
62+
private static final int _RESPONSE_STATUS_INTERNALERROR = 2;
63+
//Try again later
64+
private static final String _RESPONSE_STATUS_TRYLATER_STR = "RESPONSE_STATUS_TRYLATER";
65+
private static final int _RESPONSE_STATUS_TRYLATER = 3;
66+
//You must sign the request and resubmit
67+
private static final String _RESPONSE_STATUS_SIGREQUIRED_STR = "RESPONSE_STATUS_SIGREQUIRED";
68+
private static final int _RESPONSE_STATUS_SIGREQUIRED = 5;
69+
//Your request is unauthorized.
70+
private static final String _RESPONSE_STATUS_UNAUTHORIZED_STR = "RESPONSE_STATUS_UNAUTHORIZED";
71+
private static final int _RESPONSE_STATUS_UNAUTHORIZED = 6;
72+
73+
private static final Map<Integer, String> responseMap;
74+
75+
//The certificate was revoked for an unknown reason
76+
private static final int _REVOKED_STATUS_NOSTATUS = -1;
77+
//The certificate was revoked for an unspecified reason
78+
private static final int _REVOKED_STATUS_UNSPECIFIED = 0;
79+
//The certificate was revoked due to a key compromise
80+
private static final int _REVOKED_STATUS_KEYCOMPROMISE = 1;
81+
//This CA certificate was revoked due to a key compromise
82+
private static final int _REVOKED_STATUS_CACOMPROMISE = 2;
83+
//The certificate subject's name or other information changed
84+
private static final int _REVOKED_STATUS_AFFILIATIONCHANGED = 3;
85+
//The certificate was superseded by a new certificate
86+
private static final int _REVOKED_STATUS_SUPERSEDED = 4;
87+
//The certificate is no longer needed
88+
private static final int _REVOKED_STATUS_CESSATIONOFOPERATION = 5;
89+
//The certificate is on hold
90+
private static final int _REVOKED_STATUS_CERTIFICATEHOLD = 6;
91+
//The certificate was previously on hold and should now be removed from the CRL
92+
private static final int _REVOKED_STATUS_REMOVEFROMCRL = 8;
93+
94+
//Do not include certificates in the response
95+
private static final int _NOCERTS = 0x1;
96+
//Do not search certificates contained in the response for a signer
97+
private static final int _NOINTERN = 0x2;
98+
//Do not check the signature on the response
99+
private static final int _NOSIGS = 0x4;
100+
//Do not verify the certificate chain on the response
101+
private static final int _NOCHAIN = 0x8;
102+
//Do not verify the response at all
103+
private static final int _NOVERIFY = 0x10;
104+
//Do not check trust
105+
private static final int _NOEXPLICIT = 0x20;
106+
//(This flag is not used by OpenSSL 1.0.1g)
107+
private static final int _NOCASIGN = 0x40;
108+
//(This flag is not used by OpenSSL 1.0.1g)
109+
private static final int _NODELEGATED = 0x80;
110+
//Do not make additional signing certificate checks
111+
private static final int _NOCHECKS = 0x100;
112+
//Do not verify additional certificates
113+
private static final int _TRUSTOTHER = 0x200;
114+
//Identify the response by signing the certificate key ID
115+
private static final int _RESPID_KEY = 0x400;
116+
//Do not include producedAt time in response
117+
private static final int _NOTIME = 0x800;
118+
119+
/*
120+
* Indicates the certificate is not revoked but does not necessarily mean
121+
* the certificate was issued or that this response is within the
122+
* certificate's validity interval
123+
*/
124+
private static final int _V_CERTSTATUS_GOOD = 0;
125+
/* Indicates the certificate has been revoked either permanently or
126+
* temporarily (on hold).
127+
*/
128+
private static final int _V_CERTSTATUS_REVOKED = 1;
129+
/* Indicates the responder does not know about the certificate being
130+
* requested.
131+
*/
132+
private static final int _V_CERTSTATUS_UNKNOWN = 2;
133+
134+
//The responder ID is based on the key name.
135+
private static final int _V_RESPID_NAME = 0;
136+
//The responder ID is based on the public key.
137+
private static final int _V_RESPID_KEY =1;
138+
139+
static {
140+
Map<Integer, String> resMap = new HashMap<Integer, String>();
141+
resMap.put(_RESPONSE_STATUS_SUCCESSFUL, _RESPONSE_STATUS_SUCCESSFUL_STR);
142+
resMap.put(_RESPONSE_STATUS_MALFORMEDREQUEST, _RESPONSE_STATUS_MALFORMEDREQUEST_STR);
143+
resMap.put(_RESPONSE_STATUS_INTERNALERROR, _RESPONSE_STATUS_INTERNALERROR_STR);
144+
resMap.put(_RESPONSE_STATUS_TRYLATER, _RESPONSE_STATUS_TRYLATER_STR);
145+
resMap.put(_RESPONSE_STATUS_SIGREQUIRED, _RESPONSE_STATUS_SIGREQUIRED_STR);
146+
resMap.put(_RESPONSE_STATUS_UNAUTHORIZED, _RESPONSE_STATUS_UNAUTHORIZED_STR);
147+
responseMap = resMap;
148+
}
149+
150+
public static void createOCSP(final Ruby runtime, final RubyModule OpenSSL) {
151+
final RubyModule OCSP = OpenSSL.defineModuleUnder("OCSP");
152+
final RubyClass OpenSSLError = OpenSSL.getClass("OpenSSLError");
153+
Security.addProvider(new BouncyCastleProvider());
154+
OCSP.defineClassUnder("OCSPError", OpenSSLError, OpenSSLError.getAllocator());
155+
156+
OCSPBasicResponse.createBasicResponse(runtime, OCSP);
157+
OCSPCertificateId.createCertificateId(runtime, OCSP);
158+
OCSPRequest.createRequest(runtime, OCSP);
159+
OCSPResponse.createResponse(runtime, OCSP);
160+
OCSPSingleResponse.createSingleResponse(runtime, OCSP);
161+
162+
//ResponseStatuses
163+
OCSP.setConstant(_RESPONSE_STATUS_SUCCESSFUL_STR, runtime.newFixnum(_RESPONSE_STATUS_SUCCESSFUL));
164+
OCSP.setConstant(_RESPONSE_STATUS_MALFORMEDREQUEST_STR, runtime.newFixnum(_RESPONSE_STATUS_MALFORMEDREQUEST));
165+
OCSP.setConstant(_RESPONSE_STATUS_INTERNALERROR_STR, runtime.newFixnum(_RESPONSE_STATUS_INTERNALERROR));
166+
OCSP.setConstant(_RESPONSE_STATUS_TRYLATER_STR, runtime.newFixnum(_RESPONSE_STATUS_TRYLATER));
167+
OCSP.setConstant(_RESPONSE_STATUS_SIGREQUIRED_STR, runtime.newFixnum(_RESPONSE_STATUS_SIGREQUIRED));
168+
OCSP.setConstant(_RESPONSE_STATUS_UNAUTHORIZED_STR, runtime.newFixnum(_RESPONSE_STATUS_UNAUTHORIZED));
169+
170+
//RevocationReasons
171+
OCSP.setConstant("REVOKED_STATUS_NOSTATUS", runtime.newFixnum(_REVOKED_STATUS_NOSTATUS));
172+
OCSP.setConstant("REVOKED_STATUS_UNSPECIFIED", runtime.newFixnum(_REVOKED_STATUS_UNSPECIFIED));
173+
OCSP.setConstant("REVOKED_STATUS_KEYCOMPROMISE", runtime.newFixnum(_REVOKED_STATUS_KEYCOMPROMISE));
174+
OCSP.setConstant("REVOKED_STATUS_CACOMPROMISE", runtime.newFixnum(_REVOKED_STATUS_CACOMPROMISE));
175+
OCSP.setConstant("REVOKED_STATUS_AFFILIATIONCHANGED", runtime.newFixnum(_REVOKED_STATUS_AFFILIATIONCHANGED));
176+
OCSP.setConstant("REVOKED_STATUS_SUPERSEDED", runtime.newFixnum(_REVOKED_STATUS_SUPERSEDED));
177+
OCSP.setConstant("REVOKED_STATUS_CESSATIONOFOPERATION", runtime.newFixnum(_REVOKED_STATUS_CESSATIONOFOPERATION));
178+
OCSP.setConstant("REVOKED_STATUS_CERTIFICATEHOLD", runtime.newFixnum(_REVOKED_STATUS_CERTIFICATEHOLD));
179+
OCSP.setConstant("REVOKED_STATUS_REMOVEFROMCRL", runtime.newFixnum(_REVOKED_STATUS_REMOVEFROMCRL));
180+
181+
OCSP.setConstant("NOCERTS", runtime.newFixnum(_NOCERTS));
182+
OCSP.setConstant("NOINTERN", runtime.newFixnum(_NOINTERN));
183+
OCSP.setConstant("NOSIGS", runtime.newFixnum(_NOSIGS));
184+
OCSP.setConstant("NOCHAIN", runtime.newFixnum(_NOCHAIN));
185+
OCSP.setConstant("NOVERIFY", runtime.newFixnum(_NOVERIFY));
186+
OCSP.setConstant("NOEXPLICIT", runtime.newFixnum(_NOEXPLICIT));
187+
OCSP.setConstant("NOCASIGN", runtime.newFixnum(_NOCASIGN));
188+
OCSP.setConstant("NODELEGATED", runtime.newFixnum(_NODELEGATED));
189+
OCSP.setConstant("NOCHECKS", runtime.newFixnum(_NOCHECKS));
190+
OCSP.setConstant("TRUSTOTHER", runtime.newFixnum(_TRUSTOTHER));
191+
OCSP.setConstant("RESPID_KEY", runtime.newFixnum(_RESPID_KEY));
192+
OCSP.setConstant("NOTIME", runtime.newFixnum(_NOTIME));
193+
194+
OCSP.setConstant("V_CERTSTATUS_GOOD", runtime.newFixnum(_V_CERTSTATUS_GOOD));
195+
OCSP.setConstant("V_CERTSTATUS_REVOKED", runtime.newFixnum(_V_CERTSTATUS_REVOKED));
196+
OCSP.setConstant("V_CERTSTATUS_UNKNOWN", runtime.newFixnum(_V_CERTSTATUS_UNKNOWN));
197+
198+
OCSP.setConstant("V_RESPID_NAME", runtime.newFixnum(_V_RESPID_NAME));
199+
OCSP.setConstant("V_RESPID_KEY", runtime.newFixnum(_V_RESPID_KEY));
200+
}
201+
202+
public static String getResponseStringForValue(IRubyObject fixnum) {
203+
RubyFixnum rubyFixnum = (RubyFixnum) fixnum;
204+
return responseMap.get((int)rubyFixnum.getLongValue());
205+
}
206+
207+
public static RaiseException newOCSPError(Ruby runtime, Exception ex) {
208+
return Utils.newError(runtime, _OCSP(runtime).getClass("OCSPError"), ex);
209+
}
210+
211+
static RubyModule _OCSP(final Ruby runtime) {
212+
return (RubyModule) runtime.getModule("OpenSSL").getConstant("OCSP");
213+
}
214+
215+
}

0 commit comments

Comments
 (0)