1/*
2 * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30// #define SECMOD_DEBUG
31
32#include "j2secmod.h"
33#include "jni_util.h"
34
35
36JNIEXPORT jboolean JNICALL Java_sun_security_pkcs11_Secmod_nssVersionCheck
37 (JNIEnv *env, jclass thisClass, jlong jHandle, jstring jVersion)
38{
39 int res = 0;
40 FPTR_VersionCheck versionCheck;
41 const char *requiredVersion;
42
43 versionCheck = (FPTR_VersionCheck)findFunction(env, jHandle,
44 "NSS_VersionCheck");
45 if (versionCheck == NULL) {
46 return JNI_FALSE;
47 }
48
49 requiredVersion = (*env)->GetStringUTFChars(env, jVersion, NULL);
50 if (requiredVersion == NULL) {
51 return JNI_FALSE;
52 }
53
54 res = versionCheck(requiredVersion);
55 dprintf2("-version >=%s: %d\n", requiredVersion, res);
56 (*env)->ReleaseStringUTFChars(env, jVersion, requiredVersion);
57
58 return (res == 0) ? JNI_FALSE : JNI_TRUE;
59}
60
61/*
62 * Initializes NSS.
63 * The NSS_INIT_OPTIMIZESPACE flag is supplied by the caller.
64 * The NSS_Init* functions are mapped to the NSS_Initialize function.
65 */
66JNIEXPORT jboolean JNICALL Java_sun_security_pkcs11_Secmod_nssInitialize
67 (JNIEnv *env, jclass thisClass, jstring jFunctionName, jlong jHandle, jstring jConfigDir, jboolean jNssOptimizeSpace)
68{
69 int res = 0;
70 FPTR_Initialize initialize =
71 (FPTR_Initialize)findFunction(env, jHandle, "NSS_Initialize");
72 #ifdef SECMOD_DEBUG
73 FPTR_GetError getError =
74 (FPTR_GetError)findFunction(env, jHandle, "PORT_GetError");
75 #endif // SECMOD_DEBUG
76 unsigned int flags = 0x00;
77 const char *configDir = NULL;
78 const char *functionName = NULL;
79 const char *configFile = NULL;
80
81 /* If we cannot initialize, exit now */
82 if (initialize == NULL) {
83 res = 1;
84 goto cleanup;
85 }
86
87 functionName = (*env)->GetStringUTFChars(env, jFunctionName, NULL);
88 if (functionName == NULL) {
89 res = 1;
90 goto cleanup;
91 }
92
93 if (jConfigDir != NULL) {
94 configDir = (*env)->GetStringUTFChars(env, jConfigDir, NULL);
95 if (!configDir) {
96 res = 1;
97 goto cleanup;
98 }
99 }
100
101 if (jNssOptimizeSpace == JNI_TRUE) {
102 flags = 0x20; // NSS_INIT_OPTIMIZESPACE flag
103 }
104
105 configFile = "secmod.db";
106 if (configDir != NULL && strncmp("sql:", configDir, 4U) == 0) {
107 configFile = "pkcs11.txt";
108 }
109
110 /*
111 * If the NSS_Init function is requested then call NSS_Initialize to
112 * open the Cert, Key and Security Module databases, read only.
113 */
114 if (strcmp("NSS_Init", functionName) == 0) {
115 flags = flags | 0x01; // NSS_INIT_READONLY flag
116 res = initialize(configDir, "", "", configFile, flags);
117
118 /*
119 * If the NSS_InitReadWrite function is requested then call
120 * NSS_Initialize to open the Cert, Key and Security Module databases,
121 * read/write.
122 */
123 } else if (strcmp("NSS_InitReadWrite", functionName) == 0) {
124 res = initialize(configDir, "", "", configFile, flags);
125
126 /*
127 * If the NSS_NoDB_Init function is requested then call
128 * NSS_Initialize without creating Cert, Key or Security Module
129 * databases.
130 */
131 } else if (strcmp("NSS_NoDB_Init", functionName) == 0) {
132 flags = flags | 0x02 // NSS_INIT_NOCERTDB flag
133 | 0x04 // NSS_INIT_NOMODDB flag
134 | 0x08 // NSS_INIT_FORCEOPEN flag
135 | 0x10; // NSS_INIT_NOROOTINIT flag
136 res = initialize("", "", "", "", flags);
137
138 } else {
139 res = 2;
140 }
141
142cleanup:
143 if (functionName != NULL) {
144 (*env)->ReleaseStringUTFChars(env, jFunctionName, functionName);
145 }
146 if (configDir != NULL) {
147 (*env)->ReleaseStringUTFChars(env, jConfigDir, configDir);
148 }
149 dprintf1("-res: %d\n", res);
150 #ifdef SECMOD_DEBUG
151 if (res == -1) {
152 if (getError != NULL) {
153 dprintf1("-NSS error: %d\n", getError());
154 }
155 }
156 #endif // SECMOD_DEBUG
157
158 return (res == 0) ? JNI_TRUE : JNI_FALSE;
159}
160
161JNIEXPORT jobject JNICALL Java_sun_security_pkcs11_Secmod_nssGetModuleList
162 (JNIEnv *env, jclass thisClass, jlong jHandle, jstring jLibDir)
163{
164 FPTR_GetDBModuleList getModuleList =
165 (FPTR_GetDBModuleList)findFunction(env, jHandle, "SECMOD_GetDefaultModuleList");
166
167 SECMODModuleList *list;
168 SECMODModule *module;
169 jclass jListClass, jModuleClass;
170 jobject jList, jModule;
171 jmethodID jListConstructor, jAdd, jModuleConstructor;
172 jstring jCommonName, jDllName;
173 jboolean jFIPS;
174 jint i;
175
176 if (getModuleList == NULL) {
177 dprintf("-getmodulelist function not found\n");
178 return NULL;
179 }
180 list = getModuleList();
181 if (list == NULL) {
182 dprintf("-module list is null\n");
183 return NULL;
184 }
185
186 jListClass = (*env)->FindClass(env, "java/util/ArrayList");
187 if (jListClass == NULL) {
188 return NULL;
189 }
190 jListConstructor = (*env)->GetMethodID(env, jListClass, "<init>", "()V");
191 if (jListConstructor == NULL) {
192 return NULL;
193 }
194 jAdd = (*env)->GetMethodID(env, jListClass, "add", "(Ljava/lang/Object;)Z");
195 if (jAdd == NULL) {
196 return NULL;
197 }
198 jList = (*env)->NewObject(env, jListClass, jListConstructor);
199 if (jList == NULL) {
200 return NULL;
201 }
202 jModuleClass = (*env)->FindClass(env, "sun/security/pkcs11/Secmod$Module");
203 if (jModuleClass == NULL) {
204 return NULL;
205 }
206 jModuleConstructor = (*env)->GetMethodID(env, jModuleClass, "<init>",
207 "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZI)V");
208 if (jModuleConstructor == NULL) {
209 return NULL;
210 }
211
212 while (list != NULL) {
213 module = list->module;
214 // assert module != null
215 dprintf1("-commonname: %s\n", module->commonName);
216 dprintf1("-dllname: %s\n", (module->dllName != NULL) ? module->dllName : "NULL");
217 dprintf1("-slots: %d\n", module->slotCount);
218 dprintf1("-loaded: %d\n", module->loaded);
219 dprintf1("-internal: %d\n", module->internal);
220 dprintf1("-fips: %d\n", module->isFIPS);
221 jCommonName = (*env)->NewStringUTF(env, module->commonName);
222 if (jCommonName == NULL) {
223 return NULL;
224 }
225 if (module->dllName == NULL) {
226 jDllName = NULL;
227 } else {
228 jDllName = (*env)->NewStringUTF(env, module->dllName);
229 if (jDllName == NULL) {
230 return NULL;
231 }
232 }
233 jFIPS = module->isFIPS;
234 for (i = 0; i < module->slotCount; i++ ) {
235 jModule = (*env)->NewObject(env, jModuleClass, jModuleConstructor,
236 jLibDir, jDllName, jCommonName, jFIPS, i);
237 if (jModule == NULL) {
238 return NULL;
239 }
240 (*env)->CallVoidMethod(env, jList, jAdd, jModule);
241 if ((*env)->ExceptionCheck(env)) {
242 return NULL;
243 }
244 }
245 list = list->next;
246 }
247 dprintf("-ok\n");
248
249 return jList;
250}
251