VirtualBox

source: vbox/trunk/src/libs/openssl-1.1.1l/crypto/dso/dso_win32.c@ 91772

Last change on this file since 91772 was 91772, checked in by vboxsync, 3 years ago

openssl-1.1.1l: Applied and adjusted our OpenSSL changes to 1.1.1l. bugref:10126

File size: 20.0 KB
Line 
1/*
2 * Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include "e_os.h"
11#include "dso_local.h"
12
13#if defined(DSO_WIN32)
14
15# ifdef _WIN32_WCE
16# if _WIN32_WCE < 300
17static FARPROC GetProcAddressA(HMODULE hModule, LPCSTR lpProcName)
18{
19 WCHAR lpProcNameW[64];
20 int i;
21
22 for (i = 0; lpProcName[i] && i < 64; i++)
23 lpProcNameW[i] = (WCHAR)lpProcName[i];
24 if (i == 64)
25 return NULL;
26 lpProcNameW[i] = 0;
27
28 return GetProcAddressW(hModule, lpProcNameW);
29}
30# endif
31# undef GetProcAddress
32# define GetProcAddress GetProcAddressA
33
34static HINSTANCE LoadLibraryA(LPCSTR lpLibFileName)
35{
36 WCHAR *fnamw;
37 size_t len_0 = strlen(lpLibFileName) + 1, i;
38
39# ifdef _MSC_VER
40 fnamw = (WCHAR *)_alloca(len_0 * sizeof(WCHAR));
41# else
42 fnamw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
43# endif
44 if (fnamw == NULL) {
45 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
46 return NULL;
47 }
48# if defined(_WIN32_WCE) && _WIN32_WCE>=101
49 if (!MultiByteToWideChar(CP_ACP, 0, lpLibFileName, len_0, fnamw, len_0))
50# endif
51 for (i = 0; i < len_0; i++)
52 fnamw[i] = (WCHAR)lpLibFileName[i];
53
54 return LoadLibraryW(fnamw);
55}
56# endif
57
58/* Part of the hack in "win32_load" ... */
59# define DSO_MAX_TRANSLATED_SIZE 256
60
61static int win32_load(DSO *dso);
62static int win32_unload(DSO *dso);
63static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname);
64static char *win32_name_converter(DSO *dso, const char *filename);
65static char *win32_merger(DSO *dso, const char *filespec1,
66 const char *filespec2);
67static int win32_pathbyaddr(void *addr, char *path, int sz);
68static void *win32_globallookup(const char *name);
69
70static const char *openssl_strnchr(const char *string, int c, size_t len);
71
72static DSO_METHOD dso_meth_win32 = {
73 "OpenSSL 'win32' shared library method",
74 win32_load,
75 win32_unload,
76 win32_bind_func,
77 NULL, /* ctrl */
78 win32_name_converter,
79 win32_merger,
80 NULL, /* init */
81 NULL, /* finish */
82 win32_pathbyaddr, /* pathbyaddr */
83 win32_globallookup
84};
85
86DSO_METHOD *DSO_METHOD_openssl(void)
87{
88 return &dso_meth_win32;
89}
90
91/*
92 * For this DSO_METHOD, our meth_data STACK will contain; (i) a pointer to
93 * the handle (HINSTANCE) returned from LoadLibrary(), and copied.
94 */
95
96#ifdef VBOX
97/**
98 * Loads a system DLL.
99 *
100 * @returns Module handle or NULL
101 * @param pszName The DLL name.
102 */
103static HMODULE loadSystemDll(const char *pszName)
104{
105 char szPath[MAX_PATH];
106 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
107 size_t cbName = strlen(pszName) + 1;
108 if (cchPath + 1 + cbName > sizeof(szPath))
109 return NULL;
110 szPath[cchPath] = '\\';
111 memcpy(&szPath[cchPath + 1], pszName, cbName);
112 return LoadLibraryA(szPath);
113}
114#endif
115
116static int win32_load(DSO *dso)
117{
118 HINSTANCE h = NULL, *p = NULL;
119 /* See applicable comments from dso_dl.c */
120 char *filename = DSO_convert_filename(dso, NULL);
121
122 if (filename == NULL) {
123 DSOerr(DSO_F_WIN32_LOAD, DSO_R_NO_FILENAME);
124 goto err;
125 }
126 h = loadSystemDll(filename);
127 if (h == NULL) {
128 DSOerr(DSO_F_WIN32_LOAD, DSO_R_LOAD_FAILED);
129 ERR_add_error_data(3, "filename(", filename, ")");
130 goto err;
131 }
132 p = OPENSSL_malloc(sizeof(*p));
133 if (p == NULL) {
134 DSOerr(DSO_F_WIN32_LOAD, ERR_R_MALLOC_FAILURE);
135 goto err;
136 }
137 *p = h;
138 if (!sk_void_push(dso->meth_data, p)) {
139 DSOerr(DSO_F_WIN32_LOAD, DSO_R_STACK_ERROR);
140 goto err;
141 }
142 /* Success */
143 dso->loaded_filename = filename;
144 return 1;
145 err:
146 /* Cleanup ! */
147 OPENSSL_free(filename);
148 OPENSSL_free(p);
149 if (h != NULL)
150 FreeLibrary(h);
151 return 0;
152}
153
154static int win32_unload(DSO *dso)
155{
156 HINSTANCE *p;
157 if (dso == NULL) {
158 DSOerr(DSO_F_WIN32_UNLOAD, ERR_R_PASSED_NULL_PARAMETER);
159 return 0;
160 }
161 if (sk_void_num(dso->meth_data) < 1)
162 return 1;
163 p = sk_void_pop(dso->meth_data);
164 if (p == NULL) {
165 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_NULL_HANDLE);
166 return 0;
167 }
168 if (!FreeLibrary(*p)) {
169 DSOerr(DSO_F_WIN32_UNLOAD, DSO_R_UNLOAD_FAILED);
170 /*
171 * We should push the value back onto the stack in case of a retry.
172 */
173 sk_void_push(dso->meth_data, p);
174 return 0;
175 }
176 /* Cleanup */
177 OPENSSL_free(p);
178 return 1;
179}
180
181static DSO_FUNC_TYPE win32_bind_func(DSO *dso, const char *symname)
182{
183 HINSTANCE *ptr;
184 union {
185 void *p;
186 FARPROC f;
187 } sym;
188
189 if ((dso == NULL) || (symname == NULL)) {
190 DSOerr(DSO_F_WIN32_BIND_FUNC, ERR_R_PASSED_NULL_PARAMETER);
191 return NULL;
192 }
193 if (sk_void_num(dso->meth_data) < 1) {
194 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_STACK_ERROR);
195 return NULL;
196 }
197 ptr = sk_void_value(dso->meth_data, sk_void_num(dso->meth_data) - 1);
198 if (ptr == NULL) {
199 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_NULL_HANDLE);
200 return NULL;
201 }
202 sym.f = GetProcAddress(*ptr, symname);
203 if (sym.p == NULL) {
204 DSOerr(DSO_F_WIN32_BIND_FUNC, DSO_R_SYM_FAILURE);
205 ERR_add_error_data(3, "symname(", symname, ")");
206 return NULL;
207 }
208 return (DSO_FUNC_TYPE)sym.f;
209}
210
211struct file_st {
212 const char *node;
213 int nodelen;
214 const char *device;
215 int devicelen;
216 const char *predir;
217 int predirlen;
218 const char *dir;
219 int dirlen;
220 const char *file;
221 int filelen;
222};
223
224static struct file_st *win32_splitter(DSO *dso, const char *filename,
225 int assume_last_is_dir)
226{
227 struct file_st *result = NULL;
228 enum { IN_NODE, IN_DEVICE, IN_FILE } position;
229 const char *start = filename;
230 char last;
231
232 if (!filename) {
233 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_NO_FILENAME);
234 return NULL;
235 }
236
237 result = OPENSSL_zalloc(sizeof(*result));
238 if (result == NULL) {
239 DSOerr(DSO_F_WIN32_SPLITTER, ERR_R_MALLOC_FAILURE);
240 return NULL;
241 }
242
243 position = IN_DEVICE;
244
245 if ((filename[0] == '\\' && filename[1] == '\\')
246 || (filename[0] == '/' && filename[1] == '/')) {
247 position = IN_NODE;
248 filename += 2;
249 start = filename;
250 result->node = start;
251 }
252
253 do {
254 last = filename[0];
255 switch (last) {
256 case ':':
257 if (position != IN_DEVICE) {
258 DSOerr(DSO_F_WIN32_SPLITTER, DSO_R_INCORRECT_FILE_SYNTAX);
259 OPENSSL_free(result);
260 return NULL;
261 }
262 result->device = start;
263 result->devicelen = (int)(filename - start);
264 position = IN_FILE;
265 start = ++filename;
266 result->dir = start;
267 break;
268 case '\\':
269 case '/':
270 if (position == IN_NODE) {
271 result->nodelen = (int)(filename - start);
272 position = IN_FILE;
273 start = ++filename;
274 result->dir = start;
275 } else if (position == IN_DEVICE) {
276 position = IN_FILE;
277 filename++;
278 result->dir = start;
279 result->dirlen = (int)(filename - start);
280 start = filename;
281 } else {
282 filename++;
283 result->dirlen += (int)(filename - start);
284 start = filename;
285 }
286 break;
287 case '\0':
288 if (position == IN_NODE) {
289 result->nodelen = (int)(filename - start);
290 } else {
291 if (filename - start > 0) {
292 if (assume_last_is_dir) {
293 if (position == IN_DEVICE) {
294 result->dir = start;
295 result->dirlen = 0;
296 }
297 result->dirlen += (int)(filename - start);
298 } else {
299 result->file = start;
300 result->filelen = (int)(filename - start);
301 }
302 }
303 }
304 break;
305 default:
306 filename++;
307 break;
308 }
309 }
310 while (last);
311
312 if (!result->nodelen)
313 result->node = NULL;
314 if (!result->devicelen)
315 result->device = NULL;
316 if (!result->dirlen)
317 result->dir = NULL;
318 if (!result->filelen)
319 result->file = NULL;
320
321 return result;
322}
323
324static char *win32_joiner(DSO *dso, const struct file_st *file_split)
325{
326 int len = 0, offset = 0;
327 char *result = NULL;
328 const char *start;
329
330 if (!file_split) {
331 DSOerr(DSO_F_WIN32_JOINER, ERR_R_PASSED_NULL_PARAMETER);
332 return NULL;
333 }
334 if (file_split->node) {
335 len += 2 + file_split->nodelen; /* 2 for starting \\ */
336 if (file_split->predir || file_split->dir || file_split->file)
337 len++; /* 1 for ending \ */
338 } else if (file_split->device) {
339 len += file_split->devicelen + 1; /* 1 for ending : */
340 }
341 len += file_split->predirlen;
342 if (file_split->predir && (file_split->dir || file_split->file)) {
343 len++; /* 1 for ending \ */
344 }
345 len += file_split->dirlen;
346 if (file_split->dir && file_split->file) {
347 len++; /* 1 for ending \ */
348 }
349 len += file_split->filelen;
350
351 if (!len) {
352 DSOerr(DSO_F_WIN32_JOINER, DSO_R_EMPTY_FILE_STRUCTURE);
353 return NULL;
354 }
355
356 result = OPENSSL_malloc(len + 1);
357 if (result == NULL) {
358 DSOerr(DSO_F_WIN32_JOINER, ERR_R_MALLOC_FAILURE);
359 return NULL;
360 }
361
362 if (file_split->node) {
363 strcpy(&result[offset], "\\\\");
364 offset += 2;
365 strncpy(&result[offset], file_split->node, file_split->nodelen);
366 offset += file_split->nodelen;
367 if (file_split->predir || file_split->dir || file_split->file) {
368 result[offset] = '\\';
369 offset++;
370 }
371 } else if (file_split->device) {
372 strncpy(&result[offset], file_split->device, file_split->devicelen);
373 offset += file_split->devicelen;
374 result[offset] = ':';
375 offset++;
376 }
377 start = file_split->predir;
378 while (file_split->predirlen > (start - file_split->predir)) {
379 const char *end = openssl_strnchr(start, '/',
380 file_split->predirlen - (start -
381 file_split->predir));
382 if (!end)
383 end = start
384 + file_split->predirlen - (start - file_split->predir);
385 strncpy(&result[offset], start, end - start);
386 offset += (int)(end - start);
387 result[offset] = '\\';
388 offset++;
389 start = end + 1;
390 }
391 start = file_split->dir;
392 while (file_split->dirlen > (start - file_split->dir)) {
393 const char *end = openssl_strnchr(start, '/',
394 file_split->dirlen - (start -
395 file_split->dir));
396 if (!end)
397 end = start + file_split->dirlen - (start - file_split->dir);
398 strncpy(&result[offset], start, end - start);
399 offset += (int)(end - start);
400 result[offset] = '\\';
401 offset++;
402 start = end + 1;
403 }
404 strncpy(&result[offset], file_split->file, file_split->filelen);
405 offset += file_split->filelen;
406 result[offset] = '\0';
407 return result;
408}
409
410static char *win32_merger(DSO *dso, const char *filespec1,
411 const char *filespec2)
412{
413 char *merged = NULL;
414 struct file_st *filespec1_split = NULL;
415 struct file_st *filespec2_split = NULL;
416
417 if (!filespec1 && !filespec2) {
418 DSOerr(DSO_F_WIN32_MERGER, ERR_R_PASSED_NULL_PARAMETER);
419 return NULL;
420 }
421 if (!filespec2) {
422 merged = OPENSSL_strdup(filespec1);
423 if (merged == NULL) {
424 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
425 return NULL;
426 }
427 } else if (!filespec1) {
428 merged = OPENSSL_strdup(filespec2);
429 if (merged == NULL) {
430 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
431 return NULL;
432 }
433 } else {
434 filespec1_split = win32_splitter(dso, filespec1, 0);
435 if (!filespec1_split) {
436 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
437 return NULL;
438 }
439 filespec2_split = win32_splitter(dso, filespec2, 1);
440 if (!filespec2_split) {
441 DSOerr(DSO_F_WIN32_MERGER, ERR_R_MALLOC_FAILURE);
442 OPENSSL_free(filespec1_split);
443 return NULL;
444 }
445
446 /* Fill in into filespec1_split */
447 if (!filespec1_split->node && !filespec1_split->device) {
448 filespec1_split->node = filespec2_split->node;
449 filespec1_split->nodelen = filespec2_split->nodelen;
450 filespec1_split->device = filespec2_split->device;
451 filespec1_split->devicelen = filespec2_split->devicelen;
452 }
453 if (!filespec1_split->dir) {
454 filespec1_split->dir = filespec2_split->dir;
455 filespec1_split->dirlen = filespec2_split->dirlen;
456 } else if (filespec1_split->dir[0] != '\\'
457 && filespec1_split->dir[0] != '/') {
458 filespec1_split->predir = filespec2_split->dir;
459 filespec1_split->predirlen = filespec2_split->dirlen;
460 }
461 if (!filespec1_split->file) {
462 filespec1_split->file = filespec2_split->file;
463 filespec1_split->filelen = filespec2_split->filelen;
464 }
465
466 merged = win32_joiner(dso, filespec1_split);
467 }
468 OPENSSL_free(filespec1_split);
469 OPENSSL_free(filespec2_split);
470 return merged;
471}
472
473static char *win32_name_converter(DSO *dso, const char *filename)
474{
475 char *translated;
476 int len, transform;
477
478 len = strlen(filename);
479 transform = ((strstr(filename, "/") == NULL) &&
480 (strstr(filename, "\\") == NULL) &&
481 (strstr(filename, ":") == NULL));
482 if (transform)
483 /* We will convert this to "%s.dll" */
484 translated = OPENSSL_malloc(len + 5);
485 else
486 /* We will simply duplicate filename */
487 translated = OPENSSL_malloc(len + 1);
488 if (translated == NULL) {
489 DSOerr(DSO_F_WIN32_NAME_CONVERTER, DSO_R_NAME_TRANSLATION_FAILED);
490 return NULL;
491 }
492 if (transform)
493 sprintf(translated, "%s.dll", filename);
494 else
495 sprintf(translated, "%s", filename);
496 return translated;
497}
498
499static const char *openssl_strnchr(const char *string, int c, size_t len)
500{
501 size_t i;
502 const char *p;
503 for (i = 0, p = string; i < len && *p; i++, p++) {
504 if (*p == c)
505 return p;
506 }
507 return NULL;
508}
509
510# include <tlhelp32.h>
511# ifdef _WIN32_WCE
512# define DLLNAME "TOOLHELP.DLL"
513# else
514# ifdef MODULEENTRY32
515# undef MODULEENTRY32 /* unmask the ASCII version! */
516# endif
517# define DLLNAME "KERNEL32.DLL"
518# endif
519
520typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
521typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
522typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
523
524static int win32_pathbyaddr(void *addr, char *path, int sz)
525{
526 HMODULE dll;
527 HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
528 MODULEENTRY32 me32;
529 CREATETOOLHELP32SNAPSHOT create_snap;
530 CLOSETOOLHELP32SNAPSHOT close_snap;
531 MODULE32 module_first, module_next;
532
533 if (addr == NULL) {
534 union {
535 int (*f) (void *, char *, int);
536 void *p;
537 } t = {
538 win32_pathbyaddr
539 };
540 addr = t.p;
541 }
542
543 dll = LoadLibrary(TEXT(DLLNAME));
544 if (dll == NULL) {
545 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
546 return -1;
547 }
548
549 create_snap = (CREATETOOLHELP32SNAPSHOT)
550 GetProcAddress(dll, "CreateToolhelp32Snapshot");
551 if (create_snap == NULL) {
552 FreeLibrary(dll);
553 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
554 return -1;
555 }
556 /* We take the rest for granted... */
557# ifdef _WIN32_WCE
558 close_snap = (CLOSETOOLHELP32SNAPSHOT)
559 GetProcAddress(dll, "CloseToolhelp32Snapshot");
560# else
561 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
562# endif
563 module_first = (MODULE32) GetProcAddress(dll, "Module32First");
564 module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
565
566 /*
567 * Take a snapshot of current process which includes
568 * list of all involved modules.
569 */
570 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
571 if (hModuleSnap == INVALID_HANDLE_VALUE) {
572 FreeLibrary(dll);
573 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_UNSUPPORTED);
574 return -1;
575 }
576
577 me32.dwSize = sizeof(me32);
578
579 if (!(*module_first) (hModuleSnap, &me32)) {
580 (*close_snap) (hModuleSnap);
581 FreeLibrary(dll);
582 DSOerr(DSO_F_WIN32_PATHBYADDR, DSO_R_FAILURE);
583 return -1;
584 }
585
586 /* Enumerate the modules to find one which includes me. */
587 do {
588 if ((size_t) addr >= (size_t) me32.modBaseAddr &&
589 (size_t) addr < (size_t) (me32.modBaseAddr + me32.modBaseSize)) {
590 (*close_snap) (hModuleSnap);
591 FreeLibrary(dll);
592# ifdef _WIN32_WCE
593# if _WIN32_WCE >= 101
594 return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1,
595 path, sz, NULL, NULL);
596# else
597 {
598 int i, len = (int)wcslen(me32.szExePath);
599 if (sz <= 0)
600 return len + 1;
601 if (len >= sz)
602 len = sz - 1;
603 for (i = 0; i < len; i++)
604 path[i] = (char)me32.szExePath[i];
605 path[len++] = '\0';
606 return len;
607 }
608# endif
609# else
610 {
611 int len = (int)strlen(me32.szExePath);
612 if (sz <= 0)
613 return len + 1;
614 if (len >= sz)
615 len = sz - 1;
616 memcpy(path, me32.szExePath, len);
617 path[len++] = '\0';
618 return len;
619 }
620# endif
621 }
622 } while ((*module_next) (hModuleSnap, &me32));
623
624 (*close_snap) (hModuleSnap);
625 FreeLibrary(dll);
626 return 0;
627}
628
629static void *win32_globallookup(const char *name)
630{
631 HMODULE dll;
632 HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
633 MODULEENTRY32 me32;
634 CREATETOOLHELP32SNAPSHOT create_snap;
635 CLOSETOOLHELP32SNAPSHOT close_snap;
636 MODULE32 module_first, module_next;
637 union {
638 void *p;
639 FARPROC f;
640 } ret = { NULL };
641
642 dll = loadSystemDll(TEXT(DLLNAME));
643 if (dll == NULL) {
644 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
645 return NULL;
646 }
647
648 create_snap = (CREATETOOLHELP32SNAPSHOT)
649 GetProcAddress(dll, "CreateToolhelp32Snapshot");
650 if (create_snap == NULL) {
651 FreeLibrary(dll);
652 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
653 return NULL;
654 }
655 /* We take the rest for granted... */
656# ifdef _WIN32_WCE
657 close_snap = (CLOSETOOLHELP32SNAPSHOT)
658 GetProcAddress(dll, "CloseToolhelp32Snapshot");
659# else
660 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
661# endif
662 module_first = (MODULE32) GetProcAddress(dll, "Module32First");
663 module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
664
665 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
666 if (hModuleSnap == INVALID_HANDLE_VALUE) {
667 FreeLibrary(dll);
668 DSOerr(DSO_F_WIN32_GLOBALLOOKUP, DSO_R_UNSUPPORTED);
669 return NULL;
670 }
671
672 me32.dwSize = sizeof(me32);
673
674 if (!(*module_first) (hModuleSnap, &me32)) {
675 (*close_snap) (hModuleSnap);
676 FreeLibrary(dll);
677 return NULL;
678 }
679
680 do {
681 if ((ret.f = GetProcAddress(me32.hModule, name))) {
682 (*close_snap) (hModuleSnap);
683 FreeLibrary(dll);
684 return ret.p;
685 }
686 } while ((*module_next) (hModuleSnap, &me32));
687
688 (*close_snap) (hModuleSnap);
689 FreeLibrary(dll);
690 return NULL;
691}
692#endif /* DSO_WIN32 */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette