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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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