Fossil SCM

Code is in place to do SSL servers. It compiles. But it does not work. This is an incremental check-in.

drh 2021-12-26 20:35 ssl-server
Commit 89af3b0a4761df7690aced022a2e060aef05daa8b2f23e8b6377be3395d02fb0
+20 -4
--- src/cgi.c
+++ src/cgi.c
@@ -354,11 +354,15 @@
354354
*/
355355
static char *cgi_fgets(char *s, int size){
356356
if( !g.httpUseSSL ){
357357
return fgets(s, size, g.httpIn);
358358
}
359
- assert( !"SSL Server not yet implemented" );
359
+#ifdef FOSSIL_ENABLE_SSL
360
+ return ssl_gets(g.httpSSLConn, s, size);
361
+#else
362
+ fossil_fatal("SSL not available");
363
+#endif
360364
}
361365
362366
/* Works like fread():
363367
**
364368
** Read as many as bytes of content as we can, up to a maximum of nmemb
@@ -367,11 +371,15 @@
367371
*/
368372
size_t cgi_fread(void *ptr, size_t nmemb){
369373
if( !g.httpUseSSL ){
370374
return fread(ptr, 1, nmemb, g.httpIn);
371375
}
372
- assert( !"SSL Server not yet implemented" );
376
+#ifdef FOSSIL_ENABLE_SSL
377
+ return ssl_read_server(g.httpSSLConn, ptr, nmemb);
378
+#else
379
+ fossil_fatal("SSL not available");
380
+#endif
373381
}
374382
375383
/* Works like feof():
376384
**
377385
** Return true if end-of-input has been reached.
@@ -378,11 +386,15 @@
378386
*/
379387
int cgi_feof(void){
380388
if( !g.httpUseSSL ){
381389
return feof(g.httpIn);
382390
}
383
- assert( !"SSL Server not yet implemented" );
391
+#ifdef FOSSIL_ENABLE_SSL
392
+ return ssl_eof(g.httpSSLConn);
393
+#else
394
+ return 1;
395
+#endif
384396
}
385397
386398
/* Works like fwrite():
387399
**
388400
** Try to output nmemb bytes of content. Return the number of
@@ -390,11 +402,15 @@
390402
*/
391403
static size_t cgi_fwrite(void *ptr, size_t nmemb){
392404
if( !g.httpUseSSL ){
393405
return fwrite(ptr, 1, nmemb, g.httpOut);
394406
}
395
- assert( !"SSL Server not yet implemented" );
407
+#ifdef FOSSIL_ENABLE_SSL
408
+ return ssl_write_server(g.httpSSLConn, ptr, nmemb);
409
+#else
410
+ fossil_fatal("SSL not available");
411
+#endif
396412
}
397413
398414
/* Works like fflush():
399415
**
400416
** Make sure I/O has completed.
401417
--- src/cgi.c
+++ src/cgi.c
@@ -354,11 +354,15 @@
354 */
355 static char *cgi_fgets(char *s, int size){
356 if( !g.httpUseSSL ){
357 return fgets(s, size, g.httpIn);
358 }
359 assert( !"SSL Server not yet implemented" );
 
 
 
 
360 }
361
362 /* Works like fread():
363 **
364 ** Read as many as bytes of content as we can, up to a maximum of nmemb
@@ -367,11 +371,15 @@
367 */
368 size_t cgi_fread(void *ptr, size_t nmemb){
369 if( !g.httpUseSSL ){
370 return fread(ptr, 1, nmemb, g.httpIn);
371 }
372 assert( !"SSL Server not yet implemented" );
 
 
 
 
373 }
374
375 /* Works like feof():
376 **
377 ** Return true if end-of-input has been reached.
@@ -378,11 +386,15 @@
378 */
379 int cgi_feof(void){
380 if( !g.httpUseSSL ){
381 return feof(g.httpIn);
382 }
383 assert( !"SSL Server not yet implemented" );
 
 
 
 
384 }
385
386 /* Works like fwrite():
387 **
388 ** Try to output nmemb bytes of content. Return the number of
@@ -390,11 +402,15 @@
390 */
391 static size_t cgi_fwrite(void *ptr, size_t nmemb){
392 if( !g.httpUseSSL ){
393 return fwrite(ptr, 1, nmemb, g.httpOut);
394 }
395 assert( !"SSL Server not yet implemented" );
 
 
 
 
396 }
397
398 /* Works like fflush():
399 **
400 ** Make sure I/O has completed.
401
--- src/cgi.c
+++ src/cgi.c
@@ -354,11 +354,15 @@
354 */
355 static char *cgi_fgets(char *s, int size){
356 if( !g.httpUseSSL ){
357 return fgets(s, size, g.httpIn);
358 }
359 #ifdef FOSSIL_ENABLE_SSL
360 return ssl_gets(g.httpSSLConn, s, size);
361 #else
362 fossil_fatal("SSL not available");
363 #endif
364 }
365
366 /* Works like fread():
367 **
368 ** Read as many as bytes of content as we can, up to a maximum of nmemb
@@ -367,11 +371,15 @@
371 */
372 size_t cgi_fread(void *ptr, size_t nmemb){
373 if( !g.httpUseSSL ){
374 return fread(ptr, 1, nmemb, g.httpIn);
375 }
376 #ifdef FOSSIL_ENABLE_SSL
377 return ssl_read_server(g.httpSSLConn, ptr, nmemb);
378 #else
379 fossil_fatal("SSL not available");
380 #endif
381 }
382
383 /* Works like feof():
384 **
385 ** Return true if end-of-input has been reached.
@@ -378,11 +386,15 @@
386 */
387 int cgi_feof(void){
388 if( !g.httpUseSSL ){
389 return feof(g.httpIn);
390 }
391 #ifdef FOSSIL_ENABLE_SSL
392 return ssl_eof(g.httpSSLConn);
393 #else
394 return 1;
395 #endif
396 }
397
398 /* Works like fwrite():
399 **
400 ** Try to output nmemb bytes of content. Return the number of
@@ -390,11 +402,15 @@
402 */
403 static size_t cgi_fwrite(void *ptr, size_t nmemb){
404 if( !g.httpUseSSL ){
405 return fwrite(ptr, 1, nmemb, g.httpOut);
406 }
407 #ifdef FOSSIL_ENABLE_SSL
408 return ssl_write_server(g.httpSSLConn, ptr, nmemb);
409 #else
410 fossil_fatal("SSL not available");
411 #endif
412 }
413
414 /* Works like fflush():
415 **
416 ** Make sure I/O has completed.
417
+159 -17
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -16,12 +16,15 @@
1616
*******************************************************************************
1717
**
1818
** This file manages low-level SSL communications.
1919
**
2020
** This file implements a singleton. A single SSL connection may be active
21
-** at a time. State information is stored in static variables. The identity
22
-** of the server is held in global variables that are set by url_parse().
21
+** at a time. State information is stored in static variables.
22
+**
23
+** The SSL connections can be either a client or a server. But all
24
+** connections for a single process must be of the same type, either client
25
+** or server.
2326
**
2427
** SSL support is abstracted out into this module because Fossil can
2528
** be compiled without SSL support (which requires OpenSSL library)
2629
*/
2730
@@ -41,11 +44,11 @@
4144
/*
4245
** There can only be a single OpenSSL IO connection open at a time.
4346
** State information about that IO is stored in the following
4447
** local variables:
4548
*/
46
-static int sslIsInit = 0; /* True after global initialization */
49
+static int sslIsInit = 0; /* 0: uninit 1: init as client 2: init as server */
4750
static BIO *iBio = 0; /* OpenSSL I/O abstraction */
4851
static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
4952
static SSL_CTX *sslCtx; /* SSL context */
5053
static SSL *ssl;
5154
static struct { /* Accept this SSL cert for this session only */
@@ -134,11 +137,11 @@
134137
135138
/*
136139
** Call this routine once before any other use of the SSL interface.
137140
** This routine does initial configuration of the SSL module.
138141
*/
139
-void ssl_global_init(void){
142
+static void ssl_global_init_client(void){
140143
const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
141144
const char *identityFile;
142145
143146
if( sslIsInit==0 ){
144147
SSL_library_init();
@@ -193,10 +196,12 @@
193196
/* Register a callback to tell the user what to do when the server asks
194197
** for a cert */
195198
SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
196199
197200
sslIsInit = 1;
201
+ }else{
202
+ assert( sslIsInit==1 );
198203
}
199204
}
200205
201206
/*
202207
** Call this routine to shutdown the SSL module prior to program exit.
@@ -208,14 +213,14 @@
208213
sslIsInit = 0;
209214
}
210215
}
211216
212217
/*
213
-** Close the currently open SSL connection. If no connection is open,
218
+** Close the currently open client SSL connection. If no connection is open,
214219
** this routine is a no-op.
215220
*/
216
-void ssl_close(void){
221
+void ssl_close_client(void){
217222
if( iBio!=NULL ){
218223
(void)BIO_reset(iBio);
219224
BIO_free_all(iBio);
220225
iBio = NULL;
221226
}
@@ -280,34 +285,36 @@
280285
void ssl_disable_cert_verification(void){
281286
sslNoCertVerify = 1;
282287
}
283288
284289
/*
285
-** Open an SSL connection. The identify of the server is determined
286
-** as follows:
290
+** Open an SSL connection as a client that is to connect to the server
291
+** identified by pUrlData.
292
+**
293
+* The identify of the server is determined as follows:
287294
**
288295
** pUrlData->name Name of the server. Ex: fossil-scm.org
289296
** g.url.name Name of the proxy server, if proxying.
290297
** pUrlData->port TCP/IP port to use. Ex: 80
291298
**
292299
** Return the number of errors.
293300
*/
294
-int ssl_open(UrlData *pUrlData){
301
+int ssl_open_client(UrlData *pUrlData){
295302
X509 *cert;
296303
const char *zRemoteHost;
297304
298
- ssl_global_init();
305
+ ssl_global_init_client();
299306
if( pUrlData->useProxy ){
300307
int rc;
301308
char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
302309
BIO *sBio = BIO_new_connect(connStr);
303310
free(connStr);
304311
if( BIO_do_connect(sBio)<=0 ){
305312
ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
306313
pUrlData->name, pUrlData->port,
307314
ERR_reason_error_string(ERR_get_error()));
308
- ssl_close();
315
+ ssl_close_client();
309316
return 1;
310317
}
311318
rc = establish_proxy_tunnel(pUrlData, sBio);
312319
if( rc<200||rc>299 ){
313320
ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
@@ -355,29 +362,29 @@
355362
free(connStr);
356363
if( BIO_do_connect(iBio)<=0 ){
357364
ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
358365
pUrlData->name, pUrlData->port,
359366
ERR_reason_error_string(ERR_get_error()));
360
- ssl_close();
367
+ ssl_close_client();
361368
return 1;
362369
}
363370
}
364371
365372
if( BIO_do_handshake(iBio)<=0 ) {
366373
ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
367374
pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
368375
pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
369376
ERR_reason_error_string(ERR_get_error()));
370
- ssl_close();
377
+ ssl_close_client();
371378
return 1;
372379
}
373380
/* Check if certificate is valid */
374381
cert = SSL_get_peer_certificate(ssl);
375382
376383
if ( cert==NULL ){
377384
ssl_set_errmsg("No SSL certificate was presented by the peer");
378
- ssl_close();
385
+ ssl_close_client();
379386
return 1;
380387
}
381388
382389
/* Debugging hint: On unix-like system, run something like:
383390
**
@@ -441,11 +448,11 @@
441448
if( cReply!='y' && cReply!='Y'
442449
&& fossil_stricmp(blob_str(&ans),zHash)!=0
443450
){
444451
X509_free(cert);
445452
ssl_set_errmsg("SSL cert declined");
446
- ssl_close();
453
+ ssl_close_client();
447454
blob_reset(&ans);
448455
return 1;
449456
}
450457
blob_reset(&ans);
451458
ssl_one_time_exception(pUrlData, zHash);
@@ -528,11 +535,12 @@
528535
fossil_free(sException.zHash);
529536
sException.zHash = fossil_strdup(zHash);
530537
}
531538
532539
/*
533
-** Send content out over the SSL connection.
540
+** Send content out over the SSL connection from the client to
541
+** the server.
534542
*/
535543
size_t ssl_send(void *NotUsed, void *pContent, size_t N){
536544
size_t total = 0;
537545
while( N>0 ){
538546
int sent = BIO_write(iBio, pContent, N);
@@ -548,11 +556,12 @@
548556
}
549557
return total;
550558
}
551559
552560
/*
553
-** Receive content back from the SSL connection.
561
+** Receive content back from the client SSL connection. In other
562
+** words read the reply back from the server.
554563
*/
555564
size_t ssl_receive(void *NotUsed, void *pContent, size_t N){
556565
size_t total = 0;
557566
while( N>0 ){
558567
int got = BIO_read(iBio, pContent, N);
@@ -566,10 +575,143 @@
566575
N -= got;
567576
pContent = (void*)&((char*)pContent)[got];
568577
}
569578
return total;
570579
}
580
+
581
+/*
582
+** Initialize the SSL library so that it is able to handle
583
+** server-side connections. Invoke fossil_fatal() if there are
584
+** any problems.
585
+**
586
+** zKeyFile may be NULL, in which case zCertFile will contain both
587
+** the private key and the cert.
588
+*/
589
+void ssl_init_server(const char *zCertFile, const char *zKeyFile){
590
+ if( sslIsInit==0 ){
591
+ SSL_library_init();
592
+ SSL_load_error_strings();
593
+ OpenSSL_add_all_algorithms();
594
+ sslCtx = SSL_CTX_new(SSLv23_server_method());
595
+ if( sslCtx==0 ){
596
+ ERR_print_errors_fp(stderr);
597
+ fossil_fatal("Error initializing the SSL server");
598
+ }
599
+ if( SSL_CTX_use_certificate_file(sslCtx, zCertFile, SSL_FILETYPE_PEM)<=0 ){
600
+ ERR_print_errors_fp(stderr);
601
+ fossil_fatal("Error loading CERT file \"%s\"", zCertFile);
602
+ }
603
+ if( zKeyFile==0 ) zKeyFile = zCertFile;
604
+ if( SSL_CTX_use_PrivateKey_file(sslCtx, zKeyFile, SSL_FILETYPE_PEM)<=0 ){
605
+ ERR_print_errors_fp(stderr);
606
+ fossil_fatal("Error loading PRIVATE KEY from file \"%s\"", zKeyFile);
607
+ }
608
+ if( !SSL_CTX_check_private_key(sslCtx) ){
609
+ fossil_fatal("PRIVATE KEY \"%s\" does not match CERT \"%s\"",
610
+ zKeyFile, zCertFile);
611
+ }
612
+ sslIsInit = 2;
613
+ }else{
614
+ assert( sslIsInit==2 );
615
+ }
616
+}
617
+
618
+typedef struct SslServerConn {
619
+ SSL *ssl; /* The SSL codec */
620
+ int atEof; /* True when EOF reached. */
621
+ int fd0; /* Read channel, or socket */
622
+ int fd1; /* Write channel */
623
+} SslServerConn;
624
+
625
+/*
626
+** Create a new server-side codec. The arguments are the file
627
+** descriptors from which teh codec reads and writes, respectively.
628
+**
629
+** If the writeFd is negative, then use then the readFd is a socket
630
+** over which we both read and write.
631
+*/
632
+void *ssl_new_server(int readFd, int writeFd){
633
+ SslServerConn *pServer = fossil_malloc_zero(sizeof(*pServer));
634
+ pServer->ssl = SSL_new(sslCtx);
635
+ pServer->fd0 = readFd;
636
+ pServer->fd1 = writeFd;
637
+ if( writeFd<0 ){
638
+ SSL_set_fd(pServer->ssl, readFd);
639
+ }else{
640
+ SSL_set_rfd(pServer->ssl, readFd);
641
+ SSL_set_wfd(pServer->ssl, writeFd);
642
+ }
643
+ return (void*)pServer;
644
+}
645
+
646
+/*
647
+** Close a server-side code previously returned from ssl_new_server().
648
+*/
649
+void ssl_close_server(void *pServerArg){
650
+ SslServerConn *pServer = (SslServerConn*)pServerArg;
651
+ SSL_free(pServer->ssl);
652
+ close(pServer->fd0);
653
+ if( pServer->fd1>=0 ) close(pServer->fd0);
654
+ fossil_free(pServer);
655
+}
656
+
657
+/*
658
+** Return TRUE if there are no more bytes available to be read from
659
+** the client.
660
+*/
661
+int ssl_eof(void *pServerArg){
662
+ SslServerConn *pServer = (SslServerConn*)pServerArg;
663
+ return pServer->atEof;
664
+}
665
+
666
+/*
667
+** Read cleartext bytes that have been received from the client and
668
+** decrypted by the SSL server codec.
669
+*/
670
+size_t ssl_read_server(void *pServerArg, char *zBuf, size_t nBuf){
671
+ int n;
672
+ SslServerConn *pServer = (SslServerConn*)pServerArg;
673
+ if( pServer->atEof ) return 0;
674
+ if( nBuf>0x7fffffff ){ fossil_fatal("SSL read too big"); }
675
+ n = SSL_read(pServer->ssl, zBuf, (int)nBuf);
676
+ if( n<nBuf ) pServer->atEof = 1;
677
+ return n;
678
+}
679
+
680
+/*
681
+** Read a single line of text from the client.
682
+*/
683
+char *ssl_gets(void *pServerArg, char *zBuf, int nBuf){
684
+ int n = 0;
685
+ int i;
686
+ SslServerConn *pServer = (SslServerConn*)pServerArg;
687
+
688
+ if( pServer->atEof ) return 0;
689
+ n = SSL_peek(pServer->ssl, zBuf, nBuf-1);
690
+ if( n==0 ){
691
+ pServer->atEof = 1;
692
+ return 0;
693
+ }
694
+ for(i=0; i<n && zBuf[i]!='\n'; i++){}
695
+ SSL_read(pServer->ssl, zBuf, i);
696
+ zBuf[i+1] = 0;
697
+ return zBuf;
698
+}
699
+
700
+
701
+/*
702
+** Write cleartext bytes into the SSL server codec so that they can
703
+** be encrypted and sent back to the client.
704
+*/
705
+size_t ssl_write_server(void *pServerArg, char *zBuf, size_t nBuf){
706
+ int n;
707
+ SslServerConn *pServer = (SslServerConn*)pServerArg;
708
+ if( pServer->atEof ) return 0;
709
+ if( nBuf>0x7fffffff ){ fossil_fatal("SSL write too big"); }
710
+ n = SSL_write(pServer->ssl, zBuf, (int)nBuf);
711
+ return n;
712
+}
571713
572714
#endif /* FOSSIL_ENABLE_SSL */
573715
574716
/*
575717
** COMMAND: tls-config*
576718
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -16,12 +16,15 @@
16 *******************************************************************************
17 **
18 ** This file manages low-level SSL communications.
19 **
20 ** This file implements a singleton. A single SSL connection may be active
21 ** at a time. State information is stored in static variables. The identity
22 ** of the server is held in global variables that are set by url_parse().
 
 
 
23 **
24 ** SSL support is abstracted out into this module because Fossil can
25 ** be compiled without SSL support (which requires OpenSSL library)
26 */
27
@@ -41,11 +44,11 @@
41 /*
42 ** There can only be a single OpenSSL IO connection open at a time.
43 ** State information about that IO is stored in the following
44 ** local variables:
45 */
46 static int sslIsInit = 0; /* True after global initialization */
47 static BIO *iBio = 0; /* OpenSSL I/O abstraction */
48 static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
49 static SSL_CTX *sslCtx; /* SSL context */
50 static SSL *ssl;
51 static struct { /* Accept this SSL cert for this session only */
@@ -134,11 +137,11 @@
134
135 /*
136 ** Call this routine once before any other use of the SSL interface.
137 ** This routine does initial configuration of the SSL module.
138 */
139 void ssl_global_init(void){
140 const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
141 const char *identityFile;
142
143 if( sslIsInit==0 ){
144 SSL_library_init();
@@ -193,10 +196,12 @@
193 /* Register a callback to tell the user what to do when the server asks
194 ** for a cert */
195 SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
196
197 sslIsInit = 1;
 
 
198 }
199 }
200
201 /*
202 ** Call this routine to shutdown the SSL module prior to program exit.
@@ -208,14 +213,14 @@
208 sslIsInit = 0;
209 }
210 }
211
212 /*
213 ** Close the currently open SSL connection. If no connection is open,
214 ** this routine is a no-op.
215 */
216 void ssl_close(void){
217 if( iBio!=NULL ){
218 (void)BIO_reset(iBio);
219 BIO_free_all(iBio);
220 iBio = NULL;
221 }
@@ -280,34 +285,36 @@
280 void ssl_disable_cert_verification(void){
281 sslNoCertVerify = 1;
282 }
283
284 /*
285 ** Open an SSL connection. The identify of the server is determined
286 ** as follows:
 
 
287 **
288 ** pUrlData->name Name of the server. Ex: fossil-scm.org
289 ** g.url.name Name of the proxy server, if proxying.
290 ** pUrlData->port TCP/IP port to use. Ex: 80
291 **
292 ** Return the number of errors.
293 */
294 int ssl_open(UrlData *pUrlData){
295 X509 *cert;
296 const char *zRemoteHost;
297
298 ssl_global_init();
299 if( pUrlData->useProxy ){
300 int rc;
301 char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
302 BIO *sBio = BIO_new_connect(connStr);
303 free(connStr);
304 if( BIO_do_connect(sBio)<=0 ){
305 ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
306 pUrlData->name, pUrlData->port,
307 ERR_reason_error_string(ERR_get_error()));
308 ssl_close();
309 return 1;
310 }
311 rc = establish_proxy_tunnel(pUrlData, sBio);
312 if( rc<200||rc>299 ){
313 ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
@@ -355,29 +362,29 @@
355 free(connStr);
356 if( BIO_do_connect(iBio)<=0 ){
357 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
358 pUrlData->name, pUrlData->port,
359 ERR_reason_error_string(ERR_get_error()));
360 ssl_close();
361 return 1;
362 }
363 }
364
365 if( BIO_do_handshake(iBio)<=0 ) {
366 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
367 pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
368 pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
369 ERR_reason_error_string(ERR_get_error()));
370 ssl_close();
371 return 1;
372 }
373 /* Check if certificate is valid */
374 cert = SSL_get_peer_certificate(ssl);
375
376 if ( cert==NULL ){
377 ssl_set_errmsg("No SSL certificate was presented by the peer");
378 ssl_close();
379 return 1;
380 }
381
382 /* Debugging hint: On unix-like system, run something like:
383 **
@@ -441,11 +448,11 @@
441 if( cReply!='y' && cReply!='Y'
442 && fossil_stricmp(blob_str(&ans),zHash)!=0
443 ){
444 X509_free(cert);
445 ssl_set_errmsg("SSL cert declined");
446 ssl_close();
447 blob_reset(&ans);
448 return 1;
449 }
450 blob_reset(&ans);
451 ssl_one_time_exception(pUrlData, zHash);
@@ -528,11 +535,12 @@
528 fossil_free(sException.zHash);
529 sException.zHash = fossil_strdup(zHash);
530 }
531
532 /*
533 ** Send content out over the SSL connection.
 
534 */
535 size_t ssl_send(void *NotUsed, void *pContent, size_t N){
536 size_t total = 0;
537 while( N>0 ){
538 int sent = BIO_write(iBio, pContent, N);
@@ -548,11 +556,12 @@
548 }
549 return total;
550 }
551
552 /*
553 ** Receive content back from the SSL connection.
 
554 */
555 size_t ssl_receive(void *NotUsed, void *pContent, size_t N){
556 size_t total = 0;
557 while( N>0 ){
558 int got = BIO_read(iBio, pContent, N);
@@ -566,10 +575,143 @@
566 N -= got;
567 pContent = (void*)&((char*)pContent)[got];
568 }
569 return total;
570 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
571
572 #endif /* FOSSIL_ENABLE_SSL */
573
574 /*
575 ** COMMAND: tls-config*
576
--- src/http_ssl.c
+++ src/http_ssl.c
@@ -16,12 +16,15 @@
16 *******************************************************************************
17 **
18 ** This file manages low-level SSL communications.
19 **
20 ** This file implements a singleton. A single SSL connection may be active
21 ** at a time. State information is stored in static variables.
22 **
23 ** The SSL connections can be either a client or a server. But all
24 ** connections for a single process must be of the same type, either client
25 ** or server.
26 **
27 ** SSL support is abstracted out into this module because Fossil can
28 ** be compiled without SSL support (which requires OpenSSL library)
29 */
30
@@ -41,11 +44,11 @@
44 /*
45 ** There can only be a single OpenSSL IO connection open at a time.
46 ** State information about that IO is stored in the following
47 ** local variables:
48 */
49 static int sslIsInit = 0; /* 0: uninit 1: init as client 2: init as server */
50 static BIO *iBio = 0; /* OpenSSL I/O abstraction */
51 static char *sslErrMsg = 0; /* Text of most recent OpenSSL error */
52 static SSL_CTX *sslCtx; /* SSL context */
53 static SSL *ssl;
54 static struct { /* Accept this SSL cert for this session only */
@@ -134,11 +137,11 @@
137
138 /*
139 ** Call this routine once before any other use of the SSL interface.
140 ** This routine does initial configuration of the SSL module.
141 */
142 static void ssl_global_init_client(void){
143 const char *zCaSetting = 0, *zCaFile = 0, *zCaDirectory = 0;
144 const char *identityFile;
145
146 if( sslIsInit==0 ){
147 SSL_library_init();
@@ -193,10 +196,12 @@
196 /* Register a callback to tell the user what to do when the server asks
197 ** for a cert */
198 SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback);
199
200 sslIsInit = 1;
201 }else{
202 assert( sslIsInit==1 );
203 }
204 }
205
206 /*
207 ** Call this routine to shutdown the SSL module prior to program exit.
@@ -208,14 +213,14 @@
213 sslIsInit = 0;
214 }
215 }
216
217 /*
218 ** Close the currently open client SSL connection. If no connection is open,
219 ** this routine is a no-op.
220 */
221 void ssl_close_client(void){
222 if( iBio!=NULL ){
223 (void)BIO_reset(iBio);
224 BIO_free_all(iBio);
225 iBio = NULL;
226 }
@@ -280,34 +285,36 @@
285 void ssl_disable_cert_verification(void){
286 sslNoCertVerify = 1;
287 }
288
289 /*
290 ** Open an SSL connection as a client that is to connect to the server
291 ** identified by pUrlData.
292 **
293 * The identify of the server is determined as follows:
294 **
295 ** pUrlData->name Name of the server. Ex: fossil-scm.org
296 ** g.url.name Name of the proxy server, if proxying.
297 ** pUrlData->port TCP/IP port to use. Ex: 80
298 **
299 ** Return the number of errors.
300 */
301 int ssl_open_client(UrlData *pUrlData){
302 X509 *cert;
303 const char *zRemoteHost;
304
305 ssl_global_init_client();
306 if( pUrlData->useProxy ){
307 int rc;
308 char *connStr = mprintf("%s:%d", g.url.name, pUrlData->port);
309 BIO *sBio = BIO_new_connect(connStr);
310 free(connStr);
311 if( BIO_do_connect(sBio)<=0 ){
312 ssl_set_errmsg("SSL: cannot connect to proxy %s:%d (%s)",
313 pUrlData->name, pUrlData->port,
314 ERR_reason_error_string(ERR_get_error()));
315 ssl_close_client();
316 return 1;
317 }
318 rc = establish_proxy_tunnel(pUrlData, sBio);
319 if( rc<200||rc>299 ){
320 ssl_set_errmsg("SSL: proxy connect failed with HTTP status code %d", rc);
@@ -355,29 +362,29 @@
362 free(connStr);
363 if( BIO_do_connect(iBio)<=0 ){
364 ssl_set_errmsg("SSL: cannot connect to host %s:%d (%s)",
365 pUrlData->name, pUrlData->port,
366 ERR_reason_error_string(ERR_get_error()));
367 ssl_close_client();
368 return 1;
369 }
370 }
371
372 if( BIO_do_handshake(iBio)<=0 ) {
373 ssl_set_errmsg("Error establishing SSL connection %s:%d (%s)",
374 pUrlData->useProxy?pUrlData->hostname:pUrlData->name,
375 pUrlData->useProxy?pUrlData->proxyOrigPort:pUrlData->port,
376 ERR_reason_error_string(ERR_get_error()));
377 ssl_close_client();
378 return 1;
379 }
380 /* Check if certificate is valid */
381 cert = SSL_get_peer_certificate(ssl);
382
383 if ( cert==NULL ){
384 ssl_set_errmsg("No SSL certificate was presented by the peer");
385 ssl_close_client();
386 return 1;
387 }
388
389 /* Debugging hint: On unix-like system, run something like:
390 **
@@ -441,11 +448,11 @@
448 if( cReply!='y' && cReply!='Y'
449 && fossil_stricmp(blob_str(&ans),zHash)!=0
450 ){
451 X509_free(cert);
452 ssl_set_errmsg("SSL cert declined");
453 ssl_close_client();
454 blob_reset(&ans);
455 return 1;
456 }
457 blob_reset(&ans);
458 ssl_one_time_exception(pUrlData, zHash);
@@ -528,11 +535,12 @@
535 fossil_free(sException.zHash);
536 sException.zHash = fossil_strdup(zHash);
537 }
538
539 /*
540 ** Send content out over the SSL connection from the client to
541 ** the server.
542 */
543 size_t ssl_send(void *NotUsed, void *pContent, size_t N){
544 size_t total = 0;
545 while( N>0 ){
546 int sent = BIO_write(iBio, pContent, N);
@@ -548,11 +556,12 @@
556 }
557 return total;
558 }
559
560 /*
561 ** Receive content back from the client SSL connection. In other
562 ** words read the reply back from the server.
563 */
564 size_t ssl_receive(void *NotUsed, void *pContent, size_t N){
565 size_t total = 0;
566 while( N>0 ){
567 int got = BIO_read(iBio, pContent, N);
@@ -566,10 +575,143 @@
575 N -= got;
576 pContent = (void*)&((char*)pContent)[got];
577 }
578 return total;
579 }
580
581 /*
582 ** Initialize the SSL library so that it is able to handle
583 ** server-side connections. Invoke fossil_fatal() if there are
584 ** any problems.
585 **
586 ** zKeyFile may be NULL, in which case zCertFile will contain both
587 ** the private key and the cert.
588 */
589 void ssl_init_server(const char *zCertFile, const char *zKeyFile){
590 if( sslIsInit==0 ){
591 SSL_library_init();
592 SSL_load_error_strings();
593 OpenSSL_add_all_algorithms();
594 sslCtx = SSL_CTX_new(SSLv23_server_method());
595 if( sslCtx==0 ){
596 ERR_print_errors_fp(stderr);
597 fossil_fatal("Error initializing the SSL server");
598 }
599 if( SSL_CTX_use_certificate_file(sslCtx, zCertFile, SSL_FILETYPE_PEM)<=0 ){
600 ERR_print_errors_fp(stderr);
601 fossil_fatal("Error loading CERT file \"%s\"", zCertFile);
602 }
603 if( zKeyFile==0 ) zKeyFile = zCertFile;
604 if( SSL_CTX_use_PrivateKey_file(sslCtx, zKeyFile, SSL_FILETYPE_PEM)<=0 ){
605 ERR_print_errors_fp(stderr);
606 fossil_fatal("Error loading PRIVATE KEY from file \"%s\"", zKeyFile);
607 }
608 if( !SSL_CTX_check_private_key(sslCtx) ){
609 fossil_fatal("PRIVATE KEY \"%s\" does not match CERT \"%s\"",
610 zKeyFile, zCertFile);
611 }
612 sslIsInit = 2;
613 }else{
614 assert( sslIsInit==2 );
615 }
616 }
617
618 typedef struct SslServerConn {
619 SSL *ssl; /* The SSL codec */
620 int atEof; /* True when EOF reached. */
621 int fd0; /* Read channel, or socket */
622 int fd1; /* Write channel */
623 } SslServerConn;
624
625 /*
626 ** Create a new server-side codec. The arguments are the file
627 ** descriptors from which teh codec reads and writes, respectively.
628 **
629 ** If the writeFd is negative, then use then the readFd is a socket
630 ** over which we both read and write.
631 */
632 void *ssl_new_server(int readFd, int writeFd){
633 SslServerConn *pServer = fossil_malloc_zero(sizeof(*pServer));
634 pServer->ssl = SSL_new(sslCtx);
635 pServer->fd0 = readFd;
636 pServer->fd1 = writeFd;
637 if( writeFd<0 ){
638 SSL_set_fd(pServer->ssl, readFd);
639 }else{
640 SSL_set_rfd(pServer->ssl, readFd);
641 SSL_set_wfd(pServer->ssl, writeFd);
642 }
643 return (void*)pServer;
644 }
645
646 /*
647 ** Close a server-side code previously returned from ssl_new_server().
648 */
649 void ssl_close_server(void *pServerArg){
650 SslServerConn *pServer = (SslServerConn*)pServerArg;
651 SSL_free(pServer->ssl);
652 close(pServer->fd0);
653 if( pServer->fd1>=0 ) close(pServer->fd0);
654 fossil_free(pServer);
655 }
656
657 /*
658 ** Return TRUE if there are no more bytes available to be read from
659 ** the client.
660 */
661 int ssl_eof(void *pServerArg){
662 SslServerConn *pServer = (SslServerConn*)pServerArg;
663 return pServer->atEof;
664 }
665
666 /*
667 ** Read cleartext bytes that have been received from the client and
668 ** decrypted by the SSL server codec.
669 */
670 size_t ssl_read_server(void *pServerArg, char *zBuf, size_t nBuf){
671 int n;
672 SslServerConn *pServer = (SslServerConn*)pServerArg;
673 if( pServer->atEof ) return 0;
674 if( nBuf>0x7fffffff ){ fossil_fatal("SSL read too big"); }
675 n = SSL_read(pServer->ssl, zBuf, (int)nBuf);
676 if( n<nBuf ) pServer->atEof = 1;
677 return n;
678 }
679
680 /*
681 ** Read a single line of text from the client.
682 */
683 char *ssl_gets(void *pServerArg, char *zBuf, int nBuf){
684 int n = 0;
685 int i;
686 SslServerConn *pServer = (SslServerConn*)pServerArg;
687
688 if( pServer->atEof ) return 0;
689 n = SSL_peek(pServer->ssl, zBuf, nBuf-1);
690 if( n==0 ){
691 pServer->atEof = 1;
692 return 0;
693 }
694 for(i=0; i<n && zBuf[i]!='\n'; i++){}
695 SSL_read(pServer->ssl, zBuf, i);
696 zBuf[i+1] = 0;
697 return zBuf;
698 }
699
700
701 /*
702 ** Write cleartext bytes into the SSL server codec so that they can
703 ** be encrypted and sent back to the client.
704 */
705 size_t ssl_write_server(void *pServerArg, char *zBuf, size_t nBuf){
706 int n;
707 SslServerConn *pServer = (SslServerConn*)pServerArg;
708 if( pServer->atEof ) return 0;
709 if( nBuf>0x7fffffff ){ fossil_fatal("SSL write too big"); }
710 n = SSL_write(pServer->ssl, zBuf, (int)nBuf);
711 return n;
712 }
713
714 #endif /* FOSSIL_ENABLE_SSL */
715
716 /*
717 ** COMMAND: tls-config*
718
--- src/http_transport.c
+++ src/http_transport.c
@@ -170,11 +170,11 @@
170170
if( pUrlData->isSsh ){
171171
rc = transport_ssh_open(pUrlData);
172172
if( rc==0 ) transport.isOpen = 1;
173173
}else if( pUrlData->isHttps ){
174174
#ifdef FOSSIL_ENABLE_SSL
175
- rc = ssl_open(pUrlData);
175
+ rc = ssl_open_client(pUrlData);
176176
if( rc==0 ) transport.isOpen = 1;
177177
#else
178178
socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
179179
rc = 1;
180180
#endif
@@ -213,11 +213,11 @@
213213
}
214214
if( pUrlData->isSsh ){
215215
transport_ssh_close();
216216
}else if( pUrlData->isHttps ){
217217
#ifdef FOSSIL_ENABLE_SSL
218
- ssl_close();
218
+ ssl_close_client();
219219
#endif
220220
}else if( pUrlData->isFile ){
221221
if( transport.pFile ){
222222
fclose(transport.pFile);
223223
transport.pFile = 0;
224224
--- src/http_transport.c
+++ src/http_transport.c
@@ -170,11 +170,11 @@
170 if( pUrlData->isSsh ){
171 rc = transport_ssh_open(pUrlData);
172 if( rc==0 ) transport.isOpen = 1;
173 }else if( pUrlData->isHttps ){
174 #ifdef FOSSIL_ENABLE_SSL
175 rc = ssl_open(pUrlData);
176 if( rc==0 ) transport.isOpen = 1;
177 #else
178 socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
179 rc = 1;
180 #endif
@@ -213,11 +213,11 @@
213 }
214 if( pUrlData->isSsh ){
215 transport_ssh_close();
216 }else if( pUrlData->isHttps ){
217 #ifdef FOSSIL_ENABLE_SSL
218 ssl_close();
219 #endif
220 }else if( pUrlData->isFile ){
221 if( transport.pFile ){
222 fclose(transport.pFile);
223 transport.pFile = 0;
224
--- src/http_transport.c
+++ src/http_transport.c
@@ -170,11 +170,11 @@
170 if( pUrlData->isSsh ){
171 rc = transport_ssh_open(pUrlData);
172 if( rc==0 ) transport.isOpen = 1;
173 }else if( pUrlData->isHttps ){
174 #ifdef FOSSIL_ENABLE_SSL
175 rc = ssl_open_client(pUrlData);
176 if( rc==0 ) transport.isOpen = 1;
177 #else
178 socket_set_errmsg("HTTPS: Fossil has been compiled without SSL support");
179 rc = 1;
180 #endif
@@ -213,11 +213,11 @@
213 }
214 if( pUrlData->isSsh ){
215 transport_ssh_close();
216 }else if( pUrlData->isHttps ){
217 #ifdef FOSSIL_ENABLE_SSL
218 ssl_close_client();
219 #endif
220 }else if( pUrlData->isFile ){
221 if( transport.pFile ){
222 fclose(transport.pFile);
223 transport.pFile = 0;
224
+27 -4
--- src/main.c
+++ src/main.c
@@ -196,10 +196,11 @@
196196
char *th1Setup; /* The TH1 post-creation setup script, if any */
197197
int th1Flags; /* The TH1 integration state flags */
198198
FILE *httpIn; /* Accept HTTP input from here */
199199
FILE *httpOut; /* Send HTTP output here */
200200
int httpUseSSL; /* True to use an SSL codec for HTTP traffic */
201
+ void *httpSSLConn; /* The SSL connection */
201202
int xlinkClusterOnly; /* Set when cloning. Only process clusters */
202203
int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
203204
int *aCommitFile; /* Array of files to be committed */
204205
int markPrivate; /* All new artifacts are private if true */
205206
char *ckinLockFail; /* Check-in lock failure received from server */
@@ -2834,10 +2835,23 @@
28342835
signal(SIGALRM, sigalrm_handler);
28352836
alarm(N);
28362837
nAlarmSeconds = N;
28372838
#endif
28382839
}
2840
+
2841
+/*
2842
+** Check for options to "fossil server" or "fossil ui" that imply that
2843
+** SSL should be used, and initialize the SSL decoder.
2844
+*/
2845
+static void decode_ssl_options(void){
2846
+ const char *zCertFile = 0;
2847
+ zCertFile = find_option("tls-cert-file",0,1);
2848
+ if( zCertFile ){
2849
+ g.httpUseSSL = 1;
2850
+ ssl_init_server(zCertFile, zCertFile);
2851
+ }
2852
+}
28392853
28402854
/*
28412855
** COMMAND: server*
28422856
** COMMAND: ui
28432857
**
@@ -3009,11 +3023,12 @@
30093023
if( zAltBase ){
30103024
set_base_url(zAltBase);
30113025
}
30123026
g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
30133027
fNoBrowser = find_option("nobrowser", 0, 0)!=0;
3014
- if( find_option("https",0,0)!=0 ){
3028
+ decode_ssl_options();
3029
+ if( find_option("https",0,0)!=0 || g.httpUseSSL ){
30153030
cgi_replace_parameter("HTTPS","on");
30163031
}
30173032
if( find_option("localhost", 0, 0)!=0 ){
30183033
flags |= HTTP_SERVER_LOCALHOST;
30193034
}
@@ -3087,18 +3102,19 @@
30873102
iPort = db_get_int("http-port", 8080);
30883103
mxPort = iPort+100;
30893104
}
30903105
if( isUiCmd && !fNoBrowser ){
30913106
char *zBrowserArg;
3107
+ const char *zProtocol = g.httpUseSSL ? "https" : "http";
30923108
if( zRemote ) db_open_config(0,0);
30933109
zBrowser = fossil_web_browser();
30943110
if( zIpAddr==0 ){
3095
- zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
3111
+ zBrowserArg = mprintf("%s://localhost:%%d/%s", zProtocol, zInitPage);
30963112
}else if( strchr(zIpAddr,':') ){
3097
- zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
3113
+ zBrowserArg = mprintf("%s://[%s]:%%d/%s", zProtocol, zIpAddr, zInitPage);
30983114
}else{
3099
- zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3115
+ zBrowserArg = mprintf("%s://%s:%%d/%s", zProtocol, zIpAddr, zInitPage);
31003116
}
31013117
zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
31023118
fossil_free(zBrowserArg);
31033119
}
31043120
if( zRemote ){
@@ -3187,17 +3203,24 @@
31873203
g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
31883204
}
31893205
}
31903206
if( flags & HTTP_SERVER_SCGI ){
31913207
cgi_handle_scgi_request();
3208
+ }else if( g.httpUseSSL ){
3209
+ g.httpSSLConn = ssl_new_server(fileno(stdin),fileno(stdout));
3210
+ cgi_handle_http_request(0);
31923211
}else{
31933212
cgi_handle_http_request(0);
31943213
}
31953214
process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
31963215
if( g.fAnyTrace ){
31973216
fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
31983217
getpid());
3218
+ }
3219
+ if( g.httpUseSSL && g.httpSSLConn ){
3220
+ ssl_close_server(g.httpSSLConn);
3221
+ g.httpSSLConn = 0;
31993222
}
32003223
#else
32013224
/* Win32 implementation */
32023225
if( allowRepoList ){
32033226
flags |= HTTP_SERVER_REPOLIST;
32043227
--- src/main.c
+++ src/main.c
@@ -196,10 +196,11 @@
196 char *th1Setup; /* The TH1 post-creation setup script, if any */
197 int th1Flags; /* The TH1 integration state flags */
198 FILE *httpIn; /* Accept HTTP input from here */
199 FILE *httpOut; /* Send HTTP output here */
200 int httpUseSSL; /* True to use an SSL codec for HTTP traffic */
 
201 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
202 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
203 int *aCommitFile; /* Array of files to be committed */
204 int markPrivate; /* All new artifacts are private if true */
205 char *ckinLockFail; /* Check-in lock failure received from server */
@@ -2834,10 +2835,23 @@
2834 signal(SIGALRM, sigalrm_handler);
2835 alarm(N);
2836 nAlarmSeconds = N;
2837 #endif
2838 }
 
 
 
 
 
 
 
 
 
 
 
 
 
2839
2840 /*
2841 ** COMMAND: server*
2842 ** COMMAND: ui
2843 **
@@ -3009,11 +3023,12 @@
3009 if( zAltBase ){
3010 set_base_url(zAltBase);
3011 }
3012 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
3013 fNoBrowser = find_option("nobrowser", 0, 0)!=0;
3014 if( find_option("https",0,0)!=0 ){
 
3015 cgi_replace_parameter("HTTPS","on");
3016 }
3017 if( find_option("localhost", 0, 0)!=0 ){
3018 flags |= HTTP_SERVER_LOCALHOST;
3019 }
@@ -3087,18 +3102,19 @@
3087 iPort = db_get_int("http-port", 8080);
3088 mxPort = iPort+100;
3089 }
3090 if( isUiCmd && !fNoBrowser ){
3091 char *zBrowserArg;
 
3092 if( zRemote ) db_open_config(0,0);
3093 zBrowser = fossil_web_browser();
3094 if( zIpAddr==0 ){
3095 zBrowserArg = mprintf("http://localhost:%%d/%s", zInitPage);
3096 }else if( strchr(zIpAddr,':') ){
3097 zBrowserArg = mprintf("http://[%s]:%%d/%s", zIpAddr, zInitPage);
3098 }else{
3099 zBrowserArg = mprintf("http://%s:%%d/%s", zIpAddr, zInitPage);
3100 }
3101 zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3102 fossil_free(zBrowserArg);
3103 }
3104 if( zRemote ){
@@ -3187,17 +3203,24 @@
3187 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
3188 }
3189 }
3190 if( flags & HTTP_SERVER_SCGI ){
3191 cgi_handle_scgi_request();
 
 
 
3192 }else{
3193 cgi_handle_http_request(0);
3194 }
3195 process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
3196 if( g.fAnyTrace ){
3197 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3198 getpid());
 
 
 
 
3199 }
3200 #else
3201 /* Win32 implementation */
3202 if( allowRepoList ){
3203 flags |= HTTP_SERVER_REPOLIST;
3204
--- src/main.c
+++ src/main.c
@@ -196,10 +196,11 @@
196 char *th1Setup; /* The TH1 post-creation setup script, if any */
197 int th1Flags; /* The TH1 integration state flags */
198 FILE *httpIn; /* Accept HTTP input from here */
199 FILE *httpOut; /* Send HTTP output here */
200 int httpUseSSL; /* True to use an SSL codec for HTTP traffic */
201 void *httpSSLConn; /* The SSL connection */
202 int xlinkClusterOnly; /* Set when cloning. Only process clusters */
203 int fTimeFormat; /* 1 for UTC. 2 for localtime. 0 not yet selected */
204 int *aCommitFile; /* Array of files to be committed */
205 int markPrivate; /* All new artifacts are private if true */
206 char *ckinLockFail; /* Check-in lock failure received from server */
@@ -2834,10 +2835,23 @@
2835 signal(SIGALRM, sigalrm_handler);
2836 alarm(N);
2837 nAlarmSeconds = N;
2838 #endif
2839 }
2840
2841 /*
2842 ** Check for options to "fossil server" or "fossil ui" that imply that
2843 ** SSL should be used, and initialize the SSL decoder.
2844 */
2845 static void decode_ssl_options(void){
2846 const char *zCertFile = 0;
2847 zCertFile = find_option("tls-cert-file",0,1);
2848 if( zCertFile ){
2849 g.httpUseSSL = 1;
2850 ssl_init_server(zCertFile, zCertFile);
2851 }
2852 }
2853
2854 /*
2855 ** COMMAND: server*
2856 ** COMMAND: ui
2857 **
@@ -3009,11 +3023,12 @@
3023 if( zAltBase ){
3024 set_base_url(zAltBase);
3025 }
3026 g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
3027 fNoBrowser = find_option("nobrowser", 0, 0)!=0;
3028 decode_ssl_options();
3029 if( find_option("https",0,0)!=0 || g.httpUseSSL ){
3030 cgi_replace_parameter("HTTPS","on");
3031 }
3032 if( find_option("localhost", 0, 0)!=0 ){
3033 flags |= HTTP_SERVER_LOCALHOST;
3034 }
@@ -3087,18 +3102,19 @@
3102 iPort = db_get_int("http-port", 8080);
3103 mxPort = iPort+100;
3104 }
3105 if( isUiCmd && !fNoBrowser ){
3106 char *zBrowserArg;
3107 const char *zProtocol = g.httpUseSSL ? "https" : "http";
3108 if( zRemote ) db_open_config(0,0);
3109 zBrowser = fossil_web_browser();
3110 if( zIpAddr==0 ){
3111 zBrowserArg = mprintf("%s://localhost:%%d/%s", zProtocol, zInitPage);
3112 }else if( strchr(zIpAddr,':') ){
3113 zBrowserArg = mprintf("%s://[%s]:%%d/%s", zProtocol, zIpAddr, zInitPage);
3114 }else{
3115 zBrowserArg = mprintf("%s://%s:%%d/%s", zProtocol, zIpAddr, zInitPage);
3116 }
3117 zBrowserCmd = mprintf("%s %!$ &", zBrowser, zBrowserArg);
3118 fossil_free(zBrowserArg);
3119 }
3120 if( zRemote ){
@@ -3187,17 +3203,24 @@
3203 g.zRepositoryName = enter_chroot_jail(g.zRepositoryName, noJail);
3204 }
3205 }
3206 if( flags & HTTP_SERVER_SCGI ){
3207 cgi_handle_scgi_request();
3208 }else if( g.httpUseSSL ){
3209 g.httpSSLConn = ssl_new_server(fileno(stdin),fileno(stdout));
3210 cgi_handle_http_request(0);
3211 }else{
3212 cgi_handle_http_request(0);
3213 }
3214 process_one_web_page(zNotFound, glob_create(zFileGlob), allowRepoList);
3215 if( g.fAnyTrace ){
3216 fprintf(stderr, "/***** Webpage finished in subprocess %d *****/\n",
3217 getpid());
3218 }
3219 if( g.httpUseSSL && g.httpSSLConn ){
3220 ssl_close_server(g.httpSSLConn);
3221 g.httpSSLConn = 0;
3222 }
3223 #else
3224 /* Win32 implementation */
3225 if( allowRepoList ){
3226 flags |= HTTP_SERVER_REPOLIST;
3227

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button