This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
fetching_20a_20secure_20web_20page [2018/04/17 16:06] tbest3112 Added syntax highlighting |
fetching_20a_20secure_20web_20page [2018/07/30 22:42] (current) richardrussell Updated to TLS v1.2 |
||
---|---|---|---|
Line 1: | Line 1: | ||
=====Fetching a secure web page===== | =====Fetching a secure web page===== | ||
- | //by Richard Russell, July 2009//\\ \\ The procedure listed below fetches the contents of a secure (**https:**) web page to a specified file; it uses the [[http://www.openssl.org/|OpenSSL]] library and requires the files **libssl32.dll** and **libeay32.dll** to be available. They can be downloaded in this [[http://downloads.sourceforge.net/gnuwin32/openssl-0.9.8h-1-bin.zip|Zip file]], from which they should be extracted and copied to a location where they will be found by **LoadLibrary**, i.e. one of:\\ | + | //by Richard Russell, July 2009, updated July 2018//\\ \\ The procedure listed below fetches the contents of a secure (**https:**) web page to a specified file; it uses the [[http://www.openssl.org/|OpenSSL]] library and requires the files **libssl-1_1.dll** and **libcrypto-1_1.dll** to be available. They can be obtained from [[https://slproweb.com/products/Win32OpenSSL.html|this page]]; download and install **Win32OpenSSL_Light-1_1_0h.exe** from there. You should normally choose the option of installing the DLLs in the Windows system directory. |
+ | |||
+ | If you want to distribute **libssl-1_1.dll** and **libcrypto-1_1.dll** with your application then store them in **@dir$** and embed them in the executable. Alternatively you can put them in **@lib$** (or a sub-directory) but in that case you will need to amend the procedure below to load them explicitly from that location. | ||
+ | |||
+ | The procedure should be called in the following context: | ||
- | * The directory from which the application will be loaded (@dir$). | ||
- | * The 'current' directory. | ||
- | * The system directory (e.g. **C:\Windows\System32\**). | ||
- | * The Windows directory (e.g. **C:\Windows\**). | ||
- | * One of the directories listed in the PATH environment variable. | ||
- | \\ If you want to distribute **libssl32.dll** and **libeay32.dll** with your application then store them in **@dir$** and embed them in the executable. Alternatively you can put them in **@lib$** (or a sub-directory) but in that case you will need to amend the procedure below to load them explicitly from that location.\\ \\ The procedure should be called in the following context:\\ \\ | ||
<code bb4w> | <code bb4w> | ||
- | port$ = "443" : REM https | + | port$ = "443" : REM https |
- | host$ = "www.fortify.net" | + | host$ = "www.fortify.net" |
- | page$ = "/sslcheck.html" | + | page$ = "/sslcheck.html" |
- | file$ = @tmp$ + "sslcheck.html" | + | file$ = @tmp$ + "sslcheck.html" |
- | PROCsslfetch(port$, host$, page$, file$) | + | PROCsslfetch(port$, host$, page$, file$) |
</code> | </code> | ||
- | This fetches the page https://www.fortify.net/sslcheck.html to the file **sslcheck.html**.\\ \\ Here is the procedure:\\ \\ | ||
- | <code bb4w> | ||
- | DEF PROCsslfetch(port$, host$, page$, file$) | ||
- | LOCAL libssl%, libeay%, meth%, ctx%, sock%, temp%, res%, ssl%, sbio%, file% | ||
- | LOCAL req$, buf&() | ||
- | FIONBIO = &8004667E | + | This fetches the page https://www.fortify.net/sslcheck.html to the file **sslcheck.html**. |
- | BIO_NOCLOSE = 0 | + | |
- | BUFSIZ = 256 | + | Here is the procedure: |
+ | |||
+ | <code bb4w> | ||
+ | DEF PROCsslfetch(port$, host$, page$, file$) | ||
+ | LOCAL libssl%, libeay%, meth%, ctx%, sock%, temp%, res%, ssl%, sbio%, file% | ||
+ | LOCAL req$, buf&() | ||
- | ON ERROR LOCAL RESTORE ERROR : INSTALL @lib$+"SOCKLIB" | + | FIONBIO = &8004667E |
- | PROC_initsockets | + | BIO_NOCLOSE = 0 |
+ | BUFSIZ = 256 | ||
- | SYS "LoadLibrary", "libssl32.dll" TO libssl% | + | ON ERROR LOCAL RESTORE ERROR : INSTALL @lib$+"SOCKLIB" |
- | IF libssl% = 0 PROCsslcleanup : ERROR 100, "Cannot load LIBSSL32.DLL" | + | PROC_initsockets |
- | SYS "GetProcAddress", libssl%, "SSL_library_init" TO `SSL_library_init` | + | |
- | SYS "GetProcAddress", libssl%, "SSLv23_method" TO `SSLv23_method` | + | |
- | SYS "GetProcAddress", libssl%, "SSL_CTX_new" TO `SSL_CTX_new` | + | |
- | SYS "GetProcAddress", libssl%, "SSL_new" TO `SSL_new` | + | |
- | SYS "GetProcAddress", libssl%, "SSL_set_bio" TO `SSL_set_bio` | + | |
- | SYS "GetProcAddress", libssl%, "SSL_connect" TO `SSL_connect` | + | |
- | SYS "GetProcAddress", libssl%, "SSL_write" TO `SSL_write` | + | |
- | SYS "GetProcAddress", libssl%, "SSL_read" TO `SSL_read` | + | |
- | SYS "GetProcAddress", libssl%, "SSL_CTX_free" TO `SSL_CTX_free` | + | |
- | SYS "LoadLibrary", "libeay32.dll" TO libeay% | + | SYS "LoadLibrary", "libcrypto-1_1.dll" TO libeay% |
- | IF libeay% = 0 PROCsslcleanup : ERROR 100, "Cannot load LIBEAY32.DLL" | + | IF libeay% = 0 PROCsslcleanup : ERROR 100, "Cannot load libcrypto-1_1.dll" |
- | SYS "GetProcAddress", libeay%, "BIO_new_socket" TO `BIO_new_socket` | + | SYS "GetProcAddress", libeay%, "BIO_new_socket" TO `BIO_new_socket` |
- | REM Global system initialisation: | + | SYS "LoadLibrary", "libssl-1_1.dll" TO libssl% |
- | SYS `SSL_library_init` | + | IF libssl% = 0 PROCsslcleanup : ERROR 100, "Cannot load libssl-1_1.dll" |
+ | SYS "GetProcAddress", libssl%, "TLSv1_2_method" TO `TLSv1_2_method` | ||
+ | SYS "GetProcAddress", libssl%, "SSL_CTX_new" TO `SSL_CTX_new` | ||
+ | SYS "GetProcAddress", libssl%, "SSL_new" TO `SSL_new` | ||
+ | SYS "GetProcAddress", libssl%, "SSL_set_bio" TO `SSL_set_bio` | ||
+ | SYS "GetProcAddress", libssl%, "SSL_connect" TO `SSL_connect` | ||
+ | SYS "GetProcAddress", libssl%, "SSL_write" TO `SSL_write` | ||
+ | SYS "GetProcAddress", libssl%, "SSL_read" TO `SSL_read` | ||
+ | SYS "GetProcAddress", libssl%, "SSL_CTX_free" TO `SSL_CTX_free` | ||
- | REM Create SSL context: | + | REM Create SSL context: |
- | SYS `SSLv23_method` TO meth% | + | SYS `TLSv1_2_method` TO meth% |
- | SYS `SSL_CTX_new`, meth% TO ctx% | + | SYS `SSL_CTX_new`, meth% TO ctx% |
- | IF ctx% = 0 PROCsslcleanup : ERROR 100, "SSL_CTX_new failed" | + | IF ctx% = 0 PROCsslcleanup : ERROR 100, "SSL_CTX_new failed" |
- | REM Connect the TCP socket: | + | REM Connect the TCP socket: |
- | sock% = FN_tcpconnect(host$, port$) | + | sock% = FN_tcpconnect(host$, port$) |
- | IF sock% < 0 PROCsslcleanup : ERROR 100, "Cannot connect to " + host$ | + | IF sock% < 0 PROCsslcleanup : ERROR 100, "Cannot connect to " + host$ |
- | temp% = 0 | + | temp% = 0 |
- | SYS `ioctlsocket`, sock%, FIONBIO, ^temp% TO res% | + | SYS `ioctlsocket`, sock%, FIONBIO, ^temp% TO res% |
- | IF res% PROCsslcleanup : ERROR 105, "Cannot set socket to blocking" | + | IF res% PROCsslcleanup : ERROR 105, "Cannot set socket to blocking" |
- | REM Connect the SSL socket: | + | REM Connect the SSL socket: |
- | SYS `SSL_new`, ctx% TO ssl% | + | SYS `SSL_new`, ctx% TO ssl% |
- | SYS `BIO_new_socket`, sock%, BIO_NOCLOSE TO sbio% | + | SYS `BIO_new_socket`, sock%, BIO_NOCLOSE TO sbio% |
- | SYS `SSL_set_bio`, ssl%, sbio%, sbio% | + | SYS `SSL_set_bio`, ssl%, sbio%, sbio% |
- | SYS `SSL_connect`, ssl% TO res% | + | SYS `SSL_connect`, ssl% TO res% |
- | IF res% <= 0 PROCsslcleanup : ERROR 100, "SSL connect failed: " + STR$res% | + | IF res% <= 0 PROCsslcleanup : ERROR 100, "SSL connect failed: " + STR$res% |
- | REM Request the page: | + | REM Request the page: |
- | req$ = "GET " + page$ + " HTTP/1.0" + CHR$13 + CHR$10 | + | req$ = "GET " + page$ + " HTTP/1.0" + CHR$13 + CHR$10 |
- | req$ += "User-Agent: BB4W" + CHR$13 + CHR$10 | + | req$ += "User-Agent: BB4W" + CHR$13 + CHR$10 |
- | req$ += "Host: " + host$ + ":" + port$ + CHR$13 + CHR$10 | + | req$ += "Host: " + host$ + ":" + port$ + CHR$13 + CHR$10 |
- | req$ += CHR$13 + CHR$10 | + | req$ += CHR$13 + CHR$10 |
- | SYS `SSL_write`, ssl%, req$, LEN(req$) TO res% | + | SYS `SSL_write`, ssl%, req$, LEN(req$) TO res% |
- | IF res% <> LEN(req$) PROCsslcleanup : ERROR 100, "SSL write failed: " + STR$res% | + | IF res% <> LEN(req$) PROCsslcleanup : ERROR 100, "SSL write failed: " + STR$res% |
- | REM Copy the requested page to a file: | + | REM Copy the requested page to a file: |
- | DIM buf&(BUFSIZ-1) | + | DIM buf&(BUFSIZ-1) |
- | file% = OPENOUT(file$) | + | file% = OPENOUT(file$) |
- | REPEAT | + | REPEAT |
- | SYS `SSL_read`, ssl%, ^buf&(0), BUFSIZ TO res% | + | SYS `SSL_read`, ssl%, ^buf&(0), BUFSIZ TO res% |
- | IF res% > 0 SYS "WriteFile", @hfile%(file%), ^buf&(0), res%, ^temp%, 0 | + | IF res% > 0 SYS "WriteFile", @hfile%(file%), ^buf&(0), res%, ^temp%, 0 |
- | UNTIL res% <= 0 | + | UNTIL res% <= 0 |
- | CLOSE #file% | + | CLOSE #file% |
- | IF res% PROCsslcleanup : ERROR 100, "SSL read failed: " + STR$res% | + | IF res% PROCsslcleanup : ERROR 100, "SSL read failed: " + STR$res% |
- | REM Tidy up before exit: | + | REM Tidy up before exit: |
- | PROCsslcleanup | + | PROCsslcleanup |
- | ENDPROC | + | ENDPROC |
- | DEF PROCsslcleanup | + | DEF PROCsslcleanup |
- | sock% += 0 : IF sock% PROC_closesocket(sock%) : sock% = 0 | + | sock% += 0 : IF sock% PROC_closesocket(sock%) : sock% = 0 |
- | ctx% += 0 : IF ctx% SYS `SSL_CTX_free`, ctx% : ctx% = 0 | + | ctx% += 0 : IF ctx% SYS `SSL_CTX_free`, ctx% : ctx% = 0 |
- | libssl% += 0 : IF libssl% SYS "FreeLibrary", libssl% : libssl% = 0 | + | libssl% += 0 : IF libssl% SYS "FreeLibrary", libssl% : libssl% = 0 |
- | libeay% += 0 : IF libeay% SYS "FreeLibrary", libeay% : libeay% = 0 | + | libeay% += 0 : IF libeay% SYS "FreeLibrary", libeay% : libeay% = 0 |
- | PROC_exitsockets | + | PROC_exitsockets |
- | ENDPROC | + | ENDPROC |
</code> | </code> |