xref: /PHP-7.1/win32/winutil.c (revision 7f6387b5)
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