Coverage Report

Created: 2026-07-16 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/cryptlib.c
Line
Count
Source
1
/*
2
 * Copyright 1998-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
4
 *
5
 * Licensed under the Apache License 2.0 (the "License").  You may not use
6
 * this file except in compliance with the License.  You can obtain a copy
7
 * in the file LICENSE in the source distribution or at
8
 * https://www.openssl.org/source/license.html
9
 */
10
11
#include "internal/e_os.h"
12
#include "crypto/cryptlib.h"
13
#include <openssl/safestack.h>
14
15
#if defined(_WIN32) && !defined(OPENSSL_SYS_UEFI)
16
#include <tchar.h>
17
#include <signal.h>
18
#ifdef _MSC_VER
19
#define alloca _alloca
20
#endif
21
22
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0333
23
#ifdef OPENSSL_SYS_WIN_CORE
24
25
int OPENSSL_isservice(void)
26
{
27
    /* OneCore API cannot interact with GUI */
28
    return 1;
29
}
30
#else
31
int OPENSSL_isservice(void)
32
{
33
    HWINSTA h;
34
    DWORD len;
35
    WCHAR *name;
36
    static union {
37
        void *p;
38
        FARPROC f;
39
    } _OPENSSL_isservice = {
40
        NULL
41
    };
42
43
    if (_OPENSSL_isservice.p == NULL) {
44
        HANDLE mod = GetModuleHandle(NULL);
45
        FARPROC f = NULL;
46
47
        if (mod != NULL)
48
            f = GetProcAddress(mod, "_OPENSSL_isservice");
49
        if (f == NULL)
50
            _OPENSSL_isservice.p = (void *)-1;
51
        else
52
            _OPENSSL_isservice.f = f;
53
    }
54
55
    if (_OPENSSL_isservice.p != (void *)-1)
56
        return (int)((*_OPENSSL_isservice.f)());
57
58
    h = GetProcessWindowStation();
59
    if (h == NULL)
60
        return -1;
61
62
    if (GetUserObjectInformationW(h, UOI_NAME, NULL, 0, &len) || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
63
        return -1;
64
65
    if (len > 512)
66
        return -1; /* paranoia */
67
    len++, len &= ~1; /* paranoia */
68
    name = (WCHAR *)alloca(len + sizeof(WCHAR));
69
    if (!GetUserObjectInformationW(h, UOI_NAME, name, len, &len))
70
        return -1;
71
72
    len++, len &= ~1; /* paranoia */
73
    name[len / sizeof(WCHAR)] = L'\0'; /* paranoia */
74
#if 1
75
    /*
76
     * This doesn't cover "interactive" services [working with real
77
     * WinSta0's] nor programs started non-interactively by Task Scheduler
78
     * [those are working with SAWinSta].
79
     */
80
    if (wcsstr(name, L"Service-0x"))
81
        return 1;
82
#else
83
    /* This covers all non-interactive programs such as services. */
84
    if (!wcsstr(name, L"WinSta0"))
85
        return 1;
86
#endif
87
    else
88
        return 0;
89
}
90
#endif
91
#else
92
int OPENSSL_isservice(void)
93
{
94
    return 0;
95
}
96
#endif
97
98
void OPENSSL_showfatal(const char *fmta, ...)
99
{
100
    va_list ap;
101
    TCHAR buf[256];
102
    const TCHAR *fmt;
103
    /*
104
     * First check if it's a console application, in which case the
105
     * error message would be printed to standard error.
106
     */
107
#ifdef STD_ERROR_HANDLE
108
    HANDLE h;
109
110
    if ((h = GetStdHandle(STD_ERROR_HANDLE)) != NULL && GetFileType(h) != FILE_TYPE_UNKNOWN) {
111
        /* must be console application */
112
        int len;
113
        DWORD out;
114
115
        va_start(ap, fmta);
116
        len = _vsnprintf((char *)buf, sizeof(buf), fmta, ap);
117
        WriteFile(h, buf, len < 0 ? sizeof(buf) : (DWORD)len, &out, NULL);
118
        va_end(ap);
119
        return;
120
    }
121
#endif
122
123
    if (sizeof(TCHAR) == sizeof(char))
124
        fmt = (const TCHAR *)fmta;
125
    else
126
        do {
127
            int keepgoing;
128
            size_t len_0 = strlen(fmta) + 1, i;
129
            WCHAR *fmtw;
130
131
            fmtw = (WCHAR *)alloca(len_0 * sizeof(WCHAR));
132
            if (fmtw == NULL) {
133
                fmt = (const TCHAR *)L"no stack?";
134
                break;
135
            }
136
            if (!MultiByteToWideChar(CP_ACP, 0, fmta, (int)len_0, fmtw, (int)len_0))
137
                for (i = 0; i < len_0; i++)
138
                    fmtw[i] = (WCHAR)fmta[i];
139
            for (i = 0; i < len_0; i++) {
140
                if (fmtw[i] == L'%')
141
                    do {
142
                        keepgoing = 0;
143
                        switch (fmtw[i + 1]) {
144
                        case L'0':
145
                        case L'1':
146
                        case L'2':
147
                        case L'3':
148
                        case L'4':
149
                        case L'5':
150
                        case L'6':
151
                        case L'7':
152
                        case L'8':
153
                        case L'9':
154
                        case L'.':
155
                        case L'*':
156
                        case L'-':
157
                            i++;
158
                            keepgoing = 1;
159
                            break;
160
                        case L's':
161
                            fmtw[i + 1] = L'S';
162
                            break;
163
                        case L'S':
164
                            fmtw[i + 1] = L's';
165
                            break;
166
                        case L'c':
167
                            fmtw[i + 1] = L'C';
168
                            break;
169
                        case L'C':
170
                            fmtw[i + 1] = L'c';
171
                            break;
172
                        }
173
                    } while (keepgoing);
174
            }
175
            fmt = (const TCHAR *)fmtw;
176
        } while (0);
177
178
    va_start(ap, fmta);
179
    _vsntprintf(buf, OSSL_NELEM(buf) - 1, fmt, ap);
180
    buf[OSSL_NELEM(buf) - 1] = _T('\0');
181
    va_end(ap);
182
183
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0333
184
#ifdef OPENSSL_SYS_WIN_CORE
185
    /* ONECORE is always NONGUI and NT >= 0x0601 */
186
#if !defined(NDEBUG)
187
    /*
188
     * We are in a situation where we tried to report a critical
189
     * error and this failed for some reason. As a last resort,
190
     * in debug builds, send output to the debugger or any other
191
     * tool like DebugView which can monitor the output.
192
     */
193
    OutputDebugString(buf);
194
#endif
195
#else
196
    /* this -------------v--- guards NT-specific calls */
197
    if (check_winnt() && OPENSSL_isservice() > 0) {
198
        HANDLE hEventLog = RegisterEventSource(NULL, _T("OpenSSL"));
199
200
        if (hEventLog != NULL) {
201
            const TCHAR *pmsg = buf;
202
203
            if (!ReportEvent(hEventLog, EVENTLOG_ERROR_TYPE, 0, 0, NULL,
204
                    1, 0, &pmsg, NULL)) {
205
#if !defined(NDEBUG)
206
                /*
207
                 * We are in a situation where we tried to report a critical
208
                 * error and this failed for some reason. As a last resort,
209
                 * in debug builds, send output to the debugger or any other
210
                 * tool like DebugView which can monitor the output.
211
                 */
212
                OutputDebugString(pmsg);
213
#endif
214
            }
215
216
            (void)DeregisterEventSource(hEventLog);
217
        }
218
    } else {
219
        MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);
220
    }
221
#endif
222
#else
223
    MessageBox(NULL, buf, _T("OpenSSL: FATAL"), MB_OK | MB_ICONERROR);
224
#endif
225
}
226
#else
227
void OPENSSL_showfatal(const char *fmta, ...)
228
0
{
229
0
#ifndef OPENSSL_NO_STDIO
230
0
    va_list ap;
231
232
0
    va_start(ap, fmta);
233
0
    vfprintf(stderr, fmta, ap);
234
0
    va_end(ap);
235
0
#endif
236
0
}
237
238
int OPENSSL_isservice(void)
239
0
{
240
0
    return 0;
241
0
}
242
#endif
243
244
void OPENSSL_die(const char *message, const char *file, int line)
245
0
{
246
0
    OPENSSL_showfatal("%s:%d: OpenSSL internal error: %s\n",
247
0
        file, line, message);
248
0
#if !defined(_WIN32) || defined(OPENSSL_SYS_UEFI)
249
0
    abort();
250
#else
251
    /*
252
     * Win32 abort() customarily shows a dialog, but we just did that...
253
     */
254
    raise(SIGABRT);
255
    _exit(3);
256
#endif
257
0
}
258
259
#if defined(__TANDEM) && defined(OPENSSL_VPROC)
260
/*
261
 * Define a VPROC function for HP NonStop build crypto library.
262
 * This is used by platform version identification tools.
263
 * Do not inline this procedure or make it static.
264
 */
265
#define OPENSSL_VPROC_STRING_(x) x##_CRYPTO
266
#define OPENSSL_VPROC_STRING(x) OPENSSL_VPROC_STRING_(x)
267
#define OPENSSL_VPROC_FUNC OPENSSL_VPROC_STRING(OPENSSL_VPROC)
268
void OPENSSL_VPROC_FUNC(void) { }
269
#endif /* __TANDEM */