VirtualBox

source: vbox/trunk/src/libs/openssl-3.1.3/crypto/dso/dso_win32.c@ 102427

Last change on this file since 102427 was 101211, checked in by vboxsync, 17 months ago

openssl-3.1.3: Applied and adjusted our OpenSSL changes to 3.1.2. bugref:10527

File size: 19.8 KB
Line 
1/*
2 * Copyright 2000-2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (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 "internal/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 ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
124 goto err;
125 }
126 h = loadSystemDll(filename);
127 if (h == NULL) {
128 ERR_raise_data(ERR_LIB_DSO, DSO_R_LOAD_FAILED,
129 "filename(%s)", filename);
130 goto err;
131 }
132 p = OPENSSL_malloc(sizeof(*p));
133 if (p == NULL) {
134 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
135 goto err;
136 }
137 *p = h;
138 if (!sk_void_push(dso->meth_data, p)) {
139 ERR_raise(ERR_LIB_DSO, 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 ERR_raise(ERR_LIB_DSO, 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 ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
166 return 0;
167 }
168 if (!FreeLibrary(*p)) {
169 ERR_raise(ERR_LIB_DSO, 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 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
191 return NULL;
192 }
193 if (sk_void_num(dso->meth_data) < 1) {
194 ERR_raise(ERR_LIB_DSO, 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 ERR_raise(ERR_LIB_DSO, DSO_R_NULL_HANDLE);
200 return NULL;
201 }
202 sym.f = GetProcAddress(*ptr, symname);
203 if (sym.p == NULL) {
204 ERR_raise_data(ERR_LIB_DSO, DSO_R_SYM_FAILURE, "symname(%s)", symname);
205 return NULL;
206 }
207 return (DSO_FUNC_TYPE)sym.f;
208}
209
210struct file_st {
211 const char *node;
212 int nodelen;
213 const char *device;
214 int devicelen;
215 const char *predir;
216 int predirlen;
217 const char *dir;
218 int dirlen;
219 const char *file;
220 int filelen;
221};
222
223static struct file_st *win32_splitter(DSO *dso, const char *filename,
224 int assume_last_is_dir)
225{
226 struct file_st *result = NULL;
227 enum { IN_NODE, IN_DEVICE, IN_FILE } position;
228 const char *start = filename;
229 char last;
230
231 if (!filename) {
232 ERR_raise(ERR_LIB_DSO, DSO_R_NO_FILENAME);
233 return NULL;
234 }
235
236 result = OPENSSL_zalloc(sizeof(*result));
237 if (result == NULL) {
238 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
239 return NULL;
240 }
241
242 position = IN_DEVICE;
243
244 if ((filename[0] == '\\' && filename[1] == '\\')
245 || (filename[0] == '/' && filename[1] == '/')) {
246 position = IN_NODE;
247 filename += 2;
248 start = filename;
249 result->node = start;
250 }
251
252 do {
253 last = filename[0];
254 switch (last) {
255 case ':':
256 if (position != IN_DEVICE) {
257 ERR_raise(ERR_LIB_DSO, DSO_R_INCORRECT_FILE_SYNTAX);
258 OPENSSL_free(result);
259 return NULL;
260 }
261 result->device = start;
262 result->devicelen = (int)(filename - start);
263 position = IN_FILE;
264 start = ++filename;
265 result->dir = start;
266 break;
267 case '\\':
268 case '/':
269 if (position == IN_NODE) {
270 result->nodelen = (int)(filename - start);
271 position = IN_FILE;
272 start = ++filename;
273 result->dir = start;
274 } else if (position == IN_DEVICE) {
275 position = IN_FILE;
276 filename++;
277 result->dir = start;
278 result->dirlen = (int)(filename - start);
279 start = filename;
280 } else {
281 filename++;
282 result->dirlen += (int)(filename - start);
283 start = filename;
284 }
285 break;
286 case '\0':
287 if (position == IN_NODE) {
288 result->nodelen = (int)(filename - start);
289 } else {
290 if (filename - start > 0) {
291 if (assume_last_is_dir) {
292 if (position == IN_DEVICE) {
293 result->dir = start;
294 result->dirlen = 0;
295 }
296 result->dirlen += (int)(filename - start);
297 } else {
298 result->file = start;
299 result->filelen = (int)(filename - start);
300 }
301 }
302 }
303 break;
304 default:
305 filename++;
306 break;
307 }
308 }
309 while (last);
310
311 if (!result->nodelen)
312 result->node = NULL;
313 if (!result->devicelen)
314 result->device = NULL;
315 if (!result->dirlen)
316 result->dir = NULL;
317 if (!result->filelen)
318 result->file = NULL;
319
320 return result;
321}
322
323static char *win32_joiner(DSO *dso, const struct file_st *file_split)
324{
325 int len = 0, offset = 0;
326 char *result = NULL;
327 const char *start;
328
329 if (!file_split) {
330 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
331 return NULL;
332 }
333 if (file_split->node) {
334 len += 2 + file_split->nodelen; /* 2 for starting \\ */
335 if (file_split->predir || file_split->dir || file_split->file)
336 len++; /* 1 for ending \ */
337 } else if (file_split->device) {
338 len += file_split->devicelen + 1; /* 1 for ending : */
339 }
340 len += file_split->predirlen;
341 if (file_split->predir && (file_split->dir || file_split->file)) {
342 len++; /* 1 for ending \ */
343 }
344 len += file_split->dirlen;
345 if (file_split->dir && file_split->file) {
346 len++; /* 1 for ending \ */
347 }
348 len += file_split->filelen;
349
350 if (!len) {
351 ERR_raise(ERR_LIB_DSO, DSO_R_EMPTY_FILE_STRUCTURE);
352 return NULL;
353 }
354
355 result = OPENSSL_malloc(len + 1);
356 if (result == NULL) {
357 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
358 return NULL;
359 }
360
361 if (file_split->node) {
362 strcpy(&result[offset], "\\\\");
363 offset += 2;
364 strncpy(&result[offset], file_split->node, file_split->nodelen);
365 offset += file_split->nodelen;
366 if (file_split->predir || file_split->dir || file_split->file) {
367 result[offset] = '\\';
368 offset++;
369 }
370 } else if (file_split->device) {
371 strncpy(&result[offset], file_split->device, file_split->devicelen);
372 offset += file_split->devicelen;
373 result[offset] = ':';
374 offset++;
375 }
376 start = file_split->predir;
377 while (file_split->predirlen > (start - file_split->predir)) {
378 const char *end = openssl_strnchr(start, '/',
379 file_split->predirlen - (start -
380 file_split->predir));
381 if (!end)
382 end = start
383 + file_split->predirlen - (start - file_split->predir);
384 strncpy(&result[offset], start, end - start);
385 offset += (int)(end - start);
386 result[offset] = '\\';
387 offset++;
388 start = end + 1;
389 }
390 start = file_split->dir;
391 while (file_split->dirlen > (start - file_split->dir)) {
392 const char *end = openssl_strnchr(start, '/',
393 file_split->dirlen - (start -
394 file_split->dir));
395 if (!end)
396 end = start + file_split->dirlen - (start - file_split->dir);
397 strncpy(&result[offset], start, end - start);
398 offset += (int)(end - start);
399 result[offset] = '\\';
400 offset++;
401 start = end + 1;
402 }
403 strncpy(&result[offset], file_split->file, file_split->filelen);
404 offset += file_split->filelen;
405 result[offset] = '\0';
406 return result;
407}
408
409static char *win32_merger(DSO *dso, const char *filespec1,
410 const char *filespec2)
411{
412 char *merged = NULL;
413 struct file_st *filespec1_split = NULL;
414 struct file_st *filespec2_split = NULL;
415
416 if (!filespec1 && !filespec2) {
417 ERR_raise(ERR_LIB_DSO, ERR_R_PASSED_NULL_PARAMETER);
418 return NULL;
419 }
420 if (!filespec2) {
421 merged = OPENSSL_strdup(filespec1);
422 if (merged == NULL) {
423 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
424 return NULL;
425 }
426 } else if (!filespec1) {
427 merged = OPENSSL_strdup(filespec2);
428 if (merged == NULL) {
429 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
430 return NULL;
431 }
432 } else {
433 filespec1_split = win32_splitter(dso, filespec1, 0);
434 if (!filespec1_split) {
435 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
436 return NULL;
437 }
438 filespec2_split = win32_splitter(dso, filespec2, 1);
439 if (!filespec2_split) {
440 ERR_raise(ERR_LIB_DSO, ERR_R_MALLOC_FAILURE);
441 OPENSSL_free(filespec1_split);
442 return NULL;
443 }
444
445 /* Fill in into filespec1_split */
446 if (!filespec1_split->node && !filespec1_split->device) {
447 filespec1_split->node = filespec2_split->node;
448 filespec1_split->nodelen = filespec2_split->nodelen;
449 filespec1_split->device = filespec2_split->device;
450 filespec1_split->devicelen = filespec2_split->devicelen;
451 }
452 if (!filespec1_split->dir) {
453 filespec1_split->dir = filespec2_split->dir;
454 filespec1_split->dirlen = filespec2_split->dirlen;
455 } else if (filespec1_split->dir[0] != '\\'
456 && filespec1_split->dir[0] != '/') {
457 filespec1_split->predir = filespec2_split->dir;
458 filespec1_split->predirlen = filespec2_split->dirlen;
459 }
460 if (!filespec1_split->file) {
461 filespec1_split->file = filespec2_split->file;
462 filespec1_split->filelen = filespec2_split->filelen;
463 }
464
465 merged = win32_joiner(dso, filespec1_split);
466 }
467 OPENSSL_free(filespec1_split);
468 OPENSSL_free(filespec2_split);
469 return merged;
470}
471
472static char *win32_name_converter(DSO *dso, const char *filename)
473{
474 char *translated;
475 int len, transform;
476
477 len = strlen(filename);
478 transform = ((strstr(filename, "/") == NULL) &&
479 (strstr(filename, "\\") == NULL) &&
480 (strstr(filename, ":") == NULL));
481 if (transform)
482 /* We will convert this to "%s.dll" */
483 translated = OPENSSL_malloc(len + 5);
484 else
485 /* We will simply duplicate filename */
486 translated = OPENSSL_malloc(len + 1);
487 if (translated == NULL) {
488 ERR_raise(ERR_LIB_DSO, DSO_R_NAME_TRANSLATION_FAILED);
489 return NULL;
490 }
491 if (transform)
492 sprintf(translated, "%s.dll", filename);
493 else
494 sprintf(translated, "%s", filename);
495 return translated;
496}
497
498static const char *openssl_strnchr(const char *string, int c, size_t len)
499{
500 size_t i;
501 const char *p;
502 for (i = 0, p = string; i < len && *p; i++, p++) {
503 if (*p == c)
504 return p;
505 }
506 return NULL;
507}
508
509# include <tlhelp32.h>
510# ifdef _WIN32_WCE
511# define DLLNAME "TOOLHELP.DLL"
512# else
513# ifdef MODULEENTRY32
514# undef MODULEENTRY32 /* unmask the ASCII version! */
515# endif
516# define DLLNAME "KERNEL32.DLL"
517# endif
518
519typedef HANDLE(WINAPI *CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
520typedef BOOL(WINAPI *CLOSETOOLHELP32SNAPSHOT) (HANDLE);
521typedef BOOL(WINAPI *MODULE32) (HANDLE, MODULEENTRY32 *);
522
523static int win32_pathbyaddr(void *addr, char *path, int sz)
524{
525 HMODULE dll;
526 HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
527 MODULEENTRY32 me32;
528 CREATETOOLHELP32SNAPSHOT create_snap;
529 CLOSETOOLHELP32SNAPSHOT close_snap;
530 MODULE32 module_first, module_next;
531
532 if (addr == NULL) {
533 union {
534 int (*f) (void *, char *, int);
535 void *p;
536 } t = {
537 win32_pathbyaddr
538 };
539 addr = t.p;
540 }
541
542 dll = LoadLibrary(TEXT(DLLNAME));
543 if (dll == NULL) {
544 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
545 return -1;
546 }
547
548 create_snap = (CREATETOOLHELP32SNAPSHOT)
549 GetProcAddress(dll, "CreateToolhelp32Snapshot");
550 if (create_snap == NULL) {
551 FreeLibrary(dll);
552 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
553 return -1;
554 }
555 /* We take the rest for granted... */
556# ifdef _WIN32_WCE
557 close_snap = (CLOSETOOLHELP32SNAPSHOT)
558 GetProcAddress(dll, "CloseToolhelp32Snapshot");
559# else
560 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
561# endif
562 module_first = (MODULE32) GetProcAddress(dll, "Module32First");
563 module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
564
565 /*
566 * Take a snapshot of current process which includes
567 * list of all involved modules.
568 */
569 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
570 if (hModuleSnap == INVALID_HANDLE_VALUE) {
571 FreeLibrary(dll);
572 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
573 return -1;
574 }
575
576 me32.dwSize = sizeof(me32);
577
578 if (!(*module_first) (hModuleSnap, &me32)) {
579 (*close_snap) (hModuleSnap);
580 FreeLibrary(dll);
581 ERR_raise(ERR_LIB_DSO, DSO_R_FAILURE);
582 return -1;
583 }
584
585 /* Enumerate the modules to find one which includes me. */
586 do {
587 if ((size_t) addr >= (size_t) me32.modBaseAddr &&
588 (size_t) addr < (size_t) (me32.modBaseAddr + me32.modBaseSize)) {
589 (*close_snap) (hModuleSnap);
590 FreeLibrary(dll);
591# ifdef _WIN32_WCE
592# if _WIN32_WCE >= 101
593 return WideCharToMultiByte(CP_ACP, 0, me32.szExePath, -1,
594 path, sz, NULL, NULL);
595# else
596 {
597 int i, len = (int)wcslen(me32.szExePath);
598 if (sz <= 0)
599 return len + 1;
600 if (len >= sz)
601 len = sz - 1;
602 for (i = 0; i < len; i++)
603 path[i] = (char)me32.szExePath[i];
604 path[len++] = '\0';
605 return len;
606 }
607# endif
608# else
609 {
610 int len = (int)strlen(me32.szExePath);
611 if (sz <= 0)
612 return len + 1;
613 if (len >= sz)
614 len = sz - 1;
615 memcpy(path, me32.szExePath, len);
616 path[len++] = '\0';
617 return len;
618 }
619# endif
620 }
621 } while ((*module_next) (hModuleSnap, &me32));
622
623 (*close_snap) (hModuleSnap);
624 FreeLibrary(dll);
625 return 0;
626}
627
628static void *win32_globallookup(const char *name)
629{
630 HMODULE dll;
631 HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
632 MODULEENTRY32 me32;
633 CREATETOOLHELP32SNAPSHOT create_snap;
634 CLOSETOOLHELP32SNAPSHOT close_snap;
635 MODULE32 module_first, module_next;
636 union {
637 void *p;
638 FARPROC f;
639 } ret = { NULL };
640
641 dll = loadSystemDll(TEXT(DLLNAME));
642 if (dll == NULL) {
643 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
644 return NULL;
645 }
646
647 create_snap = (CREATETOOLHELP32SNAPSHOT)
648 GetProcAddress(dll, "CreateToolhelp32Snapshot");
649 if (create_snap == NULL) {
650 FreeLibrary(dll);
651 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
652 return NULL;
653 }
654 /* We take the rest for granted... */
655# ifdef _WIN32_WCE
656 close_snap = (CLOSETOOLHELP32SNAPSHOT)
657 GetProcAddress(dll, "CloseToolhelp32Snapshot");
658# else
659 close_snap = (CLOSETOOLHELP32SNAPSHOT) CloseHandle;
660# endif
661 module_first = (MODULE32) GetProcAddress(dll, "Module32First");
662 module_next = (MODULE32) GetProcAddress(dll, "Module32Next");
663
664 hModuleSnap = (*create_snap) (TH32CS_SNAPMODULE, 0);
665 if (hModuleSnap == INVALID_HANDLE_VALUE) {
666 FreeLibrary(dll);
667 ERR_raise(ERR_LIB_DSO, DSO_R_UNSUPPORTED);
668 return NULL;
669 }
670
671 me32.dwSize = sizeof(me32);
672
673 if (!(*module_first) (hModuleSnap, &me32)) {
674 (*close_snap) (hModuleSnap);
675 FreeLibrary(dll);
676 return NULL;
677 }
678
679 do {
680 if ((ret.f = GetProcAddress(me32.hModule, name))) {
681 (*close_snap) (hModuleSnap);
682 FreeLibrary(dll);
683 return ret.p;
684 }
685 } while ((*module_next) (hModuleSnap, &me32));
686
687 (*close_snap) (hModuleSnap);
688 FreeLibrary(dll);
689 return NULL;
690}
691#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