1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2018 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Zeev Suraski <zeev@zend.com> |
16 * Pierre Joye <pierre@php.net> |
17 +----------------------------------------------------------------------+
18 */
19
20 /* $Id$ */
21
22 #include "php.h"
23 #include "winutil.h"
24 #include <wincrypt.h>
25 #include <lmcons.h>
26
php_win32_error_to_msg(HRESULT error)27 PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error)
28 {
29 char *buf = NULL;
30
31 FormatMessage(
32 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
33 NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL
34 );
35
36 return (buf ? (char *) buf : "");
37 }
38
php_win32_check_trailing_space(const char * path,const int path_len)39 int php_win32_check_trailing_space(const char * path, const int path_len) {
40 if (path_len < 1) {
41 return 1;
42 }
43 if (path) {
44 if (path[0] == ' ' || path[path_len - 1] == ' ') {
45 return 0;
46 } else {
47 return 1;
48 }
49 } else {
50 return 0;
51 }
52 }
53
54 HCRYPTPROV hCryptProv;
55 unsigned int has_crypto_ctx = 0;
56
57 #ifdef ZTS
58 MUTEX_T php_lock_win32_cryptoctx;
php_win32_init_rng_lock()59 void php_win32_init_rng_lock()
60 {
61 php_lock_win32_cryptoctx = tsrm_mutex_alloc();
62 }
63
php_win32_free_rng_lock()64 void php_win32_free_rng_lock()
65 {
66 tsrm_mutex_lock(php_lock_win32_cryptoctx);
67 if (has_crypto_ctx == 1) {
68 CryptReleaseContext(hCryptProv, 0);
69 has_crypto_ctx = 0;
70 }
71 tsrm_mutex_unlock(php_lock_win32_cryptoctx);
72 tsrm_mutex_free(php_lock_win32_cryptoctx);
73
74 }
75 #else
76 #define php_win32_init_rng_lock();
77 #define php_win32_free_rng_lock();
78 #endif
79
80
81
php_win32_get_random_bytes(unsigned char * buf,size_t size)82 PHP_WINUTIL_API int php_win32_get_random_bytes(unsigned char *buf, size_t size) { /* {{{ */
83
84 BOOL ret;
85
86 #ifdef ZTS
87 tsrm_mutex_lock(php_lock_win32_cryptoctx);
88 #endif
89
90 if (has_crypto_ctx == 0) {
91 /* CRYPT_VERIFYCONTEXT > only hashing&co-like use, no need to acces prv keys */
92 if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_VERIFYCONTEXT )) {
93 /* Could mean that the key container does not exist, let try
94 again by asking for a new one. If it fails here, it surely means that the user running
95 this process does not have the permission(s) to use this container.
96 */
97 if (GetLastError() == NTE_BAD_KEYSET) {
98 if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET | CRYPT_VERIFYCONTEXT )) {
99 has_crypto_ctx = 1;
100 } else {
101 has_crypto_ctx = 0;
102 }
103 }
104 } else {
105 has_crypto_ctx = 1;
106 }
107 }
108
109 #ifdef ZTS
110 tsrm_mutex_unlock(php_lock_win32_cryptoctx);
111 #endif
112
113 if (has_crypto_ctx == 0) {
114 return FAILURE;
115 }
116
117 /* XXX should go in the loop if size exceeds UINT_MAX */
118 ret = CryptGenRandom(hCryptProv, (DWORD)size, buf);
119
120 if (ret) {
121 return SUCCESS;
122 } else {
123 return FAILURE;
124 }
125 }
126 /* }}} */
127
128
129 /*
130 * This functions based on the code from the UNIXem project under
131 * the BSD like license. Modified for PHP by ab@php.net
132 *
133 * Home: http://synesis.com.au/software/
134 *
135 * Copyright (c) 2005-2010, Matthew Wilson and Synesis Software
136 */
137
php_win32_code_to_errno(unsigned long w32Err)138 PHP_WINUTIL_API int php_win32_code_to_errno(unsigned long w32Err)
139 {
140 size_t i;
141
142 struct code_to_errno_map
143 {
144 unsigned long w32Err;
145 int eerrno;
146 };
147
148 static const struct code_to_errno_map errmap[] =
149 {
150 /* 1 */ { ERROR_INVALID_FUNCTION , EINVAL }
151 /* 2 */ , { ERROR_FILE_NOT_FOUND , ENOENT }
152 /* 3 */ , { ERROR_PATH_NOT_FOUND , ENOENT }
153 /* 4 */ , { ERROR_TOO_MANY_OPEN_FILES , EMFILE }
154 /* 5 */ , { ERROR_ACCESS_DENIED , EACCES }
155 /* 6 */ , { ERROR_INVALID_HANDLE , EBADF }
156 /* 7 */ , { ERROR_ARENA_TRASHED , ENOMEM }
157 /* 8 */ , { ERROR_NOT_ENOUGH_MEMORY , ENOMEM }
158 /* 9 */ , { ERROR_INVALID_BLOCK , ENOMEM }
159 /* 10 */ , { ERROR_BAD_ENVIRONMENT , E2BIG }
160 /* 11 */ , { ERROR_BAD_FORMAT , ENOEXEC }
161 /* 12 */ , { ERROR_INVALID_ACCESS , EINVAL }
162 /* 13 */ , { ERROR_INVALID_DATA , EINVAL }
163 /* 14 */ , { ERROR_OUTOFMEMORY , ENOMEM }
164 /* 15 */ , { ERROR_INVALID_DRIVE , ENOENT }
165 /* 16 */ , { ERROR_CURRENT_DIRECTORY , ECURDIR }
166 /* 17 */ , { ERROR_NOT_SAME_DEVICE , EXDEV }
167 /* 18 */ , { ERROR_NO_MORE_FILES , ENOENT }
168 /* 19 */ , { ERROR_WRITE_PROTECT , EROFS }
169 /* 20 */ , { ERROR_BAD_UNIT , ENXIO }
170 /* 21 */ , { ERROR_NOT_READY , EBUSY }
171 /* 22 */ , { ERROR_BAD_COMMAND , EIO }
172 /* 23 */ , { ERROR_CRC , EIO }
173 /* 24 */ , { ERROR_BAD_LENGTH , EIO }
174 /* 25 */ , { ERROR_SEEK , EIO }
175 /* 26 */ , { ERROR_NOT_DOS_DISK , EIO }
176 /* 27 */ , { ERROR_SECTOR_NOT_FOUND , ENXIO }
177 /* 28 */ , { ERROR_OUT_OF_PAPER , EBUSY }
178 /* 29 */ , { ERROR_WRITE_FAULT , EIO }
179 /* 30 */ , { ERROR_READ_FAULT , EIO }
180 /* 31 */ , { ERROR_GEN_FAILURE , EIO }
181 /* 32 */ , { ERROR_SHARING_VIOLATION , EAGAIN }
182 /* 33 */ , { ERROR_LOCK_VIOLATION , EACCES }
183 /* 34 */ , { ERROR_WRONG_DISK , ENXIO }
184 /* 35 */ , { 35 , ENFILE }
185 /* 36 */ , { ERROR_SHARING_BUFFER_EXCEEDED , ENFILE }
186 /* 37 */ , { ERROR_HANDLE_EOF , EINVAL }
187 /* 38 */ , { ERROR_HANDLE_DISK_FULL , ENOSPC }
188 #if 0
189 /* 39 */ , { 0 , 0 }
190 /* 40 */ , { 0 , 0 }
191 /* 41 */ , { 0 , 0 }
192 /* 42 */ , { 0 , 0 }
193 /* 43 */ , { 0 , 0 }
194 /* 44 */ , { 0 , 0 }
195 /* 45 */ , { 0 , 0 }
196 /* 46 */ , { 0 , 0 }
197 /* 47 */ , { 0 , 0 }
198 /* 48 */ , { 0 , 0 }
199 /* 49 */ , { 0 , 0 }
200 #endif
201 /* 50 */ , { ERROR_NOT_SUPPORTED , ENOSYS }
202 #if 0
203 /* 51 */ , { 0 , 0 }
204 /* 52 */ , { 0 , 0 }
205 #endif
206 /* 53 */ , { ERROR_BAD_NETPATH , ENOENT }
207 #if 0
208 /* 54 */ , { 0 , 0 }
209 /* 55 */ , { 0 , 0 }
210 /* 56 */ , { 0 , 0 }
211 /* 57 */ , { 0 , 0 }
212 /* 58 */ , { 0 , 0 }
213 /* 59 */ , { 0 , 0 }
214 /* 60 */ , { 0 , 0 }
215 /* 61 */ , { 0 , 0 }
216 /* 62 */ , { 0 , 0 }
217 /* 63 */ , { 0 , 0 }
218 /* 64 */ , { 0 , 0 }
219 #endif
220 /* 65 */ , { ERROR_NETWORK_ACCESS_DENIED , EACCES }
221 #if 0
222 /* 66 */ , { 0 , 0 }
223 #endif
224 /* 67 */ , { ERROR_BAD_NET_NAME , ENOENT }
225 #if 0
226 /* 68 */ , { 0 , 0 }
227 /* 69 */ , { 0 , 0 }
228 /* 70 */ , { 0 , 0 }
229 /* 71 */ , { 0 , 0 }
230 /* 72 */ , { 0 , 0 }
231 /* 73 */ , { 0 , 0 }
232 /* 74 */ , { 0 , 0 }
233 /* 75 */ , { 0 , 0 }
234 /* 76 */ , { 0 , 0 }
235 /* 77 */ , { 0 , 0 }
236 /* 78 */ , { 0 , 0 }
237 /* 79 */ , { 0 , 0 }
238 #endif
239 /* 80 */ , { ERROR_FILE_EXISTS , EEXIST }
240 #if 0
241 /* 81 */ , { 0 , 0 }
242 #endif
243 /* 82 */ , { ERROR_CANNOT_MAKE , EACCES }
244 /* 83 */ , { ERROR_FAIL_I24 , EACCES }
245 #if 0
246 /* 84 */ , { 0 , 0 }
247 /* 85 */ , { 0 , 0 }
248 /* 86 */ , { 0 , 0 }
249 #endif
250 /* 87 */ , { ERROR_INVALID_PARAMETER , EINVAL }
251 #if 0
252 /* 88 */ , { 0 , 0 }
253 #endif
254 /* 89 */ , { ERROR_NO_PROC_SLOTS , EAGAIN }
255 #if 0
256 /* 90 */ , { 0 , 0 }
257 /* 91 */ , { 0 , 0 }
258 /* 92 */ , { 0 , 0 }
259 /* 93 */ , { 0 , 0 }
260 /* 94 */ , { 0 , 0 }
261 /* 95 */ , { 0 , 0 }
262 /* 96 */ , { 0 , 0 }
263 /* 97 */ , { 0 , 0 }
264 /* 98 */ , { 0 , 0 }
265 /* 99 */ , { 0 , 0 }
266 /* 100 */ , { 0 , 0 }
267 /* 101 */ , { 0 , 0 }
268 /* 102 */ , { 0 , 0 }
269 /* 103 */ , { 0 , 0 }
270 /* 104 */ , { 0 , 0 }
271 /* 105 */ , { 0 , 0 }
272 /* 106 */ , { 0 , 0 }
273 /* 107 */ , { 0 , 0 }
274 #endif
275 /* 108 */ , { ERROR_DRIVE_LOCKED , EACCES }
276 /* 109 */ , { ERROR_BROKEN_PIPE , EPIPE }
277 #if 0
278 /* 110 */ , { 0 , 0 }
279 #endif
280 /* 111 */ , { ERROR_BUFFER_OVERFLOW , ENAMETOOLONG }
281 /* 112 */ , { ERROR_DISK_FULL , ENOSPC }
282 #if 0
283 /* 113 */ , { 0 , 0 }
284 #endif
285 /* 114 */ , { ERROR_INVALID_TARGET_HANDLE , EBADF }
286 #if 0
287 /* 115 */ , { 0 , 0 }
288 /* 116 */ , { 0 , 0 }
289 /* 117 */ , { 0 , 0 }
290 /* 118 */ , { 0 , 0 }
291 /* 119 */ , { 0 , 0 }
292 /* 120 */ , { 0 , 0 }
293 /* 121 */ , { 0 , 0 }
294 #endif
295 /* 122 */ , { ERROR_INSUFFICIENT_BUFFER , ERANGE }
296 /* 123 */ , { ERROR_INVALID_NAME , ENOENT }
297 /* 124 */ , { ERROR_INVALID_HANDLE , EINVAL }
298 #if 0
299 /* 125 */ , { 0 , 0 }
300 #endif
301 /* 126 */ , { ERROR_MOD_NOT_FOUND , ENOENT }
302 /* 127 */ , { ERROR_PROC_NOT_FOUND , ENOENT }
303 /* 128 */ , { ERROR_WAIT_NO_CHILDREN , ECHILD }
304 /* 129 */ , { ERROR_CHILD_NOT_COMPLETE , ECHILD }
305 /* 130 */ , { ERROR_DIRECT_ACCESS_HANDLE , EBADF }
306 /* 131 */ , { ERROR_NEGATIVE_SEEK , EINVAL }
307 /* 132 */ , { ERROR_SEEK_ON_DEVICE , EACCES }
308 #if 0
309 /* 133 */ , { 0 , 0 }
310 /* 134 */ , { 0 , 0 }
311 /* 135 */ , { 0 , 0 }
312 /* 136 */ , { 0 , 0 }
313 /* 137 */ , { 0 , 0 }
314 /* 138 */ , { 0 , 0 }
315 /* 139 */ , { 0 , 0 }
316 /* 140 */ , { 0 , 0 }
317 /* 141 */ , { 0 , 0 }
318 /* 142 */ , { 0 , 0 }
319 /* 143 */ , { 0 , 0 }
320 /* 144 */ , { 0 , 0 }
321 #endif
322 /* 145 */ , { ERROR_DIR_NOT_EMPTY , ENOTEMPTY }
323 #if 0
324 /* 146 */ , { 0 , 0 }
325 /* 147 */ , { 0 , 0 }
326 /* 148 */ , { 0 , 0 }
327 /* 149 */ , { 0 , 0 }
328 /* 150 */ , { 0 , 0 }
329 /* 151 */ , { 0 , 0 }
330 /* 152 */ , { 0 , 0 }
331 /* 153 */ , { 0 , 0 }
332 /* 154 */ , { 0 , 0 }
333 /* 155 */ , { 0 , 0 }
334 /* 156 */ , { 0 , 0 }
335 /* 157 */ , { 0 , 0 }
336 #endif
337 /* 158 */ , { ERROR_NOT_LOCKED , EACCES }
338 #if 0
339 /* 159 */ , { 0 , 0 }
340 /* 160 */ , { 0 , 0 }
341 #endif
342 /* 161 */ , { ERROR_BAD_PATHNAME , ENOENT }
343 #if 0
344 /* 162 */ , { 0 , 0 }
345 /* 163 */ , { 0 , 0 }
346 #endif
347 /* 164 */ , { ERROR_MAX_THRDS_REACHED , EAGAIN }
348 #if 0
349 /* 165 */ , { 0 , 0 }
350 /* 166 */ , { 0 , 0 }
351 #endif
352 /* 167 */ , { ERROR_LOCK_FAILED , EACCES }
353 #if 0
354 /* 168 */ , { 0 , 0 }
355 /* 169 */ , { 0 , 0 }
356 /* 170 */ , { 0 , 0 }
357 /* 171 */ , { 0 , 0 }
358 /* 172 */ , { 0 , 0 }
359 /* 173 */ , { 0 , 0 }
360 /* 174 */ , { 0 , 0 }
361 /* 175 */ , { 0 , 0 }
362 /* 176 */ , { 0 , 0 }
363 /* 177 */ , { 0 , 0 }
364 /* 178 */ , { 0 , 0 }
365 /* 179 */ , { 0 , 0 }
366 /* 180 */ , { 0 , 0 }
367 /* 181 */ , { 0 , 0 }
368 /* 182 */ , { 0 , 0 }
369 #endif
370 /* 183 */ , { ERROR_ALREADY_EXISTS , EEXIST }
371 #if 0
372 /* 184 */ , { 0 , 0 }
373 /* 185 */ , { 0 , 0 }
374 /* 186 */ , { 0 , 0 }
375 /* 187 */ , { 0 , 0 }
376 /* 188 */ , { 0 , 0 }
377 /* 189 */ , { 0 , 0 }
378 /* 190 */ , { 0 , 0 }
379 /* 191 */ , { 0 , 0 }
380 /* 192 */ , { 0 , 0 }
381 /* 193 */ , { 0 , 0 }
382 /* 194 */ , { 0 , 0 }
383 /* 195 */ , { 0 , 0 }
384 /* 196 */ , { 0 , 0 }
385 /* 197 */ , { 0 , 0 }
386 /* 198 */ , { 0 , 0 }
387 /* 199 */ , { 0 , 0 }
388 #endif
389
390 /* 206 */ , { ERROR_FILENAME_EXCED_RANGE , ENAMETOOLONG }
391
392 /* 215 */ , { ERROR_NESTING_NOT_ALLOWED , EAGAIN }
393 /* 258 */ , { WAIT_TIMEOUT, ETIME}
394
395 /* 267 */ , { ERROR_DIRECTORY , ENOTDIR }
396
397 /* 996 */ , { ERROR_IO_INCOMPLETE , EAGAIN }
398 /* 997 */ , { ERROR_IO_PENDING , EAGAIN }
399
400 /* 1004 */ , { ERROR_INVALID_FLAGS , EINVAL }
401 /* 1113 */ , { ERROR_NO_UNICODE_TRANSLATION , EINVAL }
402 /* 1168 */ , { ERROR_NOT_FOUND , ENOENT }
403 /* 1224 */ , { ERROR_USER_MAPPED_FILE , EACCES }
404 /* 1816 */ , { ERROR_NOT_ENOUGH_QUOTA , ENOMEM }
405 , { ERROR_ABANDONED_WAIT_0 , EIO }
406 };
407
408 for(i = 0; i < sizeof(errmap)/sizeof(struct code_to_errno_map); ++i)
409 {
410 if(w32Err == errmap[i].w32Err)
411 {
412 return errmap[i].eerrno;
413 }
414 }
415
416 assert(!"Unrecognised value");
417
418 return EINVAL;
419 }
420
php_win32_get_username(void)421 PHP_WINUTIL_API char *php_win32_get_username(void)
422 {
423 wchar_t unamew[UNLEN + 1];
424 size_t uname_len;
425 char *uname;
426 DWORD unsize = UNLEN;
427
428 GetUserNameW(unamew, &unsize);
429 uname = php_win32_cp_conv_w_to_any(unamew, unsize - 1, &uname_len);
430 if (!uname) {
431 return NULL;
432 }
433
434 /* Ensure the length doesn't overflow. */
435 if (uname_len > UNLEN) {
436 uname[uname_len] = '\0';
437 }
438
439 return uname;
440 }
441
442 /*
443 * Local variables:
444 * tab-width: 4
445 * c-basic-offset: 4
446 * End:
447 * vim600: sw=4 ts=4 fdm=marker
448 * vim<600: sw=4 ts=4
449 */
450