1 #ifdef __REACTOS__
2 #include "precomp.h"
3 #else
4 /*
5 * Wininet
6 *
7 * Copyright 2003 Mike McCormack for CodeWeavers Inc.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24 #include "ws2tcpip.h"
25
26 #include <stdarg.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winreg.h"
32 #include "wininet.h"
33 #include "winnetwk.h"
34 #include "wine/debug.h"
35 #include "winerror.h"
36 #define NO_SHLWAPI_STREAM
37 #include "shlwapi.h"
38 #include "cryptuiapi.h"
39
40 #include "internet.h"
41 #include "resource.h"
42 #endif /* defined(__REACTOS__) */
43
44 #define MAX_STRING_LEN 1024
45
46 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
47
48 struct WININET_ErrorDlgParams
49 {
50 http_request_t *req;
51 HWND hWnd;
52 DWORD dwError;
53 DWORD dwFlags;
54 LPVOID* lppvData;
55 };
56
57 /***********************************************************************
58 * WININET_GetAuthRealm
59 *
60 * Determine the name of the (basic) Authentication realm
61 */
WININET_GetAuthRealm(HINTERNET hRequest,LPWSTR szBuf,DWORD sz,BOOL proxy)62 static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz, BOOL proxy )
63 {
64 LPWSTR p, q;
65 DWORD index, query;
66
67 if (proxy)
68 query = HTTP_QUERY_PROXY_AUTHENTICATE;
69 else
70 query = HTTP_QUERY_WWW_AUTHENTICATE;
71
72 /* extract the Realm from the response and show it */
73 index = 0;
74 if( !HttpQueryInfoW( hRequest, query, szBuf, &sz, &index) )
75 return FALSE;
76
77 /*
78 * FIXME: maybe we should check that we're
79 * dealing with 'Basic' Authentication
80 */
81 p = wcschr( szBuf, ' ' );
82 if( !p || wcsncmp( p+1, L"realm=", lstrlenW(L"realm=") ) )
83 {
84 ERR("response wrong? (%s)\n", debugstr_w(szBuf));
85 return FALSE;
86 }
87
88 /* remove quotes */
89 p += 7;
90 if( *p == '"' )
91 {
92 p++;
93 q = wcsrchr( p, '"' );
94 if( q )
95 *q = 0;
96 }
97 lstrcpyW( szBuf, p );
98
99 return TRUE;
100 }
101
102 /* These two are not defined in the public headers */
103 extern DWORD WINAPI WNetCachePassword(LPSTR,WORD,LPSTR,WORD,BYTE,WORD);
104 extern DWORD WINAPI WNetGetCachedPassword(LPSTR,WORD,LPSTR,LPWORD,BYTE);
105
106 /***********************************************************************
107 * WININET_GetSetPassword
108 */
WININET_GetSetPassword(HWND hdlg,LPCWSTR szServer,LPCWSTR szRealm,BOOL bSet)109 static BOOL WININET_GetSetPassword( HWND hdlg, LPCWSTR szServer,
110 LPCWSTR szRealm, BOOL bSet )
111 {
112 WCHAR szResource[0x80], szUserPass[0x40];
113 LPWSTR p;
114 HWND hUserItem, hPassItem;
115 DWORD r, dwMagic = 19;
116 UINT r_len, u_len;
117 WORD sz;
118
119 hUserItem = GetDlgItem( hdlg, IDC_USERNAME );
120 hPassItem = GetDlgItem( hdlg, IDC_PASSWORD );
121
122 /* now try fetch the username and password */
123 lstrcpyW( szResource, szServer);
124 lstrcatW( szResource, L"/");
125 lstrcatW( szResource, szRealm);
126
127 /*
128 * WNetCachePassword is only concerned with the length
129 * of the data stored (which we tell it) and it does
130 * not use strlen() internally so we can add WCHAR data
131 * instead of ASCII data and get it back the same way.
132 */
133 if( bSet )
134 {
135 szUserPass[0] = 0;
136 GetWindowTextW( hUserItem, szUserPass, ARRAY_SIZE( szUserPass ) - 1 );
137 lstrcatW(szUserPass, L":");
138 u_len = lstrlenW( szUserPass );
139 GetWindowTextW( hPassItem, szUserPass+u_len, ARRAY_SIZE( szUserPass ) - u_len );
140
141 r_len = (lstrlenW( szResource ) + 1)*sizeof(WCHAR);
142 u_len = (lstrlenW( szUserPass ) + 1)*sizeof(WCHAR);
143 r = WNetCachePassword( (CHAR*)szResource, r_len,
144 (CHAR*)szUserPass, u_len, dwMagic, 0 );
145
146 return ( r == WN_SUCCESS );
147 }
148
149 sz = sizeof szUserPass;
150 r_len = (lstrlenW( szResource ) + 1)*sizeof(WCHAR);
151 r = WNetGetCachedPassword( (CHAR*)szResource, r_len,
152 (CHAR*)szUserPass, &sz, dwMagic );
153 if( r != WN_SUCCESS )
154 return FALSE;
155
156 p = wcschr( szUserPass, ':' );
157 if( p )
158 {
159 *p = 0;
160 SetWindowTextW( hUserItem, szUserPass );
161 SetWindowTextW( hPassItem, p+1 );
162 }
163
164 return TRUE;
165 }
166
167 /***********************************************************************
168 * WININET_SetAuthorization
169 */
WININET_SetAuthorization(http_request_t * request,LPWSTR username,LPWSTR password,BOOL proxy)170 static BOOL WININET_SetAuthorization( http_request_t *request, LPWSTR username,
171 LPWSTR password, BOOL proxy )
172 {
173 http_session_t *session = request->session;
174 LPWSTR p, q;
175
176 p = heap_strdupW(username);
177 if( !p )
178 return FALSE;
179
180 q = heap_strdupW(password);
181 if( !q )
182 {
183 heap_free(p);
184 return FALSE;
185 }
186
187 if (proxy)
188 {
189 appinfo_t *hIC = session->appInfo;
190
191 heap_free(hIC->proxyUsername);
192 hIC->proxyUsername = p;
193
194 heap_free(hIC->proxyPassword);
195 hIC->proxyPassword = q;
196 }
197 else
198 {
199 heap_free(session->userName);
200 session->userName = p;
201
202 heap_free(session->password);
203 session->password = q;
204 }
205
206 return TRUE;
207 }
208
209 /***********************************************************************
210 * WININET_ProxyPasswordDialog
211 */
WININET_ProxyPasswordDialog(HWND hdlg,UINT uMsg,WPARAM wParam,LPARAM lParam)212 static INT_PTR WINAPI WININET_ProxyPasswordDialog(
213 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
214 {
215 HWND hitem;
216 struct WININET_ErrorDlgParams *params;
217 WCHAR szRealm[0x80];
218
219 if( uMsg == WM_INITDIALOG )
220 {
221 TRACE("WM_INITDIALOG (%08lx)\n", lParam);
222
223 /* save the parameter list */
224 params = (struct WININET_ErrorDlgParams*) lParam;
225 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
226
227 /* extract the Realm from the proxy response and show it */
228 if( WININET_GetAuthRealm( params->req->hdr.hInternet,
229 szRealm, ARRAY_SIZE( szRealm ), TRUE ) )
230 {
231 hitem = GetDlgItem( hdlg, IDC_REALM );
232 SetWindowTextW( hitem, szRealm );
233 }
234
235 hitem = GetDlgItem( hdlg, IDC_PROXY );
236 SetWindowTextW( hitem, params->req->session->appInfo->proxy );
237
238 WININET_GetSetPassword( hdlg, params->req->session->appInfo->proxy, szRealm, FALSE );
239
240 return TRUE;
241 }
242
243 params = (struct WININET_ErrorDlgParams*)
244 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
245
246 switch( uMsg )
247 {
248 case WM_COMMAND:
249 if( wParam == IDOK )
250 {
251 WCHAR username[0x20], password[0x20];
252
253 username[0] = 0;
254 hitem = GetDlgItem( hdlg, IDC_USERNAME );
255 if( hitem )
256 GetWindowTextW( hitem, username, ARRAY_SIZE( username ));
257
258 password[0] = 0;
259 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
260 if( hitem )
261 GetWindowTextW( hitem, password, ARRAY_SIZE( password ));
262
263 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
264 if( hitem &&
265 SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
266 WININET_GetAuthRealm( params->req->hdr.hInternet,
267 szRealm, ARRAY_SIZE( szRealm ), TRUE) )
268 WININET_GetSetPassword( hdlg, params->req->session->appInfo->proxy, szRealm, TRUE );
269 WININET_SetAuthorization( params->req, username, password, TRUE );
270
271 EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
272 return TRUE;
273 }
274 if( wParam == IDCANCEL )
275 {
276 EndDialog( hdlg, 0 );
277 return TRUE;
278 }
279 break;
280 }
281 return FALSE;
282 }
283
284 /***********************************************************************
285 * WININET_PasswordDialog
286 */
WININET_PasswordDialog(HWND hdlg,UINT uMsg,WPARAM wParam,LPARAM lParam)287 static INT_PTR WINAPI WININET_PasswordDialog(
288 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
289 {
290 HWND hitem;
291 struct WININET_ErrorDlgParams *params;
292 WCHAR szRealm[0x80];
293
294 if( uMsg == WM_INITDIALOG )
295 {
296 TRACE("WM_INITDIALOG (%08lx)\n", lParam);
297
298 /* save the parameter list */
299 params = (struct WININET_ErrorDlgParams*) lParam;
300 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
301
302 /* extract the Realm from the response and show it */
303 if( WININET_GetAuthRealm( params->req->hdr.hInternet,
304 szRealm, ARRAY_SIZE( szRealm ), FALSE ) )
305 {
306 hitem = GetDlgItem( hdlg, IDC_REALM );
307 SetWindowTextW( hitem, szRealm );
308 }
309
310 hitem = GetDlgItem( hdlg, IDC_SERVER );
311 SetWindowTextW( hitem, params->req->session->hostName );
312
313 WININET_GetSetPassword( hdlg, params->req->session->hostName, szRealm, FALSE );
314
315 return TRUE;
316 }
317
318 params = (struct WININET_ErrorDlgParams*)
319 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
320
321 switch( uMsg )
322 {
323 case WM_COMMAND:
324 if( wParam == IDOK )
325 {
326 WCHAR username[0x20], password[0x20];
327
328 username[0] = 0;
329 hitem = GetDlgItem( hdlg, IDC_USERNAME );
330 if( hitem )
331 GetWindowTextW( hitem, username, ARRAY_SIZE( username ));
332
333 password[0] = 0;
334 hitem = GetDlgItem( hdlg, IDC_PASSWORD );
335 if( hitem )
336 GetWindowTextW( hitem, password, ARRAY_SIZE( password ));
337
338 hitem = GetDlgItem( hdlg, IDC_SAVEPASSWORD );
339 if( hitem &&
340 SendMessageW( hitem, BM_GETSTATE, 0, 0 ) &&
341 WININET_GetAuthRealm( params->req->hdr.hInternet,
342 szRealm, ARRAY_SIZE( szRealm ), FALSE ))
343 {
344 WININET_GetSetPassword( hdlg, params->req->session->hostName, szRealm, TRUE );
345 }
346 WININET_SetAuthorization( params->req, username, password, FALSE );
347
348 EndDialog( hdlg, ERROR_INTERNET_FORCE_RETRY );
349 return TRUE;
350 }
351 if( wParam == IDCANCEL )
352 {
353 EndDialog( hdlg, 0 );
354 return TRUE;
355 }
356 break;
357 }
358 return FALSE;
359 }
360
361 /***********************************************************************
362 * WININET_InvalidCertificateDialog
363 */
WININET_InvalidCertificateDialog(HWND hdlg,UINT uMsg,WPARAM wParam,LPARAM lParam)364 static INT_PTR WINAPI WININET_InvalidCertificateDialog(
365 HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
366 {
367 struct WININET_ErrorDlgParams *params;
368 HWND hitem;
369 WCHAR buf[1024];
370
371 if( uMsg == WM_INITDIALOG )
372 {
373 TRACE("WM_INITDIALOG (%08lx)\n", lParam);
374
375 /* save the parameter list */
376 params = (struct WININET_ErrorDlgParams*) lParam;
377 SetWindowLongPtrW( hdlg, GWLP_USERDATA, lParam );
378
379 switch( params->dwError )
380 {
381 case ERROR_INTERNET_INVALID_CA:
382 LoadStringW( WININET_hModule, IDS_CERT_CA_INVALID, buf, 1024 );
383 break;
384 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
385 LoadStringW( WININET_hModule, IDS_CERT_DATE_INVALID, buf, 1024 );
386 break;
387 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
388 LoadStringW( WININET_hModule, IDS_CERT_CN_INVALID, buf, 1024 );
389 break;
390 case ERROR_INTERNET_SEC_CERT_ERRORS:
391 /* FIXME: We should fetch information about the
392 * certificate here and show all the relevant errors.
393 */
394 LoadStringW( WININET_hModule, IDS_CERT_ERRORS, buf, 1024 );
395 break;
396 default:
397 FIXME( "No message for error %d\n", params->dwError );
398 buf[0] = '\0';
399 }
400
401 hitem = GetDlgItem( hdlg, IDC_CERT_ERROR );
402 SetWindowTextW( hitem, buf );
403
404 return TRUE;
405 }
406
407 params = (struct WININET_ErrorDlgParams*)
408 GetWindowLongPtrW( hdlg, GWLP_USERDATA );
409
410 switch( uMsg )
411 {
412 case WM_COMMAND:
413 if( wParam == IDOK )
414 {
415 if( params->dwFlags & FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
416 {
417 http_request_t *req = params->req;
418 DWORD flags, size = sizeof(flags);
419
420 InternetQueryOptionW( req->hdr.hInternet, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size );
421 switch( params->dwError )
422 {
423 case ERROR_INTERNET_INVALID_CA:
424 flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
425 break;
426 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
427 flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
428 break;
429 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
430 flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
431 break;
432 case ERROR_INTERNET_SEC_CERT_REV_FAILED:
433 flags |= SECURITY_FLAG_IGNORE_REVOCATION;
434 break;
435 case ERROR_INTERNET_SEC_CERT_ERRORS:
436 if(flags & _SECURITY_FLAG_CERT_REV_FAILED)
437 flags |= SECURITY_FLAG_IGNORE_REVOCATION;
438 if(flags & _SECURITY_FLAG_CERT_INVALID_CA)
439 flags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
440 if(flags & _SECURITY_FLAG_CERT_INVALID_CN)
441 flags |= SECURITY_FLAG_IGNORE_CERT_CN_INVALID;
442 if(flags & _SECURITY_FLAG_CERT_INVALID_DATE)
443 flags |= SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
444 break;
445 }
446 /* FIXME: Use helper function */
447 flags |= SECURITY_FLAG_SECURE;
448 req->security_flags |= flags;
449 if(is_valid_netconn(req->netconn))
450 req->netconn->security_flags |= flags;
451 }
452
453 EndDialog( hdlg, ERROR_SUCCESS );
454 return TRUE;
455 }
456 if( wParam == IDCANCEL )
457 {
458 TRACE("Pressed cancel.\n");
459
460 EndDialog( hdlg, ERROR_CANCELLED );
461 return TRUE;
462 }
463 break;
464 }
465
466 return FALSE;
467 }
468
469 /***********************************************************************
470 * InternetErrorDlg
471 */
InternetErrorDlg(HWND hWnd,HINTERNET hRequest,DWORD dwError,DWORD dwFlags,LPVOID * lppvData)472 DWORD WINAPI InternetErrorDlg(HWND hWnd, HINTERNET hRequest,
473 DWORD dwError, DWORD dwFlags, LPVOID* lppvData)
474 {
475 struct WININET_ErrorDlgParams params;
476 http_request_t *req = NULL;
477 DWORD res = ERROR_SUCCESS;
478
479 TRACE("%p %p %d %08x %p\n", hWnd, hRequest, dwError, dwFlags, lppvData);
480
481 if( !hWnd && !(dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI) )
482 return ERROR_INVALID_HANDLE;
483
484 if(hRequest) {
485 req = (http_request_t*)get_handle_object(hRequest);
486 if(!req)
487 return ERROR_INVALID_HANDLE;
488 if(req->hdr.htype != WH_HHTTPREQ)
489 return ERROR_SUCCESS; /* Yes, that was tested */
490 }
491
492 params.req = req;
493 params.hWnd = hWnd;
494 params.dwError = dwError;
495 params.dwFlags = dwFlags;
496 params.lppvData = lppvData;
497
498 switch( dwError )
499 {
500 case ERROR_SUCCESS:
501 case ERROR_INTERNET_INCORRECT_PASSWORD: {
502 if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
503 break;
504 if(!req)
505 return ERROR_INVALID_HANDLE;
506
507 switch(req->status_code) {
508 case HTTP_STATUS_PROXY_AUTH_REQ:
509 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_PROXYDLG ),
510 hWnd, WININET_ProxyPasswordDialog, (LPARAM) ¶ms );
511 break;
512 case HTTP_STATUS_DENIED:
513 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_AUTHDLG ),
514 hWnd, WININET_PasswordDialog, (LPARAM) ¶ms );
515 break;
516 default:
517 WARN("unhandled status %u\n", req->status_code);
518 }
519 break;
520 }
521 case ERROR_INTERNET_SEC_CERT_ERRORS:
522 case ERROR_INTERNET_SEC_CERT_CN_INVALID:
523 case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
524 case ERROR_INTERNET_INVALID_CA:
525 case ERROR_INTERNET_SEC_CERT_REV_FAILED:
526 if( dwFlags & FLAGS_ERROR_UI_FLAGS_NO_UI ) {
527 res = ERROR_CANCELLED;
528 break;
529 }
530 if(!req)
531 return ERROR_INVALID_HANDLE;
532
533
534 if( dwFlags & ~FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS )
535 FIXME("%08x contains unsupported flags.\n", dwFlags);
536
537 res = DialogBoxParamW( WININET_hModule, MAKEINTRESOURCEW( IDD_INVCERTDLG ),
538 hWnd, WININET_InvalidCertificateDialog, (LPARAM) ¶ms );
539 break;
540 case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
541 case ERROR_INTERNET_POST_IS_NON_SECURE:
542 FIXME("Need to display dialog for error %d\n", dwError);
543 res = ERROR_SUCCESS;
544 break;
545 default:
546 res = ERROR_NOT_SUPPORTED;
547 }
548
549 if(req)
550 WININET_Release(&req->hdr);
551 return res;
552 }
553
554 /***********************************************************************
555 * InternetShowSecurityInfoByURLA (@)
556 */
InternetShowSecurityInfoByURLA(LPCSTR url,HWND window)557 BOOL WINAPI InternetShowSecurityInfoByURLA(LPCSTR url, HWND window)
558 {
559 FIXME("stub: %s %p\n", url, window);
560 return FALSE;
561 }
562
563 /***********************************************************************
564 * InternetShowSecurityInfoByURLW (@)
565 */
InternetShowSecurityInfoByURLW(LPCWSTR url,HWND window)566 BOOL WINAPI InternetShowSecurityInfoByURLW(LPCWSTR url, HWND window)
567 {
568 FIXME("stub: %s %p\n", debugstr_w(url), window);
569 return FALSE;
570 }
571
572 /***********************************************************************
573 * ParseX509EncodedCertificateForListBoxEntry (@)
574 */
ParseX509EncodedCertificateForListBoxEntry(LPBYTE cert,DWORD len,LPSTR szlistbox,LPDWORD listbox)575 DWORD WINAPI ParseX509EncodedCertificateForListBoxEntry(LPBYTE cert, DWORD len, LPSTR szlistbox, LPDWORD listbox)
576 {
577 FIXME("stub: %p %d %s %p\n", cert, len, debugstr_a(szlistbox), listbox);
578 return ERROR_CALL_NOT_IMPLEMENTED;
579 }
580
581 /***********************************************************************
582 * ShowX509EncodedCertificate (@)
583 */
ShowX509EncodedCertificate(HWND parent,LPBYTE cert,DWORD len)584 DWORD WINAPI ShowX509EncodedCertificate(HWND parent, LPBYTE cert, DWORD len)
585 {
586 PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING,
587 cert, len);
588 DWORD ret;
589
590 if (certContext)
591 {
592 CRYPTUI_VIEWCERTIFICATE_STRUCTW view;
593
594 memset(&view, 0, sizeof(view));
595 view.hwndParent = parent;
596 view.pCertContext = certContext;
597 if (CryptUIDlgViewCertificateW(&view, NULL))
598 ret = ERROR_SUCCESS;
599 else
600 ret = GetLastError();
601 CertFreeCertificateContext(certContext);
602 }
603 else
604 ret = GetLastError();
605 return ret;
606 }
607