11cb0ef41Sopenharmony_ci/*
21cb0ef41Sopenharmony_ci * Copyright 2018-2020 The OpenSSL Project Authors. All Rights Reserved.
31cb0ef41Sopenharmony_ci *
41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
51cb0ef41Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at
71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html
81cb0ef41Sopenharmony_ci */
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#ifndef _GNU_SOURCE
111cb0ef41Sopenharmony_ci# define _GNU_SOURCE
121cb0ef41Sopenharmony_ci#endif
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#include <stdlib.h>
151cb0ef41Sopenharmony_ci#include "internal/cryptlib.h"
161cb0ef41Sopenharmony_ci#include "e_os.h"
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cichar *ossl_safe_getenv(const char *name)
191cb0ef41Sopenharmony_ci{
201cb0ef41Sopenharmony_ci#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE)
211cb0ef41Sopenharmony_ci    if (GetEnvironmentVariableW(L"OPENSSL_WIN32_UTF8", NULL, 0) != 0) {
221cb0ef41Sopenharmony_ci        char *val = NULL;
231cb0ef41Sopenharmony_ci        int vallen = 0;
241cb0ef41Sopenharmony_ci        WCHAR *namew = NULL;
251cb0ef41Sopenharmony_ci        WCHAR *valw = NULL;
261cb0ef41Sopenharmony_ci        DWORD envlen = 0;
271cb0ef41Sopenharmony_ci        DWORD dwFlags = MB_ERR_INVALID_CHARS;
281cb0ef41Sopenharmony_ci        int rsize, fsize;
291cb0ef41Sopenharmony_ci        UINT curacp;
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci        curacp = GetACP();
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci        /*
341cb0ef41Sopenharmony_ci         * For the code pages listed below, dwFlags must be set to 0.
351cb0ef41Sopenharmony_ci         * Otherwise, the function fails with ERROR_INVALID_FLAGS.
361cb0ef41Sopenharmony_ci         */
371cb0ef41Sopenharmony_ci        if (curacp == 50220 || curacp == 50221 || curacp == 50222 ||
381cb0ef41Sopenharmony_ci            curacp == 50225 || curacp == 50227 || curacp == 50229 ||
391cb0ef41Sopenharmony_ci            (57002 <= curacp && curacp <=57011) || curacp == 65000 ||
401cb0ef41Sopenharmony_ci            curacp == 42)
411cb0ef41Sopenharmony_ci            dwFlags = 0;
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci        /* query for buffer len */
441cb0ef41Sopenharmony_ci        rsize = MultiByteToWideChar(curacp, dwFlags, name, -1, NULL, 0);
451cb0ef41Sopenharmony_ci        /* if name is valid string and can be converted to wide string */
461cb0ef41Sopenharmony_ci        if (rsize > 0)
471cb0ef41Sopenharmony_ci            namew = _malloca(rsize * sizeof(WCHAR));
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci        if (NULL != namew) {
501cb0ef41Sopenharmony_ci            /* convert name to wide string */
511cb0ef41Sopenharmony_ci            fsize = MultiByteToWideChar(curacp, dwFlags, name, -1, namew, rsize);
521cb0ef41Sopenharmony_ci            /* if conversion is ok, then determine value string size in wchars */
531cb0ef41Sopenharmony_ci            if (fsize > 0)
541cb0ef41Sopenharmony_ci                envlen = GetEnvironmentVariableW(namew, NULL, 0);
551cb0ef41Sopenharmony_ci        }
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci        if (envlen > 0)
581cb0ef41Sopenharmony_ci            valw = _malloca(envlen * sizeof(WCHAR));
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci        if (NULL != valw) {
611cb0ef41Sopenharmony_ci            /* if can get env value as wide string */
621cb0ef41Sopenharmony_ci            if (GetEnvironmentVariableW(namew, valw, envlen) < envlen) {
631cb0ef41Sopenharmony_ci                /* determine value string size in utf-8 */
641cb0ef41Sopenharmony_ci                vallen = WideCharToMultiByte(CP_UTF8, 0, valw, -1, NULL, 0,
651cb0ef41Sopenharmony_ci                                             NULL, NULL);
661cb0ef41Sopenharmony_ci            }
671cb0ef41Sopenharmony_ci        }
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ci        if (vallen > 0)
701cb0ef41Sopenharmony_ci            val = OPENSSL_malloc(vallen);
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci        if (NULL != val) {
731cb0ef41Sopenharmony_ci            /* convert value string from wide to utf-8 */
741cb0ef41Sopenharmony_ci            if (WideCharToMultiByte(CP_UTF8, 0, valw, -1, val, vallen,
751cb0ef41Sopenharmony_ci                                    NULL, NULL) == 0) {
761cb0ef41Sopenharmony_ci                OPENSSL_free(val);
771cb0ef41Sopenharmony_ci                val = NULL;
781cb0ef41Sopenharmony_ci            }
791cb0ef41Sopenharmony_ci        }
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci        if (NULL != namew)
821cb0ef41Sopenharmony_ci            _freea(namew);
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ci        if (NULL != valw)
851cb0ef41Sopenharmony_ci            _freea(valw);
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci        return val;
881cb0ef41Sopenharmony_ci    }
891cb0ef41Sopenharmony_ci#endif
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
921cb0ef41Sopenharmony_ci# if __GLIBC_PREREQ(2, 17)
931cb0ef41Sopenharmony_ci#  define SECURE_GETENV
941cb0ef41Sopenharmony_ci    return secure_getenv(name);
951cb0ef41Sopenharmony_ci# endif
961cb0ef41Sopenharmony_ci#endif
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ci#ifndef SECURE_GETENV
991cb0ef41Sopenharmony_ci    if (OPENSSL_issetugid())
1001cb0ef41Sopenharmony_ci        return NULL;
1011cb0ef41Sopenharmony_ci    return getenv(name);
1021cb0ef41Sopenharmony_ci#endif
1031cb0ef41Sopenharmony_ci}
104