Fossil

Changes On Branch tls-server-fix
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch tls-server-fix Excluding Merge-Ins

This is equivalent to a diff from ba95498d36 to 60d1581ff0

2022-01-17
13:47
This branch superceded by [d7008b34579d2f41|check-in d7008b34579d2f41] and therefore closed. Was: move the checking for --https to before verify_options is called ... (Closed-Leaf check-in: 60d1581ff0 user: rdb tags: tls-server-fix)
2022-01-16
11:29
merge latest trunk ... (check-in: 8dde277768 user: rdb tags: tls-server-fix)
10:55
/pikchrshow: in demo pikchrs which use an ampersand, write them as literals instead of HTML-escaped, to account for changes made to how pikchr handles those. ... (check-in: 4364ad05eb user: stephan tags: trunk)
10:09
Implement -p|--prototype option for diff command. This commit introduces support for displaying in the chunk header which C function each change is in. Tested on OpenBSD, Ubuntu, and macOS. <b>[closed: feature rejected]</b> ... (Closed-Leaf check-in: 792674372e user: jamsek tags: diff-show-func)
02:03
When reading POST via TLS, fail fatally on a read error. Add SERVER_SOFTWARE to the environment when running in server mode. ... (check-in: ba95498d36 user: stephan tags: trunk)
01:34
Show the value of SERVER_SOFTWARE on the /test_env page. ... (check-in: f1729c4736 user: drh tags: trunk)

Changes to src/http_ssl.c.
703
704
705
706
707
708
709


