| 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 |  | 
| 36 | JNIEXPORT 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 |  */ | 
| 66 | JNIEXPORT 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 |  | 
| 142 | cleanup: | 
| 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 |  | 
| 161 | JNIEXPORT 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 |  |