Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fix the SSL-server code so that the "fossil ui --tls" command (and similar) now work on Windows. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
7a3bf55f5489f5348830c5f116d872c2 |
| User & Date: | drh 2021-12-29 02:59:38.883 |
References
|
2022-01-27
| ||
| 04:34 | Fix an off by 1 bug in "win32_http_request()" which was causing POST request to fail on windows. (e.g. wikiedit preview or upload of a file on the chat) Problem appear in checkin [7a3bf55f5489f534] ... (check-in: e4b49ce37d user: mgagnon tags: trunk) | |
Context
|
2021-12-29
| ||
| 03:15 | Adapted ssl_new_server() docs to account for code changes. ... (check-in: 258479650b user: stephan tags: trunk) | |
| 02:59 | Fix the SSL-server code so that the "fossil ui --tls" command (and similar) now work on Windows. ... (check-in: 7a3bf55f54 user: drh tags: trunk) | |
| 00:49 | Update buildmsvc.bat after testing successful compilation with the Visual Studio 2022 toolchain. ... (check-in: 2ed7465cf7 user: danield tags: trunk) | |
Changes
Changes to src/http_ssl.c.
| ︙ | ︙ | |||
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 |
|| sslctx_use_pkey_from_mem(sslCtx, sslSelfPKey, -1) ){
fossil_fatal("Error loading self-signed CERT");
}
if( !SSL_CTX_check_private_key(sslCtx) ){
fossil_fatal("PRIVATE KEY \"%s\" does not match CERT \"%s\"",
zKeyFile, zCertFile);
}
sslIsInit = 2;
}else{
assert( sslIsInit==2 );
}
}
typedef struct SslServerConn {
SSL *ssl; /* The SSL codec */
int atEof; /* True when EOF reached. */
| > < | | > | | < | < < < < < < | 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 |
|| sslctx_use_pkey_from_mem(sslCtx, sslSelfPKey, -1) ){
fossil_fatal("Error loading self-signed CERT");
}
if( !SSL_CTX_check_private_key(sslCtx) ){
fossil_fatal("PRIVATE KEY \"%s\" does not match CERT \"%s\"",
zKeyFile, zCertFile);
}
SSL_CTX_set_mode(sslCtx, SSL_MODE_AUTO_RETRY);
sslIsInit = 2;
}else{
assert( sslIsInit==2 );
}
}
typedef struct SslServerConn {
SSL *ssl; /* The SSL codec */
int atEof; /* True when EOF reached. */
int iSocket; /* The socket */
} SslServerConn;
/*
** Create a new server-side codec. The arguments are the file
** descriptors from which teh codec reads and writes, respectively.
**
** If the writeFd is negative, then use then the readFd is a socket
** over which we both read and write.
*/
void *ssl_new_server(int iSocket){
SslServerConn *pServer = fossil_malloc_zero(sizeof(*pServer));
BIO *b = BIO_new_socket(iSocket, 0);
pServer->ssl = SSL_new(sslCtx);
pServer->atEof = 0;
pServer->iSocket = iSocket;
SSL_set_bio(pServer->ssl, b, b);
SSL_accept(pServer->ssl);
return (void*)pServer;
}
/*
** Close a server-side code previously returned from ssl_new_server().
*/
void ssl_close_server(void *pServerArg){
SslServerConn *pServer = (SslServerConn*)pServerArg;
SSL_free(pServer->ssl);
fossil_free(pServer);
}
/*
** Return TRUE if there are no more bytes available to be read from
** the client.
*/
|
| ︙ | ︙ | |||
802 803 804 805 806 807 808 |
*/
size_t ssl_read_server(void *pServerArg, char *zBuf, size_t nBuf){
int n;
SslServerConn *pServer = (SslServerConn*)pServerArg;
if( pServer->atEof ) return 0;
if( nBuf>0x7fffffff ){ fossil_fatal("SSL read too big"); }
n = SSL_read(pServer->ssl, zBuf, (int)nBuf);
| | | | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 |
*/
size_t ssl_read_server(void *pServerArg, char *zBuf, size_t nBuf){
int n;
SslServerConn *pServer = (SslServerConn*)pServerArg;
if( pServer->atEof ) return 0;
if( nBuf>0x7fffffff ){ fossil_fatal("SSL read too big"); }
n = SSL_read(pServer->ssl, zBuf, (int)nBuf);
if( n==0 ) pServer->atEof = 1;
return n<=0 ? 0 : n;
}
/*
** Read a single line of text from the client.
*/
char *ssl_gets(void *pServerArg, char *zBuf, int nBuf){
int n = 0;
|
| ︙ | ︙ | |||
834 835 836 837 838 839 840 |
/*
** Write cleartext bytes into the SSL server codec so that they can
** be encrypted and sent back to the client.
*/
size_t ssl_write_server(void *pServerArg, char *zBuf, size_t nBuf){
int n;
SslServerConn *pServer = (SslServerConn*)pServerArg;
| | > > > | > | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 |
/*
** Write cleartext bytes into the SSL server codec so that they can
** be encrypted and sent back to the client.
*/
size_t ssl_write_server(void *pServerArg, char *zBuf, size_t nBuf){
int n;
SslServerConn *pServer = (SslServerConn*)pServerArg;
if( nBuf<=0 ) return 0;
if( nBuf>0x7fffffff ){ fossil_fatal("SSL write too big"); }
n = SSL_write(pServer->ssl, zBuf, (int)nBuf);
if( n<=0 ){
return -SSL_get_error(pServer->ssl, n);
}else{
return n;
}
}
#endif /* FOSSIL_ENABLE_SSL */
/*
** COMMAND: tls-config*
** COMMAND: ssl-config
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
2784 2785 2786 2787 2788 2789 2790 |
if( useSCGI ){
cgi_handle_scgi_request();
}else if( g.fSshClient & CGI_SSH_CLIENT ){
ssh_request_loop(zIpAddr, glob_create(zFileGlob));
}else{
#if FOSSIL_ENABLE_SSL
if( g.httpUseSSL ){
| | | 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 |
if( useSCGI ){
cgi_handle_scgi_request();
}else if( g.fSshClient & CGI_SSH_CLIENT ){
ssh_request_loop(zIpAddr, glob_create(zFileGlob));
}else{
#if FOSSIL_ENABLE_SSL
if( g.httpUseSSL ){
g.httpSSLConn = ssl_new_server(0);
}
#endif
cgi_handle_http_request(zIpAddr);
}
process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
#if FOSSIL_ENABLE_SSL
if( g.httpUseSSL && g.httpSSLConn ){
|
| ︙ | ︙ | |||
3284 3285 3286 3287 3288 3289 3290 |
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
}
}
if( flags & HTTP_SERVER_SCGI ){
cgi_handle_scgi_request();
}else if( g.httpUseSSL ){
#if FOSSIL_ENABLE_SSL
| | < < < | 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 |
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
}
}
if( flags & HTTP_SERVER_SCGI ){
cgi_handle_scgi_request();
}else if( g.httpUseSSL ){
#if FOSSIL_ENABLE_SSL
g.httpSSLConn = ssl_new_server(0);
#endif
cgi_handle_http_request(0);
}else{
cgi_handle_http_request(0);
}
process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
if( g.fAnyTrace ){
fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
getpid());
}
#if FOSSIL_ENABLE_SSL
if( g.httpUseSSL && g.httpSSLConn ){
ssl_close_server(g.httpSSLConn);
g.httpSSLConn = 0;
}
#endif /* FOSSIL_ENABLE_SSL */
#else /* WIN32 */
/* Win32 implementation */
if( allowRepoList ){
flags |= HTTP_SERVER_REPOLIST;
}
if( win32_http_service(iPort, zAltBase, zNotFound, zFileGlob, flags) ){
win32_http_server(iPort, mxPort, zBrowserCmd, zStopperFile,
zAltBase, zNotFound, zFileGlob, zIpAddr, flags);
}
|
| ︙ | ︙ |
Changes to src/winhttp.c.
| ︙ | ︙ | |||
338 339 340 341 342 343 344 345 346 347 348 |
static void win32_http_request(void *pAppData){
HttpRequest *p = (HttpRequest*)pAppData;
FILE *in = 0, *out = 0, *aux = 0;
int amt, got, i;
int wanted = 0;
char *z;
char *zIp;
char zCmdFName[MAX_PATH];
char zRequestFName[MAX_PATH];
char zReplyFName[MAX_PATH];
char zCmd[2000]; /* Command-line to process the request */
| > | > > > > > > | > > > > > | | > | | | > > > > > | | > | | > > > > > | | > | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 |
static void win32_http_request(void *pAppData){
HttpRequest *p = (HttpRequest*)pAppData;
FILE *in = 0, *out = 0, *aux = 0;
int amt, got, i;
int wanted = 0;
char *z;
char *zIp;
void *sslConn = 0;
char zCmdFName[MAX_PATH];
char zRequestFName[MAX_PATH];
char zReplyFName[MAX_PATH];
char zCmd[2000]; /* Command-line to process the request */
char zBuf[65536]; /* The HTTP request header */
const int szHdr = 4000; /* Reduced header size */
sqlite3_snprintf(MAX_PATH, zCmdFName,
"%s_%06d_cmd.txt", zTempPrefix, p->id);
sqlite3_snprintf(MAX_PATH, zRequestFName,
"%s_%06d_in.txt", zTempPrefix, p->id);
sqlite3_snprintf(MAX_PATH, zReplyFName,
"%s_%06d_out.txt", zTempPrefix, p->id);
amt = 0;
if( g.httpUseSSL ){
#ifdef FOSSIL_ENABLE_SSL
sslConn = ssl_new_server(p->s);
#endif
}
while( amt<szHdr ){
if( sslConn ){
#ifdef FOSSIL_ENABLE_SSL
got = ssl_read_server(sslConn, &zBuf[amt], szHdr-amt);
#endif
}else{
got = recv(p->s, &zBuf[amt], szHdr-amt, 0);
if( got==SOCKET_ERROR ) goto end_request;
}
if( got==0 ){
wanted = 0;
break;
}
amt += got;
zBuf[amt] = 0;
z = strstr(zBuf, "\r\n\r\n");
if( z ){
wanted = find_content_length(zBuf) + (&z[4]-zBuf) - amt;
break;
}else{
z = strstr(zBuf, "\n\n");
if( z ){
wanted = find_content_length(zBuf) + (&z[2]-zBuf) - amt;
break;
}
}
}
if( amt>=szHdr ) goto end_request;
out = fossil_fopen(zRequestFName, "wb");
if( out==0 ) goto end_request;
fwrite(zBuf, 1, amt, out);
while( wanted>0 ){
if( sslConn ){
#ifdef FOSSIL_ENABLE_SSL
got = ssl_read_server(sslConn, zBuf, sizeof(zBuf));
#endif
}else{
got = recv(p->s, zBuf, sizeof(zBuf), 0);
if( got==SOCKET_ERROR ) goto end_request;
}
if( got>0 ){
fwrite(zBuf, 1, got, out);
}else{
break;
}
wanted -= got;
}
/*
|
| ︙ | ︙ | |||
403 404 405 406 407 408 409 | } fossil_free(zIp); aux = fossil_fopen(zCmdFName, "wb"); if( aux==0 ) goto end_request; fwrite(zCmd, 1, strlen(zCmd), aux); sqlite3_snprintf(sizeof(zCmd), zCmd, | | | > | > > > > > | > > > > > > | 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 |
}
fossil_free(zIp);
aux = fossil_fopen(zCmdFName, "wb");
if( aux==0 ) goto end_request;
fwrite(zCmd, 1, strlen(zCmd), aux);
sqlite3_snprintf(sizeof(zCmd), zCmd,
"\"%s\" http -args \"%s\"%s%s",
g.nameOfExe, zCmdFName,
g.httpUseSSL ? "" : " --nossl", p->zOptions
);
in = fossil_fopen(zReplyFName, "w+b");
fflush(out);
fflush(aux);
fossil_system(zCmd);
if( in ){
while( (got = fread(zBuf, 1, sizeof(zBuf), in))>0 ){
if( sslConn ){
#ifdef FOSSIL_ENABLE_SSL
ssl_write_server(sslConn, zBuf, got);
#endif
}else{
send(p->s, zBuf, got, 0);
}
}
}
end_request:
if( out ) fclose(out);
if( aux ) fclose(aux);
if( in ) fclose(in);
/* Initiate shutdown prior to closing the socket */
if( sslConn!=0 ){
#ifdef FOSSIL_ENABLE_SSL
ssl_close_server(sslConn);
#endif
}
if( shutdown(p->s,1)==0 ) shutdown(p->s,0);
closesocket(p->s);
/* Make multiple attempts to delete the temporary files. Sometimes AV
** software keeps the files open for a few seconds, preventing the file
** from being deleted on the first try. */
for(i=1; i<=10 && file_delete(zRequestFName); i++){ Sleep(1000*i); }
for(i=1; i<=10 && file_delete(zCmdFName); i++){ Sleep(1000*i); }
|
| ︙ | ︙ | |||
617 618 619 620 621 622 623 |
if( !GetTempPathW(MAX_PATH, zTmpPath) ){
fossil_panic("unable to get path to the temporary directory.");
}
zTempPrefix = mprintf("%sfossil_server_P%d",
fossil_unicode_to_utf8(zTmpPath), iPort);
fossil_print("Temporary files: %s*\n", zTempPrefix);
fossil_print("Listening for %s requests on TCP port %d\n",
| | > | 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 |
if( !GetTempPathW(MAX_PATH, zTmpPath) ){
fossil_panic("unable to get path to the temporary directory.");
}
zTempPrefix = mprintf("%sfossil_server_P%d",
fossil_unicode_to_utf8(zTmpPath), iPort);
fossil_print("Temporary files: %s*\n", zTempPrefix);
fossil_print("Listening for %s requests on TCP port %d\n",
(flags&HTTP_SERVER_SCGI)!=0 ? "SCGI" :
g.httpUseSSL ? "TLS-encrypted HTTPS" : "HTTP", iPort);
if( zBrowser ){
zBrowser = mprintf(zBrowser /*works-like:"%d"*/, iPort);
fossil_print("Launch webbrowser: %s\n", zBrowser);
fossil_system(zBrowser);
}
fossil_print("Type Ctrl-C to stop the HTTP server\n");
/* Create an event used to signal when this server is exiting. */
|
| ︙ | ︙ |