710
711
712
713
714
715
716
** to get the certificate and private-key (concatenated together, in
** the PEM format).  If there is no ssl-cert setting, then
** a built-in self-signed cert is used.
*/
void ssl_init_server(const char *zCertFile, const char *zKeyFile){
  if( sslIsInit==0 ){
    const char *zTlsCert;


    SSL_library_init();
    SSL_load_error_strings();
    OpenSSL_add_all_algorithms();
    sslCtx = SSL_CTX_new(SSLv23_server_method());
    if( sslCtx==0 ){
      ERR_print_errors_fp(stderr);
      fossil_fatal("Error initializing the SSL server");







>
>







703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
** to get the certificate and private-key (concatenated together, in
** the PEM format).  If there is no ssl-cert setting, then
** a built-in self-signed cert is used.
*/
void ssl_init_server(const char *zCertFile, const char *zKeyFile){
  if( sslIsInit==0 ){
    const char *zTlsCert;
    db_find_and_open_repository(OPEN_OK_NOT_FOUND|OPEN_SUBSTITUTE,0);
    db_open_config(1,0);
    SSL_library_init();
    SSL_load_error_strings();
    OpenSSL_add_all_algorithms();
    sslCtx = SSL_CTX_new(SSLv23_server_method());
    if( sslCtx==0 ){
      ERR_print_errors_fp(stderr);
      fossil_fatal("Error initializing the SSL server");
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
        fossil_exit(1);
      }
    }
    db_unprotect(PROTECT_ALL);
    db_multi_exec(
      "PRAGMA secure_delete=ON;"
      "DELETE FROM config "
      " WHERE name IN ('ssl-cert','ssl-cert-file','ssl-cert-key');"
    );
    db_protect_pop();
  }else
  if( strncmp("load-cert",zCmd,nCmd)==0 && nCmd>=4 ){
    int bFN = find_option("filename",0,0)!=0;
    int i;
    Blob allText = BLOB_INITIALIZER;
    int haveCert = 0;
    int haveKey = 0;
    verify_all_options();
    db_begin_transaction();
    db_unprotect(PROTECT_ALL);
    db_multi_exec(
      "PRAGMA secure_delete=ON;"
      "DELETE FROM config "
      " WHERE name IN ('ssl-cert','ssl-cert-file','ssl-cert-key');"
    );
    nHit = 0;
    for(i=3; i<g.argc; i++){
      Blob x;
      int isCert;
      int isKey;
      if( !file_isfile(g.argv[i], ExtFILE) ){







|















|







919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
        fossil_exit(1);
      }
    }
    db_unprotect(PROTECT_ALL);
    db_multi_exec(
      "PRAGMA secure_delete=ON;"
      "DELETE FROM config "
      " WHERE name IN ('ssl-cert','ssl-cert-file','ssl-key-file');"
    );
    db_protect_pop();
  }else
  if( strncmp("load-cert",zCmd,nCmd)==0 && nCmd>=4 ){
    int bFN = find_option("filename",0,0)!=0;
    int i;
    Blob allText = BLOB_INITIALIZER;
    int haveCert = 0;
    int haveKey = 0;
    verify_all_options();
    db_begin_transaction();
    db_unprotect(PROTECT_ALL);
    db_multi_exec(
      "PRAGMA secure_delete=ON;"
      "DELETE FROM config "
      " WHERE name IN ('ssl-cert','ssl-cert-file','ssl-key-file');"
    );
    nHit = 0;
    for(i=3; i<g.argc; i++){
      Blob x;
      int isCert;
      int isKey;
      if( !file_isfile(g.argv[i], ExtFILE) ){
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
      if( isCert ){
        if( haveCert ){
          fossil_fatal("more than one certificate provided");
        }
        haveCert = 1;
        if( bFN ){
          db_set("ssl-cert-file", file_canonical_name_dup(g.argv[i]), 0);
        }else{
          blob_append(&allText, blob_buffer(&x), blob_size(&x));
        }
        if( isKey && !haveKey ){
          haveKey = 1;
          isKey = 0;
        }
      }
      if( isKey ){
        if( haveKey ){
          fossil_fatal("more than one private key provided");
        }
        haveKey = 1;
        if( bFN ){
          db_set("ssl-key-file", file_canonical_name_dup(g.argv[i]), 0);
        }else{
          blob_append(&allText, blob_buffer(&x), blob_size(&x));
        }
      }
    }
    if( !haveCert ){
      if( !haveKey ){
        fossil_fatal("missing certificate and private-key");
      }else{
        fossil_fatal("missing certificate");
      }
    }else if( !haveKey ){
      fossil_fatal("missing private-key");
    }
    if( !bFN ){
      db_set("ssl-cert", blob_str(&allText), 0);
    }
    db_protect_pop();
    db_commit_transaction();
  }else
  if( strncmp("scrub",zCmd,nCmd)==0 && nCmd>4 ){
    int bForce = find_option("force","f",0)!=0;







<














<













|







958
959
960
961
962
963
964

965
966
967
968
969
970
971
972
973
974
975
976
977
978

979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
      if( isCert ){
        if( haveCert ){
          fossil_fatal("more than one certificate provided");
        }
        haveCert = 1;
        if( bFN ){
          db_set("ssl-cert-file", file_canonical_name_dup(g.argv[i]), 0);

          blob_append(&allText, blob_buffer(&x), blob_size(&x));
        }
        if( isKey && !haveKey ){
          haveKey = 1;
          isKey = 0;
        }
      }
      if( isKey ){
        if( haveKey ){
          fossil_fatal("more than one private key provided");
        }
        haveKey = 1;
        if( bFN ){
          db_set("ssl-key-file", file_canonical_name_dup(g.argv[i]), 0);

          blob_append(&allText, blob_buffer(&x), blob_size(&x));
        }
      }
    }
    if( !haveCert ){
      if( !haveKey ){
        fossil_fatal("missing certificate and private-key");
      }else{
        fossil_fatal("missing certificate");
      }
    }else if( !haveKey ){
      fossil_fatal("missing private-key");
    }
    if( bFN ){
      db_set("ssl-cert", blob_str(&allText), 0);
    }
    db_protect_pop();
    db_commit_transaction();
  }else
  if( strncmp("scrub",zCmd,nCmd)==0 && nCmd>4 ){
    int bForce = find_option("force","f",0)!=0;
Changes to src/main.c.
2587
2588
2589
2590
2591
2592
2593
















2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
        return;
      }
    }
  }
#endif
  @ %d(GETPID())
}

















/*
** Check for options to "fossil server" or "fossil ui" that imply that
** SSL should be used, and initialize the SSL decoder.
*/
static void decode_ssl_options(void){
#if FOSSIL_ENABLE_SSL
  const char *zCertFile = 0;
  zCertFile = find_option("tls-cert-file",0,1);
  if( zCertFile ){
    g.httpUseSSL = 1;
    ssl_init_server(zCertFile, zCertFile);
  }
  if( find_option("tls",0,0)!=0 || find_option("ssl",0,0)!=0 ){
    g.httpUseSSL = 1;
    ssl_init_server(0,0);
  }
#endif
}

