1 /* crypto/cryptlib.c */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <stdio.h> 60 #include <string.h> 61 #include "cryptlib.h" 62 #include <openssl/crypto.h> 63 64 #if defined(WIN32) || defined(WIN16) 65 static double SSLeay_MSVC5_hack=0.0; /* and for VC1.5 */ 66 #endif 67 68 /* real #defines in crypto.h, keep these upto date */ 69 static const char* lock_names[CRYPTO_NUM_LOCKS] = 70 { 71 "<<ERROR>>", 72 "err", 73 "err_hash", 74 "x509", 75 "x509_info", 76 "x509_pkey", 77 "x509_crl", 78 "x509_req", 79 "dsa", 80 "rsa", 81 "evp_pkey", 82 "x509_store", 83 "ssl_ctx", 84 "ssl_cert", 85 "ssl_session", 86 "ssl_sess_cert", 87 "ssl", 88 "rand", 89 "debug_malloc", 90 "BIO", 91 "gethostbyname", 92 "getservbyname", 93 "readdir", 94 "RSA_blinding", 95 "dh", 96 "debug_malloc2", 97 #if CRYPTO_NUM_LOCKS != 26 98 # error "Inconsistency between crypto.h and cryptlib.c" 99 #endif 100 }; 101 102 static STACK *app_locks=NULL; 103 104 static void (MS_FAR *locking_callback)(int mode,int type, 105 const char *file,int line)=NULL; 106 static int (MS_FAR *add_lock_callback)(int *pointer,int amount, 107 int type,const char *file,int line)=NULL; 108 static unsigned long (MS_FAR *id_callback)(void)=NULL; 109 int CRYPTO_get_new_lockid(char *name) 110 { 111 char *str; 112 int i; 113 114 /* A hack to make Visual C++ 5.0 work correctly when linking as 115 * a DLL using /MT. Without this, the application cannot use 116 * and floating point printf's. 117 * It also seems to be needed for Visual C 1.5 (win16) */ 118 #if defined(WIN32) || defined(WIN16) 119 SSLeay_MSVC5_hack=(double)name[0]*(double)name[1]; 120 #endif 121 122 if ((app_locks == NULL) && ((app_locks=sk_new_null()) == NULL)) 123 { 124 CRYPTOerr(CRYPTO_F_CRYPTO_GET_NEW_LOCKID,ERR_R_MALLOC_FAILURE); 125 return(0); 126 } 127 if ((str=BUF_strdup(name)) == NULL) 128 return(0); 129 i=sk_push(app_locks,str); 130 if (!i) 131 Free(str); 132 else 133 i+=CRYPTO_NUM_LOCKS; /* gap of one :-) */ 134 return(i); 135 } 136 137 int CRYPTO_num_locks(void) 138 { 139 return CRYPTO_NUM_LOCKS; 140 } 141 142 void (*CRYPTO_get_locking_callback(void))(int mode,int type,const char *file, 143 int line) 144 { 145 return(locking_callback); 146 } 147 148 int (*CRYPTO_get_add_lock_callback(void))(int *num,int mount,int type, 149 const char *file,int line) 150 { 151 return(add_lock_callback); 152 } 153 154 void CRYPTO_set_locking_callback(void (*func)(int mode,int type, 155 const char *file,int line)) 156 { 157 locking_callback=func; 158 } 159 160 void CRYPTO_set_add_lock_callback(int (*func)(int *num,int mount,int type, 161 const char *file,int line)) 162 { 163 add_lock_callback=func; 164 } 165 166 unsigned long (*CRYPTO_get_id_callback(void))(void) 167 { 168 return(id_callback); 169 } 170 171 void CRYPTO_set_id_callback(unsigned long (*func)(void)) 172 { 173 id_callback=func; 174 } 175 176 unsigned long CRYPTO_thread_id(void) 177 { 178 unsigned long ret=0; 179 180 if (id_callback == NULL) 181 { 182 #ifdef WIN16 183 ret=(unsigned long)GetCurrentTask(); 184 #elif defined(WIN32) 185 ret=(unsigned long)GetCurrentThreadId(); 186 #elif defined(GETPID_IS_MEANINGLESS) 187 ret=1L; 188 #else 189 ret=(unsigned long)getpid(); 190 #endif 191 } 192 else 193 ret=id_callback(); 194 return(ret); 195 } 196 197 void CRYPTO_lock(int mode, int type, const char *file, int line) 198 { 199 #ifdef LOCK_DEBUG 200 { 201 char *rw_text,*operation_text; 202 203 if (mode & CRYPTO_LOCK) 204 operation_text="lock "; 205 else if (mode & CRYPTO_UNLOCK) 206 operation_text="unlock"; 207 else 208 operation_text="ERROR "; 209 210 if (mode & CRYPTO_READ) 211 rw_text="r"; 212 else if (mode & CRYPTO_WRITE) 213 rw_text="w"; 214 else 215 rw_text="ERROR"; 216 217 fprintf(stderr,"lock:%08lx:(%s)%s %-18s %s:%d\n", 218 CRYPTO_thread_id(), rw_text, operation_text, 219 CRYPTO_get_lock_name(type), file, line); 220 } 221 #endif 222 if (locking_callback != NULL) 223 locking_callback(mode,type,file,line); 224 } 225 226 int CRYPTO_add_lock(int *pointer, int amount, int type, const char *file, 227 int line) 228 { 229 int ret; 230 231 if (add_lock_callback != NULL) 232 { 233 #ifdef LOCK_DEBUG 234 int before= *pointer; 235 #endif 236 237 ret=add_lock_callback(pointer,amount,type,file,line); 238 #ifdef LOCK_DEBUG 239 fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 240 CRYPTO_thread_id(), 241 before,amount,ret, 242 CRYPTO_get_lock_name(type), 243 file,line); 244 #endif 245 *pointer=ret; 246 } 247 else 248 { 249 CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,file,line); 250 251 ret= *pointer+amount; 252 #ifdef LOCK_DEBUG 253 fprintf(stderr,"ladd:%08lx:%2d+%2d->%2d %-18s %s:%d\n", 254 CRYPTO_thread_id(), 255 *pointer,amount,ret, 256 CRYPTO_get_lock_name(type), 257 file,line); 258 #endif 259 *pointer=ret; 260 CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,file,line); 261 } 262 return(ret); 263 } 264 265 const char *CRYPTO_get_lock_name(int type) 266 { 267 if (type < 0) 268 return("ERROR"); 269 else if (type < CRYPTO_NUM_LOCKS) 270 return(lock_names[type]); 271 else if (type-CRYPTO_NUM_LOCKS >= sk_num(app_locks)) 272 return("ERROR"); 273 else 274 return(sk_value(app_locks,type-CRYPTO_NUM_LOCKS)); 275 } 276 277 #ifdef _DLL 278 #ifdef WIN32 279 280 /* All we really need to do is remove the 'error' state when a thread 281 * detaches */ 282 283 BOOL WINAPI DLLEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, 284 LPVOID lpvReserved) 285 { 286 switch(fdwReason) 287 { 288 case DLL_PROCESS_ATTACH: 289 break; 290 case DLL_THREAD_ATTACH: 291 break; 292 case DLL_THREAD_DETACH: 293 ERR_remove_state(0); 294 break; 295 case DLL_PROCESS_DETACH: 296 break; 297 } 298 return(TRUE); 299 } 300 #endif 301 302 #endif 303