/*
** COMMAND: http*
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










<
|


<
|







2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619

2620
2621
2622

2623
2624
2625
2626
2627
2628
2629
2630
        return;
      }
    }
  }
#endif
  @ %d(GETPID())
}

/*
** Initialize the SSL decoder.
*/
static void init_ssl_decoder(const char *zCertFile, int tls){
#if FOSSIL_ENABLE_SSL
  if( zCertFile ){
    g.httpUseSSL = 1;
    ssl_init_server(zCertFile, zCertFile);
  }
  if( 1 == tls ){
    g.httpUseSSL = 1;
    ssl_init_server(0,0);
  }
#endif
}

/*
** Check for options to "fossil server" or "fossil ui" that imply that
** SSL should be used, and initialize the SSL decoder.
*/
static void decode_ssl_options(void){
#if FOSSIL_ENABLE_SSL
  const char *zCertFile = 0;
  zCertFile = find_option("tls-cert-file",0,1);
  if( zCertFile ){

    init_ssl_decoder(zCertFile, 0);
  }
  if( find_option("tls",0,0)!=0 || find_option("ssl",0,0)!=0 ){

    init_ssl_decoder(0, 1);
  }
#endif
}

/*
** COMMAND: http*
**
3047
3048
3049
3050
3051
3052
3053
3054
3055



3056
3057
3058
3059
3060
3061
3062
  int fCreate = 0;           /* The --create flag */
  int fNoBrowser = 0;        /* Do not auto-launch web-browser */
  const char *zInitPage = 0; /* Start on this page.  --page option */
  int findServerArg = 2;     /* argv index for find_server_repository() */
  char *zRemote = 0;         /* Remote host on which to run "fossil ui" */
  const char *zJsMode;       /* The --jsmode parameter */
  const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */
  




#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */
  zStopperFile = find_option("stopper", 0, 1);
#endif

  if( g.zErrlog==0 ){
    g.zErrlog = "-";







|
|
>
>
>







3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
  int fCreate = 0;           /* The --create flag */
  int fNoBrowser = 0;        /* Do not auto-launch web-browser */
  const char *zInitPage = 0; /* Start on this page.  --page option */
  int findServerArg = 2;     /* argv index for find_server_repository() */
  char *zRemote = 0;         /* Remote host on which to run "fossil ui" */
  const char *zJsMode;       /* The --jsmode parameter */
  const char *zFossilCmd =0; /* Name of "fossil" binary on remote system */
#if FOSSIL_ENABLE_SSL 
  const char *zCertFile =0;  /* Internal - TLS/SSL cert filename of the --tls-cert-file option */
  int zTls =0;               /* Internal - 1 = use a TLS/SSL cert that has been previously loaded by ssl-config load-cert command or 0 if no TLS / SSL has been loaeded  */
#endif
  const char *zHttps =0;     /* Internal - set if if --https is present */
#if defined(_WIN32)
  const char *zStopperFile;    /* Name of file used to terminate server */
  zStopperFile = find_option("stopper", 0, 1);
#endif

  if( g.zErrlog==0 ){
    g.zErrlog = "-";
3094
3095
3096
3097
3098
3099
3100
3101



3102
3103





3104

3105
3106
3107
3108
3109
3110
3111
  fCreate = find_option("create",0,0)!=0;
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
  fNoBrowser = find_option("nobrowser", 0, 0)!=0;
  decode_ssl_options();



  if( find_option("https",0,0)!=0 || g.httpUseSSL ){
    cgi_replace_parameter("HTTPS","on");





  }

  if( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }
  g.zCkoutAlias = find_option("ckout-alias",0,1);
  g.zMainMenuFile = find_option("mainmenu",0,1);
  if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
    fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);







|
>
>
>
|
|
>
>
>
>
>

>







3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
  fCreate = find_option("create",0,0)!=0;
  if( find_option("scgi", 0, 0)!=0 ) flags |= HTTP_SERVER_SCGI;
  if( zAltBase ){
    set_base_url(zAltBase);
  }
  g.sslNotAvailable = find_option("nossl", 0, 0)!=0 || isUiCmd;
  fNoBrowser = find_option("nobrowser", 0, 0)!=0;

  /* 
  ** get tls / ssl options, the calls that use these options need 
  ** access to the repo database which has not been found yet.
  ** we get and store them now, as find_option removes them from
  ** argv
  */
#if FOSSIL_ENABLE_SSL
  zCertFile = find_option("tls-cert-file",0,1);
  if( find_option("tls",0,0)!=0 || find_option("ssl",0,0)!=0 ){
    zTls = 1;
  }
#endif
  if( find_option("localhost", 0, 0)!=0 ){
    flags |= HTTP_SERVER_LOCALHOST;
  }
  g.zCkoutAlias = find_option("ckout-alias",0,1);
  g.zMainMenuFile = find_option("mainmenu",0,1);
  if( g.zMainMenuFile!=0 && file_size(g.zMainMenuFile,ExtFILE)<0 ){
    fossil_fatal("Cannot read --mainmenu file %s", g.zMainMenuFile);
3121
3122
3123
3124
3125
3126
3127

3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
  if( find_option("debug-nofork",0,0)!=0 ){
    flags |= HTTP_SERVER_NOFORK;
#if !defined(_WIN32)
    /* Disable the timeout during debugging */
    zTimeout = "100000000";
#endif
  }

  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");
  if( g.httpUseSSL && (flags & HTTP_SERVER_SCGI)!=0 ){
    fossil_fatal("SCGI does not (yet) support TLS-encrypted connections");
  }
  if( isUiCmd && 3==g.argc && file_isdir(g.argv[2], ExtFILE)>0 ){
    /* If REPOSITORY arg is the root of a checkout,
    ** chdir to that checkout so that the current version
    ** gets highlighted in the timeline by default. */
    const char * zDir = g.argv[2];
    if(dir_has_ckout_db(zDir)){
      if(0!=file_chdir(zDir, 0)){







>




<
<
<







3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158



3159
3160
3161
3162
3163
3164
3165
  if( find_option("debug-nofork",0,0)!=0 ){
    flags |= HTTP_SERVER_NOFORK;
#if !defined(_WIN32)
    /* Disable the timeout during debugging */
    zTimeout = "100000000";
#endif
  }
  zHttps = find_option("https",0,0);
  /* We should be done with options.. */
  verify_all_options();

  if( g.argc!=2 && g.argc!=3 ) usage("?REPOSITORY?");



  if( isUiCmd && 3==g.argc && file_isdir(g.argv[2], ExtFILE)>0 ){
    /* If REPOSITORY arg is the root of a checkout,
    ** chdir to that checkout so that the current version
    ** gets highlighted in the timeline by default. */
    const char * zDir = g.argv[2];
    if(dir_has_ckout_db(zDir)){
      if(0!=file_chdir(zDir, 0)){
3164
3165
3166
3167
3168
3169
3170
















3171
3172
3173
3174
3175
3176
3177
    flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
    g.useLocalauth = 1;
    allowRepoList = 1;
  }
  if( !zRemote ){
    find_server_repository(findServerArg, fCreate);
  }
















  if( zInitPage==0 ){
    if( isUiCmd && g.localOpen ){
      zInitPage = "timeline?c=current";
    }else{
      zInitPage = "";
    }
  }







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
    flags |= HTTP_SERVER_LOCALHOST|HTTP_SERVER_REPOLIST;
    g.useLocalauth = 1;
    allowRepoList = 1;
  }
  if( !zRemote ){
    find_server_repository(findServerArg, fCreate);
  }
  /* 
  ** We need call enable TLS / SSL here as we need query the 
  ** repo database to access the certificate if its been loaded
  **     
  ** The database has only just been found and made available
  */
#if FOSSIL_ENABLE_SSL
    init_ssl_decoder(zCertFile, zTls);
#endif
  if( zHttps !=0 || g.httpUseSSL ){
    cgi_replace_parameter("HTTPS","on");
  }
  if( g.httpUseSSL && (flags & HTTP_SERVER_SCGI)!=0 ){
    fossil_fatal("SCGI does not (yet) support TLS-encrypted connections");
  }

  if( zInitPage==0 ){
    if( isUiCmd && g.localOpen ){
      zInitPage = "timeline?c=current";
    }else{
      zInitPage = "";
    }
  }